A scaffold generates the new action like this:
def new
@product = Product.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @product }
end
end
def create
@product = Product.new(params[:product])
respond_to do |format|
if @product.save
format.html { redirect_to(@product, :notice => 'Product was successfully created.') }
format.xml { render :xml => @product, :status => :created, :location => @product }
else
format.html { render :action => "new" }
format.xml { render :xml => @product.errors, :status => :unprocessable_entity }
end
end
end
and the view renders a partial, named form
. Since the new
form renders with the action set to create a new product, what is the purpose of @product
? I see that the create
action instantiates a new object as well. Is it only used so that you can tie the form to an object, so that everything goes from action to action correctly?
You can think of @product in the new action as being an unsaved object that simply fills out the form fields that are rendered in the view. This makes new.html.erb pretty much the same as edit.html.erb and allows them to share a single partial, _form.html.erb.
When this partial is used in the new action, the fields are populated by a fresh, empty, and unsaved @product object. This is the Product.new that appears in the new action. When the partial is used in the edit action, you've got a @product object that presumably has values for all its attributes. Now, suppose you didn't use @product in the new action. The form used in new.html.erb would need to be different than the form used in edit. Good luck maintaining them if you ever add a new field to the model.
Another advantage of this approach is that you can pre-populate attributes of the new @product before they're rendered in the view. Suppose you want to use the name "new product" as the default name for each product. You can do this in the new action this way:
def new
@product = Product.new(:name => 'new product')
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @product }
end
end