ActiveRecord: Update a record if exists else create?

后端 未结 7 1712
北荒
北荒 2020-12-30 19:04

Trying to implement an create if not exists else update record in Active Record.

Currently using:

@student = Student.where(:user_id          


        
7条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-30 19:44

    ::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.)

提交回复
热议问题