2

一个脚手架生成这样的新动作:

  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

并且视图呈现一个局部的,命名为form. 既然new表单呈现了创建新产品的操作集,那么目的是@product什么?我看到该create操作也实例化了一个新对象。它是否仅用于将表单与对象联系起来,以便一切都正确地从动作到动作?

4

3 回答 3

4

您可以将新操作中的 @product 视为一个未保存的对象,它只是填写在视图中呈现的表单字段。这使得 new.html.erb 与 edit.html.erb 几乎相同,并允许它们共享单个部分,_form.html.erb。

在新操作中使用此部分时,字段将由新的、空的且未保存的 @product 对象填充。这是出现在新操作中的 Product.new。在编辑操作中使用部分时,您将获得一个 @product 对象,该对象可能具有其所有属性的值。现在,假设您没有在新操作中使用@product。new.html.erb 中使用的表单需要与编辑中使用的表单不​​同。如果您向模型添加新字段,祝您好运。

这种方法的另一个优点是您可以在新的@product 属性在视图中呈现之前预先填充它们。假设您想使用名称“新产品”作为每个产品的默认名称。您可以通过以下方式在新操作中执行此操作:

def new
    @product = Product.new(:name => 'new product')

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @product }
    end
  end
于 2011-03-09T17:20:43.420 回答
3

一个主要目的是让您可以使用相同的表单进行新建和编辑。

控制器传递@product 对象(新的或现有的),Rails 会查看它是新记录还是现有记录。它基于此做出某些决定,例如将记录值拉入输入字段(现有)以及在提交时发送表单的控制器操作。

于 2011-03-09T17:20:41.887 回答
1

如果您有一个 form_for,则新操作用于正确初始化 @product in form_for @product,它需要一个 ActiveRecord 模型。如果我没记错的话,产品的范围(对于任何控制器操作)以请求结束,因此创建操作不知道新操作,需要初始化另一个产品。

form_for方法使用该@product变量将表单正确分配给资源控制器,以找到正确的 URL、id(在更新的情况下)等。您可以在http://guides.rubyonrails.org/form_helpers.html的第 2.3 节中了解它

如果您非常担心内存使用情况,则不必进行初始化@product,但是您必须手动创建自己的表单,而无需使用 nice resource-based form_for

于 2011-03-09T16:59:36.657 回答