attribute-kit 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -0
- data/Gemfile.lock +32 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +36 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/lib/attribute-kit.rb +1 -0
- data/lib/attribute-kit/attribute-kit.rb +1 -0
- data/lib/attribute-kit/attribute_hash.rb +247 -0
- data/spec/attribute-kit_spec.rb +646 -0
- data/spec/spec_helper.rb +12 -0
- metadata +135 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.2)
|
5
|
+
git (1.2.5)
|
6
|
+
jeweler (1.6.4)
|
7
|
+
bundler (~> 1.0)
|
8
|
+
git (>= 1.2.5)
|
9
|
+
rake
|
10
|
+
rake (0.9.2)
|
11
|
+
rcov (0.9.9)
|
12
|
+
rdiscount (1.6.8)
|
13
|
+
rspec (2.3.0)
|
14
|
+
rspec-core (~> 2.3.0)
|
15
|
+
rspec-expectations (~> 2.3.0)
|
16
|
+
rspec-mocks (~> 2.3.0)
|
17
|
+
rspec-core (2.3.1)
|
18
|
+
rspec-expectations (2.3.0)
|
19
|
+
diff-lcs (~> 1.1.2)
|
20
|
+
rspec-mocks (2.3.0)
|
21
|
+
yard (0.7.2)
|
22
|
+
|
23
|
+
PLATFORMS
|
24
|
+
ruby
|
25
|
+
|
26
|
+
DEPENDENCIES
|
27
|
+
bundler (~> 1.0.0)
|
28
|
+
jeweler (~> 1.6.4)
|
29
|
+
rcov
|
30
|
+
rdiscount
|
31
|
+
rspec (~> 2.3.0)
|
32
|
+
yard
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Jonathan Mischo
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# attribute-kit
|
2
|
+
|
3
|
+
Tools for attribute tracking like Hashes with dirty tracking and events, for building hybrid models and generally going beyond what's provided by your local ORM/DRM, while allowing you to expand what you can do with them, live without them, or roll your own
|
4
|
+
|
5
|
+
## Contributing to attribute-kit
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
|
+
* Fork the project
|
10
|
+
* Start a feature/bugfix branch
|
11
|
+
* Commit and push until you are happy with your contribution
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
## Copyright and License
|
16
|
+
|
17
|
+
Copyright (c) 2011 Jonathan Mischo
|
18
|
+
|
19
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
20
|
+
a copy of this software and associated documentation files (the
|
21
|
+
"Software"), to deal in the Software without restriction, including
|
22
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
23
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
24
|
+
permit persons to whom the Software is furnished to do so, subject to
|
25
|
+
the following conditions:
|
26
|
+
|
27
|
+
The above copyright notice and this permission notice shall be
|
28
|
+
included in all copies or substantial portions of the Software.
|
29
|
+
|
30
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
31
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
32
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
33
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
34
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
35
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
36
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "attribute-kit"
|
18
|
+
gem.homepage = "http://github.com/supertaz/attribute-kit"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Tools for attribute tracking like Hashes with dirty tracking and events, for building hybrid models and generally going beyond what's provided by your local ORM/DRM, while allowing you to expand what you can do with them, live without them, or roll your own}
|
21
|
+
gem.description = %Q{Tools for attribute tracking like Hashes with dirty tracking and events, for building hybrid models and generally going beyond what's provided by your local ORM/DRM, while allowing you to expand what you can do with them, live without them, or roll your own}
|
22
|
+
gem.email = "jon.mischo@gmail.com"
|
23
|
+
gem.authors = ["Jonathan Mischo"]
|
24
|
+
gem.version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
25
|
+
gem.files = FileList['lib/**/*.rb', '[A-Z]*', 'spec/**/*'].to_a
|
26
|
+
# dependencies defined in Gemfile
|
27
|
+
end
|
28
|
+
Jeweler::RubygemsDotOrgTasks.new
|
29
|
+
|
30
|
+
require 'rspec/core'
|
31
|
+
require 'rspec/core/rake_task'
|
32
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
33
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
34
|
+
end
|
35
|
+
|
36
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
37
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
38
|
+
spec.rcov = true
|
39
|
+
end
|
40
|
+
|
41
|
+
task :default => :spec
|
42
|
+
|
43
|
+
require 'yard'
|
44
|
+
YARD::Rake::YardocTask.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'attribute-kit/attribute-kit.rb'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'attribute-kit/attribute_hash'
|
@@ -0,0 +1,247 @@
|
|
1
|
+
# A group of classes and other tools that are designed to make handling of attributes and dealing with changes to
|
2
|
+
# groups of attributes easy and convenient. This is particularly useful if you intend to build, extend, or even
|
3
|
+
# simply wish to avoid using someone else's ORM or DRM.
|
4
|
+
#
|
5
|
+
# The original intent of this library was to make it easier to store and track changes to attributes on a model that
|
6
|
+
# was not managed by an ORM, yet needed to be selectively synchronized between a client, server, and data store. From
|
7
|
+
# those humble beginnings, this optimized library was created.
|
8
|
+
#
|
9
|
+
# @author Jonathan Mischo
|
10
|
+
# @note Copyright (c) 2011 Jonathan Mischo
|
11
|
+
# @note Distributed under the MIT license (see LICENSE.txt, distributed with the original source code)
|
12
|
+
|
13
|
+
module AttributeKit
|
14
|
+
|
15
|
+
# AttributeHash inherits from and extends Hash, to provide tracking of attribute status (changed/deleted keys).
|
16
|
+
class AttributeHash < Hash
|
17
|
+
|
18
|
+
# @visibility private
|
19
|
+
def self.cond_deletion_method(method_name)
|
20
|
+
define_method(method_name) { |&block|
|
21
|
+
unless block.nil?
|
22
|
+
keys = self.keys
|
23
|
+
r = super(&block)
|
24
|
+
@deleted_keys += keys - self.keys
|
25
|
+
r
|
26
|
+
else
|
27
|
+
super()
|
28
|
+
end
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
private_class_method :cond_deletion_method
|
33
|
+
|
34
|
+
# Creates a new instance, using identical syntax to Hash
|
35
|
+
# @see Hash#new
|
36
|
+
def initialize(*args)
|
37
|
+
super(*args)
|
38
|
+
@dirty_keys = []
|
39
|
+
@deleted_keys = []
|
40
|
+
end
|
41
|
+
|
42
|
+
# Assigns a value to a key
|
43
|
+
# @param [Object] k key of key-value pair to insert or change in instance
|
44
|
+
# @param [Object] v value of key-value pair to insert or change in instance
|
45
|
+
# @return [Object] value of key-value pair inserted
|
46
|
+
# @see Hash#[]=
|
47
|
+
def []=(k,v)
|
48
|
+
if self[k].eql? v
|
49
|
+
v
|
50
|
+
else
|
51
|
+
@dirty_keys << k
|
52
|
+
super
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
alias_method :store, :[]=
|
57
|
+
|
58
|
+
# Delete a key-value pair
|
59
|
+
# @param [Object] key key of key-value pair to delete from instance
|
60
|
+
# @return [Object] value of key-value pair deleted
|
61
|
+
# @see Hash#delete
|
62
|
+
def delete(k)
|
63
|
+
@deleted_keys << k
|
64
|
+
@dirty_keys.delete(k)
|
65
|
+
super
|
66
|
+
end
|
67
|
+
|
68
|
+
# @method reject!
|
69
|
+
# Delete keys matching an expression in the provided block
|
70
|
+
# @return [AttributeHash] if changes are made
|
71
|
+
# @return [Nil] if no changes are made
|
72
|
+
# @yield [key, value] block is executed for every key-value pair stored in the instance
|
73
|
+
# @yieldparam [Object] key the key from the key-value pair being evaluated
|
74
|
+
# @yieldparam [Object] value the value from the key-value pair being evaluated
|
75
|
+
# @yieldreturn [Boolean] whether or not to delete a particular stored key-value pair from the instance
|
76
|
+
# @see Hash#reject!
|
77
|
+
cond_deletion_method(:reject!)
|
78
|
+
|
79
|
+
# @method select!
|
80
|
+
# Delete keys not matching an expression in the provided block
|
81
|
+
# @return [AttributeHash] if changes are made
|
82
|
+
# @return [Nil] if no changes are made
|
83
|
+
# @yield [key, value] block is executed for every key-value pair stored in the instance
|
84
|
+
# @yieldparam [Object] key the key from the key-value pair being evaluated
|
85
|
+
# @yieldparam [Object] value the value from the key-value pair being evaluated
|
86
|
+
# @yieldreturn [Boolean] whether or not to keep a particular stored key-value pair in the instance
|
87
|
+
# @see Hash#select!
|
88
|
+
cond_deletion_method(:select!)
|
89
|
+
|
90
|
+
# @method keep_if
|
91
|
+
# Delete keys not matching an expression in the provided block
|
92
|
+
# @return [AttributeHash] self with changes applied
|
93
|
+
# @yield [key, value] block is executed for every key-value pair stored in the instance
|
94
|
+
# @yieldparam [Object] key the key from the key-value pair being evaluated
|
95
|
+
# @yieldparam [Object] value the value from the key-value pair being evaluated
|
96
|
+
# @yieldreturn [Boolean] whether or not to keep a particular stored key-value pair in the instance
|
97
|
+
# @see Hash#keep_if
|
98
|
+
cond_deletion_method(:keep_if)
|
99
|
+
|
100
|
+
# @method delete_if
|
101
|
+
# Delete keys matching an expression in the provided block
|
102
|
+
# @return [AttributeHash] self with changes applied
|
103
|
+
# @yield [key, value] block is executed for every key-value pair stored in the instance
|
104
|
+
# @yieldparam [Object] key the key from the key-value pair being evaluated
|
105
|
+
# @yieldparam [Object] value the value from the key-value pair being evaluated
|
106
|
+
# @yieldreturn [Boolean] whether or not to delete a particular stored key-value pair from the instance
|
107
|
+
# @see Hash#delete_if
|
108
|
+
cond_deletion_method(:delete_if)
|
109
|
+
|
110
|
+
# Replace the contents of this object with the contents of the supplied hash
|
111
|
+
# @param [Hash] other_hash hash of values to replace instance contents with
|
112
|
+
# @return [AttributeHash] self with changes applied
|
113
|
+
# @see Hash#replace
|
114
|
+
def replace(other_hash)
|
115
|
+
old_keys = self.keys
|
116
|
+
r = super
|
117
|
+
new_keys = self.keys
|
118
|
+
@dirty_keys = new_keys
|
119
|
+
@deleted_keys += (old_keys - new_keys)
|
120
|
+
r
|
121
|
+
end
|
122
|
+
|
123
|
+
# Combine the contents of this object with the contents of the supplied hash, calling an optional supplied block to
|
124
|
+
# determine what value is used when there are duplicate keys. Without the block, values from the supplied hash will
|
125
|
+
# be used in the case of duplicate keys
|
126
|
+
# @param [Hash] other_hash hash of values to merge in to the instance
|
127
|
+
# @yield [key, oldval, newval] block is executed for every duplicate key between the instance and other_hash
|
128
|
+
# @yieldparam [Object] key the key being evaluated
|
129
|
+
# @yieldparam [Object] oldval the value from the value from the instance
|
130
|
+
# @yieldparam [Object] newval the value from the value from other_hash
|
131
|
+
# @yieldreturn [Object] the value to store for the key in question
|
132
|
+
# @return [AttributeHash] self with changes applied
|
133
|
+
# @see Hash#merge!
|
134
|
+
def merge!(other_hash, &block)
|
135
|
+
old_keys = self.keys
|
136
|
+
overlapping_keys = old_keys.dup.keep_if {|v| other_hash.keys.include?(v)}
|
137
|
+
r = super
|
138
|
+
if block.nil?
|
139
|
+
@dirty_keys += (self.keys - old_keys) + overlapping_keys
|
140
|
+
else
|
141
|
+
new_values = other_hash.keep_if {|k,v| overlapping_keys.include?(k)}
|
142
|
+
@dirty_keys += (self.keys - old_keys) + (new_values.keep_if {|k,v| !self[k].eql?(v) }).keys
|
143
|
+
end
|
144
|
+
r
|
145
|
+
end
|
146
|
+
|
147
|
+
alias_method :update, :merge!
|
148
|
+
|
149
|
+
# Returns a key-value pair from the instance and deletes it.
|
150
|
+
# @return [Array] key-value pair
|
151
|
+
# @see Hash#shift
|
152
|
+
def shift
|
153
|
+
(k,v) = super
|
154
|
+
@deleted_keys << k
|
155
|
+
[k,v]
|
156
|
+
end
|
157
|
+
|
158
|
+
# Clear all contents of the object.
|
159
|
+
# @see Hash#clear
|
160
|
+
def clear
|
161
|
+
@deleted_keys += self.keys
|
162
|
+
@dirty_keys.clear
|
163
|
+
super
|
164
|
+
end
|
165
|
+
|
166
|
+
# Check whether the contents of the object have changed since the last time clean_attributes was run.
|
167
|
+
# @return [Boolean] value indicating whether or not key-value pairs have been added, changed, or deleted
|
168
|
+
def dirty?
|
169
|
+
!(@dirty_keys.empty? && @deleted_keys.empty?)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returns the set of keys that have been modified since the AttributeHash was last marked clean.
|
173
|
+
# @return [Array] all of the changed keys
|
174
|
+
def dirty_keys
|
175
|
+
@dirty_keys.uniq!
|
176
|
+
@dirty_keys + self.deleted_keys
|
177
|
+
end
|
178
|
+
|
179
|
+
# Returns the set of keys that have been deleted since the AttributeHash was last marked clean.
|
180
|
+
# @return [Array] all of the deleted keys
|
181
|
+
def deleted_keys
|
182
|
+
@deleted_keys.uniq!
|
183
|
+
@deleted_keys
|
184
|
+
end
|
185
|
+
|
186
|
+
# Calls a block with a hash of all keys, actions (:changed or :deleted), and current values (if :changed) of keys
|
187
|
+
# that have changed since the object was last marked clean. Marks the object as clean when it compiles
|
188
|
+
# the list of keys that have been modified.
|
189
|
+
# @param [Block] block to execute with hash of modified keys, actions, and values
|
190
|
+
def clean_attributes(&block)
|
191
|
+
if !@dirty_keys.empty?
|
192
|
+
dirty_attrs = {}
|
193
|
+
@dirty_keys.uniq!
|
194
|
+
dirty = @dirty_keys.dup
|
195
|
+
@dirty_keys.clear
|
196
|
+
deleted = @deleted_keys.dup
|
197
|
+
@deleted_keys.clear
|
198
|
+
|
199
|
+
while dirty.length > 0 do
|
200
|
+
key = dirty.shift
|
201
|
+
dirty_attrs[key] = [:changed, self[key]]
|
202
|
+
end
|
203
|
+
|
204
|
+
while deleted.length > 0 do
|
205
|
+
key = deleted.shift
|
206
|
+
dirty_attrs[key] = [:deleted, nil]
|
207
|
+
end
|
208
|
+
|
209
|
+
block.call(dirty_attrs)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# @overload KEY_dirty?()
|
214
|
+
# Check whether a particular key is dirty - KEY is a string representation of the key name for the key-value pair being queried
|
215
|
+
# @note There can be conflicts if you have multiple keys that are similar, i.e. :blue and 'blue', so only use this
|
216
|
+
# when you can guarantee homogenous keys and are using either strings or symbols for the key (the only cases where
|
217
|
+
# it will work)
|
218
|
+
# @return [Boolean] value indicating key-value pair state
|
219
|
+
# @note Uses method_missing to implement the check
|
220
|
+
# @overload KEY_deleted?()
|
221
|
+
# Check whether a particular key has been deleted - KEY is a string representation of the key name for the key-value pair being queried
|
222
|
+
# @note There can be conflicts if you have multiple keys that are similar, i.e. :blue and 'blue', so only use this
|
223
|
+
# when you can guarantee homogenous keys and are using either strings or symbols for the key (the only cases where
|
224
|
+
# it will work)
|
225
|
+
# @return [Boolean] value indicating key-value pair state
|
226
|
+
# @note Uses method_missing to implement the check
|
227
|
+
|
228
|
+
def method_missing(method, *args, &block)
|
229
|
+
method_name = method.to_s
|
230
|
+
case method_name
|
231
|
+
when /(.*)_dirty?/
|
232
|
+
return @dirty_keys.include?($1) if self.has_key?($1)
|
233
|
+
return @dirty_keys.include?($1.to_sym) if self.has_key?($1.to_sym)
|
234
|
+
@deleted_keys.include?($1) || @deleted_keys.include?($1.to_sym)
|
235
|
+
when /(.*)_deleted?/
|
236
|
+
@deleted_keys.include?($1) || @deleted_keys.include?($1.to_sym)
|
237
|
+
else
|
238
|
+
if self.class.superclass.instance_methods.include?('method_missing')
|
239
|
+
super(method, *args, &block)
|
240
|
+
else
|
241
|
+
raise NoMethodError.new("undefined method '#{method_name}' for #{self}")
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,646 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "AttributeKit" do
|
4
|
+
it "loads" do
|
5
|
+
defined?(AttributeKit).should == 'constant'
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "::AttributeHash" do
|
9
|
+
describe '#new' do
|
10
|
+
it "should return an empty AttributeHash when initialized without arguments" do
|
11
|
+
test_hash = AttributeKit::AttributeHash.new
|
12
|
+
test_hash.empty?.should be_true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should return a 0 length AttributeHash when initialized' do
|
16
|
+
test_hash = AttributeKit::AttributeHash.new
|
17
|
+
test_hash.length.should == 0
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return a default value for invalid keys when initialized with a default value" do
|
21
|
+
test_hash = AttributeKit::AttributeHash.new('blue')
|
22
|
+
test_hash.empty?.should be_true
|
23
|
+
test_hash[:blue].should == 'blue'
|
24
|
+
test_hash[:red].should == 'blue'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should execute and return the result of a block for invalid keys when initialized with a block" do
|
28
|
+
test_hash = AttributeKit::AttributeHash.new { |hash, key| [hash, key] }
|
29
|
+
test_hash.empty?.should be_true
|
30
|
+
test_hash[:blue].eql?([test_hash, :blue]).should be_true
|
31
|
+
test_hash[:red].eql?([test_hash, :red]).should be_true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#[]=' do
|
36
|
+
before(:each) do
|
37
|
+
@test_hash = AttributeKit::AttributeHash.new
|
38
|
+
@test_hash[:blue] = 'blue'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should store a value" do
|
42
|
+
@test_hash.empty?.should be_false
|
43
|
+
@test_hash[:blue].should == 'blue'
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should mark the attribute as dirty" do
|
47
|
+
@test_hash.blue_dirty?.should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should not mark the attribute as deleted" do
|
51
|
+
@test_hash.blue_deleted?.should be_false
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should mark the AttributeHash as dirty" do
|
55
|
+
@test_hash.dirty?.should be_true
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return the value set" do
|
59
|
+
ret = @test_hash[:red] = 'red'
|
60
|
+
ret.should == 'red'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#store' do
|
65
|
+
before(:each) do
|
66
|
+
@test_hash = AttributeKit::AttributeHash.new
|
67
|
+
@test_hash.store(:blue, 'blue')
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should store a value" do
|
71
|
+
@test_hash.empty?.should be_false
|
72
|
+
@test_hash[:blue].should == 'blue'
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should be dirty" do
|
76
|
+
@test_hash.blue_dirty?.should be_true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should not be deleted" do
|
80
|
+
@test_hash.blue_deleted?.should be_false
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should return the value set" do
|
84
|
+
ret = @test_hash.store(:red, 'red')
|
85
|
+
ret.should == 'red'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#[]' do
|
90
|
+
before(:each) do
|
91
|
+
@test_hash = AttributeKit::AttributeHash.new('red')
|
92
|
+
@test_hash[:blue] = 'blue'
|
93
|
+
@test_hash.clean_attributes {}
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should get a correct value (sanity check)" do
|
97
|
+
@test_hash.empty?.should be_false
|
98
|
+
@test_hash[:blue].should == 'blue'
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should be clean" do
|
102
|
+
@test_hash.dirty?.should be_false
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '#delete' do
|
107
|
+
before(:each) do
|
108
|
+
@test_hash = AttributeKit::AttributeHash.new
|
109
|
+
@test_hash[:blue] = 'blue'
|
110
|
+
@test_hash.clean_attributes {}
|
111
|
+
@test_hash.delete(:blue)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should delete a value" do
|
115
|
+
@test_hash[:blue].should be_nil
|
116
|
+
@test_hash.empty?.should be_true
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should mark the attribute as deleted" do
|
120
|
+
@test_hash.blue_deleted?.should be_true
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should mark the AttributeHash as dirty" do
|
124
|
+
@test_hash.dirty?.should be_true
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should include the attribute in dirty_keys" do
|
128
|
+
@test_hash.dirty_keys.include?(:blue).should be_true
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should include the attribute in deleted_keys" do
|
132
|
+
@test_hash.deleted_keys.include?(:blue).should be_true
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe '#delete_if' do
|
137
|
+
before(:each) do
|
138
|
+
@test_hash = AttributeKit::AttributeHash.new
|
139
|
+
@test_hash[:blue] = 'blue'
|
140
|
+
@test_hash[:red] = 'red'
|
141
|
+
@test_hash.clean_attributes {}
|
142
|
+
@test_hash.delete_if {|k,v| v == 'blue'}
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should delete only the matching items" do
|
146
|
+
@test_hash[:blue].should be_nil
|
147
|
+
@test_hash[:red].should == 'red'
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should mark deleted attributes as deleted" do
|
151
|
+
@test_hash.blue_deleted?.should be_true
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should not mark untouched attributes as deleted" do
|
155
|
+
@test_hash.red_deleted?.should be_false
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should include deleted attributes in dirty_keys" do
|
159
|
+
@test_hash.dirty_keys.include?(:blue).should be_true
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should include deleted attributes in deleted_keys" do
|
163
|
+
@test_hash.deleted_keys.include?(:blue).should be_true
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should not include undeleted attributes in dirty_keys" do
|
167
|
+
@test_hash.dirty_keys.include?(:red).should be_false
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should not include undeleted attributes in deleted_keys" do
|
171
|
+
@test_hash.deleted_keys.include?(:red).should be_false
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should mark the AttributeHash as dirty" do
|
175
|
+
@test_hash.dirty?.should be_true
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe '#keep_if' do
|
180
|
+
before(:each) do
|
181
|
+
@test_hash = AttributeKit::AttributeHash.new
|
182
|
+
@test_hash[:blue] = 'blue'
|
183
|
+
@test_hash[:red] = 'red'
|
184
|
+
@test_hash.clean_attributes {}
|
185
|
+
@test_hash.keep_if {|k,v| v == 'red'}
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should delete only the matching items" do
|
189
|
+
@test_hash[:blue].should be_nil
|
190
|
+
@test_hash[:red].should == 'red'
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should mark deleted attributes as deleted" do
|
194
|
+
@test_hash.blue_deleted?.should be_true
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should not mark untouched attributes as deleted" do
|
198
|
+
@test_hash.red_deleted?.should be_false
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should include deleted attributes in dirty_keys" do
|
202
|
+
@test_hash.dirty_keys.include?(:blue).should be_true
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should include deleted attributes in deleted_keys" do
|
206
|
+
@test_hash.deleted_keys.include?(:blue).should be_true
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should not include undeleted attributes in dirty_keys" do
|
210
|
+
@test_hash.dirty_keys.include?(:red).should be_false
|
211
|
+
end
|
212
|
+
|
213
|
+
it "should not include undeleted attributes in deleted_keys" do
|
214
|
+
@test_hash.deleted_keys.include?(:red).should be_false
|
215
|
+
end
|
216
|
+
|
217
|
+
it "should mark the AttributeHash as dirty" do
|
218
|
+
@test_hash.dirty?.should be_true
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe '#reject!' do
|
223
|
+
before(:each) do
|
224
|
+
@test_hash = AttributeKit::AttributeHash.new
|
225
|
+
@test_hash[:blue] = 'blue'
|
226
|
+
@test_hash[:red] = 'red'
|
227
|
+
@test_hash.clean_attributes {}
|
228
|
+
@test_hash.reject! {|k,v| v == 'blue'}
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should delete only the matching items" do
|
232
|
+
@test_hash[:blue].should be_nil
|
233
|
+
@test_hash[:red].should == 'red'
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should mark deleted attributes as deleted" do
|
237
|
+
@test_hash.blue_deleted?.should be_true
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should not mark untouched attributes as deleted" do
|
241
|
+
@test_hash.red_deleted?.should be_false
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should include deleted attributes in dirty_keys" do
|
245
|
+
@test_hash.dirty_keys.include?(:blue).should be_true
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should include deleted attributes in deleted_keys" do
|
249
|
+
@test_hash.deleted_keys.include?(:blue).should be_true
|
250
|
+
end
|
251
|
+
|
252
|
+
it "should not include undeleted attributes in dirty_keys" do
|
253
|
+
@test_hash.dirty_keys.include?(:red).should be_false
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should not include undeleted attributes in deleted_keys" do
|
257
|
+
@test_hash.deleted_keys.include?(:red).should be_false
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should mark the AttributeHash as dirty" do
|
261
|
+
@test_hash.dirty?.should be_true
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should return nil if no changes are made" do
|
265
|
+
test_hash = AttributeKit::AttributeHash.new
|
266
|
+
test_hash[:blue] = 'blue'
|
267
|
+
test_hash.clean_attributes {}
|
268
|
+
ret = test_hash.reject! {|k,v| v == 'red'}
|
269
|
+
ret.should be_nil
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe '#select!' do
|
274
|
+
before(:each) do
|
275
|
+
@test_hash = AttributeKit::AttributeHash.new
|
276
|
+
@test_hash[:blue] = 'blue'
|
277
|
+
@test_hash[:red] = 'red'
|
278
|
+
@test_hash.clean_attributes {}
|
279
|
+
@test_hash.select! {|k,v| v == 'red'}
|
280
|
+
end
|
281
|
+
|
282
|
+
it "should delete only the matching items" do
|
283
|
+
@test_hash[:blue].should be_nil
|
284
|
+
@test_hash[:red].should == 'red'
|
285
|
+
end
|
286
|
+
|
287
|
+
it "should mark deleted attributes as deleted" do
|
288
|
+
@test_hash.blue_deleted?.should be_true
|
289
|
+
end
|
290
|
+
|
291
|
+
it "should not mark untouched attributes as deleted" do
|
292
|
+
@test_hash.red_deleted?.should be_false
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should include deleted attributes in dirty_keys" do
|
296
|
+
@test_hash.dirty_keys.include?(:blue).should be_true
|
297
|
+
end
|
298
|
+
|
299
|
+
it "should include deleted attributes in deleted_keys" do
|
300
|
+
@test_hash.deleted_keys.include?(:blue).should be_true
|
301
|
+
end
|
302
|
+
|
303
|
+
it "should not include undeleted attributes in dirty_keys" do
|
304
|
+
@test_hash.dirty_keys.include?(:red).should be_false
|
305
|
+
end
|
306
|
+
|
307
|
+
it "should not include undeleted attributes in deleted_keys" do
|
308
|
+
@test_hash.deleted_keys.include?(:red).should be_false
|
309
|
+
end
|
310
|
+
|
311
|
+
it "should mark the AttributeHash as dirty" do
|
312
|
+
@test_hash.dirty?.should be_true
|
313
|
+
end
|
314
|
+
|
315
|
+
it "should return nil if no changes are made" do
|
316
|
+
test_hash = AttributeKit::AttributeHash.new
|
317
|
+
test_hash[:blue] = 'blue'
|
318
|
+
test_hash.clean_attributes {}
|
319
|
+
ret = test_hash.select! {|k,v| v == 'blue'}
|
320
|
+
ret.should be_nil
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
describe "#replace" do
|
325
|
+
before(:each) do
|
326
|
+
@test_hash = AttributeKit::AttributeHash.new
|
327
|
+
@test_hash[:blue] = 'blue'
|
328
|
+
@test_hash[:red] = 'red'
|
329
|
+
@test_hash.clean_attributes {}
|
330
|
+
@ret_val = @test_hash.replace({:yellow => 'yellow', :green => 'green'})
|
331
|
+
end
|
332
|
+
|
333
|
+
it "should remove old contents" do
|
334
|
+
@test_hash[:blue].should be_nil
|
335
|
+
@test_hash[:red].should be_nil
|
336
|
+
end
|
337
|
+
|
338
|
+
it "should replace contents with supplied hash's contents" do
|
339
|
+
@test_hash[:yellow].should == 'yellow'
|
340
|
+
@test_hash[:green].should == 'green'
|
341
|
+
end
|
342
|
+
|
343
|
+
it "should mark old attributes as deleted" do
|
344
|
+
@test_hash.blue_deleted?.should be_true
|
345
|
+
@test_hash.red_deleted?.should be_true
|
346
|
+
end
|
347
|
+
|
348
|
+
it "should mark new attributes as dirty" do
|
349
|
+
@test_hash.yellow_dirty?.should be_true
|
350
|
+
@test_hash.green_dirty?.should be_true
|
351
|
+
end
|
352
|
+
|
353
|
+
it "should include old keys in deleted_keys" do
|
354
|
+
@test_hash.deleted_keys.include?(:blue).should be_true
|
355
|
+
@test_hash.deleted_keys.include?(:red).should be_true
|
356
|
+
end
|
357
|
+
|
358
|
+
it "should not include new keys in deleted_keys" do
|
359
|
+
@test_hash.deleted_keys.include?(:yellow).should be_false
|
360
|
+
@test_hash.deleted_keys.include?(:green).should be_false
|
361
|
+
end
|
362
|
+
|
363
|
+
it "should mark instance as dirty" do
|
364
|
+
@test_hash.dirty?.should be_true
|
365
|
+
end
|
366
|
+
|
367
|
+
it "should return an AttributeHash containing the new contents" do
|
368
|
+
@ret_val.class.should == AttributeKit::AttributeHash
|
369
|
+
@ret_val.eql?({:yellow => 'yellow', :green => 'green'}).should be_true
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
describe "#merge!" do
|
374
|
+
before(:each) do
|
375
|
+
@test_hash = AttributeKit::AttributeHash.new
|
376
|
+
@test_hash[:blue] = 'blue'
|
377
|
+
@test_hash[:red] = 'red'
|
378
|
+
@test_hash[:green] = 'grn'
|
379
|
+
@test_hash.clean_attributes {}
|
380
|
+
@ret_val = @test_hash.merge!({:yellow => 'yellow', :green => 'green'})
|
381
|
+
end
|
382
|
+
|
383
|
+
it "should retain unupdated contents" do
|
384
|
+
@test_hash.blue_deleted?.should be_false
|
385
|
+
@test_hash.red_deleted?.should be_false
|
386
|
+
@test_hash[:blue].should == 'blue'
|
387
|
+
@test_hash[:red].should == 'red'
|
388
|
+
end
|
389
|
+
|
390
|
+
it "should add supplied hash's contents to object's contents" do
|
391
|
+
@test_hash[:yellow].should == 'yellow'
|
392
|
+
@test_hash[:green].should == 'green'
|
393
|
+
end
|
394
|
+
|
395
|
+
it "should mark new attributes as dirty" do
|
396
|
+
@test_hash.yellow_dirty?.should be_true
|
397
|
+
end
|
398
|
+
|
399
|
+
it "should mark changed attributes as dirty" do
|
400
|
+
@test_hash.green_dirty?.should be_true
|
401
|
+
end
|
402
|
+
|
403
|
+
it "should not include unupdated keys in dirty_keys" do
|
404
|
+
@test_hash.dirty_keys.include?(:blue).should be_false
|
405
|
+
@test_hash.dirty_keys.include?(:red).should be_false
|
406
|
+
end
|
407
|
+
|
408
|
+
it "should include new keys in dirty_keys" do
|
409
|
+
@test_hash.dirty_keys.include?(:yellow).should be_true
|
410
|
+
end
|
411
|
+
|
412
|
+
it "should include changed keys in dirty_keys" do
|
413
|
+
@test_hash.dirty_keys.include?(:green).should be_true
|
414
|
+
end
|
415
|
+
|
416
|
+
it "should not include unupdated keys in deleted_keys" do
|
417
|
+
@test_hash.deleted_keys.include?(:blue).should be_false
|
418
|
+
@test_hash.deleted_keys.include?(:red).should be_false
|
419
|
+
end
|
420
|
+
|
421
|
+
it "should not include new keys in deleted_keys" do
|
422
|
+
@test_hash.deleted_keys.include?(:yellow).should be_false
|
423
|
+
@test_hash.deleted_keys.include?(:green).should be_false
|
424
|
+
end
|
425
|
+
|
426
|
+
it "should mark instance as dirty" do
|
427
|
+
@test_hash.dirty?.should be_true
|
428
|
+
end
|
429
|
+
|
430
|
+
it "should return an AttributeHash containing the new contents" do
|
431
|
+
@ret_val.class.should == AttributeKit::AttributeHash
|
432
|
+
@ret_val.eql?({:blue => 'blue', :red => 'red', :yellow => 'yellow', :green => 'green'}).should be_true
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
describe "#update" do
|
437
|
+
before(:each) do
|
438
|
+
@test_hash = AttributeKit::AttributeHash.new
|
439
|
+
@test_hash[:blue] = 'blue'
|
440
|
+
@test_hash[:red] = 'red'
|
441
|
+
@test_hash[:green] = 'grn'
|
442
|
+
@test_hash.clean_attributes {}
|
443
|
+
@ret_val = @test_hash.update({:yellow => 'yellow', :green => 'green'})
|
444
|
+
end
|
445
|
+
|
446
|
+
it "should retain unupdated contents" do
|
447
|
+
@test_hash.blue_deleted?.should be_false
|
448
|
+
@test_hash.red_deleted?.should be_false
|
449
|
+
@test_hash[:blue].should == 'blue'
|
450
|
+
@test_hash[:red].should == 'red'
|
451
|
+
end
|
452
|
+
|
453
|
+
it "should add supplied hash's contents to object's contents" do
|
454
|
+
@test_hash[:yellow].should == 'yellow'
|
455
|
+
@test_hash[:green].should == 'green'
|
456
|
+
end
|
457
|
+
|
458
|
+
it "should mark new attributes as dirty" do
|
459
|
+
@test_hash.yellow_dirty?.should be_true
|
460
|
+
end
|
461
|
+
|
462
|
+
it "should mark changed attributes as dirty" do
|
463
|
+
@test_hash.green_dirty?.should be_true
|
464
|
+
end
|
465
|
+
|
466
|
+
it "should not include unupdated keys in dirty_keys" do
|
467
|
+
@test_hash.dirty_keys.include?(:blue).should be_false
|
468
|
+
@test_hash.dirty_keys.include?(:red).should be_false
|
469
|
+
end
|
470
|
+
|
471
|
+
it "should include new keys in dirty_keys" do
|
472
|
+
@test_hash.dirty_keys.include?(:yellow).should be_true
|
473
|
+
end
|
474
|
+
|
475
|
+
it "should include changed keys in dirty_keys" do
|
476
|
+
@test_hash.dirty_keys.include?(:green).should be_true
|
477
|
+
end
|
478
|
+
|
479
|
+
it "should not include unupdated keys in deleted_keys" do
|
480
|
+
@test_hash.deleted_keys.include?(:blue).should be_false
|
481
|
+
@test_hash.deleted_keys.include?(:red).should be_false
|
482
|
+
end
|
483
|
+
|
484
|
+
it "should not include new keys in deleted_keys" do
|
485
|
+
@test_hash.deleted_keys.include?(:yellow).should be_false
|
486
|
+
@test_hash.deleted_keys.include?(:green).should be_false
|
487
|
+
end
|
488
|
+
|
489
|
+
it "should mark instance as dirty" do
|
490
|
+
@test_hash.dirty?.should be_true
|
491
|
+
end
|
492
|
+
|
493
|
+
it "should return an AttributeHash containing the new contents" do
|
494
|
+
@ret_val.class.should == AttributeKit::AttributeHash
|
495
|
+
@ret_val.eql?({:blue => 'blue', :red => 'red', :yellow => 'yellow', :green => 'green'}).should be_true
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
describe "#shift" do
|
500
|
+
before(:each) do
|
501
|
+
@test_hash = AttributeKit::AttributeHash.new
|
502
|
+
@test_hash[:blue] = 'blue'
|
503
|
+
@test_hash[:red] = 'red'
|
504
|
+
@test_hash.clean_attributes {}
|
505
|
+
@ret = @test_hash.shift
|
506
|
+
end
|
507
|
+
|
508
|
+
it "should delete a key-value pair" do
|
509
|
+
if @ret[0] == :blue
|
510
|
+
@test_hash[:blue].should be_nil
|
511
|
+
else
|
512
|
+
@test_hash[:red].should be_nil
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
516
|
+
it "should return a key-value pair" do
|
517
|
+
@ret.class.should == Array
|
518
|
+
if @ret[0] == :blue
|
519
|
+
@ret[1].should == 'blue'
|
520
|
+
else
|
521
|
+
@ret[1].should == 'red'
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
it "should mark the attribute as deleted" do
|
526
|
+
if @ret[0] == :blue
|
527
|
+
@test_hash.blue_deleted?.should be_true
|
528
|
+
else
|
529
|
+
@test_hash.red_deleted?.should be_true
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
it "should mark the AttributeHash as dirty" do
|
534
|
+
@test_hash.dirty?.should be_true
|
535
|
+
end
|
536
|
+
|
537
|
+
it "should include the attribute in dirty_keys" do
|
538
|
+
if @ret[0] == :blue
|
539
|
+
@test_hash.dirty_keys.include?(:blue).should be_true
|
540
|
+
else
|
541
|
+
@test_hash.dirty_keys.include?(:red).should be_true
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
it "should include the attribute in deleted_keys" do
|
546
|
+
if @ret[0] == :blue
|
547
|
+
@test_hash.deleted_keys.include?(:blue).should be_true
|
548
|
+
else
|
549
|
+
@test_hash.deleted_keys.include?(:red).should be_true
|
550
|
+
end
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
describe "#clear" do
|
555
|
+
before(:each) do
|
556
|
+
@test_hash = AttributeKit::AttributeHash.new
|
557
|
+
@test_hash[:blue] = 'blue'
|
558
|
+
@test_hash[:red] = 'red'
|
559
|
+
@test_hash[:green] = 'grn'
|
560
|
+
@test_hash.clean_attributes {}
|
561
|
+
@test_hash[:green] = 'green'
|
562
|
+
@old_keys = @test_hash.keys
|
563
|
+
@test_hash.clear
|
564
|
+
end
|
565
|
+
|
566
|
+
it "should empty the hash" do
|
567
|
+
@test_hash.empty?.should be_true
|
568
|
+
end
|
569
|
+
|
570
|
+
it 'should list all former keys as deleted' do
|
571
|
+
@test_hash.deleted_keys.should == @old_keys
|
572
|
+
end
|
573
|
+
|
574
|
+
it 'should list all former keys (and only former keys) as dirty, with no duplicates' do
|
575
|
+
@test_hash.dirty_keys.should == @old_keys
|
576
|
+
end
|
577
|
+
|
578
|
+
it 'should respond with true when sent #<key>_deleted?' do
|
579
|
+
@test_hash.green_deleted?.should be_true
|
580
|
+
end
|
581
|
+
|
582
|
+
it 'should mark the object as dirty' do
|
583
|
+
@test_hash.dirty?.should be_true
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
describe '#clean_attributes' do
|
588
|
+
before(:each) do
|
589
|
+
@test_hash = AttributeKit::AttributeHash.new
|
590
|
+
@test_hash[:blue] = 'blue'
|
591
|
+
@test_hash[:red] = 'red'
|
592
|
+
@test_hash[:green] = 'grn'
|
593
|
+
@test_hash.clean_attributes {}
|
594
|
+
@test_hash[:green] = 'green'
|
595
|
+
@test_hash[:yellow] = 'yellow'
|
596
|
+
@test_hash.delete(:red)
|
597
|
+
@test_hash.clean_attributes { |change_hash| @change_hash = change_hash }
|
598
|
+
end
|
599
|
+
|
600
|
+
it "should unmark the hash as dirty" do
|
601
|
+
@test_hash.dirty?.should be_false
|
602
|
+
end
|
603
|
+
|
604
|
+
it "should unmark an attribute as dirty" do
|
605
|
+
@test_hash.blue_dirty.should be_false
|
606
|
+
end
|
607
|
+
|
608
|
+
it "should unmark an attribute as deleted" do
|
609
|
+
@test_hash.red_deleted?.should be_false
|
610
|
+
end
|
611
|
+
|
612
|
+
it 'should pass the block a hash of changed keys' do
|
613
|
+
@change_hash.class.should == Hash
|
614
|
+
end
|
615
|
+
|
616
|
+
it 'should contain deleted keys in the passed hash' do
|
617
|
+
@change_hash.has_key?(:red).should be_true
|
618
|
+
end
|
619
|
+
|
620
|
+
it 'should contain changed keys in the passed hash' do
|
621
|
+
@change_hash.has_key?(:green).should be_true
|
622
|
+
end
|
623
|
+
|
624
|
+
it 'should contain added keys in the passed hash' do
|
625
|
+
@change_hash.has_key?(:yellow).should be_true
|
626
|
+
end
|
627
|
+
|
628
|
+
it 'should not contain unchanged keys in the passed hash' do
|
629
|
+
@change_hash.has_key?(:bluw).should be_false
|
630
|
+
end
|
631
|
+
|
632
|
+
it 'should contain deleted keys in the passed hash with an Array containing :deleted and nil as the value' do
|
633
|
+
@change_hash[:red].eql?([:deleted, nil]).should be_true
|
634
|
+
end
|
635
|
+
|
636
|
+
it 'should contain changed keys in the passed hash with an Array containing :changed and the new value as the value' do
|
637
|
+
@change_hash[:green].eql?([:changed, 'green']).should be_true
|
638
|
+
end
|
639
|
+
|
640
|
+
it 'should contain added keys in the passed hash with an Array containing :changed and the new value as the value' do
|
641
|
+
@change_hash[:yellow].eql?([:changed, 'yellow']).should be_true
|
642
|
+
end
|
643
|
+
end
|
644
|
+
|
645
|
+
end
|
646
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'attribute-kit'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: attribute-kit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jonathan Mischo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-07-11 00:00:00 -07:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rspec
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.3.0
|
24
|
+
type: :development
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.0.0
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: jeweler
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.6.4
|
46
|
+
type: :development
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rcov
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: yard
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *id005
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: rdiscount
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: *id006
|
82
|
+
description: Tools for attribute tracking like Hashes with dirty tracking and events, for building hybrid models and generally going beyond what's provided by your local ORM/DRM, while allowing you to expand what you can do with them, live without them, or roll your own
|
83
|
+
email: jon.mischo@gmail.com
|
84
|
+
executables: []
|
85
|
+
|
86
|
+
extensions: []
|
87
|
+
|
88
|
+
extra_rdoc_files:
|
89
|
+
- LICENSE.txt
|
90
|
+
- README.markdown
|
91
|
+
files:
|
92
|
+
- Gemfile
|
93
|
+
- Gemfile.lock
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.markdown
|
96
|
+
- Rakefile
|
97
|
+
- VERSION
|
98
|
+
- lib/attribute-kit.rb
|
99
|
+
- lib/attribute-kit/attribute-kit.rb
|
100
|
+
- lib/attribute-kit/attribute_hash.rb
|
101
|
+
- spec/attribute-kit_spec.rb
|
102
|
+
- spec/spec_helper.rb
|
103
|
+
has_rdoc: true
|
104
|
+
homepage: http://github.com/supertaz/attribute-kit
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
hash: 3580658089229278680
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
version: "0"
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: "0"
|
127
|
+
requirements: []
|
128
|
+
|
129
|
+
rubyforge_project:
|
130
|
+
rubygems_version: 1.5.3
|
131
|
+
signing_key:
|
132
|
+
specification_version: 3
|
133
|
+
summary: Tools for attribute tracking like Hashes with dirty tracking and events, for building hybrid models and generally going beyond what's provided by your local ORM/DRM, while allowing you to expand what you can do with them, live without them, or roll your own
|
134
|
+
test_files: []
|
135
|
+
|