Active Model Dirty
提供一种跟踪对象更改的方式,与 Active Record 相同。
实现 ActiveModel::Dirty
的要求是
-
在你的对象中
include ActiveModel::Dirty
。 -
调用
define_attribute_methods
传递你想要跟踪的每个方法。 -
在对跟踪属性进行任何更改之前调用
*_will_change!
。 -
在更改持久化后调用
changes_applied
。 -
当你想要重置更改信息时调用
clear_changes_information
。 -
当你想要恢复之前的数据时调用
restore_attributes
。
一个最小的实现可以是
class Person
include ActiveModel::Dirty
define_attribute_methods :name
def initialize
@name = nil
end
def name
@name
end
def name=(val)
name_will_change! unless val == @name
@name = val
end
def save
# do persistence work
changes_applied
end
def reload!
# get the values from the persistence layer
clear_changes_information
end
def rollback!
restore_attributes
end
end
一个新实例化的 Person
对象没有更改
person = Person.new
person.changed? # => false
更改姓名
person.name = 'Bob'
person.changed? # => true
person.name_changed? # => true
person.name_changed?(from: nil, to: "Bob") # => true
person.name_was # => nil
person.name_change # => [nil, "Bob"]
person.name = 'Bill'
person.name_change # => [nil, "Bill"]
保存更改
person.save
person.changed? # => false
person.name_changed? # => false
重置更改
person.previous_changes # => {"name" => [nil, "Bill"]}
person.name_previously_changed? # => true
person.name_previously_changed?(from: nil, to: "Bill") # => true
person.name_previous_change # => [nil, "Bill"]
person.name_previously_was # => nil
person.reload!
person.previous_changes # => {}
回滚更改
person.name = "Uncle Bob"
person.rollback!
person.name # => "Bill"
person.name_changed? # => false
分配相同的值会使属性保持不变
person.name = 'Bill'
person.name_changed? # => false
person.name_change # => nil
哪些属性发生了更改?
person.name = 'Bob'
person.changed # => ["name"]
person.changes # => {"name" => ["Bill", "Bob"]}
如果一个属性被就地修改,那么使用 *_will_change! 来标记该属性正在更改。否则 Active Model 无法跟踪对就地属性的更改。注意 Active Record 可以自动检测就地修改。你不必在 Active Record 模型上调用 *_will_change!
。
person.name_will_change!
person.name_change # => ["Bill", "Bill"]
person.name << 'y'
person.name_change # => ["Bill", "Billy"]
方法可以被调用为 name_changed?
或者通过将参数传递给通用方法 attribute_changed?("name")
。
- #
- A
- C
- P
- R
实例公有方法
*_change 链接
此方法为每个属性生成。
返回属性的旧值和新值。
person = Person.new
person.name = 'Nick'
person.name_change # => [nil, 'Nick']
来源:在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 155
*_changed? 链接
此方法为每个属性生成。
如果属性有未保存的更改,则返回 true。
person = Person.new
person.name = 'Andrew'
person.name_changed? # => true
来源:在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 144
*_previous_change 链接
此方法为每个属性生成。
返回上次保存之前属性的旧值和新值。
person = Person.new
person.name = 'Emmanuel'
person.save
person.name_previous_change # => [nil, 'Emmanuel']
来源:在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 193
*_previously_changed?(**options) 链接
此方法为每个属性生成。
如果属性之前有未保存的更改,则返回 true。
person = Person.new
person.name = 'Britanny'
person.save
person.name_previously_changed? # => true
person.name_previously_changed?(from: nil, to: 'Britanny') # => true
来源:在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 129
*_previously_was 链接
此方法为每个属性生成。
返回上次保存之前属性的旧值。
person = Person.new
person.name = 'Sage'
person.save
person.name_previously_was # => nil
来源:在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 205
*_was 链接
此方法为每个属性生成。
返回属性的旧值。
person = Person.new(name: 'Steph')
person.name = 'Stephanie'
person.name_was # => 'Steph'
来源:在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 182
*_will_change! 链接
此方法为每个属性生成。
如果一个属性被就地修改,那么使用 *_will_change!
来标记该属性正在更改。否则 Active Model
无法跟踪对就地属性的更改。注意 Active Record 可以自动检测就地修改。你不必在 Active Record 模型上调用 *_will_change!
。
person = Person.new('Sandy')
person.name_will_change!
person.name_change # => ['Sandy', 'Sandy']
来源:在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 166
attribute_changed?(attr_name, **options) 链接
用于 *_changed? 属性方法的调度目标。
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 300 def attribute_changed?(attr_name, **options) mutations_from_database.changed?(attr_name.to_s, **options) end
attribute_previously_changed?(attr_name, **options) 链接
用于 *_previously_changed? 属性方法的调度目标。
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 310 def attribute_previously_changed?(attr_name, **options) mutations_before_last_save.changed?(attr_name.to_s, **options) end
attribute_previously_was(attr_name) 链接
用于 *_previously_was 属性方法的调度目标。
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 315 def attribute_previously_was(attr_name) mutations_before_last_save.original_value(attr_name.to_s) end
attribute_was(attr_name) 链接
用于 *_was 属性方法的调度目标。
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 305 def attribute_was(attr_name) mutations_from_database.original_value(attr_name.to_s) end
changed() 链接
返回一个数组,其中包含具有未保存更改的属性的名称。
person.changed # => []
person.name = 'bob'
person.changed # => ["name"]
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 295 def changed mutations_from_database.changed_attribute_names end
changed?() 链接
如果任何属性都有未保存的更改,则返回 true
,否则返回 false
。
person.changed? # => false
person.name = 'bob'
person.changed? # => true
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 286 def changed? mutations_from_database.any_changes? end
changed_attributes() 链接
返回一个哈希表,其中包含具有未保存更改的属性,并指示它们的原始值,例如 attr => 原始值
。
person.name # => "bob"
person.name = 'robert'
person.changed_attributes # => {"name" => "bob"}
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 343 def changed_attributes mutations_from_database.changed_values end
changes() 链接
返回一个哈希表,其中包含已更改的属性,并指示它们的原始值和新值,例如 attr => [原始值,新值]
。
person.changes # => {}
person.name = 'bob'
person.changes # => { "name" => ["bill", "bob"] }
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 353 def changes mutations_from_database.changes end
changes_applied() 链接
清除脏数据,并将 changes
移动到 previous_changes
,并将 mutations_from_database
移动到 mutations_before_last_save
。
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 272 def changes_applied unless defined?(@attributes) mutations_from_database.finalize_changes end @mutations_before_last_save = mutations_from_database forget_attribute_assignments @mutations_from_database = nil end
clear_*_change 链接
此方法为每个属性生成。
清除属性的所有脏数据:当前更改和先前更改。
person = Person.new(name: 'Chris')
person.name = 'Jason'
person.name_change # => ['Chris', 'Jason']
person.clear_name_change
person.name_change # => nil
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 241 attribute_method_suffix "_previously_changed?", "_changed?", parameters: "**options"
clear_attribute_changes(attr_names) 链接
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 331 def clear_attribute_changes(attr_names) attr_names.each do |attr_name| clear_attribute_change(attr_name) end end
clear_changes_information() 链接
清除所有脏数据:当前更改和先前更改。
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 325 def clear_changes_information @mutations_before_last_save = nil forget_attribute_assignments @mutations_from_database = nil end
previous_changes() 链接
返回一个哈希表,其中包含模型保存之前已更改的属性。
person.name # => "bob"
person.name = 'robert'
person.save
person.previous_changes # => {"name" => ["bob", "robert"]}
来源:显示 | 在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 363 def previous_changes mutations_before_last_save.changes end
restore_*! 链接
此方法为每个属性生成。
将属性恢复为旧值。
person = Person.new
person.name = 'Amanda'
person.restore_name!
person.name # => nil
来源:在 GitHub 上
# File activemodel/lib/active_model/dirty.rb, line 217
restore_attributes(attr_names = changed) 链接
恢复所提供属性的所有先前数据。
来源: 显示 | 在 GitHub 上查看
# File activemodel/lib/active_model/dirty.rb, line 320 def restore_attributes(attr_names = changed) attr_names.each { |attr_name| restore_attribute!(attr_name) } end