Module: VirtualBox::AbstractModel::Dirty
- Defined in:
- lib/virtualbox/abstract_model/dirty.rb
Overview
Tracks "dirtiness" of values for a class. Its not tied to AbstractModel in any way other than the namespace.
Checking if a Value was Changed
Dynamic methods allow functionality for checking if values changed:
obj.foo_changed?
Previous Value
Can also view the previous value of an attribute:
obj.foo # => "foo" initially obj.foo = "bar" obj.foo_was # => "foo"
Previous and Current Value
Using the _change
dynamic method, can view the changes of a field.
obj.foo # => "foo" initially obj.foo = "bar" obj.foo_change # => ["foo", "bar"]
All Changes
Can also view all changes for a class with the changes
method.
obj.foo # => "foo" initially obj. # => "bar" initially obj.foo = "far" obj. = "baz" obj.changes # => { :foo => ["foo", "far"], :bar => ["bar", "baz"]}
Setting Dirty
Dirtiness tracking only occurs for values which the implementor explicitly sets as dirty. This is done with the #set_dirty! method. Example implementation below:
class Person include VirtualBox::AbstractModel::Dirty attr_reader :name def name=(value) set_dirty!(:name, @name, value) @name = value end end
The above example has all the changes necessary to track changes on an attribute.
Ignoring Dirtiness Tracking
Sometimes, for features such as mass assignment, dirtiness tracking
should be disabled. This can be done with the ignore_dirty
method.
ignore_dirty do |obj| obj.name = "Foo" end obj.changed? # => false
Clearing Dirty State
Sometimes, such as after saving a model, dirty states should be cleared.
This can be done with the clear_dirty!
method.
obj.clear_dirty!(:name) obj.name_changed? # => false
If no specific field is speciied, clear_dirty!
will clear the dirty
status on the entire model.
obj.changed? # => assume true obj.clear_dirty! obj.changed? # => false
Instance Method Summary
- - (Boolean) changed?(attribute = nil) Returns boolean denoting if field changed or not.
- - (Hash) changes Returns hash of changes.
- - (Object) clear_dirty!(key = nil) Clears dirty state for a field.
- - (Object) ignore_dirty(&block) {|_self| ... } Ignores any dirty changes during the duration of the block.
-
- (Object) method_missing(meth, *args)
Method missing is used to implement the "magic" methods of
field_changed
,field_change
, andfield_was
. - - (Object) set_dirty!(name, current, value) Manages dirty state for an attribute.
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
- (Object) method_missing(meth, *args)
Method missing is used to implement the "magic" methods of
field_changed
, field_change
, and field_was
.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/virtualbox/abstract_model/dirty.rb', line 155 def method_missing(meth, *args) meth_string = meth.to_s if meth_string =~ /^(.+?)_changed\?$/ changed?($1.to_sym) elsif meth_string =~ /^(.+?)_change$/ changes[$1.to_sym] elsif meth_string =~ /^(.+?)_was$/ change = changes[$1.to_sym] if change.nil? nil else change[0] end else super end end |
Instance Method Details
- (Boolean) changed?(attribute = nil)
Returns boolean denoting if field changed or not. If no attribute is specified, returns true of false showing whether the model changed at all.
137 138 139 140 141 142 143 |
# File 'lib/virtualbox/abstract_model/dirty.rb', line 137 def changed?(attribute = nil) if attribute.nil? !changes.empty? else changes.has_key?(attribute) end end |
- (Hash) changes
Returns hash of changes. Keys are fields, values are an array of the original value and the current value.
149 150 151 |
# File 'lib/virtualbox/abstract_model/dirty.rb', line 149 def changes @changed_attributes ||= {} end |
- (Object) clear_dirty!(key = nil)
Clears dirty state for a field.
114 115 116 117 118 119 120 |
# File 'lib/virtualbox/abstract_model/dirty.rb', line 114 def clear_dirty!(key=nil) if key.nil? @changed_attributes = {} else changes.delete(key) end end |
- (Object) ignore_dirty(&block) {|_self| ... }
Ignores any dirty changes during the duration of the block. Guarantees the dirty state will be the same before and after the method call, but not within the block itself.
125 126 127 128 129 |
# File 'lib/virtualbox/abstract_model/dirty.rb', line 125 def ignore_dirty(&block) current_changes = @changed_attributes.dup rescue nil yield self @changed_attributes = current_changes end |
- (Object) set_dirty!(name, current, value)
Manages dirty state for an attribute. This method will handle setting the dirty state of an attribute (or even clearing it if the old value is reset). Any implementors of this mixin should call this for any fields they want tracked.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/virtualbox/abstract_model/dirty.rb', line 94 def set_dirty!(name, current, value) if current != value # If its the first time this attribute has changed, store the # original value in the first field changes[name] ||= [current, nil] # Then store the changed value changes[name][1] = value # If the value changed back to the original value, remove from the # dirty hash if changes[name][0] == changes[name][1] changes.delete(name) end end end |