Как использовать метод крана Ruby для предварительного заполнения начальных данных - PullRequest
0 голосов
/ 18 апреля 2019

Я использую метод нажатия Ruby в моем seed.rb следующим образом: -

 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 Это работало нормально, но послеЯ добавил ограничение null: false в свой PaymentMode (см. Схему), получаю эту ошибку: -

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

Могу ли я обойти эту ошибку?Если нет, то есть ли способ поместить данные в мой seed.rb, чтобы, если кто-то обновляет семя, он обновил соответствующий объект ActiveRecord?

PS Я не хочу сохранять столбец с ограничениямивнутри параметров find_or_create_by, подобных этому PaymentMode.find_or_create_by(name: "Cash", instrument: false).tap, так как это создаст другой объект, если кто-то обновит инструмент: false на инструмент: true

1 Ответ

3 голосов
/ 18 апреля 2019

Проблема не в методе tap. find_or_create Звоните, буквально, violates not-null constraint. В tap вы работаете с существующим объектом, который не может быть записан в базу данных с аргументами, указанными вами в find_or_create_by. Есть также последовательные вызовы create и update вместо просто create.

Есть еще один способ сделать это, который работает так же, как tap, но в блоке вы работаете с объектом до того, как он будет записан в базу данных:

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

Что касается меня ... Я бы просто использовал find_or_initialize_by и save.

...