2016-04-21 52 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。