Create_Or_Update Method in Rails

Rails create or update magic?

Rails 6

Rails 6 added an upsert and upsert_all methods that deliver this functionality.

Model.upsert(column_name: value)

[upsert] It does not instantiate any models nor does it trigger Active Record callbacks or validations.

Rails 5, 4, and 3

Not if you are looking for an "upsert" (where the database executes an update or an insert statement in the same operation) type of statement. Out of the box, Rails and ActiveRecord have no such feature. You can use the upsert gem, however.

Otherwise, you can use: find_or_initialize_by or find_or_create_by, which offer similar functionality, albeit at the cost of an additional database hit, which, in most cases, is hardly an issue at all. So unless you have serious performance concerns, I would not use the gem.

For example, if no user is found with the name "Roger", a new user instance is instantiated with its name set to "Roger".

user = User.where(name: "Roger").first_or_initialize
user.email = "email@example.com"
user.save

Alternatively, you can use find_or_initialize_by.

user = User.find_or_initialize_by(name: "Roger")

In Rails 3.

user = User.find_or_initialize_by_name("Roger")
user.email = "email@example.com"
user.save

You can use a block, but the block only runs if the record is new.

User.where(name: "Roger").first_or_initialize do |user|
# this won't run if a user with name "Roger" is found
user.save
end

User.find_or_initialize_by(name: "Roger") do |user|
# this also won't run if a user with name "Roger" is found
user.save
end

If you want to use a block regardless of the record's persistence, use tap on the result:

User.where(name: "Roger").first_or_initialize.tap do |user|
user.email = "email@example.com"
user.save
end

create_or_update method in rails

my_class = ClassName.find_or_initialize_by_name(name)

my_class.update_attributes(
:street_address => self.street_address,
:city_name => self.city_name,
:federalid => self.federalid,
:state_prov_id => self.state_prov_id,
:zip_code => self.zip_code
)

As of Rails 6, update_attributes! and update_attributes is deprecated for update! and update, respectively:

my_class.update(
:street_address => self.street_address,
:city_name => self.city_name,
:federalid => self.federalid,
:state_prov_id => self.state_prov_id,
:zip_code => self.zip_code
)

Create or update object in table

This is the solution:

person = Person.find_or_create_by(firstname: row["firstname"])
person.update_attributes({firstname: row['firstname'], lastname: row['lastname'], home_phone_number: row['home_phone_number'], mobile_phone_number: row['mobile_phone_number'], address: row['address'], email: row['email']})

I can't explain why this solution is working and not the one you proposed to me.
But thanks @sohail_khalil and @abhilash for your help !

Updating if exist or create if not rails

Firstly, the model.Model part should be just Model, as Model is your class.

locked is supposed to be a column/attribute of the Model class, although it seems is not the case judging from your error. Therefore, I'm gonna use other_column_name as an example.

Explanation of what this is doing:

Model.where(column_name: value).first_or_initialize(other_column_name: some_value)

Model.where(column_name: value): gets models that satisfy the condition column_name == value

first_or_initialize: if a model such that column_name == value was found, that one is returned. Otherwise, it initializes a model with column_name = value.

By passing other_column_name: some_value, if the model was not found and needs to be initialized, it sets other_column_name to some_value but: 1) it does not update it if it was initially found and 2) it does not save the record.

The equivalent of first_or_initialize that saves the new record would be first_or_create but this would still not update the record if it already existed.

So, you should do something like this:

m = Model.where(column_name: value).first_or_initialize
m.other_column_name = some_value
m.save

This way, you first get a model where column_name is value or initialize a new one with this value if it didn't already exist. Then, you set the attribute other_column_name to some_value and save the model.

A one-liner alternative would be

Model.where(column_name: value).first_or_create.update(other_column_name: some_value)

However, note that if it needs to be created, this one will perform 2 queries (the insert and the update).

About the error part. It says the attribute locked does not exist on the Model record. Are these classes you created? Are you using some pre-existing project? You could try posting Model.attribute_names and maybe your schema.rb

Rails Activerecord: create or update after HTTP POST method

You want to use PUT for update and POST for create. If you know the user exists, but you don't have the id, you would use a PUT request, and in the update method, you would have something like this:

def update
@user = User.find_by_ip(params[:ip])
if @user.update_attributes(...)
#success
else
#failure
end
end

Again, the ideal method would be to pass the id into the update, but if you are unable to do that, you don't want to sacrifice RESTful conventions.

Ruby/Rails worker to create or update record if exists - avoid DRY

Take a look at find_or_initialize_by method:

class StoreActivityWorker
include Sidekiq::Worker

def perform(webhook)
entity = webhook.dig 'entity'

activity = Activity.find_or_initialize_by(cms_activity_id: entity['id'])

activity.update!(
is_separate_activity: entity.dig('attributes', 'is_separate_activity'),
content_full: retrieve_full_content(webhook),
content_basic: retrieve_basic_content(webhook),
)
end
end

What is the correct HTTP method for a create or update action in a Rails API?

IMHO, most appropriate would be PUT. See HTTP 1.1, section 4.3.4 PUT, which is a "create or replace".

Rails models not being set on create or update

You're creating accessor methods which impede access to the methods ActiveRecord already generates for you.

Your definition should be:

class UnsupportedInstitution < ActiveRecord::Base
validates :bank_name, presence: true
validates :reason, presence: true

has_many :unsupported_institution_routing_numbers
end

Where bank_name will be auto-generated as a method if there is a corresponding field in the database, which there is if your migration ran successfully.



Related Topics



Leave a reply



Submit