当id已存在时创建失败

时间:2013-02-18 18:59:43

标签: ruby-on-rails ruby-on-rails-3

我正在使用rake任务用一些初始数据填充我的数据库。我想在表格中创建一堆条目,其中包含前几个ID,因此它们始终存在,并且始终具有这些ID。我不介意在开发环境中,有人添加/删除/修改记录,但我总是希望前5个ID具有值。这是我的lib / tasks / bootstrap.rb文件的简化版本:

namespace :bootstrap do
    desc "Create the default problem types"
    task :default_problem_types => :environment do
        ProblemType.create( :id => 1, :name => 'Wrong location', :description => 'blah' )
        ProblemType.create( :id => 2, :name =>  'Wrong name', :description => 'blah' )
        ProblemType.create( :id => 3, :name =>  'Wrong details', :description => 'blah' )
        ProblemType.create( :id => 4, :name =>  'Duplicate', :description => 'blah' )
        ProblemType.create( :id => 5, :name =>  'No longer exists', :description => 'blah' )
    end

    desc "Run all bootstrapping tasks"
    task :all => [:default_problem_types]
end

这适用于空数据库。它在problem_types表中创建了5个新条目:

1 - Wrong Location 
2 - Wrong name 
3 - Wrong details 
4 - Duplicate 
5 - No longer exists

问题是,如果我再次运行它,它会创建5条新记录,ID为6,7,8,9,10。尽管我提供了id已经存在的create()调用。我期待这些调用失败,因为如果我尝试执行以下SQL:

insert into problem_types (id, name, description) values (1, 'foo', 'bar');

......它失败了:

ERROR 1062(23000):密钥'PRIMARY'重复输入'1'

如果ID已存在,如何让create()方法失败?

感谢。

2 个答案:

答案 0 :(得分:0)

经验法则:你不能自己分配身份证。让数据库完成它的工作。如果您希望问题名称是唯一的,则可以将validates_uniqueness_of :name添加到模型文件中,如果存在相同的名称,则不会创建记录

答案 1 :(得分:0)

使用动态find_or_create_byfind_or_initialize_by方法。您可以在Rails guides for the Active Record query interface中详细了解这些内容。它们允许您为每个ProblemType编写类似的内容,而不会按名称创建重复项:

problem_type = ProblemType.find_or_initialize_by_name('Wrong location')
problem_type.description = "blah"
problem_type.save

我同意@benchwarmer;最好避免自己管理主键。如果您必须具有某个语义值的数字标识符,请尝试添加单独的列并相应地设置该值。