7

Rails introduces ActiveRecord::Persistence#update_attribute!

 2 years ago
source link: https://blog.saeloun.com/2022/01/27/rails-introduces-update-attribute
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Rails has multiple methods to update a record, each one reserved for a unique purpose. While the traditional update is used to update records by executing validations, callbacks and track changes, there might be a few instances where one would like to skip validations. Using update_attribute does just that.

Before

To skip validations on the update, use update_attribute that ensures:

  • Validations are skipped
  • Callbacks are invoked
  • updated_at / updated_on column is updated (if that column is available)
  • Tracks changes via ActiveModel::Dirty

Let’s look at an example!

class Blog < ApplicationRecord
  validates_presence_of :text
  before_save :check_if_title_contains_special_characters

  def check_if_title_contains_special_characters
    throw(:abort) if title.index( /[^[:alnum:]]/ ).present?
  end
end

Now let’s compare the differences between update, update! and update_attribute,

> blog = Blog.last
=> #<Blog id: 1, title: "Ruby on Rails Tutorial: Learn Web Development with...", text: nil ... >

> blog.update text: nil
=> false

> blog.update! text: nil
Traceback (most recent call last):
        1: from (irb):4
ActiveRecord::RecordInvalid (Validation failed: Text can't be blank)

> blog.update_attribute :text, nil
=> true

As we can see, validations are skipped when using update_attribute but what is interesting is the behavior of update and update!. While update silently fails, calling update! throws an ActiveRecord::RecordInvalid error.

Let’s compare callbacks now.

> blog.update title: "Hel@lo"
=> false

> blog.update! title: "Hel@lo"
Traceback (most recent call last):
        1: from (irb):10
ActiveRecord::RecordNotSaved (Failed to save the record)

> blog.update_attribute :title, "Hel@lo"
=> false

Now update and update_attribute silently fail, while update! gives us a better understanding.

Unfortunately, there is no equivalent of update! for update_attribute that can give us insights into record updates.

After

Fortunately, Rails introduces update_attribute! which can be used to prevent “silent” updates.

> blog.update title: "Hel@lo"
=> false

> blog.update! title: "Hel@lo"
Traceback (most recent call last):
        1: from (irb):10
ActiveRecord::RecordNotSaved (Failed to save the record)

> blog.update_attribute :title, "Hel@lo"
=> false

> blog.update_attribute! :title, "Hel@lo"
Traceback (most recent call last):
        1: from (irb):12
ActiveRecord::RecordNotSaved (Failed to save the record)

This change adds a new method, ActiveRecord::Persistence#update_attribute! which calls save! instead of save. The update_attribute! method will now raise an ActiveRecord::RecordNotSaved error should any before_* callbacks throw :abort.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK