2016-04-21 77 views
0

我正在尝试复制记录及其所有后续深度嵌套的子关联。以下是该问题的简化。复制记录时记录存在错误

我有以下Foo型号:

class Foo < ActiveRecord::Base 

    belongs_to :project, 
    inverse_of::foos 
    validates :name,presence:true,uniqueness:{ scope: :project_id }, 
       format:{ with: /[0-9a-zA-Z\s\/_:\-.|]*/ } 

end 

我复制project这样的:

origin = Project.first 
clone = origin.dup 

clone.foos << clone_records(origin.foos) 

clone.save 

def clone_records(records) 
    clones = [] 

    records.each do |record| 
    cloned_record = record.dup 
    cloned_record.project_id = nil 
    cloned_record.name = "Copy of " + record.name 

    # Which Generates: 
    #<Foo:0x007f94353fc200> { 
    #     :id => nil, 
    #     :name => "Copy of Some Foo", 
    #   :project_id => nil 
    # 
    # } 


    clones.push(cloned_record) 
    end 

    return clones 

end 

的问题是,当我重复project并指定新生成的,改名,foos,节省后我得到错误:

Foo Exists (0.4ms) SELECT 1 AS one FROM "foos" WHERE ("foos"."name" = 'Copy of Some Foo' AND "foos"."project_id" = 1) LIMIT 1 

然而,没有foo存在同名:

Foo.where(name: "Copy of Some Foo") 

# Foo Load (0.6ms) SELECT "foos".* FROM "foos" WHERE "foos"."name" = $1 ORDER BY "foos"."id" ASC [["name", "Copy of Some Foo"]] 

# [] 

谁能告诉我什么可能会在这里吗?我认为它与验证有关,但我不明白为什么:1)它认为这个新记录存在,以及2)为什么新记录有一个project_id设置为原始项目,当我明确无效那个领域。

回答

0

问题是uniqueness: { scope: :project_id }也适用于nil值。所以如果你有两个记录,并且他们都有project_id == nil这将违反唯一性约束。

这里是允许零值,同时仍保持唯一性约束的一种方法:

uniqueness: { scope: :project_id }, unless: Proc.new { |record| record.project_id.blank? } 

当ActiveRecord的抱怨Foo Exists,它就会回滚承诺,让您的克隆FOOS不会持续到数据库中。

0

首先,这条线:

Foo Exists (0.4ms) SELECT 1 AS one FROM "foos" WHERE ("foos"."name" = 'Copy of Some Foo' AND "foos"."project_id" = 1) LIMIT 1 

是不是一个错误的话,那只是一个记录表明Rails正在运行你的独特性验证。并且,

2)为什么新记录的project_id设置为原始项目时,我明确地将该字段置为无效。

你确定吗?它的project_id是否设置为原始项目?在我看来,project_id只是设置为新创建的项目的ID。