attribute-kit 0.1.4 → 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/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/README.markdown +94 -1
- data/VERSION +1 -1
- data/lib/attribute-kit/attribute-kit.rb +1 -0
- data/lib/attribute-kit/attribute_hash.rb +43 -1
- data/lib/attribute-kit/json_serializable_hash.rb +107 -0
- data/spec/AttributeKit/json_serializable_hash_spec.rb +98 -0
- data/spec/attribute-kit_spec.rb +20 -16
- metadata +28 -15
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.markdown
CHANGED
@@ -2,8 +2,101 @@
|
|
2
2
|
|
3
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
4
|
|
5
|
+
## Rationale
|
6
|
+
|
7
|
+
ORM and DRM frameworks implement many of the same concepts that this kit makes available, but they don't generally expose them
|
8
|
+
as smaller pieces of functionality that you can consume and mix in as you please. It is also difficult to get more ORMs to
|
9
|
+
'play nice' with columns that are really schemaless hashes, because they just aren't meant to handle such things. While DRMs
|
10
|
+
are generally designed to work with schemaless data, there are times when you need to have both behaviors.
|
11
|
+
|
12
|
+
The idea behind building AttributeKit was to make these concepts available in an ad-hoc format, so that classes could either
|
13
|
+
inherit or mix in the behaviors that they want and/or need, without the overhead of the pieces they don't want or need. This
|
14
|
+
all stemmed from a side project that had a need for exactly that...ORM/DRM-like behavior, without the extra weight of actually
|
15
|
+
using one of the ORMs or DRMs on the market and then extending them to handle both types of data, in two separate data stores.
|
16
|
+
|
17
|
+
## Basic usage
|
18
|
+
|
19
|
+
attributes = AttributeKit::AttributeHash.new #=> {}
|
20
|
+
|
21
|
+
attributes.empty? #=> true
|
22
|
+
attributes.dirty? #=> false
|
23
|
+
attributes[:foo] = 'bar' #=> 'bar'
|
24
|
+
attributes.dirty? #=> true
|
25
|
+
attributes.dirty_keys #=> [:foo]
|
26
|
+
attributes #=> {:foo=>"bar"}
|
27
|
+
|
28
|
+
attributes[:bar] = 5 #=> 5
|
29
|
+
attributes #=> {:foo=>"bar", :bar=>5}
|
30
|
+
attributes.dirty_keys #=> [:foo, :bar]
|
31
|
+
attributes.deleted_keys #=> []
|
32
|
+
|
33
|
+
attributes.delete(:foo) #=> "bar"
|
34
|
+
attributes.dirty_keys #=> [:bar, :foo]
|
35
|
+
attributes.deleted_keys #=> [:foo]
|
36
|
+
|
37
|
+
attributes.clean_attributes { |dirty_attrs| # Deleted: foo Nil value: true
|
38
|
+
dirty_attrs.each_pair do |k,v| # Changed: bar New value: 5
|
39
|
+
case v[0]
|
40
|
+
when :changed #=> {:foo=>[:deleted, nil], :bar=>[:changed, 5]}
|
41
|
+
puts "Changed: #{k} New value: #{v[1]}"
|
42
|
+
when :deleted # NOTE: The lack of a return value in this block
|
43
|
+
puts "Deleted: #{k} Nil value: #{v[1].nil?}" # means that dirty_attrs was returned by both
|
44
|
+
end # the block and the method itself. You may
|
45
|
+
end # want to write a block to return true if it
|
46
|
+
} # succeeds, and the dirty_attrs hash if it
|
47
|
+
# fails, so you can pass the hash to a
|
48
|
+
# method that can retry later.
|
49
|
+
|
50
|
+
## Serializing and deserializing a Hash with JSON
|
51
|
+
|
52
|
+
class JHash < Hash
|
53
|
+
include AttributeKit::JSONSerializableHash
|
54
|
+
end
|
55
|
+
|
56
|
+
attr_hash = JHash.new #=> {}
|
57
|
+
attr_hash[:foo] = 'bar' #=> 'bar'
|
58
|
+
attr_hash[:bar] = 5 #=> 5
|
59
|
+
attr_hash #=> {:foo=>"bar", :bar=>5}
|
60
|
+
|
61
|
+
j = attr_hash.to_json #=> "{\"foo\":\"bar\",\"bar\":5}"
|
62
|
+
new_hash = JHash.new #=> {}
|
63
|
+
new_hash.from_json(j) #=> {:foo=>"bar", :bar=>5}
|
64
|
+
new_hash #=> {:foo=>"bar", :bar=>5}
|
65
|
+
new_hash.clear #=> {}
|
66
|
+
|
67
|
+
f = attr_hash.get_json(:foo) #=> "{\"foo\":\"bar\"}"
|
68
|
+
new_hash[:bar] = 5 #=> 5
|
69
|
+
new_hash.store_json(f) #=> {:bar=>5, :foo=>"bar"}
|
70
|
+
new_hash #=> {:bar=>5, :foo=>"bar"}
|
71
|
+
|
72
|
+
## Serializing and deserializing an AttributeHash with JSON
|
73
|
+
|
74
|
+
class MyHash < AttributeKit::AttributeHash
|
75
|
+
include AttributeKit::JSONSerializableHash
|
76
|
+
end
|
77
|
+
|
78
|
+
attr_hash = MyHash.new #=> {}
|
79
|
+
attr_hash.empty? #=> true
|
80
|
+
attr_hash.dirty? #=> false
|
81
|
+
attr_hash[:foo] = 'bar' #=> 'bar'
|
82
|
+
attr_hash.dirty? #=> true
|
83
|
+
attr_hash.dirty_keys #=> [:foo]
|
84
|
+
attr_hash[:bar] = 5 #=> 5
|
85
|
+
attr_hash #=> {:foo=>"bar", :bar=>5}
|
86
|
+
|
87
|
+
j = attr_hash.to_json #=> "{\"foo\":\"bar\",\"bar\":5}"
|
88
|
+
new_hash = MyHash.new #=> {}
|
89
|
+
new_hash.from_json(j) #=> {:foo=>"bar", :bar=>5}
|
90
|
+
new_hash #=> {:foo=>"bar", :bar=>5}
|
91
|
+
new_hash.clear #=> {}
|
92
|
+
|
93
|
+
f = attr_hash.get_json(:foo) #=> "{\"foo\":\"bar\"}"
|
94
|
+
new_hash[:bar] = 5 #=> 5
|
95
|
+
new_hash.store_json(f) #=> {:bar=>5, :foo=>"bar"}
|
96
|
+
new_hash #=> {:bar=>5, :foo=>"bar"}
|
97
|
+
|
5
98
|
## Contributing to attribute-kit
|
6
|
-
|
99
|
+
|
7
100
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
101
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
102
|
* Fork the project
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -13,6 +13,39 @@
|
|
13
13
|
module AttributeKit
|
14
14
|
|
15
15
|
# AttributeHash inherits from and extends Hash, to provide tracking of attribute status (changed/deleted keys).
|
16
|
+
#
|
17
|
+
# @example Basic usage
|
18
|
+
# attributes = AttributeKit::AttributeHash.new #=> {}
|
19
|
+
#
|
20
|
+
# attributes.empty? #=> true
|
21
|
+
# attributes.dirty? #=> false
|
22
|
+
# attributes[:foo] = 'bar' #=> 'bar'
|
23
|
+
# attributes.dirty? #=> true
|
24
|
+
# attributes.dirty_keys #=> [:foo]
|
25
|
+
# attributes #=> {:foo=>"bar"}
|
26
|
+
#
|
27
|
+
# attributes[:bar] = 5 #=> 5
|
28
|
+
# attributes #=> {:foo=>"bar", :bar=>5}
|
29
|
+
# attributes.dirty_keys #=> [:foo, :bar]
|
30
|
+
# attributes.deleted_keys #=> []
|
31
|
+
#
|
32
|
+
# attributes.delete(:foo) #=> "bar"
|
33
|
+
# attributes.dirty_keys #=> [:bar, :foo]
|
34
|
+
# attributes.deleted_keys #=> [:foo]
|
35
|
+
#
|
36
|
+
# attributes.clean_attributes { |dirty_attrs| # Deleted: foo Nil value: true
|
37
|
+
# dirty_attrs.each_pair do |k,v| # Changed: bar New value: 5
|
38
|
+
# case v[0]
|
39
|
+
# when :changed #=> {:foo=>[:deleted, nil], :bar=>[:changed, 5]}
|
40
|
+
# puts "Changed: #{k} New value: #{v[1]}"
|
41
|
+
# when :deleted # NOTE: The lack of a return value in this block
|
42
|
+
# puts "Deleted: #{k} Nil value: #{v[1].nil?}" # means that dirty_attrs was returned by both
|
43
|
+
# end # the block and the method itself. You may
|
44
|
+
# end # want to write a block to return true if it
|
45
|
+
# } # succeeds, and the dirty_attrs hash if it
|
46
|
+
# # fails, so you can pass the hash to a
|
47
|
+
# # method that can retry later.
|
48
|
+
#
|
16
49
|
class AttributeHash < Hash
|
17
50
|
|
18
51
|
# @visibility private
|
@@ -32,6 +65,7 @@ module AttributeKit
|
|
32
65
|
private_class_method :cond_deletion_method
|
33
66
|
|
34
67
|
# Creates a new instance, using identical syntax to Hash
|
68
|
+
# @return [AttributeHash] new instance
|
35
69
|
# @see Hash#new
|
36
70
|
def initialize(*args)
|
37
71
|
super(*args)
|
@@ -155,7 +189,8 @@ module AttributeKit
|
|
155
189
|
[k,v]
|
156
190
|
end
|
157
191
|
|
158
|
-
# Clear all contents of the object.
|
192
|
+
# Clear all contents of the object and mark it as dirty. An array of all removed keys is available via #deleted_keys.
|
193
|
+
# @return [AttributeHash] an empty AttributeHash
|
159
194
|
# @see Hash#clear
|
160
195
|
def clear
|
161
196
|
@deleted_keys += self.keys
|
@@ -187,6 +222,13 @@ module AttributeKit
|
|
187
222
|
# that have changed since the object was last marked clean. Marks the object as clean when it compiles
|
188
223
|
# the list of keys that have been modified.
|
189
224
|
# @param [Block] block to execute with hash of modified keys, actions, and values
|
225
|
+
# @yield [dirty_attrs] block is executed once, with a hash of dirty attributes
|
226
|
+
# @yieldparam [Hash] dirty_attrs the hash of changed/deleted attributes with the modified key as the key and a value
|
227
|
+
# of an array in the format: [ACTION, VALUE] where ACTION is either :changed or :deleted, and VALUE is either the
|
228
|
+
# new value or nil if the attribute is deleted. A nil value does NOT mean the attribute is deleted if the ACTION
|
229
|
+
# is :changed, it means the value was actually set to nil
|
230
|
+
# @yieldreturn [Object] any value the block returns bubbles up, otherwise
|
231
|
+
# @return [Object] the return value of the block is returned
|
190
232
|
def clean_attributes(&block)
|
191
233
|
if !@dirty_keys.empty?
|
192
234
|
dirty_attrs = {}
|
@@ -0,0 +1,107 @@
|
|
1
|
+
begin
|
2
|
+
require 'yajl/json_gem'
|
3
|
+
rescue LoadError
|
4
|
+
begin
|
5
|
+
require 'json'
|
6
|
+
rescue LoadError
|
7
|
+
require 'json_pure'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module AttributeKit
|
12
|
+
|
13
|
+
# JSONSerializableHash adds a set of methods to manage serialization and deserialization of hashes and Hash decendants
|
14
|
+
# in a consistent manner. By default, the methods symbolize the keys when they are deserialized, which greatly
|
15
|
+
# improves performance and also provides consistency in how keys appear both in JSON and in the hash.
|
16
|
+
#
|
17
|
+
# @example Serializing and deserializing a Hash with JSON
|
18
|
+
#
|
19
|
+
# class JHash < Hash
|
20
|
+
# include AttributeKit::JSONSerializableHash
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# attr_hash = JHash.new #=> {}
|
24
|
+
# attr_hash[:foo] = 'bar' #=> 'bar'
|
25
|
+
# attr_hash[:bar] = 5 #=> 5
|
26
|
+
# attr_hash #=> {:foo=>"bar", :bar=>5}
|
27
|
+
#
|
28
|
+
# j = attr_hash.to_json #=> "{\"foo\":\"bar\",\"bar\":5}"
|
29
|
+
# new_hash = JHash.new #=> {}
|
30
|
+
# new_hash.from_json(j) #=> {:foo=>"bar", :bar=>5}
|
31
|
+
# new_hash #=> {:foo=>"bar", :bar=>5}
|
32
|
+
# new_hash.clear #=> {}
|
33
|
+
#
|
34
|
+
# f = attr_hash.get_json(:foo) #=> "{\"foo\":\"bar\"}"
|
35
|
+
# new_hash[:bar] = 5 #=> 5
|
36
|
+
# new_hash.store_json(f) #=> {:bar=>5, :foo=>"bar"}
|
37
|
+
# new_hash #=> {:bar=>5, :foo=>"bar"}
|
38
|
+
#
|
39
|
+
#
|
40
|
+
# @example Serializing and deserializing an AttributeHash with JSON
|
41
|
+
#
|
42
|
+
# class MyHash < AttributeKit::AttributeHash
|
43
|
+
# include AttributeKit::JSONSerializableHash
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# attr_hash = MyHash.new #=> {}
|
47
|
+
# attr_hash.empty? #=> true
|
48
|
+
# attr_hash.dirty? #=> false
|
49
|
+
# attr_hash[:foo] = 'bar' #=> 'bar'
|
50
|
+
# attr_hash.dirty? #=> true
|
51
|
+
# attr_hash.dirty_keys #=> [:foo]
|
52
|
+
# attr_hash[:bar] = 5 #=> 5
|
53
|
+
# attr_hash #=> {:foo=>"bar", :bar=>5}
|
54
|
+
#
|
55
|
+
# j = attr_hash.to_json #=> "{\"foo\":\"bar\",\"bar\":5}"
|
56
|
+
# new_hash = MyHash.new #=> {}
|
57
|
+
# new_hash.from_json(j) #=> {:foo=>"bar", :bar=>5}
|
58
|
+
# new_hash #=> {:foo=>"bar", :bar=>5}
|
59
|
+
# new_hash.clear #=> {}
|
60
|
+
#
|
61
|
+
# f = attr_hash.get_json(:foo) #=> "{\"foo\":\"bar\"}"
|
62
|
+
# new_hash[:bar] = 5 #=> 5
|
63
|
+
# new_hash.store_json(f) #=> {:bar=>5, :foo=>"bar"}
|
64
|
+
# new_hash #=> {:bar=>5, :foo=>"bar"}
|
65
|
+
#
|
66
|
+
module JSONSerializableHash
|
67
|
+
|
68
|
+
# Serializes the entire hash contents into a JSON string.
|
69
|
+
# @param [Hash] opts A hash of options to be passed to the JSON generator, empty by default
|
70
|
+
# @return [String] A JSON encoded string describing the contents of the hash
|
71
|
+
def to_json(opts = {})
|
72
|
+
JSON.generate(self, opts)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Deserializes hash contents from a JSON string, replacing the contents of the hash if they already exist
|
76
|
+
# @param [String] json A JSON formatted string to be parsed and assigned as the contents of the hash
|
77
|
+
# @param [Hash] opts A hash of options to be passed to the JSON generator, :symbolize_keys => true is set by default
|
78
|
+
# @return [Hash] The new contents of the hash
|
79
|
+
def from_json(json, opts = {})
|
80
|
+
defaults = {
|
81
|
+
:symbolize_keys => true
|
82
|
+
}
|
83
|
+
opts.merge!(defaults){ |key, param, default| param }
|
84
|
+
self.replace(JSON.parse(json, opts))
|
85
|
+
end
|
86
|
+
|
87
|
+
# Serializes a single key-value pair from the hash contents into a JSON string.
|
88
|
+
# @param [Symbol] key The key for the key-value pair to retrieve and encode
|
89
|
+
# @param [Hash] opts A hash of options to be passed to the JSON generator, empty by default
|
90
|
+
# @return [String] A JSON encoded string describing the key-value pair
|
91
|
+
def get_json(key, opts = {})
|
92
|
+
JSON.generate({key => self[key]}, opts)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Deserializes hash contents from a JSON string, merging the contents with any contents of the hash that already exist
|
96
|
+
# @param [String] json A JSON formatted string to be parsed and update the contents of the hash with
|
97
|
+
# @param [Hash] opts A hash of options to be passed to the JSON generator, :symbolize_keys => true is set by default
|
98
|
+
# @return [Hash] The new contents of the hash
|
99
|
+
def store_json(json, opts = {})
|
100
|
+
defaults = {
|
101
|
+
:symbolize_keys => true
|
102
|
+
}
|
103
|
+
opts.merge!(defaults){ |key, param, default| param }
|
104
|
+
self.update(JSON.parse(json, opts))
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
class JSONSerializableHashTestHash < Hash
|
4
|
+
include AttributeKit::JSONSerializableHash
|
5
|
+
end
|
6
|
+
|
7
|
+
describe "AttributeKit" do
|
8
|
+
context '::JSONSerializableHash' do
|
9
|
+
it 'should load' do
|
10
|
+
defined?(AttributeKit::JSONSerializableHash).should == 'constant'
|
11
|
+
end
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
@hash = JSONSerializableHashTestHash.new
|
15
|
+
@hash[:a] = 'a'
|
16
|
+
@hash[:b] = 2
|
17
|
+
@hash[:c] = nil
|
18
|
+
@hash[:float] = 3.14
|
19
|
+
@hash[:integer] = 5.to_i
|
20
|
+
end
|
21
|
+
|
22
|
+
context '#to_json' do
|
23
|
+
it 'should serialize the contents of the hash to JSON' do
|
24
|
+
json = @hash.to_json
|
25
|
+
json.should == '{"a":"a","b":2,"c":null,"float":3.14,"integer":5}'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context '#from_json' do
|
30
|
+
before(:each) do
|
31
|
+
@new_hash = JSONSerializableHashTestHash.new
|
32
|
+
@new_hash.from_json('{"a":"a","b":2,"c":null,"float":3.14,"integer":5}')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should use symbols for the keys instead of strings or other objects' do
|
36
|
+
@new_hash.has_key?(:a).should be_true
|
37
|
+
@new_hash.has_key?('a').should be_false
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should deserialize JSON into the correct contents of the hash' do
|
41
|
+
@new_hash.length.should == 5
|
42
|
+
@new_hash[:a].should == 'a'
|
43
|
+
@new_hash[:b].should == 2
|
44
|
+
@new_hash[:c].should be_nil
|
45
|
+
@new_hash[:float].should == 3.14
|
46
|
+
@new_hash[:integer].should == 5
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context '#get_json' do
|
51
|
+
it 'should retrieve a key-value pair with a String value and JSON encode it' do
|
52
|
+
json = @hash.get_json(:a)
|
53
|
+
json.should == '{"a":"a"}'
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should retrieve a key-value pair with a Fixnum value and JSON encode it' do
|
57
|
+
json = @hash.get_json(:b)
|
58
|
+
json.should == '{"b":2}'
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should retrieve a key-value pair with a Nil value and JSON encode it' do
|
62
|
+
json = @hash.get_json(:c)
|
63
|
+
json.should == '{"c":null}'
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should retrieve a key-value pair with a Float value and JSON encode it' do
|
67
|
+
json = @hash.get_json(:float)
|
68
|
+
json.should == '{"float":3.14}'
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should retrieve a key-value pair with an Integer value and JSON encode it' do
|
72
|
+
json = @hash.get_json(:integer)
|
73
|
+
json.should == '{"integer":5}'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context '#store_json' do
|
78
|
+
before(:each) do
|
79
|
+
@new_hash = JSONSerializableHashTestHash.new
|
80
|
+
@new_hash.store_json('{"a":"a"}')
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should use symbols for the keys instead of strings or other objects' do
|
84
|
+
@new_hash.has_key?(:a).should be_true
|
85
|
+
@new_hash.has_key?('a').should be_false
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should parse the provided JSON and store it as a key-value pair' do
|
89
|
+
@new_hash[:a].should == 'a'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should parse the provided JSON and replace an existing key-value pair' do
|
93
|
+
@new_hash.store_json('{"a":"b"}')
|
94
|
+
@new_hash[:a].should == 'b'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/spec/attribute-kit_spec.rb
CHANGED
@@ -5,8 +5,12 @@ describe "AttributeKit" do
|
|
5
5
|
defined?(AttributeKit).should == 'constant'
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
context "::AttributeHash" do
|
9
|
+
it 'loads' do
|
10
|
+
defined?(AttributeKit::AttributeHash).should == 'constant'
|
11
|
+
end
|
12
|
+
|
13
|
+
context '#new' do
|
10
14
|
it "should return an empty AttributeHash when initialized without arguments" do
|
11
15
|
test_hash = AttributeKit::AttributeHash.new
|
12
16
|
test_hash.empty?.should be_true
|
@@ -32,7 +36,7 @@ describe "AttributeKit" do
|
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
35
|
-
|
39
|
+
context '#[]=' do
|
36
40
|
before(:each) do
|
37
41
|
@test_hash = AttributeKit::AttributeHash.new
|
38
42
|
@test_hash[:blue] = 'blue'
|
@@ -61,7 +65,7 @@ describe "AttributeKit" do
|
|
61
65
|
end
|
62
66
|
end
|
63
67
|
|
64
|
-
|
68
|
+
context '#store' do
|
65
69
|
before(:each) do
|
66
70
|
@test_hash = AttributeKit::AttributeHash.new
|
67
71
|
@test_hash.store(:blue, 'blue')
|
@@ -86,7 +90,7 @@ describe "AttributeKit" do
|
|
86
90
|
end
|
87
91
|
end
|
88
92
|
|
89
|
-
|
93
|
+
context '#[]' do
|
90
94
|
before(:each) do
|
91
95
|
@test_hash = AttributeKit::AttributeHash.new('red')
|
92
96
|
@test_hash[:blue] = 'blue'
|
@@ -103,7 +107,7 @@ describe "AttributeKit" do
|
|
103
107
|
end
|
104
108
|
end
|
105
109
|
|
106
|
-
|
110
|
+
context '#delete' do
|
107
111
|
before(:each) do
|
108
112
|
@test_hash = AttributeKit::AttributeHash.new
|
109
113
|
@test_hash[:blue] = 'blue'
|
@@ -133,7 +137,7 @@ describe "AttributeKit" do
|
|
133
137
|
end
|
134
138
|
end
|
135
139
|
|
136
|
-
|
140
|
+
context '#delete_if' do
|
137
141
|
before(:each) do
|
138
142
|
@test_hash = AttributeKit::AttributeHash.new
|
139
143
|
@test_hash[:blue] = 'blue'
|
@@ -176,7 +180,7 @@ describe "AttributeKit" do
|
|
176
180
|
end
|
177
181
|
end
|
178
182
|
|
179
|
-
|
183
|
+
context '#keep_if' do
|
180
184
|
before(:each) do
|
181
185
|
@test_hash = AttributeKit::AttributeHash.new
|
182
186
|
@test_hash[:blue] = 'blue'
|
@@ -219,7 +223,7 @@ describe "AttributeKit" do
|
|
219
223
|
end
|
220
224
|
end
|
221
225
|
|
222
|
-
|
226
|
+
context '#reject!' do
|
223
227
|
before(:each) do
|
224
228
|
@test_hash = AttributeKit::AttributeHash.new
|
225
229
|
@test_hash[:blue] = 'blue'
|
@@ -270,7 +274,7 @@ describe "AttributeKit" do
|
|
270
274
|
end
|
271
275
|
end
|
272
276
|
|
273
|
-
|
277
|
+
context '#select!' do
|
274
278
|
before(:each) do
|
275
279
|
@test_hash = AttributeKit::AttributeHash.new
|
276
280
|
@test_hash[:blue] = 'blue'
|
@@ -321,7 +325,7 @@ describe "AttributeKit" do
|
|
321
325
|
end
|
322
326
|
end
|
323
327
|
|
324
|
-
|
328
|
+
context "#replace" do
|
325
329
|
before(:each) do
|
326
330
|
@test_hash = AttributeKit::AttributeHash.new
|
327
331
|
@test_hash[:blue] = 'blue'
|
@@ -370,7 +374,7 @@ describe "AttributeKit" do
|
|
370
374
|
end
|
371
375
|
end
|
372
376
|
|
373
|
-
|
377
|
+
context "#merge!" do
|
374
378
|
before(:each) do
|
375
379
|
@test_hash = AttributeKit::AttributeHash.new
|
376
380
|
@test_hash[:blue] = 'blue'
|
@@ -433,7 +437,7 @@ describe "AttributeKit" do
|
|
433
437
|
end
|
434
438
|
end
|
435
439
|
|
436
|
-
|
440
|
+
context "#update" do
|
437
441
|
before(:each) do
|
438
442
|
@test_hash = AttributeKit::AttributeHash.new
|
439
443
|
@test_hash[:blue] = 'blue'
|
@@ -496,7 +500,7 @@ describe "AttributeKit" do
|
|
496
500
|
end
|
497
501
|
end
|
498
502
|
|
499
|
-
|
503
|
+
context "#shift" do
|
500
504
|
before(:each) do
|
501
505
|
@test_hash = AttributeKit::AttributeHash.new
|
502
506
|
@test_hash[:blue] = 'blue'
|
@@ -551,7 +555,7 @@ describe "AttributeKit" do
|
|
551
555
|
end
|
552
556
|
end
|
553
557
|
|
554
|
-
|
558
|
+
context "#clear" do
|
555
559
|
before(:each) do
|
556
560
|
@test_hash = AttributeKit::AttributeHash.new
|
557
561
|
@test_hash[:blue] = 'blue'
|
@@ -584,7 +588,7 @@ describe "AttributeKit" do
|
|
584
588
|
end
|
585
589
|
end
|
586
590
|
|
587
|
-
|
591
|
+
context '#clean_attributes' do
|
588
592
|
before(:each) do
|
589
593
|
@test_hash = AttributeKit::AttributeHash.new
|
590
594
|
@test_hash[:blue] = 'blue'
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: attribute-kit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jonathan Mischo
|
@@ -10,55 +10,55 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-07-
|
13
|
+
date: 2011-07-16 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
|
-
name:
|
17
|
+
name: yajl-ruby
|
18
18
|
requirement: &id001 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
|
-
- -
|
21
|
+
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version:
|
23
|
+
version: 0.8.2
|
24
24
|
type: :development
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: *id001
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: rspec
|
29
29
|
requirement: &id002 !ruby/object:Gem::Requirement
|
30
30
|
none: false
|
31
31
|
requirements:
|
32
32
|
- - ~>
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
34
|
+
version: 2.3.0
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: *id002
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
|
-
name:
|
39
|
+
name: bundler
|
40
40
|
requirement: &id003 !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.
|
45
|
+
version: 1.0.0
|
46
46
|
type: :development
|
47
47
|
prerelease: false
|
48
48
|
version_requirements: *id003
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
|
-
name:
|
50
|
+
name: jeweler
|
51
51
|
requirement: &id004 !ruby/object:Gem::Requirement
|
52
52
|
none: false
|
53
53
|
requirements:
|
54
|
-
- -
|
54
|
+
- - ~>
|
55
55
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
56
|
+
version: 1.6.4
|
57
57
|
type: :development
|
58
58
|
prerelease: false
|
59
59
|
version_requirements: *id004
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
|
-
name:
|
61
|
+
name: rcov
|
62
62
|
requirement: &id005 !ruby/object:Gem::Requirement
|
63
63
|
none: false
|
64
64
|
requirements:
|
@@ -69,7 +69,7 @@ dependencies:
|
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: *id005
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
|
-
name:
|
72
|
+
name: yard
|
73
73
|
requirement: &id006 !ruby/object:Gem::Requirement
|
74
74
|
none: false
|
75
75
|
requirements:
|
@@ -79,6 +79,17 @@ dependencies:
|
|
79
79
|
type: :development
|
80
80
|
prerelease: false
|
81
81
|
version_requirements: *id006
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: rdiscount
|
84
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: "0"
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: *id007
|
82
93
|
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
94
|
email: jon.mischo@gmail.com
|
84
95
|
executables: []
|
@@ -98,6 +109,8 @@ files:
|
|
98
109
|
- lib/attribute-kit.rb
|
99
110
|
- lib/attribute-kit/attribute-kit.rb
|
100
111
|
- lib/attribute-kit/attribute_hash.rb
|
112
|
+
- lib/attribute-kit/json_serializable_hash.rb
|
113
|
+
- spec/AttributeKit/json_serializable_hash_spec.rb
|
101
114
|
- spec/attribute-kit_spec.rb
|
102
115
|
- spec/spec_helper.rb
|
103
116
|
has_rdoc: true
|
@@ -114,7 +127,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
114
127
|
requirements:
|
115
128
|
- - ">="
|
116
129
|
- !ruby/object:Gem::Version
|
117
|
-
hash:
|
130
|
+
hash: -293996943625060104
|
118
131
|
segments:
|
119
132
|
- 0
|
120
133
|
version: "0"
|