If you want to do it in one call instead of two, you can use the update_all method like this:

Player.where(:grepo_id => a[:grepo_id]).update_all(a)

This will result in the following SQL:

UPDATE players SET ... = ..., ... = ... WHERE players.grepo_id = ...

Also works if the grepo_id doesn't exist: nothing will get updated. Note however that this just runs the SQL; any validations or callbacks on your model are ignored.

Answer from Mischa on Stack Overflow
🌐
Mintbit
mintbit.com › blog › update-all-vs-update-in-rails
update_all vs update in Rails - Mintbit
November 15, 2020 - The difference between update_all and update in Rails is that with the update_all method, you can only use it on lists of objects.
🌐
Ruby on Rails
api.rubyonrails.org › v3.2.3 › classes › ActiveRecord › Relation.html
ActiveRecord::Relation - Rails API
# Update all customers with the given attributes Customer.update_all :wants_email => true # Update all books with 'Rails' in their title Book.update_all "author = 'David'", "title LIKE '%Rails%'" # Update all avatars migrated more than a week ago Avatar.update_all ['migrated_at = ?', Time.now.utc], ['migrated_at > ?', 1.week.ago] # Update all books that match conditions, but limit it to 5 ordered by date Book.update_all "author = 'David'", "title LIKE '%Rails%'", :order => 'created_at', :limit => 5 # Conditions from the current relation also works Book.where('title LIKE ?', '%Rails%').update_all(:author => 'David') # The same idea applies to limit and order Book.where('title LIKE ?', '%Rails%').order(:created_at).limit(5).update_all(:author => 'David') Source: show | on GitHub ·
🌐
Medium
medium.com › @derekfan › rails-update-vs-update-all-9945aa1211f2
[Rails] update vs. update_all. model_object vs. relational_object | by Derek Fan | Medium
August 20, 2018 - [Rails] update vs. update_all model_object vs. relational_object update works on model object User.where(id: 1).take.update(position: 1) User.find_by(id: 1).update(position: 1) update_all works on …
🌐
Reddit
reddit.com › r/rails › best practice for an action to update all records of a resource?
r/rails on Reddit: Best practice for an action to update all records of a resource?
November 27, 2021 -

Howdy all -

In my app I have some resources with the standard CRUD actions. I need an action that can be used in the administrator panel to update all of the records in one hit.

What's best practice here? Is it okay to add a post action in the controller #update_all in addition to the standard CRUD actions? Or is there a more preferred way for rails purists?

🌐
APIdock
apidock.com › rails › v4.0.2 › ActiveRecord › Relation › update_all
update_all (ActiveRecord::Relation) - APIdock
Updates all records with details given if they match a set of conditions supplied, limits and order can also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the database.
🌐
Sqlbot
sqlbot.co › blog › quick-rails-db-performance-hack-update_all-method
Quick Rails DB Performance Hack - update_all Method | SqlBot
According to some simple logging, it takes about 10ms for the read, and another 10ms for the update. That's 20ms per record, 8 million times, which would take 1.8 DAYS, eeks. And that's just for one stroll through the records for one term. Now, let's consider a better option... Now, imagine a buffet. A grand table where you spread out all ingredients, assemble all sandwiches simultaneously, and bam – lunch for everyone!
🌐
DEV Community
dev.to › andy › why-is-rails-activerelationupdateall-updating-a-different-set-of-records-404g
Why is Rails ActiveRelation.update_all updating a different set of records? - DEV Community
January 23, 2019 - The final chained query should produce a single SQL query, and then I want to update_all a single collection/relation of records. The where is called on the ActiveRecord relation and not an individual ActiveRecord record, which is how I can chain the where after doing union. ... What is the SQL generated by related_comments.count. Count will change the query sometimes if Rails decides it doesn't need the join/includes.
Find elsewhere
🌐
RubyDoc
rubydoc.info › gems › activerecord › 4.2.0 › ActiveRecord › Relation:update_all
RubyDoc.info: Method: ActiveRecord::Relation#update_all – Documentation for activerecord (4.2.0) – RubyDoc.info
Updates all records in the current relation with details given. This method constructs a single SQL UPDATE statement and sends it straight to the database. It does not instantiate the involved models and it does not trigger Active Record callbacks ...
🌐
BigBinary
bigbinary.com › blog › rails-5-allows-updating-relation-objects-along-with-callbacks-and-validations
Rails 5 Updating records in AR Relation
For scenarios where running validations and callbacks is not important and/or where performance is a concern it is advisable to use update_all method instead of update method.
🌐
Priyanka Pathak
priyankapathak.wordpress.com › 2010 › 08 › 21 › difference-between-active-record-methods-update-update_all-update_attribute-update_attributes
Difference between active record methods – update, update_all, update_attribute, update_attributes
August 23, 2010 - Model.update([1,2],[{:language => “ruby”,:framework => “rails”},{:ide => “aptana”}]) 2. update_all(attribute, conditions, options) It updates the attribute of object by invoking specified conditions and options like order, limit.
🌐
Test Double
testdouble.com › home › insights › speed up your rails app with upsert_all
Speed up your Rails app with upsert_all
May 6, 2025 - Sadly, prior to Rails 6, ActiveRecord itself didn’t offer any real alternatives short of dropping down to raw SQL (Rails has long had an update_all method, but it merely updates every record in a relation with an identical set of attributes).
🌐
Medium
medium.com › @danielmutubait › options-for-better-performance-in-rails-3cbc9d2e8aa4
Options for better performance in Rails. | by DANIEL MUTUBA | Medium
July 2, 2024 - The Efficiency of update_all: The update_all method performs a single query to update all records that match the criteria, greatly improving performance.
🌐
Reddit
reddit.com › r/rails › [help] why is update_all updating more records than it has/should-have access to?
r/rails on Reddit: [HELP] Why is update_all updating more records than it has/should-have access to?
September 6, 2015 -

I have a questions variable from another method, where I've already done some filtering. I want to mark these particular questions as active. So I have a method called change_status_to_active. However, when I call the method, it marks every single record in the Question model to status = "A". Why is this?

def change_status_to_active(questions)
    puts "MARKING ACTIVE1: #{questions.pluck(:id).to_s}"
    originalCount = questions.count
    before = Question.where(status: QUESTION_STATUS_ACTIVE).count
    questions.update_all(status: QUESTION_STATUS_ACTIVE)
    after = Question.where(status: QUESTION_STATUS_ACTIVE).count
    puts "Active Orig: #{originalCount.to_s} Before: #{before.to_s} After: #{after.to_s}"
end

Look at the output I get...

Active Orig: 26 Before: 0 After: 122

As you can see... questions.count = 26... yet questions.update_all(status: QUESTION_STATUS_ACTIVE) is affecting 122 records.

Why is this?

Top answer
1 of 5
17

As of Rails 4.0.2, #update returns false if the update failed. Before Rails 4.0.2, #update returned the object that got updated. The main difference therefore was the return value. After this change, #update_attributes is just an alias of #update.

As of Rails 6.0, #update_attributes is deprecated in favor of #update.

2 of 5
2

From the rails 5 files it seems to me update can be used to update multiple objects(array of records) but update_attributes only work on single records otherwise both are same

From rails core files for update_attributes:

Updates a single attribute and saves the record. This is especially useful for boolean flags on existing records. Also note that

  • Validation is skipped.
  • \Callbacks are invoked.
  • updated_at/updated_on column is updated if that column is available.
  • Updates all the attributes that are dirty in this object.

This method raises an ActiveRecord::ActiveRecordError if the attribute is marked as readonly.

def update_attribute(name, value)
  name = name.to_s
  verify_readonly_attribute(name)
  public_send("#{name}=", value)

  save(validate: false)
end

For Update

Updates an object (or multiple objects) and saves it to the database, if validations pass. The resulting object is returned whether the object was saved successfully to the database or not.

==== Parameters

  • +id+ - This should be the id or an array of ids to be updated.
  • +attributes+ - This should be a hash of attributes or an array of hashes.

==== Examples

# Updates one record Person.update(15, user_name: "Samuel", group: "expert")

# Updates multiple records people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } } Person.update(people.keys, people.values)

# Updates multiple records from the result of a relation people = Person.where(group: "expert") people.update(group: "masters")

Note: Updating a large number of records will run an UPDATE query for each record, which may cause a performance issue. When running callbacks is not needed for each record update, it is preferred to use {update_all}[rdoc-ref:Relation#update_all] for updating all records in a single query.

def update(id, attributes)
  if id.is_a?(Array)
    id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
      object.update(attributes[idx])
    }
  else
    if ActiveRecord::Base === id
      raise ArgumentError,
        "You are passing an instance of ActiveRecord::Base to `update`. " \
        "Please pass the id of the object by calling `.id`."
    end
    object = find(id)
    object.update(attributes)
    object
  end
end
Top answer
1 of 4
17

From the ActiveRecord#update documentation:

people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
Person.update(people.keys, people.values)

So in your case:

updates = {22974 => {column: 2}, 22975 => {column: 33}, 22976 => {column: 94}, 22977 => {column: 32}}
Model.update(updates.keys, updates.values)

Edit: Just had a look at the source, and this is generating n SQL queries too... So probably not the best solution

2 of 4
12

The only way I found to do it is to generate INSERT INTO request with updated values. I'm using gem "activerecord-import" for that.

For example, I have a table with val values

+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
| pkey   | id           | site_id | feature_id | val | created_at              | updated_at              |
+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
| 1      |              | 125     | 7          | 88  | 2016-01-27 10:25:45 UTC | 2016-02-05 11:18:14 UTC |
| 111765 | 0001-0000024 | 125     | 7          | 86  | 2016-01-27 11:33:22 UTC | 2016-02-05 11:18:14 UTC |
| 111766 | 0001-0000062 | 125     | 7          | 15  | 2016-01-27 11:33:22 UTC | 2016-02-05 11:18:14 UTC |
| 111767 | 0001-0000079 | 125     | 7          | 19  | 2016-01-27 11:33:22 UTC | 2016-02-05 11:18:14 UTC |
| 111768 | 0001-0000086 | 125     | 7          | 33  | 2016-01-27 11:33:22 UTC | 2016-02-05 11:18:14 UTC |
+--------+--------------+---------+------------+-----+-------------------------+-------------------------+

select records

products = CustomProduct.limit(5)

update records as you need

products.each_with_index{|p, i| p.val = i}

save records in single request

CustomProduct.import products.to_a, :on_duplicate_key_update => [:val]

All you records will be updated in single request. Please find out gem "activerecord-import" documentation for more details.

+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
| pkey   | id           | site_id | feature_id | val | created_at              | updated_at              |
+--------+--------------+---------+------------+-----+-------------------------+-------------------------+
| 1      |              | 125     | 7          | 0   | 2016-01-27 10:25:45 UTC | 2016-02-05 11:19:49 UTC |
| 111765 | 0001-0000024 | 125     | 7          | 1   | 2016-01-27 11:33:22 UTC | 2016-02-05 11:19:49 UTC |
| 111766 | 0001-0000062 | 125     | 7          | 2   | 2016-01-27 11:33:22 UTC | 2016-02-05 11:19:49 UTC |
| 111767 | 0001-0000079 | 125     | 7          | 3   | 2016-01-27 11:33:22 UTC | 2016-02-05 11:19:49 UTC |
| 111768 | 0001-0000086 | 125     | 7          | 4   | 2016-01-27 11:33:22 UTC | 2016-02-05 11:19:49 UTC |
+--------+--------------+---------+------------+-----+-------------------------+-------------------------+