即使无法保存1条记录,也会使seeds.rb文件继续播种

时间:2015-02-01 20:19:49

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

我有一个seed.rb,它将为我的数据库提供种子。

当我运行它时,我收到此错误:

$ rake db:seed

rake aborted!
ActiveRecord::StatementInvalid: PG::StringDataRightTruncation: ERROR:  value too long for type character varying(255)
: INSERT INTO "jobs" ("name", "location", "industry", "description") VALUES ($1, $2, $3, $4) RETURNING "id"

显然,string列的值太长。

如何将string列更改为text,而不是将seeds.rb文件或其他任何内容(可能是验证)更改为不将此行插入数据库并继续?

seeds.rb

Job.create([
  {name: "foo", location: "indiana", industry: "cooking", description: "Making lobster all day biznatch"},
  {name: "booz", location: "kentucky", industry: "chicken_mining", description: "We mine mad chickens so you can eat derrish KFC."},
  ...
])

1 个答案:

答案 0 :(得分:1)

如果您使用#create代替#create!,则ActiveRecord在验证错误时不会引发。实际上,如果未创建记录,#create将返回false。

但是,你的情况有点不同。失败的原因不是ActiveRecord验证错误(在bang方法的情况下会引发ActiveRecord::RecordInvalid),但它是数据库级错误。更具体地说,它是一个引发ActiveRecord::StatementInvalid的约束违规。

即使您使用非爆炸版本,也无法绕过此类异常,因为ActiveRecord认为它是低级故障。

有几种可能的解决方案。首先,您可以逐个执行每条记录的创建,并拯救RuntimeError(s)

attributes = [
  {name: "foo", location: "indiana", industry: "cooking", description: "Making lobster all day biznatch"},
  {name: "booz", location: "kentucky", industry: "chicken_mining", description: "We mine mad chickens so you can eat derrish KFC."},
  ...
]

attributes.each do |params|
  begin
    Job.create(params)
  rescue => e
    puts "Error #{e.message} with params #{params}"
  end
end

此外,您可以在ActiveRecord模型中的字段上添加大小验证,以确保内容将被预先验证,并且ActiveRecord不会尝试创建和执行无效的SQL语句。

一般来说,这类错误应该被视为代码中的错误,而您并不是真的想要沉默。这就是为什么即使你使用非爆炸create版本,ActiveRecord也会抱怨。

您将一些无效数据传递给数据库引擎,除非您已准备好承担风险(并处理异常),否则不会发生这种情况。