dirty_hashy 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +7 -0
- data/README.textile +29 -20
- data/VERSION +1 -1
- data/dirty_hashy.gemspec +1 -1
- data/lib/dirty.rb +2 -0
- data/lib/dirty/attributes.rb +39 -0
- data/lib/dirty/hash.rb +108 -0
- data/lib/dirty_hashy.rb +4 -84
- data/lib/dirty_hashy/version.rb +3 -3
- data/lib/dirty_indifferent_hashy.rb +5 -0
- data/test/unit/dirty/test_attributes.rb +176 -0
- data/test/unit/test_dirty_hashy.rb +109 -94
- data/test/unit/test_dirty_indifferent_hashy.rb +500 -0
- metadata +47 -35
- data/lib/dirty_attributes.rb +0 -37
- data/test/unit/test_dirty_attributes.rb +0 -174
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
= DirtyHashy CHANGELOG
|
2
2
|
|
3
|
+
== Version 0.2.0 (January 4, 2011)
|
4
|
+
|
5
|
+
* Extracted DirtyHashy implementation to Dirty::Hash
|
6
|
+
* Renamed DirtyAttributes to Dirty::Attributes
|
7
|
+
* Inheriting DirtyHashy from Hash instead of HashWithIndifferentAccess on request of @technoweenie
|
8
|
+
* Introducing DirtyIndifferentHashy which is the previously known DirtyHashy
|
9
|
+
|
3
10
|
== Version 0.1.3 (December 24, 2011)
|
4
11
|
|
5
12
|
* Fixed incorrect regular expressions within dirty_map!
|
data/README.textile
CHANGED
@@ -26,15 +26,23 @@ Run the following in your console to install with Bundler:
|
|
26
26
|
bundle install
|
27
27
|
</pre>
|
28
28
|
|
29
|
+
h2. DirtyHashy versus DirtyIndifferentHashy
|
30
|
+
|
31
|
+
"On request":https://github.com/archan937/dirty_hashy/issues/1 of "@technoweenie":https://twitter.com/technoweenie, I have released DirtyHashy v0.2.0. Previous to this release, the @DirtyHashy@ class inherited from ActiveSupport's @HashWithIndifferentAccess@ *but that has changed*.
|
32
|
+
|
33
|
+
As of the @0.2.0@ release, the @DirtyHashy@ class is inherited from the @Hash@ class. So I have introduced @DirtyIndifferentHashy@ which resembles the @DirtyHashy@ class of the @0.1.x@ releases. You can check out the different types of behaviour by looking at the "DirtyHashy test":https://github.com/archan937/dirty_hashy/blob/279da72873a91216dbecadb3a6d53ebae2fd8198/test/unit/test_dirty_hashy.rb and "DirtyIndifferentHashy test":https://github.com/archan937/dirty_hashy/blob/279da72873a91216dbecadb3a6d53ebae2fd8198/test/unit/test_dirty_indifferent_hashy.rb.
|
34
|
+
|
35
|
+
*Note*: This README will continue focusing on the usage of the @DirtyIndifferentHashy@ class and @Dirty::Attributes@ module.
|
36
|
+
|
29
37
|
h2. Usage
|
30
38
|
|
31
|
-
Using @
|
39
|
+
Using @DirtyIndifferentHashy@ is pretty straightforward and can be used as follows:
|
32
40
|
|
33
41
|
<pre>
|
34
42
|
require "rubygems"
|
35
43
|
require "dirty_hashy"
|
36
44
|
|
37
|
-
h =
|
45
|
+
h = DirtyIndifferentHashy.new
|
38
46
|
h.dirty? #=> false
|
39
47
|
h[:name] = "Paul"
|
40
48
|
h.dirty? #=> true
|
@@ -64,17 +72,17 @@ Using @DirtyHashy@ is pretty straightforward and can be used as follows:
|
|
64
72
|
h.change :company #=> ["Internetbureau Holder B.V.", nil]
|
65
73
|
</pre>
|
66
74
|
|
67
|
-
h3. Method mapping
|
75
|
+
h3. Method mapping DirtyIndifferentHashy
|
68
76
|
|
69
|
-
You can map methods within a
|
77
|
+
You can map methods within a DirtyIndifferentHashy in order to provide convenience methods like @name@, @name=@, @name_changed?@, @name_was@ and @name_change@. Just pass @true@ for the @map_methods@ argument when initializing a DirtyIndifferentHashy:
|
70
78
|
|
71
79
|
<pre>
|
72
80
|
require "rubygems"
|
73
81
|
require "dirty_hashy"
|
74
82
|
|
75
|
-
h =
|
83
|
+
h = DirtyIndifferentHashy.new({}, true)
|
76
84
|
h.dirty? #=> false
|
77
|
-
h.name #=> NoMethodError: undefined method `name' for {}:
|
85
|
+
h.name #=> NoMethodError: undefined method `name' for {}:DirtyIndifferentHashy
|
78
86
|
h.name = "Paul"
|
79
87
|
h.dirty? #=> true
|
80
88
|
h.name_changed? #=> true
|
@@ -92,15 +100,15 @@ You can map methods within a DirtyHashy in order to provide convenience methods
|
|
92
100
|
h.changes #=> {"name"=>["Paul", "Engel"], "foo"=>[nil, "bar"]}
|
93
101
|
</pre>
|
94
102
|
|
95
|
-
h3. Method mapping
|
103
|
+
h3. Method mapping DirtyIndifferentHashy with key restriction
|
96
104
|
|
97
|
-
Along with providing convenience methods, you can also restrict the range of keys you are permitted to read / write / merge / replace of a
|
105
|
+
Along with providing convenience methods, you can also restrict the range of keys you are permitted to read / write / merge / replace of a DirtyIndifferentHashy:
|
98
106
|
|
99
107
|
<pre>
|
100
108
|
require "rubygems"
|
101
109
|
require "dirty_hashy"
|
102
110
|
|
103
|
-
h =
|
111
|
+
h = DirtyIndifferentHashy.new({}, true, [:name])
|
104
112
|
h.dirty? #=> false
|
105
113
|
h.name #=> nil
|
106
114
|
h.name = "Paul"
|
@@ -112,8 +120,8 @@ Along with providing convenience methods, you can also restrict the range of key
|
|
112
120
|
h.name #=> "Engel"
|
113
121
|
h.name_was #=> nil
|
114
122
|
h.name_change #=> [nil, "Engel"]
|
115
|
-
h.foo #=> NoMethodError: undefined method `foo' for {"name"=>"Engel"}:
|
116
|
-
h.foo = "bar" #=> NoMethodError: undefined method `foo=' for {"name"=>"Engel"}:
|
123
|
+
h.foo #=> NoMethodError: undefined method `foo' for {"name"=>"Engel"}:DirtyIndifferentHashy
|
124
|
+
h.foo = "bar" #=> NoMethodError: undefined method `foo=' for {"name"=>"Engel"}:DirtyIndifferentHashy
|
117
125
|
h.clean_up!
|
118
126
|
h.replace :name => "Paul"
|
119
127
|
h.changes #=> {"name"=>["Engel", "Paul"]}
|
@@ -121,12 +129,12 @@ Along with providing convenience methods, you can also restrict the range of key
|
|
121
129
|
|
122
130
|
h3. Dirty tracking objects (models)
|
123
131
|
|
124
|
-
Like "ActiveModel::Dirty":http://api.rubyonrails.org/classes/ActiveModel/Dirty.html, you can use "
|
132
|
+
Like "ActiveModel::Dirty":http://api.rubyonrails.org/classes/ActiveModel/Dirty.html, you can use "Dirty::Attributes":https://github.com/archan937/dirty_hashy/blob/master/lib/dirty_attributes.rb to dirty track your own objects (models). But there are two differences:
|
125
133
|
|
126
|
-
# Setting up @
|
127
|
-
# The implementation of "
|
134
|
+
# Setting up @Dirty::Attributes@ is easier to setup than @ActiveModel::Dirty@
|
135
|
+
# The implementation of "Dirty::Attributes":https://github.com/archan937/dirty_hashy/tree/master/lib is more minimalistic and thus looks a bit cleaner than "ActiveModel::Dirty":https://github.com/rails/rails/blob/master/activemodel/lib/active_model/dirty.rb with "ActiveModel::AttributeMethods":https://github.com/rails/rails/blob/master/activemodel/lib/active_model/attribute_methods.rb
|
128
136
|
|
129
|
-
The following illustrates the differences between @
|
137
|
+
The following illustrates the differences between @Dirty::Attributes@ and @ActiveModel::Dirty@ when implementing a simple @Person@ model:
|
130
138
|
|
131
139
|
h4. When using ActiveModel::Dirty
|
132
140
|
|
@@ -151,11 +159,11 @@ h4. When using ActiveModel::Dirty
|
|
151
159
|
end
|
152
160
|
</pre>
|
153
161
|
|
154
|
-
h4. When using
|
162
|
+
h4. When using Dirty::Attributes
|
155
163
|
|
156
164
|
<pre>
|
157
165
|
class Person
|
158
|
-
include
|
166
|
+
include Dirty::Attributes
|
159
167
|
attrs :name
|
160
168
|
|
161
169
|
def save
|
@@ -171,7 +179,7 @@ You can use @Person@ objects as you would expect:
|
|
171
179
|
require "dirty_hashy"
|
172
180
|
|
173
181
|
class Person
|
174
|
-
include
|
182
|
+
include Dirty::Attributes
|
175
183
|
attrs :name
|
176
184
|
end
|
177
185
|
|
@@ -196,7 +204,7 @@ And last but not least: don't care about specifying the attributes available? We
|
|
196
204
|
require "dirty_hashy"
|
197
205
|
|
198
206
|
class Person
|
199
|
-
include
|
207
|
+
include Dirty::Attributes
|
200
208
|
end
|
201
209
|
|
202
210
|
p = Person.new
|
@@ -217,7 +225,8 @@ And last but not least: don't care about specifying the attributes available? We
|
|
217
225
|
|
218
226
|
h2. Last remarks
|
219
227
|
|
220
|
-
Please check out "test/unit/test_dirty_hashy.rb":https://github.com/archan937/dirty_hashy/blob/master/test/unit/test_dirty_hashy.rb and "test/unit/test_dirty_attributes.rb":https://github.com/archan937/dirty_hashy/blob/master/test/unit/test_dirty_attributes.rb the tests available.
|
228
|
+
Please check out "test/unit/test_dirty_hashy.rb":https://github.com/archan937/dirty_hashy/blob/master/test/unit/test_dirty_hashy.rb, "test/unit/test_dirty_indifferent_hashy.rb":https://github.com/archan937/dirty_hashy/blob/master/test/unit/test_dirty_indifferent_hashy.rb and "test/unit/test_dirty_attributes.rb":https://github.com/archan937/dirty_hashy/blob/master/test/unit/test_dirty_attributes.rb the tests available.
|
229
|
+
You can run the unit tests with @rake@ within the terminal.
|
221
230
|
|
222
231
|
Also, the DirtyHashy repo is provided with @script/console@ which you can use for testing purposes.
|
223
232
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/dirty_hashy.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
|
|
12
12
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
13
13
|
gem.name = "dirty_hashy"
|
14
14
|
gem.require_paths = ["lib"]
|
15
|
-
gem.version = "0.
|
15
|
+
gem.version = "0.2.0"
|
16
16
|
|
17
17
|
gem.add_dependency "activesupport", ">= 3.0.0"
|
18
18
|
end
|
data/lib/dirty.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Dirty
|
2
|
+
module Attributes
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
base.send :include, InstanceMethods
|
7
|
+
base.send :include, MethodMap
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def attrs(*names)
|
12
|
+
@attrs = names.collect(&:to_s)
|
13
|
+
end
|
14
|
+
|
15
|
+
def attributes
|
16
|
+
@attrs
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module InstanceMethods
|
21
|
+
attr_reader :attributes
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@attributes = DirtyIndifferentHashy.new({}, true, self.class.attributes).tap do |hashy|
|
25
|
+
dirty_map! hashy
|
26
|
+
clean_up!
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def attributes=(other)
|
31
|
+
attributes.replace other
|
32
|
+
rescue IndexError => e
|
33
|
+
e.message.match /"(.*)"/
|
34
|
+
raise NoMethodError, "undefined method `#{$1}=' for #{self.inspect}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/dirty/hash.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
module Dirty
|
2
|
+
module Hash
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.method_defined?(:regular_writer).tap do |defined|
|
6
|
+
base.send :include, InstanceMethods
|
7
|
+
unless defined
|
8
|
+
base.send :alias_method, :_store, :store
|
9
|
+
base.send :alias_method, :store, :regular_writer
|
10
|
+
base.send :alias_method, :[]=, :store
|
11
|
+
base.send :define_method, :update do |other|
|
12
|
+
other.each{|key, value| store key, value}
|
13
|
+
end
|
14
|
+
base.send :alias_method, :merge!, :update
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
def initialize(constructor = {}, map_methods = false, restricted_keys = nil)
|
21
|
+
constructor.each do |key, value|
|
22
|
+
self[key] = value
|
23
|
+
end
|
24
|
+
if map_methods
|
25
|
+
extend MethodMap
|
26
|
+
dirty_map!
|
27
|
+
end
|
28
|
+
if restricted_keys
|
29
|
+
restricted_keys.each{|key| self[correct_key(key, map_methods)] ||= nil}
|
30
|
+
@restricted_keys = keys
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def replace(other)
|
35
|
+
clear
|
36
|
+
merge! other
|
37
|
+
end
|
38
|
+
|
39
|
+
def clear
|
40
|
+
keys.each{|key| delete key}
|
41
|
+
end
|
42
|
+
|
43
|
+
def [](key, mapped = false)
|
44
|
+
validate_read!(key) if mapped || restricted_keys?
|
45
|
+
super(key)
|
46
|
+
end
|
47
|
+
|
48
|
+
def regular_writer(key, value)
|
49
|
+
validate_write!(key)
|
50
|
+
original_value = changes.key?(key) ? was(key) : fetch(key, nil)
|
51
|
+
if original_value == value
|
52
|
+
changes.delete key
|
53
|
+
else
|
54
|
+
changes[key] = [original_value, value]
|
55
|
+
end
|
56
|
+
defined?(_store) ? _store(key, value) : super(key, value)
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete(key)
|
60
|
+
self[key] = nil
|
61
|
+
super
|
62
|
+
end
|
63
|
+
|
64
|
+
def changes
|
65
|
+
@changes ||= self.class.superclass.new
|
66
|
+
end
|
67
|
+
|
68
|
+
def changed?(key = nil, mapped = false)
|
69
|
+
validate_read!(correct_key(key, mapped)) if !key.nil? && (mapped || restricted_keys?)
|
70
|
+
key.nil? ? !changes.empty? : changes.key?(key)
|
71
|
+
end
|
72
|
+
alias :dirty? :changed?
|
73
|
+
|
74
|
+
def change(key, mapped = false)
|
75
|
+
changes[key] if changed?(key, mapped)
|
76
|
+
end
|
77
|
+
|
78
|
+
def was(key, mapped = false)
|
79
|
+
change(key).first if changed?(key, mapped)
|
80
|
+
end
|
81
|
+
|
82
|
+
def clean_up!
|
83
|
+
changes.clear
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def correct_key(key, mapped = false)
|
90
|
+
mapped || is_a?(HashWithIndifferentAccess) ? key.to_s : key
|
91
|
+
end
|
92
|
+
|
93
|
+
def restricted_keys?
|
94
|
+
!(@restricted_keys || []).empty?
|
95
|
+
end
|
96
|
+
|
97
|
+
def validate_read!(key)
|
98
|
+
raise IndexError, "Invalid key: \"#{key}\"" unless (keys + changes.keys).include?(key)
|
99
|
+
end
|
100
|
+
|
101
|
+
def validate_write!(key)
|
102
|
+
raise IndexError, "Invalid key: \"#{key}\"" unless @restricted_keys.nil? || @restricted_keys.empty? || @restricted_keys.include?(key)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
data/lib/dirty_hashy.rb
CHANGED
@@ -1,88 +1,8 @@
|
|
1
|
-
require "
|
1
|
+
require "dirty"
|
2
|
+
require "dirty_indifferent_hashy"
|
2
3
|
require "dirty_hashy/version"
|
3
|
-
require "dirty_attributes"
|
4
4
|
require "method_map"
|
5
5
|
|
6
|
-
class DirtyHashy <
|
7
|
-
|
8
|
-
def initialize(constructor = {}, map_methods = false, restricted_keys = nil)
|
9
|
-
super constructor
|
10
|
-
if map_methods
|
11
|
-
extend MethodMap
|
12
|
-
dirty_map!
|
13
|
-
end
|
14
|
-
if restricted_keys
|
15
|
-
restricted_keys.each{|key| self[key] ||= nil}
|
16
|
-
@restricted_keys = keys
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def replace(other)
|
21
|
-
clear
|
22
|
-
merge! other
|
23
|
-
end
|
24
|
-
|
25
|
-
def clear
|
26
|
-
keys.each{|key| delete key}
|
27
|
-
end
|
28
|
-
|
29
|
-
def [](key, mapped = false)
|
30
|
-
validate_read!(key) if mapped || restricted_keys?
|
31
|
-
super(key)
|
32
|
-
end
|
33
|
-
|
34
|
-
alias :_regular_writer :regular_writer
|
35
|
-
def regular_writer(key, value)
|
36
|
-
validate_write!(key)
|
37
|
-
original_value = changes.key?(key) ? was(key) : fetch(key, nil)
|
38
|
-
if original_value == value
|
39
|
-
changes.delete key
|
40
|
-
else
|
41
|
-
changes[key] = [original_value, value]
|
42
|
-
end
|
43
|
-
_regular_writer key, value
|
44
|
-
end
|
45
|
-
|
46
|
-
def delete(key)
|
47
|
-
self[key] = nil
|
48
|
-
super
|
49
|
-
end
|
50
|
-
|
51
|
-
def changes
|
52
|
-
@changes ||= HashWithIndifferentAccess.new
|
53
|
-
end
|
54
|
-
|
55
|
-
def changed?(key = nil, mapped = false)
|
56
|
-
validate_read!(key) if !key.nil? && (mapped || restricted_keys?)
|
57
|
-
key.nil? ? !changes.empty? : changes.key?(key)
|
58
|
-
end
|
59
|
-
alias :dirty? :changed?
|
60
|
-
|
61
|
-
def change(key, mapped = false)
|
62
|
-
changes[key] if changed?(key, mapped)
|
63
|
-
end
|
64
|
-
|
65
|
-
def was(key, mapped = false)
|
66
|
-
change(key).first if changed?(key, mapped)
|
67
|
-
end
|
68
|
-
|
69
|
-
def clean_up!
|
70
|
-
changes.clear
|
71
|
-
nil
|
72
|
-
end
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
def restricted_keys?
|
77
|
-
!(@restricted_keys || []).empty?
|
78
|
-
end
|
79
|
-
|
80
|
-
def validate_read!(key)
|
81
|
-
raise IndexError, "Invalid key: \"#{key}\"" unless (keys + changes.keys).include?(key.to_s)
|
82
|
-
end
|
83
|
-
|
84
|
-
def validate_write!(key)
|
85
|
-
raise IndexError, "Invalid key: \"#{key}\"" unless @restricted_keys.nil? || @restricted_keys.empty? || @restricted_keys.include?(key.to_s)
|
86
|
-
end
|
87
|
-
|
6
|
+
class DirtyHashy < Hash
|
7
|
+
include Dirty::Hash
|
88
8
|
end
|
data/lib/dirty_hashy/version.rb
CHANGED
@@ -0,0 +1,176 @@
|
|
1
|
+
require File.expand_path("../../../test_helper", __FILE__)
|
2
|
+
|
3
|
+
module Unit
|
4
|
+
module Dirty
|
5
|
+
class TestAttributes < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
describe ::Dirty::Attributes do
|
8
|
+
it "should behave as expected without key restriction" do
|
9
|
+
class Person
|
10
|
+
include ::Dirty::Attributes
|
11
|
+
end
|
12
|
+
|
13
|
+
person = Person.new
|
14
|
+
|
15
|
+
assert_equal({}, person.attributes)
|
16
|
+
assert_equal false, person.dirty?
|
17
|
+
assert_equal false, person.changed?
|
18
|
+
assert_equal({}, person.changes)
|
19
|
+
|
20
|
+
assert_raises(NoMethodError) do
|
21
|
+
person.name
|
22
|
+
end
|
23
|
+
|
24
|
+
person.name = "Paul"
|
25
|
+
|
26
|
+
assert_equal "Paul", person.name
|
27
|
+
assert_equal true, person.dirty?
|
28
|
+
assert_equal true, person.changed?
|
29
|
+
assert_equal true, person.name_changed?
|
30
|
+
assert_equal [nil, "Paul"], person.name_change
|
31
|
+
assert_equal({"name" => [nil, "Paul"]}, person.changes)
|
32
|
+
|
33
|
+
person.name = nil
|
34
|
+
|
35
|
+
assert_equal false, person.dirty?
|
36
|
+
assert_equal false, person.changed?
|
37
|
+
assert_equal false, person.name_changed?
|
38
|
+
assert_equal nil, person.name_change
|
39
|
+
assert_equal({}, person.changes)
|
40
|
+
|
41
|
+
person.name = "Stephan"
|
42
|
+
|
43
|
+
assert_equal true, person.dirty?
|
44
|
+
assert_equal true, person.changed?
|
45
|
+
assert_equal true, person.name_changed?
|
46
|
+
assert_equal [nil, "Stephan"], person.name_change
|
47
|
+
assert_equal({"name" => [nil, "Stephan"]}, person.changes)
|
48
|
+
|
49
|
+
person.clean_up!
|
50
|
+
|
51
|
+
assert_equal false, person.dirty?
|
52
|
+
assert_equal false, person.changed?
|
53
|
+
assert_equal false, person.name_changed?
|
54
|
+
assert_equal nil, person.name_change
|
55
|
+
assert_equal({}, person.changes)
|
56
|
+
|
57
|
+
person.foo = "Bar"
|
58
|
+
|
59
|
+
assert_equal "Bar", person.foo
|
60
|
+
assert_equal true, person.dirty?
|
61
|
+
assert_equal true, person.changed?
|
62
|
+
assert_equal false, person.name_changed?
|
63
|
+
assert_equal true, person.foo_changed?
|
64
|
+
assert_equal nil, person.name_change
|
65
|
+
assert_equal [nil, "Bar"], person.foo_change
|
66
|
+
assert_equal({"foo" => [nil, "Bar"]}, person.changes)
|
67
|
+
|
68
|
+
person.attributes.merge! :company => "Internetbureau Holder B.V."
|
69
|
+
|
70
|
+
assert_equal true, person.dirty?
|
71
|
+
assert_equal true, person.changed?
|
72
|
+
assert_equal false, person.name_changed?
|
73
|
+
assert_equal true, person.foo_changed?
|
74
|
+
assert_equal true, person.company_changed?
|
75
|
+
assert_equal nil, person.name_change
|
76
|
+
assert_equal [nil, "Bar"], person.foo_change
|
77
|
+
assert_equal [nil, "Internetbureau Holder B.V."], person.company_change
|
78
|
+
assert_equal({"foo" => [nil, "Bar"], "company" => [nil, "Internetbureau Holder B.V."]}, person.changes)
|
79
|
+
|
80
|
+
person.attributes.delete :foo
|
81
|
+
person.clean_up!
|
82
|
+
|
83
|
+
assert_equal false, person.dirty?
|
84
|
+
assert_equal false, person.changed?
|
85
|
+
assert_equal({"name" => "Stephan", "company" => "Internetbureau Holder B.V."}, person.attributes)
|
86
|
+
assert_equal({}, person.changes)
|
87
|
+
|
88
|
+
person.attributes = {"name" => "Paul", "city" => "Amsterdam"}
|
89
|
+
|
90
|
+
assert_equal true, person.dirty?
|
91
|
+
assert_equal true, person.changed?
|
92
|
+
assert_equal true, person.name_changed?
|
93
|
+
assert_equal true, person.company_changed?
|
94
|
+
assert_equal true, person.city_changed?
|
95
|
+
assert_equal ["Stephan", "Paul"], person.name_change
|
96
|
+
assert_equal ["Internetbureau Holder B.V.", nil], person.company_change
|
97
|
+
assert_equal [nil, "Amsterdam"], person.city_change
|
98
|
+
assert_equal({"name" => ["Stephan", "Paul"], "company" => ["Internetbureau Holder B.V.", nil], "city" => [nil, "Amsterdam"]}, person.changes)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should behave as expected with key restriction" do
|
102
|
+
class User
|
103
|
+
include ::Dirty::Attributes
|
104
|
+
attrs :name
|
105
|
+
end
|
106
|
+
|
107
|
+
user = User.new
|
108
|
+
|
109
|
+
assert_equal({"name" => nil}, user.attributes)
|
110
|
+
assert_equal nil, user.name
|
111
|
+
assert_equal false, user.dirty?
|
112
|
+
assert_equal false, user.changed?
|
113
|
+
assert_equal({}, user.changes)
|
114
|
+
|
115
|
+
assert_raises(NoMethodError) do
|
116
|
+
user.foo
|
117
|
+
end
|
118
|
+
|
119
|
+
assert_raises(NoMethodError) do
|
120
|
+
user.foo = "Bar"
|
121
|
+
end
|
122
|
+
|
123
|
+
user.name = "Paul"
|
124
|
+
|
125
|
+
assert_equal "Paul", user.name
|
126
|
+
assert_equal true, user.dirty?
|
127
|
+
assert_equal true, user.changed?
|
128
|
+
assert_equal true, user.name_changed?
|
129
|
+
assert_equal [nil, "Paul"], user.name_change
|
130
|
+
assert_equal({"name" => [nil, "Paul"]}, user.changes)
|
131
|
+
|
132
|
+
user.name = nil
|
133
|
+
|
134
|
+
assert_equal false, user.dirty?
|
135
|
+
assert_equal false, user.changed?
|
136
|
+
assert_equal false, user.name_changed?
|
137
|
+
assert_equal nil, user.name_change
|
138
|
+
assert_equal({}, user.changes)
|
139
|
+
|
140
|
+
user.name = "Stephan"
|
141
|
+
|
142
|
+
assert_equal true, user.dirty?
|
143
|
+
assert_equal true, user.changed?
|
144
|
+
assert_equal true, user.name_changed?
|
145
|
+
assert_equal [nil, "Stephan"], user.name_change
|
146
|
+
assert_equal({"name" => [nil, "Stephan"]}, user.changes)
|
147
|
+
|
148
|
+
user.clean_up!
|
149
|
+
|
150
|
+
assert_equal false, user.dirty?
|
151
|
+
assert_equal false, user.changed?
|
152
|
+
assert_equal false, user.name_changed?
|
153
|
+
assert_equal nil, user.name_change
|
154
|
+
assert_equal({}, user.changes)
|
155
|
+
|
156
|
+
user.attributes = {"name" => "Paul"}
|
157
|
+
|
158
|
+
assert_equal true, user.dirty?
|
159
|
+
assert_equal true, user.changed?
|
160
|
+
assert_equal true, user.name_changed?
|
161
|
+
assert_equal ["Stephan", "Paul"], user.name_change
|
162
|
+
assert_equal({"name" => ["Stephan", "Paul"]}, user.changes)
|
163
|
+
|
164
|
+
assert_raises(NoMethodError) do
|
165
|
+
user.attributes = {"company" => "Internetbureau Holder B.V."}
|
166
|
+
end
|
167
|
+
|
168
|
+
assert_raises(IndexError) do
|
169
|
+
user.attributes.merge! "company" => "Internetbureau Holder B.V."
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|