Home > OS >  Rails upsert using find_or_create_by, create_with and optional chaining
Rails upsert using find_or_create_by, create_with and optional chaining

Time:09-17

I am using below code to upsertmy Model which works correctly but is verbose. I wanted to shorten it by using find_or_create_by, create_with and optional chaining but it is not working as expected.

Can someone please advice...

Verbose Code which works -

user_attr = {
              first_name: 'Scarlett',
              last_name: 'Johansson',
              profession: 'Actress',
              address: 'Los Angeles'
            }

....
existing_user = User.find_by(first_name: user_attr.fetch(:first_name), 
                             last_name: user_attr.fetch(:last_name))
if existing_user
  existing_user.update!(user_attr)
 else
  User.create!(user_attr)
end

Output:
# => #<User id: 2, first_name: "Scarlett", last_name: "Johansson", profession: "Actress", address: "Los Angeles">

Shorter version which does not return correct output:

User
  .create_with(user_attr)
  .find_or_create_by(first_name: user_attr.fetch(:first_name), 
                     last_name: user_attr.fetch(:last_name))

Reference - https://apidock.com/rails/v4.0.2/ActiveRecord/Relation/find_or_create_by

CodePudding user response:

You could find_or_create_by first, then update:

user = User.find_or_create_by!(first_name: 'Scarlett', last_name: 'Johansson')

user.update!(profession: 'Actress', address: 'Los Angeles')
  • Related