Rails 7.0 Added Class Level update! Method To ActiveRecord::Base

June 13, 2021

Ruby on Rails has update_all class method which is used to update a batch of records without running validations and callbacks defined in the model.

On the contrary, we can update batch of records using update class method which also runs validations and callbacks defined in our model.

Let's see an example:

class Employee < ApplicationRecord validate :salary_for_experience_level, on: :update private def salary_for_experience_level if experience < 2 && salary >= 1_00_000 errors.add(:salary, "Invalid") end end end

In our Employee model, while trying to update the salary we have a validation check on employee having salary more than 1_00_000 and experience level less than 2 years.

We will now create two employee records as follows:

Employee.create! experience: 3, salary: 100000 Employee.create! experience: 1, salary: 80000

Having the salary validation in our Employee model, let's try to update salary of all employees:

Employee.update(salary: 1_30_000) #=> [#<Employee id: 1, salary: 130000, experience: 3>, #<Employee id: 2, salary: 130000, experience: 1>] Employee.all #=> [#<Employee id: 1, salary: 130000, experience: 3>, #<Employee id: 2, salary: 80000, experience: 1>]

As we see above, update method partially updated employee record with id 1 but
silently failed to update the employee record with id 2 due to validation check.

Rails 7.0 has added update! method to raise ActiveRecord::RecordInvalid error for employee record with id 2.

# After Rails 7.0 Employee.update!(salary: 1_50_000) #=> Employee Load (0.2ms) SELECT "employees".* FROM "employees" # TRANSACTION (0.1ms) begin transaction # Employee Update (0.6ms) UPDATE "employees" SET "salary" = ?, "updated_at" = ? WHERE "employees"."id" = ? [["salary", 150000], ["updated_at", "2021-06-13 18:09:14.800151"], ["id", 1]] # TRANSACTION (1.8ms) commit transaction # Traceback (most recent call last): # 1: from (irb):18:in `<main>' # ActiveRecord::RecordInvalid (Validation failed: Salary Invalid)

Here is the link to the relevant pull request.

Got something to share with us ? Please inbox


© All rights reserved 2021