dirty_hashy 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|