::first_or_create
(доступно начиная с версии 3.2.1) делает то, что написано на коробке.
Model.where(find: 'find_value').
first_or_create(create: 'create_value')
# If a record with {find: 'find_value'} already exists:
before #=> #
after #=> #
# Otherwise:
before #=> nil
after #=> #
Если вы также хотите, чтобы он обновил уже существующей записи, попробуйте:
Model.where(find: 'find_value').
first_or_create(create: 'create_value').
update(update: 'update_value')
# If one already exists:
before #=> #
after #=> #
# If it already matches, no UPDATE statement will be run:
before #=> #
after #=> #
# Otherwise:
before #=> nil
after #=> #
РЕДАКТИРОВАТЬ 2016-03-08: Согласно Дагу комментарий , если ваши проверки не выполняются между вызовами #create
и #update
, или вы хотите минимизировать вызовы базы данных, вы можете использовать вместо этого ::first_or_initialize
, чтобы избежать сохранения записи в первый звонок Тем не менее, вы должны убедиться, что вы вызываете #save
или #update
впоследствии, чтобы сохранить запись (и я не уверен, что #update
работает с записями, которые еще не были сохранены) :
Model.validates :update, presence: true # The create call would fail this
Model.where(find: 'find_value').
first_or_initialize(create: 'create_value'). # doesn't call validations
update(update: 'update_value')
(NB. Существует метод , называемый #create_or_update
, но не обманывайте себя никакими документами , которые вы можете найти в Google; это просто частный метод, используемый #save
.)
Тривиального способа сделать это нет, но есть несколько возможностей:
Вы также можете попробуйте другие проекты с открытым исходным кодом, предназначенные для решения этой проблемы. AppRocket был многообещающим, но у проекта только один коммитер, и в последние месяцы не было никакой активности ...
Кроме того, проблемы со звездочкой 59 и 776 , чтобы Google официально включил его.