Ruby on rails Rails创建和新建不同的对象

Ruby on rails Rails创建和新建不同的对象,ruby-on-rails,Ruby On Rails,我有一个模型项目和一个模型测试。这个项目有很多测试 我的测试\u控制器具有: 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 因此,在我的

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

我的
测试\u控制器
具有:

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
的表单,当按下submit时,就会调用
create
。然而,我感到困惑,因为显然发生的事情是,我在
new
中创建了一个测试,在
create
中创建了一个完全不同的测试。我想要实现的正确范例是什么


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

创建
操作应该如下所示:

  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
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
为什么Rails不在
#new
控制器操作中持久化对象?
  • HTTP请求一致性

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

  • 验证

    验证背后的整体思想是,在持久化数据之前应该应用验证。因此在
    #new
    操作中,我们通常将自己限制为实例化模型类,然后在
    #create
    操作中,我们至少可以有两种可能的响应——一种是在清除验证并持久化对象时成功响应,另一种是在持久化对象时出错时失败响应

  • 保持数据库中没有空对象

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

  • 也就是说,如果您在请求用户输入之前仍然有充分的理由保留对象,并且您不需要验证,也不介意数据库中有空对象,那么您可以完全跳过
    #new
    操作,类似这样:

      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
    
    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
    

    它们是不同的对象,因为它们不会在请求之间持久化。但是在第一个操作中,您并没有实际创建测试,您只是实例化了测试类。你的问题到底是什么?@depa那么我如何在请求之间保持它们?典型的处理方式是什么?为什么要坚持?您没有数据在第一个操作中保存它,这只发生在第二个操作中,因为您有test_参数。这是处理这一问题的典型方式。@depa当我展示create表单时,我希望表单知道新测试对象的潜在id。这就是为什么在
    new
    方法中我要创建一个测试对象。在实际将主键保存到数据库之前,您不会知道主键。您没有任何阻止您持久化空对象的验证?我遇到的问题是我正在使用([@project,test]..
    ,如果我不调用new,那么我就没有机会进行设置,@project和test都将为零,因此没有表单。但是你应该将表单基于新对象的空对象。你能告诉我你得到的确切错误消息吗?告诉Rails..我得到一个异常:
    表单中的第一个参数不能包含n nil或为空
    ,它指的是行的表单。好的,这就是为什么你在提问时总是要讲述整个故事。请尝试在你的
    \new
    操作中简单地使用
    @test=test.new
    。是的,但是现在当我在表单上点击submit时,我在new中创建的测试将在create方法中被忽略。我需要跟踪它的id。