Rails创建和创建不同的对象

时间:2013-09-08 13:43:39

标签: ruby-on-rails

我有一个模型项目和模型测试。项目有很多测试。

我的tests_controller有:

def new
    @project = Project.find(params[:project_id])
    @test = @project.tests.new
end

def create
    @project = Project.find(params[:project_id])
    @test = @project.tests.create(test_params)
end

因此,在我的new.html.erb中,我提供了一个调用new的表单,当按下提交时,会调用create。我很困惑,因为显然发生的事情是我在new中创建了一个测试,在create中创建了一个完全不同的测试。对于我想要实现的目标,正确的范例是什么?

我在new中创建新测试的原因是因为我希望我的创建表单知道要创建的测试对象的id。

2 个答案:

答案 0 :(得分:0)

create操作应如下所示:

  def create
    @project = Project.find(params[:project_id])
    @test = @project.test.create(params[:test])
    if @test.save
      redirect_to SOME_path, flash: { success: "Test added successfully" }
    else
      flash.now[:error] = "Something's gone wrong.  Please try again!"
      render 'new' 
    end    
  end

答案 1 :(得分:0)

为什么Rails不会在#new控制器操作中持久保存对象?

  1. HTTP请求一致性

    所有#new个操作都映射到GET请求,这些请求不应用于创建资源。创建资源可以通过两种方式完成:非幂等方式,使用映射到POST的#create;和幂等方式,使用映射到PUT(或某些情况下为PATCH)的#update。当您想要创建您已经知道其身份的资源时,后者就是您的选择。

  2. <强>验证

    验证背后的整个想法是应该在持久化数据之前应用。因此,在#new操作中,我们通常将自己限制为实例化模型类,然后在#create操作中我们可以至少有两个可能的响应 - 在验证已被清除时成功的响应和对象当我们在持久化对象时遇到错误时,它一直存在,并且是不成功的。

  3. 保持数据库远离空对象

    #new#create是不同操作的另一个原因是服务器可能会丢失与客户端之间的连接。而且,当发生这种情况时,您不希望在数据库中存在空对象,因为第二个操作永远不会出现。

  4. 那就是说,如果你仍然有充分的理由在要求输入用户输入之前保留对象,那么你就不需要验证了,你不介意在数据库中有空对象,你可以通过完全跳过#new动作来做到这一点,有点像这样:

    def create
      @project = Project.find(params[:project_id])
      @test = @project.tests.create
    end
    
    def update
      @project = Project.find(params[:project_id])
      @test = @project.tests.update(test_params)
    end