【问题标题】:How to use Ruby tap method to pre-fill seed data如何使用 Ruby Tap 方法预填充种子数据
【发布时间】:2019-09-08 15:13:15
【问题描述】:

我在我的 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 的数据应该更新,这就是我使用find_or_create_by 的原因它正在工作很好,但是在我的 PaymentMode 中添加了 null: false 约束(请参阅架构)后,我收到了这个错误:-

PG::NotNullViolation: ERROR:  null value in column "instrument" violates not-null constraint

我可以解决这个错误吗?如果没有,有没有办法可以将数据放入我的 seed.rb 中,这样如果有人更新了种子,它应该更新相应的 ActiveRecord 对象?

附:我不想像这样 PaymentMode.find_or_create_by(name: "Cash", instrument: false).tap 将受约束的列保留在 find_or_create_by 参数中,因为如果有人将 instrument: false 更新为 instrument: true ,它会创建另一个对象

【问题讨论】:

  • 我相信当您运行rails db:migrate 时会发生错误,对吗?如果是这种情况,那仅仅是因为您已经有一些 PaymentMode 记录,因此在不指定默认值的情况下创建列将意味着为其分配 nil 值,这显然是您在迁移中指定的不具有的值。
  • 运行 rake db:seed 时出现错误,请再次阅读问题
  • 哦,我明白你的意思了。我认为#find_or_create_by 不可能。可能最简单的方法是将其分解为多种方法。
  • 也许你可以使用create_withPaymentMode.create_with(instrument: false).find_or_create_by(name: "Cash")

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


【解决方案1】:

问题不在于tap 方法。 find_or_create 打电话,从字面上看,violates not-null constraint。在tap 中,您正在使用现有对象,无法使用您在中指定的参数将其写入数据库 find_or_create_by。随后还会调用createupdate 而不仅仅是create

还有另一种方法可以做到这一点,就像点击一样,但是在将对象写入数据库之前,您可以在块中使用它:

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

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

【讨论】:

  • 是的,这不再给我 PG::NotNullViolation: ERROR,但是当我在像 validates :name, :instrument, :bank_account_allocation, presence: true 这样的 Rails 应用程序中进行验证时,我收到了这个错误:- ActiveRecord::RecordInvalid: Validation failed: Instrument can't be blank, Bank account allocation can't be blank
  • 嗯,那是因为false.blank?true。尝试另一个验证为 validates :instrument, inclusion: { in: [true, false] }exclusion: { in: [nil]}
  • 看看Active Record Validations Guide。所有这些问题都在那里得到彻底考虑
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多