Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails: Are "form_for(:product, ...)" and "form_for(@product, ...)" equivalent?

Is

<%= form_for(:product, :url => {:action => 'update', :id => @product.id})) do |f| %>
  ...
<% end %>

and

<%= form_for(@product, :url => {:action => 'update', :id => @product.id})) do |f| %>
  ...
<% end %>

exactly the same ?

like image 539
Misha Moroshko Avatar asked Dec 14 '10 07:12

Misha Moroshko


3 Answers

The @product in the form_for helper ships with more features.

The :product only affects the input field's id and name. For example you have a text filed in the form:

<%= form_for :product, :url => {...} do |f| %>
  <%= f.text_field :price %>
<% end %>

The generated html would look like:

<input type="text" id="product_price" name="product[price]" />

The id and name value is determined by the :product.to_s and the text field name.

While if you use @product, the :url is not necessary because the url would be determined according to the @product's status:

  • if the @product is a new record, the url would post to create
  • otherwise, the url would post to update

And the input filed's id and name is affected by @product's class name, so it's important when you're using single table inheritant. The input filed's value is automatically assigned with the @product's attribute value. So if you use @product, the html output would look like:

<input type="text" id="product_price" name="product[price]" value="some value" />

Assume the @product's class name is Item, then the output would change to:

<input type="text" id="item_price" name="item[price]" value="some value" />

And of course you can use both of :product and @product:

<%= form_for :product, @product do |f| %>

The :product controls input filed's name and id, and the @product controls the url and input field's value.

like image 194
Kevin Avatar answered Sep 23 '22 13:09

Kevin


Similar, but not the same. When you use @product you have the benefit of being able to automatically populate values to the form fields from the model instance.

For example, if you in the action :new in your Controller assign @product like this:

@product = Product.new

Then there will probably not be any difference in the generated form. However, if you follow this up in you :create action like this:

@product = Product.new(params[:product])
if @product.save
  ...
else
  render :action => :new
end

Then if it is unable to save the @product instance, then it will render the same form as in :new but this time have all the fields populated with the values posted. That would not have been possible if you used :product

like image 22
DanneManne Avatar answered Sep 19 '22 13:09

DanneManne


That's quite a long form_for you've got there. The short answer to your question: @product is useful for determining what action to go to for a resource that can have many objects, which is what this sounds like. :product on the other hand will always go to the same action, update. This is best used for singular resources. A great explanation of the resources can be found in the Routing Guide. It's also explained in the Getting Started guide.

Your second form_for could be shorted right down to this:

<%= form_for @product do |f| %>
   ...
<% end %>

All is explained in the Routing and Getting Started guides.

Also, I saw in your profile you're from Melbourne. There's the Ruby on Rails Oceania Google group which lists the meetups around the country. There's one each month in Melbourne which you may want to attend to meet like minded people.

like image 22
Ryan Bigg Avatar answered Sep 22 '22 13:09

Ryan Bigg