Trying to implement an create if not exists else update record in Active Record.
Currently using:
@student = Student.where(:user_id
::first_or_create
(available since v3.2.1) does what it says on the box.
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 #=> #
If you also want it to update an already-existing record, try:
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 #=> #
EDIT 2016-03-08: As per Doug's comment, if your validations fail between the #create
and #update
calls, or you want to minimise database calls, you can use ::first_or_initialize
instead, to avoid persisting the record on the first call. However, you must make sure you call #save
or #update
afterwards in order to persist the record (and I'm not sure if #update
works on records that haven't been persisted yet):
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. There is a method called #create_or_update
, but don't be fooled by any documentation you may find on Google; that's just a private method used by #save
.)