-1

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

我的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。

4

2 回答 2

0

为什么 Rails 不在#new控制器动作中持久化对象?

  1. HTTP 请求一致性

    所有#new操作都映射到 GET 请求,不应用于创建资源。创建资源有两种方式:非幂等方式,使用#createwhich映射到POST;以及幂等方式,通过使用#updatewhich 映射到 PUT(或 PATCH 在某些情况下)。当您想要创建您已经知道其 id 的资源时,后者是要走的路。

  2. 验证

    验证背后的整个想法是应该在持久化数据之前应用它们。所以在#new动作中我们通常将自己限制为实例化模型类,然后在#create动作中我们至少可以有两种可能的响应——一个成功的时候验证已经被清除并且对象已经被持久化,一个不成功的时候我们持久化对象时出错。

  3. 保持数据库中没有空对象

    #new和是不同动作的另一个原因#create是服务器可能会失去它们之间与客户端的连接。而且,当这种情况发生时,您不希望数据库中有一个空对象,因为第二个操作从未通过。

也就是说,如果您仍然有充分的理由在请求用户输入之前持久化对象并且您不需要验证并且您不介意数据库中有空对象,您可以通过#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
于 2013-09-08T15:00:56.503 回答
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
于 2013-09-08T13:56:56.627 回答