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 CHANGED
@@ -1,6 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  group :development do
4
+ gem 'yajl-ruby', '>= 0.8.2', :require => 'yajl/json_gem'
4
5
  gem "rspec", "~> 2.3.0"
5
6
  gem "bundler", "~> 1.0.0"
6
7
  gem "jeweler", "~> 1.6.4"
@@ -18,6 +18,7 @@ GEM
18
18
  rspec-expectations (2.3.0)
19
19
  diff-lcs (~> 1.1.2)
20
20
  rspec-mocks (2.3.0)
21
+ yajl-ruby (0.8.2)
21
22
  yard (0.7.2)
22
23
 
23
24
  PLATFORMS
@@ -29,4 +30,5 @@ DEPENDENCIES
29
30
  rcov
30
31
  rdiscount
31
32
  rspec (~> 2.3.0)
33
+ yajl-ruby (>= 0.8.2)
32
34
  yard
@@ -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.4
1
+ 0.2.0
@@ -1 +1,2 @@
1
1
  require 'attribute-kit/attribute_hash'
2
+ require 'attribute-kit/json_serializable_hash'
@@ -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
@@ -5,8 +5,12 @@ describe "AttributeKit" do
5
5
  defined?(AttributeKit).should == 'constant'
6
6
  end
7
7
 
8
- describe "::AttributeHash" do
9
- describe '#new' do
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
- describe '#[]=' do
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
- describe '#store' do
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
- describe '#[]' do
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
- describe '#delete' do
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
- describe '#delete_if' do
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
- describe '#keep_if' do
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
- describe '#reject!' do
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
- describe '#select!' do
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
- describe "#replace" do
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
- describe "#merge!" do
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
- describe "#update" do
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
- describe "#shift" do
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
- describe "#clear" do
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
- describe '#clean_attributes' do
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.1.4
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-15 00:00:00 -07:00
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: rspec
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: 2.3.0
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: bundler
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: 1.0.0
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: jeweler
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.6.4
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: rcov
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: "0"
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: yard
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: rdiscount
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: 464791598370222701
130
+ hash: -293996943625060104
118
131
  segments:
119
132
  - 0
120
133
  version: "0"