Reputation: 18771
I've generated a scaffold, let's call it scaffold test. Within that scaffold, I've got a _form.html.erb thats being render for action's :new => :create and :edit => :update
Rails does a lot of magic sometimes and I cannot figure out how the form_for knows how to call the proper :action when pressing submit between :new and :edit
Scaffolded Form
<%= form_for(@test) do |f| %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
vs. Un-scaffolded Form
<% form_for @test :url => {:action => "new"}, :method => "post" do |f| %>
<%= f.submit %>
<% end %>
#Edit template
<%= render 'form' %>
#New template
<%= render 'form' %>
As you can see theres no difference between the forms How can both templates render the same form but use different actions?
Upvotes: 34
Views: 16954
Reputation: 26193
If the @test
instance variable is instantiated via the Test.new
class method, then the create
method is executed. If @test
is an instance of Test
that exists in the database, the update
method is executed.
In other words:
# app/controllers/tests_controller.rb
def new
@test = Test.new
end
<%= form_for(@test) |do| %>
yields a block that is sent to the create
controller method.
If, instead:
# app/controllers/tests_controller.rb
def edit
@test = Test.find(params[:id])
end
<%= form_for(@test) |do| %>
yields a block that is sent to the update
controller method.
UPDATE:
The precise function that Rails uses to recognize whether or not a record is new is the persisted?
method.
Upvotes: 4
Reputation: 8169
It checks if the record is new or not.
@test.new_record? # if true then create action else update action
Upvotes: 10
Reputation: 29860
It checks @test.persisted?
If it is persisted then it is an edit form. If it isn't, it is a new form.
Upvotes: 69