🛤️
ActiveRecord の change 系メソッドまとめ
「作成」→「更新」→「空更新」とした場合の変化。
作成 create(foo: "a")
| method | before_save | after_save |
|---|---|---|
| will_save_change_to_attribute?(:foo) | true | false |
| attribute_change_to_be_saved(:foo) | [nil, "a"] | nil |
| attribute_in_database(:foo) | nil | "a" |
| changes_to_save | {"foo"=>[nil, "a"]} | {} |
| has_changes_to_save? | true | false |
| changed_attribute_names_to_save | ["foo"] | [] |
| attributes_in_database | {"foo"=>nil} | {} |
| saved_change_to_attribute?(:foo) | false | true |
| saved_change_to_attribute(:foo) | nil | [nil, "a"] |
| attribute_before_last_save(:foo) | nil | nil |
| saved_changes | {} | {"id"=>[nil, 1], "foo"=>[nil, "a"]} |
| saved_changes? | false | true |
更新 update(foo: "b")
| method | before_save | after_save |
|---|---|---|
| will_save_change_to_attribute?(:foo) | true | false |
| attribute_change_to_be_saved(:foo) | ["a", "b"] | nil |
| attribute_in_database(:foo) | "a" | "b" |
| changes_to_save | {"foo"=>["a", "b"]} | {} |
| has_changes_to_save? | true | false |
| changed_attribute_names_to_save | ["foo"] | [] |
| attributes_in_database | {"foo"=>"a"} | {} |
| saved_change_to_attribute?(:foo) | true | true |
| saved_change_to_attribute(:foo) | nil | ["a", "b"] |
| attribute_before_last_save(:foo) | nil | "a" |
| saved_changes | {} | {"foo"=>["a", "b"]} |
| saved_changes? | false | true |
空更新 update({})
| method | before_save | after_save |
|---|---|---|
| will_save_change_to_attribute?(:foo) | false | false |
| attribute_change_to_be_saved(:foo) | nil | nil |
| attribute_in_database(:foo) | "b" | "b" |
| changes_to_save | {} | {} |
| has_changes_to_save? | false | false |
| changed_attribute_names_to_save | [] | [] |
| attributes_in_database | {} | {} |
| saved_change_to_attribute?(:foo) | false | false |
| saved_change_to_attribute(:foo) | nil | nil |
| attribute_before_last_save(:foo) | nil | "b" |
| saved_changes | {} | {} |
| saved_changes? | false | false |
検証用のコード
require "active_record"
ActiveRecord::VERSION::STRING # => "7.1.3.2"
ActiveSupport::LogSubscriber.colorize_logging = false
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Migration.verbose = false
ActiveRecord::Schema.define do
create_table :users do |t|
t.string :foo
end
end
class User < ActiveRecord::Base
before_save do
will_save_change_to_attribute?(:foo) # => true, true, false
attribute_change_to_be_saved(:foo) # => [nil, "a"], ["a", "b"], nil
attribute_in_database(:foo) # => nil, "a", "b"
changes_to_save # => {"foo"=>[nil, "a"]}, {"foo"=>["a", "b"]}, {}
has_changes_to_save? # => true, true, false
changed_attribute_names_to_save # => ["foo"], ["foo"], []
attributes_in_database # => {"foo"=>nil}, {"foo"=>"a"}, {}
saved_change_to_attribute?(:foo) # => false, false, false
saved_change_to_attribute(:foo) # => nil, nil, nil
attribute_before_last_save(:foo) # => nil, nil, nil
saved_changes # => {}, {}, {}
saved_changes? # => false, false, false
end
after_save do
will_save_change_to_attribute?(:foo) # => false, false, false
attribute_change_to_be_saved(:foo) # => nil, nil, nil
attribute_in_database(:foo) # => "a", "b", "b"
changes_to_save # => {}, {}, {}
has_changes_to_save? # => false, false, false
changed_attribute_names_to_save # => [], [], []
attributes_in_database # => {}, {}, {}
saved_change_to_attribute?(:foo) # => true, true, false
saved_change_to_attribute(:foo) # => [nil, "a"], ["a", "b"], nil
attribute_before_last_save(:foo) # => nil, "a", "b"
saved_changes # => {"id"=>[nil, 1], "foo"=>[nil, "a"]}, {"foo"=>["a", "b"]}, {}
saved_changes? # => true, true, false
end
end
user = User.create!(foo: "a") # => #<User id: 1, foo: "a">
user.reload # => #<User id: 1, foo: "a">
user.update!(foo: "b") # => true
user.reload # => #<User id: 1, foo: "b">
user.update!({}) # => true
Discussion