Here are some explanations on "form_for" :
How does form_for
works:
<%= form_for(@pet) do |f| %>
...
<% end %>
Will generate the following HTML:
<form class="new_pet" id="new_pet" action="/pets" method="post">
</form>
So form_for
takes an object and from this object, infers if it should be an update or a create and sets the URL (action attribute in the form) to the right thing, same for the method.
For instance for a create the url should be "/pets" and the method should be POST.
For an update, the url should be "/pets/1" and the method should be PATCH.
How does form_for
does that, here is what the code looks like ?
@pet = Pet.new
# The process is as follow:
@pet.class # => Pet
@pet.class.to_s # => "Pet"
@pet.class.to_s.downcase # => "pet"
@pet.class.to_s.downcase.pluralize # => "pets"
# Therefore the code is:
if @pet.id == nil # Then it is a create
url = "/" + @pet.class.to_s.downcase.pluralize
# => /pets
method = "POST"
else # Then this is an update
url = "/" + @pet.class.to_s.downcase.pluralize + "/" + @pet.id
# => /pets/1
method = "PATCH"
end
Et Voila.
Same goes for a nested form even though it is a bit more complex: Provided that:
@restaurant = Restaurant.find(params[:restaurant_id])
@review = Review.new
<%= form_for([@restaurant, @review]) do |f| %>
...
<% end %>
Will generate the following HTML:
<form class="new_restaurant_review" id="new_restaurant_review" action="/restaurants/1/reviews" method="post">
</form>
How does form_for
does that ?
@restaurant = Restaurant.find(params[:restaurant_id])
@review = Review.new
# The process is as follow:
@restaurant.class # => Restaurant
@restaurant.class.to_s # => "Restaurant"
@restaurant.class.to_s.downcase # => "restaurant"
@restaurant.class.to_s.downcase.pluralize # => "restaurants"
# The process is as follow:
@review.class # => Review
@review.class.to_s # => "Review"
@review.class.to_s.downcase # => "review"
@review.class.to_s.downcase.pluralize # => "reviews"
# Then the url is pretty much generated like that:
"#{@restaurant.class.to_s.downcase.pluralize}/#{@restaurant.id}/#{@review.class.to_s.downcase.pluralize}"
# And this gives you: /restaurants/1/reviews