Rails 4验证唯一性:{scope :: parent_id}用于嵌套资源

时间:2014-04-10 15:06:15

标签: ruby-on-rails validation activerecord ruby-on-rails-4 model

我想知道是否有人能够帮助我弄清楚为什么这不起作用。

我有一个模型让我们称它为属于项目模型的任务。我基本上希望每个任务在每个项目中都有一个唯一的名称(Project1可以有一个名为task1的任务,因此Project2可以只有一个名为task1的任务。这似乎是:scope选项的用途,但它似乎并不适合我。

任务模型是项目中的嵌套资源,因此我通过project_tasks_path(@project)调用创建操作。它可以很好地创建任务并将它们分配给项目,但唯一性验证的范围并未实现。如果我在task1中创建任务Project1,我无法在任务2中创建一个具有相同名称的任务。

这是我的设置:

Task.rb

class Task < ActiveRecord::Base
  belongs_to :project
  validates :name, presence: true, uniqueness: {scope: :project_id}

tasks_controller.rb

def create
    @project = Project.find_by(id: params[:project_id])
    @task = Task.new(model_params)
    #print task to stdout
    puts "@task"
    ap @task

    respond_to do |format|
      if @task.save
        flash[:notice] = "Successfully created task"
        format.js
      else
        # no flash as form handles errors
        format.js { render action: 'new' }
        format.html { render action: 'new' }
      end
    end
  end

由于某种原因,当我输出新创建的任务的内容时,我得到以下

#<Task:0x007ff7c7c3b178> {
            :id => nil,
          :name => "test",
    :project_id => nil,
    :created_at => nil,
    :updated_at => nil
}

似乎因为project_id目前尚未设置,所以它使用的是“nil”。作为价值。

解决这个问题的最佳方法是什么?它只是一个自定义验证器吗?

修改1

def model_params
  params.require(:model).permit(:name, :project_id)
end

1 个答案:

答案 0 :(得分:0)

是的,一直在玩这个,似乎进行这种验证的方式非常简单。它需要的是嵌套资源是根据它的项目构建的,这会强制:parent_id按预期传递给验证。

对于这个玩具示例,这意味着创建动作必须类似于:

@project = Project.find_by(id: params[:project_id])
@task = @project.tasks.build(model_params)

应该注意的是,由于Rails不支持从命令行生成嵌套资源,脚手架生成控制器处理创建的方式是Model.new(model_params)然后保存,这似乎没有提升:parent_id及时进行验证,因此需要如上所述进行更改(就父级而言)。