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| %>
Any information would be nice, I would love to know!
Rails forms made easy. Simple Form aims to be as flexible as possible while helping you with powerful components to create your forms. The basic goal of Simple Form is to not touch your way of defining the layout, letting you find the better design for your eyes.
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.
All three approaches yield the same form (assuming you're setting @pack
to be Pack.find(params[:id])
, however there are trade-offs:
It's not advisable to have an ActiveRecord call in your view code. Views should just be responsible for laying out the form, not for querying the database. Maintaining this separation will make long-term maintenance much more straightforward. Using a variable also means you can have the same form for both the new
and edit
screens, by setting @pack = Pack.new
in your controller for the new
view. For these reasons, I'd advise against option [1].
Using the object (@pack
) or the symbol (:pack
) yields the same results because internally the Rails form_for
helper uses the symbol to look up the variable. IMHO option [2] and referencing the object directly is "better" because there's less magic going on, so it's easier for people new to the project (or you in a year's time) to understand. Option [2] is also consistent with the Rails docs and SimpleForm docs, so it's less of a surprise for people to see.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With