开发者

What is the purpose of the new controller action in Rails?

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 =&开发者_运维问答gt; @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


One main purpose is so that you can use the same form for new and edit.

The controller passes the @product object (new or existing) and Rails sees whether it's a new record or an existing record. It makes certain decisions based on that such as to pull the record values into the input fields (existing) and which controller action to send the form on submission.


If you have a form_for, the new action is used to properly initialize the @product in form_for @product, which expects an ActiveRecord model. If I remember correctly, the Product's scope (for any controller action) ends with the request, so the create action has no knowledge of the new action, requiring another Product to be initialized.

The form_for method uses the @product variable to correctly assign the form to the resource controller to find the correct URL, id (in the case of an update), and more. You can read about it in section 2.3 of http://guides.rubyonrails.org/form_helpers.html

If you're that concerned about memory usage, you don't have to initialize @product, but then you would have to manually create your own form without using the nice resource-based form_for.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜