Reputation: 25307
I am following this official guide to learn about Rails, where a blog is built, and I noticed that it doesn't seem to be complete.
On Point 5.13 "Using partials to clean up duplication in views", it recommends to take the form to create a post and to edit it inside a partial, because both are so similar. It does speak about a small difference about the routes that both forms use, but it says it is a problem that will be explained later
Everything except for the form_for declaration remained the same. How form_for can figure out the right action and method attributes when building the form will be explained in just a moment. [...]
But I noticed the guide never actually explains how to do this. (Maybe they just forgot...?)
Can someone explain me how can I solve this problem?
Upvotes: 1
Views: 168
Reputation: 8829
If you follow the Rails conventions, you won't have to do anything. This is well explained in the documentation (http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for).
However, further simplification is possible if the record passed to form_for is a resource, i.e. it corresponds to a set of RESTful routes, e.g. defined using the resources method in config/routes.rb. In this case Rails will simply infer the appropriate URL from the record itself.
Basically, you need to:
form_for
helperroutes.rb
f.i. resources :posts
So if you have form_for(@post)
, Rails will determine which route to use by checking if @post
is a new record.
If you want a complete example, just create a new rails app and create any scaffold:
rails g scaffold User name
You can check that Rails had put a form in a partial: app/views/users/_form.html.erb
.
If you want to dig deep, check the source code. The interesting part is in this file.
action, method = object.respond_to?(:persisted?) && object.persisted? ? [:edit, :patch] : [:new, :post]
In our example the @post
is assigned to object
. Rails is full of such short-cuts, and sometimes the best way of learning about them is looking at the source code. If you know Ruby well, you'll often find source code to be a better explanation that the docs and guides.
Upvotes: 5
Reputation: 6421
It doesn't do a great job of explaining it. If you look up the page at the two versions of the form, one for new
and one for edit
you will see they have two different pieces of code after form_for
, but they are both passing the @post
variable. In the first case, the variable contains a new, empty, Post
object.
<%= form_for :post, url: posts_path do |f| %>
In the edit
version it is looking up the record, putting it in the @post
variable and passing it to the form.
<%= form_for :post, url: post_path(@post), method: :patch do |f| %>
The final version, the partial, does not have the extra code indicating if it's a new
action or edit
. But due to the URL and the action calling the view, Rails knows which code to sub into the form when using a form partial. More "Rails magic".
<%= form_for @post do |f| %>
Upvotes: 1
Reputation: 412
<%= form_for @product do |f| %>
.
.
.
<% end %>
When @product is a new record, Rails know about it and uses products_path. However when the @product is existed one, Rails uses product_path(@product).
Upvotes: 1