What is the difference between these methods of addressing an edit form for "packs"?
How do these different approaches affect the stability of the application? It's versatility?
Where would these run into major problems? Why is one better than the other?
<%= simple_form_for Pack.find(params[:id]), method: :patch do |f| %>
<%= simple_form_for @pack, url: pack_path(@pack), method: :patch do |f| %>
<%= simple_form_for :pack, url: pack_path(@pack), method: :patch do |f| %>
Are basically identical besides the fact that in 2. you're referencing a model instance from an instance variable instead of just passing the return value of a method call.
The end result is that you get a form that is bound to a model instance. This means that the value attributes of the inputs will contain the values from the model.
In fact all of these will give the same result:
<%
@pack = Pack.find(params[:id])
pack = Pack.find(params[:id])
%>
<%= simple_form_for Pack.find(params[:id]), method: :patch do |f| %>
<%= simple_form_for @pack |f| %>
<%= simple_form_for pack |f| %>
But the first is less desirable since you should avoid doing queries directly from the view. The view should recieve data from the controler and use it to create HTML and be as simple and declarative as possible. Another major problem is that .find
will raise ActiveRecord::RecordNotFoundError
which should have been caught much earlier in the controller if the id is invalid.
<%= simple_form_for :pack, url: pack_path(@pack), method: :patch do |f| %>
This creates a form that is "scoped" without necissarily being bound to an specific model instance. Take this example:
<%= simple_form_for :thing do |f| %>
<%= f.input :name %>
<% end %>
This generates the following HTML:
<form novalidate="novalidate" class="simple_form thing" action="/things/new" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="F4r1gLuboZc1CKIdn9qac0sefxSVIvkjxk9KsD+sRl1wnVtEIKzHvWY0mPuLPvHI1Kcv3TIWD883YXHKXA+yJQ==" />
<div class="input string required thing_name">
<label class="string required" for="thing_name"><abbr title="required">*</abbr> Name</label>
<input class="string required" type="text" name="thing[name]" id="thing_name" />
</div>
</form>
Note name="thing[name]"
which means it will give a params hash which is just like if we had a model instance:
{
thing: {
name: "foo"
}
}
This is not as commonly used (at least not correctly) since most of the time you're manipulating model instances but it does have a use in special cases like search forms.
Note that Rails will try to resolve the local variable @thing
but will not raise an error if it is nil. Using this form is therefore generally not advised as it can mask errors.
The best way to understand this behavior is to read the docs for ActionView::FormHelpers which SimpleForm is just sugar on top of.