activerecord-typedstore 0.3.2 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8790af5ac7b68a121e6d5cd21305421b49b5799c
4
- data.tar.gz: 0afe8bfce070b6f1d87f5c3f39334870ce9decc2
3
+ metadata.gz: 960e7c0f770dab59201ece58bcfa91927216eeea
4
+ data.tar.gz: 5a9f38f6153167050d7e5a57bfcba6fb717dd9e6
5
5
  SHA512:
6
- metadata.gz: 10d34e86b936c3c9d1f85dd35c6d2414f18c0c4346784f39ce9e4e741c02b23a8657fed819b8ed39a63c9ffb5d36b8b78b559dd2a877e1be64352a5e3b9b9cc8
7
- data.tar.gz: d9954012cc7fbec9501a19b7b10e8091c9d3447fc7413cbd09023d822e75f7a00ee505c3712720bac1b8de8d47d6a9ad8b4f5c7f1ca6265a09b454f0328c1621
6
+ metadata.gz: 363573dd39996321d853554cc49c1712966a515e8260bfaa9e6b6bf2763b8d5600b516e76559eff1e480c4527f43f472e403573b9a44b5b986307550345a3455
7
+ data.tar.gz: 2b7945d7a87685f0178cca67c84eb662feb21cafe2d944a4883265917508dacf70f75bb1cffef473338dd870c5f44c3069f2f16f2cc4cf3c34c0e66ce077707f
data/.travis.yml CHANGED
@@ -4,6 +4,7 @@ rvm:
4
4
  gemfile:
5
5
  - gemfiles/Gemfile.ar-3.2
6
6
  - gemfiles/Gemfile.ar-4.0
7
+ - gemfiles/Gemfile.ar-4.1
7
8
  - gemfiles/Gemfile.ar-edge
8
9
 
9
10
  before_script:
@@ -12,3 +13,7 @@ before_script:
12
13
  env:
13
14
  - TIMEZONE_AWARE=1 POSTGRES=1 MYSQL=1 POSTGRES_URL=$(curl http://api.postgression.com)
14
15
  - TIMEZONE_AWARE=0 POSTGRES=1 MYSQL=1 POSTGRES_URL=$(curl http://api.postgression.com)
16
+
17
+ matrix:
18
+ allow_failures:
19
+ - gemfile: gemfiles/Gemfile.ar-edge
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![Build Status](https://secure.travis-ci.org/byroot/activerecord-typedstore.png)](http://travis-ci.org/byroot/activerecord-typedstore)
4
4
  [![Code Climate](https://codeclimate.com/github/byroot/activerecord-typedstore.png)](https://codeclimate.com/github/byroot/activerecord-typedstore)
5
5
  [![Coverage Status](https://coveralls.io/repos/byroot/activerecord-typedstore/badge.png)](https://coveralls.io/r/byroot/activerecord-typedstore)
6
+ [![Gem Version](https://badge.fury.io/rb/activerecord-typedstore.png)](http://badge.fury.io/rb/activerecord-typedstore)
6
7
 
7
8
  [ActiveRecord::Store](http://api.rubyonrails.org/classes/ActiveRecord/Store.html) but with typed attributes.
8
9
 
@@ -78,6 +79,19 @@ shop.save
78
79
  shop.reload
79
80
  shop.settings[:unknown] # => 'Hello World'
80
81
 
82
+ # If you only want type casting and default handling without accessors
83
+
84
+ # you can disable them store wide
85
+ typed_store :settings, accessors: false do |s|
86
+ # ...
87
+ end
88
+
89
+ # or on a per attribute basis
90
+ typed_store :settings do |s|
91
+ s.integer :age
92
+ s.string :postal_code, accessor: false
93
+ end
94
+
81
95
  ```
82
96
 
83
97
  Type casting rules and attribute behavior are exactly the same as a for real database columns.
@@ -92,8 +106,3 @@ If not, please fill an issue.
92
106
  3. Commit your changes (`git commit -am 'Add some feature'`)
93
107
  4. Push to the branch (`git push origin my-new-feature`)
94
108
  5. Create new Pull Request
95
-
96
- ## TODO
97
-
98
- - HStore support with ActiveRecord 4.1.0.beta (master)
99
- - Handle casting and default at the store layer, so accessors are not mandatory anymore. See #4
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 4.1.0.beta1'
4
+ gem 'bundler', '~> 1.3'
5
+ gem 'rake'
6
+ gem 'rspec'
7
+ gem 'sqlite3'
8
+ gem 'pg', '~> 0.11'
9
+ gem 'mysql2'
10
+ gem 'database_cleaner'
11
+ gem 'coveralls', require: false
12
+ gem 'debugger'
@@ -1,3 +1,24 @@
1
+ class ActiveRecord::Store::IndifferentCoder
2
+ # Backport from rails 4.0
3
+ def initialize(coder_or_class_name)
4
+ @coder =
5
+ if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
6
+ coder_or_class_name
7
+ else
8
+ ActiveRecord::Coders::YAMLColumn.new(coder_or_class_name || Object)
9
+ end
10
+ end
11
+
12
+ def dump(obj)
13
+ @coder.dump self.class.as_indifferent_hash(obj)
14
+ end
15
+
16
+ def load(yaml)
17
+ self.class.as_indifferent_hash @coder.load(yaml)
18
+ end
19
+
20
+ end
21
+
1
22
  module ActiveRecord::TypedStore
2
23
 
3
24
  module AR32Fallbacks
@@ -11,7 +32,7 @@ module ActiveRecord::TypedStore
11
32
  module ClassMethods
12
33
 
13
34
  def typed_store(store_attribute, dsl)
14
- _ar_32_fallback_accessors(store_attribute, dsl.column_names)
35
+ _ar_32_fallback_accessors(store_attribute, dsl.accessors)
15
36
  end
16
37
 
17
38
  protected
@@ -34,9 +55,9 @@ module ActiveRecord::TypedStore
34
55
  attribute_method_matchers_cache.clear
35
56
  end
36
57
 
37
- def _ar_32_fallback_accessors(store_attribute, column_names)
38
- column_names.each do |name|
39
- _ar_32_fallback_accessor(store_attribute, name)
58
+ def _ar_32_fallback_accessors(store_attribute, accessors)
59
+ accessors.each do |accessor|
60
+ _ar_32_fallback_accessor(store_attribute, accessor)
40
61
  end
41
62
  end
42
63
 
@@ -0,0 +1,22 @@
1
+ module ActiveRecord::TypedStore
2
+
3
+ class Coder < ::ActiveRecord::Store::IndifferentCoder
4
+
5
+ class << self
6
+
7
+ def create(store_class)
8
+ Class.new(self) do
9
+ @store_class = store_class
10
+ end
11
+ end
12
+
13
+ def as_indifferent_hash(obj)
14
+ return obj if obj.is_a?(@store_class)
15
+ @store_class.new(obj)
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -10,6 +10,11 @@ module ActiveRecord::TypedStore
10
10
  @default = extract_default(options.fetch(:default, nil))
11
11
  @null = options.fetch(:null, true)
12
12
  @blank = options.fetch(:blank, true)
13
+ @accessor = options.fetch(:accessor, true)
14
+ end
15
+
16
+ def accessor?
17
+ @accessor
13
18
  end
14
19
 
15
20
  def cast(value)
@@ -4,18 +4,19 @@ module ActiveRecord::TypedStore
4
4
 
5
5
  attr_reader :columns
6
6
 
7
- def initialize
7
+ def initialize(accessors=true)
8
+ @accessors = accessors
8
9
  @columns = []
9
10
  yield self
10
11
  end
11
12
 
12
- def column_names
13
- @columns.map(&:name)
13
+ def accessors
14
+ @columns.select(&:accessor?).map(&:name)
14
15
  end
15
16
 
16
17
  [:string, :integer, :float, :decimal, :datetime, :date, :boolean, :any].each do |type|
17
18
  define_method(type) do |name, options={}|
18
- @columns << Column.new(name, type, options)
19
+ @columns << Column.new(name, type, options.reverse_merge(accessor: @accessors))
19
20
  end
20
21
  end
21
22
 
@@ -1,5 +1,6 @@
1
1
  require 'active_record/typed_store/column'
2
2
  require 'active_record/typed_store/dsl'
3
+ require 'active_record/typed_store/typed_hash'
3
4
 
4
5
  module ActiveRecord::TypedStore
5
6
  AR_VERSION = Gem::Version.new(ActiveRecord::VERSION::STRING)
@@ -17,18 +18,15 @@ module ActiveRecord::TypedStore
17
18
  module ClassMethods
18
19
 
19
20
  def typed_store(store_attribute, options={}, &block)
20
- dsl = DSL.new(&block)
21
+ dsl = DSL.new(options.fetch(:accessors, true), &block)
21
22
 
22
- if hstore?(store_attribute)
23
- store_accessor(store_attribute, dsl.column_names)
24
- else
25
- store(store_attribute, options.merge(accessors: dsl.column_names))
26
- end
23
+ serialize store_attribute, create_coder(store_attribute, dsl.columns).new(options[:coder])
24
+ store_accessor(store_attribute, dsl.accessors)
27
25
 
28
26
  register_typed_store_columns(store_attribute, dsl.columns)
29
27
  super(store_attribute, dsl) if defined?(super)
30
28
 
31
- dsl.column_names.each { |c| define_store_attribute_queries(store_attribute, c) }
29
+ dsl.accessors.each { |c| define_store_attribute_queries(store_attribute, c) }
32
30
 
33
31
  dsl
34
32
  end
@@ -40,6 +38,12 @@ module ActiveRecord::TypedStore
40
38
 
41
39
  private
42
40
 
41
+ def create_coder(store_attribute, columns)
42
+ store_class = TypedHash.create(columns)
43
+ const_set("#{store_attribute}_hash".camelize, store_class)
44
+ Coder.create(store_class)
45
+ end
46
+
43
47
  def register_typed_store_columns(store_attribute, columns)
44
48
  self.typed_stores ||= {}
45
49
  self.typed_store_attributes ||= {}
@@ -49,12 +53,16 @@ module ActiveRecord::TypedStore
49
53
  end
50
54
 
51
55
  def define_typed_store_attribute_methods
52
- return unless typed_store_attributes
53
- typed_store_attributes.keys.each do |attribute|
56
+ store_accessors.each do |attribute|
54
57
  define_virtual_attribute_method(attribute)
55
58
  end
56
59
  end
57
60
 
61
+ def store_accessors
62
+ return [] unless typed_store_attributes
63
+ typed_store_attributes.values.select(&:accessor?).map(&:name).map(&:to_s)
64
+ end
65
+
58
66
  def hstore?(store_attribute)
59
67
  columns_hash[store_attribute.to_s].try(:type) == :hstore
60
68
  end
@@ -72,11 +80,6 @@ module ActiveRecord::TypedStore
72
80
 
73
81
  end
74
82
 
75
- def reload(*)
76
- reload_stores!
77
- super
78
- end
79
-
80
83
  protected
81
84
 
82
85
  def write_store_attribute(store_attribute, key, value)
@@ -86,18 +89,12 @@ module ActiveRecord::TypedStore
86
89
  end
87
90
 
88
91
  previous_value = read_store_attribute(store_attribute, key)
89
- casted_value = cast_store_attribute(store_attribute, key, value)
90
- attribute_will_change!(key.to_s) if casted_value != previous_value
91
- super(store_attribute, key, casted_value)
92
+ attribute_will_change!(key.to_s) if value != previous_value
93
+ super
92
94
  end
93
95
 
94
96
  private
95
97
 
96
- def cast_store_attribute(store_attribute, key, value)
97
- column = store_column(store_attribute, key)
98
- column ? column.cast(value) : value
99
- end
100
-
101
98
  def store_column(store_attribute, key)
102
99
  store = store_columns(store_attribute)
103
100
  store && store[key]
@@ -107,43 +104,6 @@ module ActiveRecord::TypedStore
107
104
  self.class.typed_stores.try(:[], store_attribute)
108
105
  end
109
106
 
110
- def if_store_uninitialized(store_attribute)
111
- initialized = "@_#{store_attribute}_initialized"
112
- unless instance_variable_get(initialized)
113
- yield
114
- instance_variable_set(initialized, true)
115
- end
116
- end
117
-
118
- def reload_stores!
119
- return unless self.class.typed_stores
120
- self.class.typed_stores.keys.each do |store_attribute|
121
- instance_variable_set("@_#{store_attribute}_initialized", false)
122
- end
123
- end
124
-
125
- def initialize_store_attribute(store_attribute)
126
- store = defined?(super) ? super : send(store_attribute)
127
- store.tap do |store|
128
- if_store_uninitialized(store_attribute) do
129
- if columns = store_columns(store_attribute)
130
- initialize_store(store, columns.values)
131
- end
132
- end
133
- end
134
- end
135
-
136
- def initialize_store(store, columns)
137
- columns.each do |column|
138
- if store.has_key?(column.name)
139
- store[column.name] = column.cast(store[column.name])
140
- else
141
- store[column.name] = column.default if column.has_default?
142
- end
143
- end
144
- store
145
- end
146
-
147
107
  # heavilly inspired from ActiveRecord::Base#query_attribute
148
108
  def query_store_attribute(store_attribute, key)
149
109
  value = read_store_attribute(store_attribute, key)
@@ -165,7 +125,8 @@ module ActiveRecord::TypedStore
165
125
  end
166
126
 
167
127
  require 'active_record/typed_store/ar_32_fallbacks' if IS_AR_3_2
168
- require 'active_record/typed_store/ar_41_fallbacks' if IS_AR_4_1
128
+ require 'active_record/typed_store/coder'
129
+
169
130
  unless IS_AR_3_2
170
131
  ActiveModel::AttributeMethods::ClassMethods.send(:alias_method, :define_virtual_attribute_method, :define_attribute_method)
171
132
  end
@@ -0,0 +1,63 @@
1
+ module ActiveRecord::TypedStore
2
+
3
+ class TypedHash < HashWithIndifferentAccess
4
+
5
+ class << self
6
+
7
+ attr_reader :columns
8
+
9
+ def create(columns)
10
+ Class.new(self) do
11
+ @columns = columns.index_by { |c| c.name.to_s }
12
+ end
13
+ end
14
+
15
+ end
16
+
17
+ def initialize(constructor={})
18
+ super()
19
+ update(defaults_hash)
20
+ update(constructor) if constructor.is_a?(Hash)
21
+ end
22
+
23
+ def []=(key, value)
24
+ super(key, cast_value(key, value))
25
+ end
26
+ alias_method :store, :[]=
27
+
28
+ def merge!(other_hash)
29
+ other_hash.each_pair do |key, value|
30
+ if block_given? && key?(key)
31
+ value = yield(convert_key(key), self[key], value)
32
+ end
33
+ self[convert_key(key)] = convert_value(value)
34
+ end
35
+ self
36
+ end
37
+ alias_method :update, :merge!
38
+
39
+ private
40
+
41
+ delegate :columns, to: 'self.class'
42
+
43
+ def defaults_hash
44
+ Hash[self.class.columns.values.select(&:has_default?).map { |c| [c.name, c.default] }]
45
+ end
46
+
47
+ def cast_value(key, value)
48
+ key = convert_key(key)
49
+ column = columns[key]
50
+ return value unless columns
51
+
52
+ casted_value = column.cast(value)
53
+
54
+ if casted_value.nil? && !column.null && column.has_default?
55
+ return column.default
56
+ end
57
+
58
+ casted_value
59
+ end
60
+
61
+ end
62
+
63
+ end
@@ -1,5 +1,5 @@
1
1
  module ActiveRecord
2
2
  module TypedStore
3
- VERSION = '0.3.2'
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end
@@ -0,0 +1,204 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveRecord::TypedStore::TypedHash do
4
+
5
+ def create_hash_class(*args)
6
+ described_class.create([ActiveRecord::TypedStore::Column.new(*args)])
7
+ end
8
+
9
+ def build_hash(*args)
10
+ create_hash_class(*args).new
11
+ end
12
+
13
+ let(:hash) { build_hash(*column) }
14
+
15
+ let(:hash_class) { create_hash_class(*column) }
16
+
17
+ context 'nullable column without default' do
18
+
19
+ let(:column) { ['age', :integer] }
20
+
21
+ describe '.new' do
22
+
23
+ it 'apply casting' do
24
+ hash = hash_class.new(age: '24')
25
+ expect(hash[:age]).to be == 24
26
+ end
27
+
28
+ end
29
+
30
+ describe '#initialize' do
31
+
32
+ it 'has nil as default value' do
33
+ expect(hash[:age]).to be_nil
34
+ end
35
+
36
+ end
37
+
38
+ describe '#[]=' do
39
+
40
+ it 'apply casting' do
41
+ hash[:age] = '24'
42
+ expect(hash[:age]).to be == 24
43
+ end
44
+
45
+ it 'can be nil' do
46
+ hash[:age] = nil
47
+ expect(hash[:age]).to be_nil
48
+ end
49
+
50
+ end
51
+
52
+ describe '#merge!' do
53
+
54
+ it 'apply casting' do
55
+ hash.merge!(age: '24')
56
+ expect(hash[:age]).to be == 24
57
+ end
58
+
59
+ it 'can be nil' do
60
+ hash.merge!(age: nil)
61
+ expect(hash[:age]).to be_nil
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ context 'nullable column with default' do
69
+
70
+ let(:column) { ['age', :integer, default: 42] }
71
+
72
+ describe '#initialize' do
73
+
74
+ it 'has the default value' do
75
+ expect(hash[:age]).to be == 42
76
+ end
77
+
78
+ end
79
+
80
+ describe '#[]=' do
81
+
82
+ it 'apply casting' do
83
+ hash[:age] = '24'
84
+ expect(hash[:age]).to be == 24
85
+ end
86
+
87
+ it 'can be nil' do
88
+ hash[:age] = nil
89
+ expect(hash[:age]).to be_nil
90
+ end
91
+
92
+ end
93
+
94
+ describe '#merge!' do
95
+
96
+ it 'apply casting' do
97
+ hash.merge!(age: '24')
98
+ expect(hash[:age]).to be == 24
99
+ end
100
+
101
+ it 'can be nil' do
102
+ hash.merge!(age: nil)
103
+ expect(hash[:age]).to be_nil
104
+ end
105
+
106
+ end
107
+
108
+ end
109
+
110
+ context 'non nullable column with default' do
111
+
112
+ let(:column) { ['age', :integer, null: false, default: 42] }
113
+
114
+ describe '#intialize' do
115
+
116
+ it 'has the default value' do
117
+ expect(hash[:age]).to be == 42
118
+ end
119
+
120
+ end
121
+
122
+ describe '#[]=' do
123
+
124
+ it 'apply casting' do
125
+ hash[:age] = '24'
126
+ expect(hash[:age]).to be == 24
127
+ end
128
+
129
+ it 'cannot be nil' do
130
+ hash[:age] = nil
131
+ expect(hash[:age]).to be == 42
132
+ end
133
+
134
+ end
135
+
136
+ describe '#merge!' do
137
+
138
+ it 'apply casting' do
139
+ hash.merge!(age: '24')
140
+ expect(hash[:age]).to be == 24
141
+ end
142
+
143
+ it 'cannot be nil' do
144
+ hash.merge!(age: nil)
145
+ expect(hash[:age]).to be == 42
146
+ end
147
+
148
+ end
149
+
150
+ end
151
+
152
+ context 'non blankable column with default' do
153
+
154
+ let(:column) { ['source', :string, blank: false, default: 'web'] }
155
+
156
+ describe '#intialize' do
157
+
158
+ it 'has the default value' do
159
+ expect(hash[:source]).to be == 'web'
160
+ end
161
+
162
+ end
163
+
164
+ describe '#[]=' do
165
+
166
+ it 'apply casting' do
167
+ hash[:source] = :mailing
168
+ expect(hash[:source]).to be == 'mailing'
169
+ end
170
+
171
+ it 'cannot be nil' do
172
+ hash[:source] = nil
173
+ expect(hash[:source]).to be == 'web'
174
+ end
175
+
176
+ it 'cannot be blank' do
177
+ hash[:source] = ''
178
+ expect(hash[:source]).to be == 'web'
179
+ end
180
+
181
+ end
182
+
183
+ describe '#merge!' do
184
+
185
+ it 'apply casting' do
186
+ hash.merge!(source: :mailing)
187
+ expect(hash[:source]).to be == 'mailing'
188
+ end
189
+
190
+ it 'cannot be nil' do
191
+ hash.merge!(source: nil)
192
+ expect(hash[:source]).to be == 'web'
193
+ end
194
+
195
+ it 'cannot be blank' do
196
+ hash.merge!(source: '')
197
+ expect(hash[:source]).to be == 'web'
198
+ end
199
+
200
+ end
201
+
202
+ end
203
+
204
+ end
@@ -447,39 +447,6 @@ shared_examples 'a store' do |retain_type=true|
447
447
 
448
448
  let(:model) { described_class.new }
449
449
 
450
- describe 'initialization' do
451
-
452
- it 'is done only once' do
453
- model.should_receive(:initialize_store).once
454
- 3.times do
455
- model.age = (rand * 100).to_i
456
- model.age
457
- end
458
- end
459
-
460
- it 'is done again after a reload' do
461
- model.save
462
-
463
- model.should_receive(:initialize_store).twice
464
- 3.times do
465
- model.age = (rand * 100).to_i
466
- model.age
467
- end
468
- model.reload
469
- 3.times do
470
- model.age = (rand * 100).to_i
471
- model.age
472
- end
473
- end
474
-
475
- it 'is not performe if no store attributes are accessed' do
476
- model.should_not_receive(:initialize_store)
477
- model.update_attributes(untyped_settings: {foo: :bar})
478
- model.update_attributes(untyped_settings: {})
479
- end
480
-
481
- end
482
-
483
450
  describe 'attributes' do
484
451
 
485
452
  it 'retrieve default if assigned nil and null not allowed' do
@@ -494,6 +461,27 @@ shared_examples 'a store' do |retain_type=true|
494
461
 
495
462
  end
496
463
 
464
+ describe 'attributes without accessors' do
465
+
466
+ it 'cannot be accessed as a model attribute' do
467
+ expect(model).to_not respond_to :country
468
+ expect(model).to_not respond_to :country=
469
+ end
470
+
471
+ it 'cannot be queried' do
472
+ expect(model).to_not respond_to :country?
473
+ end
474
+
475
+ it 'cannot be reset' do
476
+ expect(model).to_not respond_to :reset_country!
477
+ end
478
+
479
+ it 'still has casting a default handling' do
480
+ expect(model.settings[:country]).to be == 'Canada'
481
+ end
482
+
483
+ end
484
+
497
485
  describe '`any` attributes' do
498
486
 
499
487
  it 'accept any type' do
@@ -48,6 +48,7 @@ def define_store_columns(t)
48
48
  define_columns(t)
49
49
  t.any :author
50
50
  t.any :source, blank: false, default: 'web'
51
+ t.string :country, blank: false, default: 'Canada', accessor: false
51
52
  end
52
53
 
53
54
  class CreateAllTables < ActiveRecord::Migration
@@ -171,10 +172,23 @@ class JsonTypedStoreModel < ActiveRecord::Base
171
172
  end
172
173
  end
173
174
 
175
+ module MarshalCoder
176
+ extend self
177
+
178
+ def load(serial)
179
+ Marshal.load(Base64.decode64(serial))
180
+ end
181
+
182
+ def dump(value)
183
+ Base64.encode64(Marshal.dump(value))
184
+ end
185
+
186
+ end
187
+
174
188
  class MarshalTypedStoreModel < ActiveRecord::Base
175
189
  establish_connection 'test_sqlite3'
176
190
  store :untyped_settings, accessors: [:title]
177
- typed_store :settings, coder: ColumnCoder.new(Marshal) do |s|
191
+ typed_store :settings, coder: ColumnCoder.new(MarshalCoder) do |s|
178
192
  define_store_columns(s)
179
193
  end
180
194
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-typedstore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-14 00:00:00.000000000 Z
11
+ date: 2013-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -153,15 +153,18 @@ files:
153
153
  - activerecord-typedstore.gemspec
154
154
  - gemfiles/Gemfile.ar-3.2
155
155
  - gemfiles/Gemfile.ar-4.0
156
+ - gemfiles/Gemfile.ar-4.1
156
157
  - gemfiles/Gemfile.ar-edge
157
158
  - lib/active_record/typed_store.rb
158
159
  - lib/active_record/typed_store/ar_32_fallbacks.rb
159
- - lib/active_record/typed_store/ar_41_fallbacks.rb
160
+ - lib/active_record/typed_store/coder.rb
160
161
  - lib/active_record/typed_store/column.rb
161
162
  - lib/active_record/typed_store/dsl.rb
162
163
  - lib/active_record/typed_store/extension.rb
164
+ - lib/active_record/typed_store/typed_hash.rb
163
165
  - lib/active_record/typed_store/version.rb
164
166
  - lib/activerecord-typedstore.rb
167
+ - spec/active_record/typed_store/typed_hash_spec.rb
165
168
  - spec/active_record/typed_store_spec.rb
166
169
  - spec/spec_helper.rb
167
170
  - spec/support/database_cleaner.rb
@@ -191,6 +194,7 @@ signing_key:
191
194
  specification_version: 4
192
195
  summary: ActiveRecord::Store but with type definition
193
196
  test_files:
197
+ - spec/active_record/typed_store/typed_hash_spec.rb
194
198
  - spec/active_record/typed_store_spec.rb
195
199
  - spec/spec_helper.rb
196
200
  - spec/support/database_cleaner.rb
@@ -1,26 +0,0 @@
1
- module ActiveRecord::TypedStore
2
-
3
- module AR41Fallbacks
4
-
5
- private
6
-
7
- module HashAccessorPatch
8
-
9
- def self.extended(hash_accessor)
10
- hash_accessor.singleton_class.alias_method_chain :prepare, :initialization
11
- end
12
-
13
- protected
14
-
15
- def prepare_with_initialization(object, store_attribute)
16
- prepare_without_initialization(object, store_attribute)
17
- object.send(:initialize_store_attribute, store_attribute)
18
- end
19
-
20
- end
21
-
22
- ActiveRecord::Store::HashAccessor.extend(HashAccessorPatch)
23
- ActiveRecord::Store::IndifferentHashAccessor.extend(HashAccessorPatch)
24
- end
25
-
26
- end