如何使用Ruby Tap方法预填充种子数据

时间:2019-04-18 09:45:31

标签: ruby-on-rails ruby activerecord ruby-on-rails-5 seeding

我在我的seed.rb中使用Ruby的tap方法,如下所示:-

 PaymentMode.find_or_create_by(name: "Cash").tap do |pm|
  pm.instrument = false
  pm.bank_account_allocation = false
  pm.save!
 end

在schema.rb中,PaymentMode模型如下所示:-

  create_table "payment_modes", force: :cascade do |t|
    t.string "name"
    t.boolean "instrument", null: false
    t.boolean "bank_account_allocation"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["name"], name: "index_payment_modes_on_name", unique: true
  end

我希望如果有人更新种子文件(例如有人可以更新pm.bank_account_allocation = true),然后运行rake db:seed,则应更新相应的payment_mode的数据,这就是为什么我使用{{1} }工作正常,但是我在我的PaymentMode中添加了null:false约束(请参阅架构)后,出现此错误:-

find_or_create_by

我可以解决此错误吗?如果没有,是否有办法将数据放入seed.rb,以便如果有人更新了种子,则应该更新各自的ActiveRecord对象?

P.S。我不想将受约束的列保留在像PG::NotNullViolation: ERROR: null value in column "instrument" violates not-null constraint 这样的find_or_create_by参数内,因为如果有人将Instrument:false更改为Instrument:true,它将创建另一个对象

1 个答案:

答案 0 :(得分:3)

问题不在于tap方法。 find_or_create的字面意思是violates not-null constraint。在tap中,您正在使用现有对象,该对象不能使用在中指定的参数写入数据库。 find_or_create_by。随后还有createupdate的调用,而不仅仅是create

还有另一种方法,其工作方式与tap一样,但是在块中,您需要先将对象写入数据库:

PaymentMode.where(name: "Cash").first_or_create do |pm|
  pm.instrument = false
  pm.bank_account_allocation = false
end

至于我...我只会使用find_or_initialize_bysave