activerecord-typedstore 1.2.2 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +13 -19
- data/activerecord-typedstore.gemspec +1 -1
- data/gemfiles/{Gemfile.ar-5.1 → Gemfile.ar-6.0} +1 -1
- data/lib/active_record/typed_store.rb +3 -1
- data/lib/active_record/typed_store/behavior.rb +75 -0
- data/lib/active_record/typed_store/dsl.rb +2 -0
- data/lib/active_record/typed_store/extension.rb +23 -102
- data/lib/active_record/typed_store/field.rb +2 -0
- data/lib/active_record/typed_store/identity_coder.rb +2 -0
- data/lib/active_record/typed_store/type.rb +2 -0
- data/lib/active_record/typed_store/typed_hash.rb +2 -0
- data/lib/active_record/typed_store/version.rb +3 -1
- data/lib/activerecord-typedstore.rb +2 -0
- data/spec/active_record/typed_store_spec.rb +35 -109
- data/spec/support/models.rb +7 -46
- metadata +7 -8
- data/gemfiles/Gemfile.ar-4.2 +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c3c305575dc1d19ea16344072768e7c4dc2f36de6261a5f7c18e638428b61d3d
|
4
|
+
data.tar.gz: 7b2e6454da64d6e1138cfc2bf0f52fe88869a27b687d7624d51f3723e601f21f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbdbe06798896b11e98b9abdc04c5b87147a8724665e0fc85c6e87f3e44ba4f7284bd42f86120c5ca1683593d6b6010bfa248f3c071ba45145964c7bde614ae4
|
7
|
+
data.tar.gz: c33b750f4873d9709ab1a453b667b1a1938bc05db8b0cb4ac6f8c6a60127d4b73714695b042551671e499a67ffecaf72fee00f714b1731c9e25939ff037b1b10
|
data/.travis.yml
CHANGED
@@ -1,39 +1,33 @@
|
|
1
|
+
sudo: false
|
1
2
|
language: ruby
|
3
|
+
cache: bundler
|
2
4
|
|
3
5
|
before_install:
|
4
6
|
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
5
7
|
- gem install bundler -v '< 2'
|
6
8
|
|
7
9
|
rvm:
|
8
|
-
- 2.
|
9
|
-
- 2.
|
10
|
-
- 2.5.5
|
11
|
-
- 2.6.2
|
10
|
+
- "2.5"
|
11
|
+
- "2.6"
|
12
12
|
gemfile:
|
13
|
-
- gemfiles/Gemfile.ar-4.2
|
14
|
-
- gemfiles/Gemfile.ar-5.0
|
15
|
-
- gemfiles/Gemfile.ar-5.1
|
16
13
|
- gemfiles/Gemfile.ar-5.2
|
14
|
+
- gemfiles/Gemfile.ar-6.0
|
17
15
|
- gemfiles/Gemfile.ar-master
|
18
16
|
|
19
17
|
env:
|
20
|
-
- TIMEZONE_AWARE=1 POSTGRES=1 MYSQL=1
|
21
|
-
- TIMEZONE_AWARE=0 POSTGRES=1 MYSQL=1
|
22
|
-
- TIMEZONE_AWARE=1 POSTGRES=1 POSTGRES_JSON=1
|
23
|
-
- TIMEZONE_AWARE=0 POSTGRES=1 POSTGRES_JSON=1
|
18
|
+
- TIMEZONE_AWARE=1 POSTGRES=1 MYSQL=1 POSTGRES_JSON=1
|
19
|
+
- TIMEZONE_AWARE=0 POSTGRES=1 MYSQL=1 POSTGRES_JSON=1
|
24
20
|
|
25
21
|
matrix:
|
26
22
|
exclude:
|
27
|
-
- rvm: 2.
|
28
|
-
gemfile: 'gemfiles/Gemfile.
|
29
|
-
- rvm: 2.
|
23
|
+
- rvm: "2.6"
|
24
|
+
gemfile: 'gemfiles/Gemfile.6-0'
|
25
|
+
- rvm: "2.6"
|
30
26
|
gemfile: 'gemfiles/Gemfile.ar-master'
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
sudo: false
|
36
|
-
cache: bundler
|
28
|
+
services:
|
29
|
+
- mysql
|
30
|
+
- postgresql
|
37
31
|
|
38
32
|
before_script:
|
39
33
|
- mysql -e 'create database typed_store_test;'
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency 'activerecord', '>=
|
21
|
+
spec.add_dependency 'activerecord', '>= 5.2'
|
22
22
|
|
23
23
|
spec.add_development_dependency 'bundler'
|
24
24
|
spec.add_development_dependency 'rake', '~> 10'
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_support'
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -7,5 +9,5 @@ end
|
|
7
9
|
|
8
10
|
ActiveSupport.on_load(:active_record) do
|
9
11
|
require 'active_record/typed_store/extension'
|
10
|
-
::ActiveRecord::Base.
|
12
|
+
::ActiveRecord::Base.extend(ActiveRecord::TypedStore::Extension)
|
11
13
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord::TypedStore
|
4
|
+
module Behavior
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def define_attribute_methods
|
9
|
+
super
|
10
|
+
define_typed_store_attribute_methods
|
11
|
+
end
|
12
|
+
|
13
|
+
def undefine_attribute_methods # :nodoc:
|
14
|
+
super if @typed_store_attribute_methods_generated
|
15
|
+
@typed_store_attribute_methods_generated = false
|
16
|
+
end
|
17
|
+
|
18
|
+
def define_typed_store_attribute_methods
|
19
|
+
return if @typed_store_attribute_methods_generated
|
20
|
+
store_accessors.each do |attribute|
|
21
|
+
define_attribute_method(attribute)
|
22
|
+
undefine_before_type_cast_method(attribute)
|
23
|
+
end
|
24
|
+
@typed_store_attribute_methods_generated = true
|
25
|
+
end
|
26
|
+
|
27
|
+
def undefine_before_type_cast_method(attribute)
|
28
|
+
# because it mess with ActionView forms, see #14.
|
29
|
+
method = "#{attribute}_before_type_cast"
|
30
|
+
undef_method(method) if method_defined?(method)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def changes
|
35
|
+
changes = super
|
36
|
+
self.class.store_accessors.each do |attr|
|
37
|
+
if send("#{attr}_changed?")
|
38
|
+
changes[attr] = [send("#{attr}_was"), send(attr)]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
changes
|
42
|
+
end
|
43
|
+
|
44
|
+
def clear_attribute_change(attr_name)
|
45
|
+
return if self.class.store_accessors.include?(attr_name.to_s)
|
46
|
+
super
|
47
|
+
end
|
48
|
+
|
49
|
+
def read_attribute(attr_name)
|
50
|
+
if self.class.store_accessors.include?(attr_name.to_s)
|
51
|
+
return public_send(attr_name)
|
52
|
+
end
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
def query_attribute(attr_name)
|
57
|
+
if self.class.store_accessors.include?(attr_name.to_s)
|
58
|
+
value = public_send(attr_name)
|
59
|
+
|
60
|
+
case value
|
61
|
+
when true then true
|
62
|
+
when false, nil then false
|
63
|
+
else
|
64
|
+
if value.respond_to?(:zero?)
|
65
|
+
!value.zero?
|
66
|
+
else
|
67
|
+
!value.blank?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
else
|
71
|
+
super
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -1,123 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'active_record/typed_store/dsl'
|
4
|
+
require 'active_record/typed_store/behavior'
|
2
5
|
require 'active_record/typed_store/type'
|
3
6
|
require 'active_record/typed_store/typed_hash'
|
4
7
|
require 'active_record/typed_store/identity_coder'
|
5
8
|
|
6
9
|
module ActiveRecord::TypedStore
|
7
10
|
module Extension
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
self.typed_stores = {}
|
13
|
-
end
|
14
|
-
|
15
|
-
module ClassMethods
|
16
|
-
def store_accessors
|
17
|
-
typed_stores.each_value.flat_map(&:accessors)
|
11
|
+
def typed_store(store_attribute, options={}, &block)
|
12
|
+
unless self < Behavior
|
13
|
+
include Behavior
|
14
|
+
class_attribute :typed_stores, :store_accessors, instance_accessor: false
|
18
15
|
end
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
typed_klass = TypedHash.create(dsl.fields.values)
|
25
|
-
const_set("#{store_attribute}_hash".camelize, typed_klass)
|
26
|
-
|
27
|
-
decorate_attribute_type(store_attribute, :typed_store) do |subtype|
|
28
|
-
Type.new(typed_klass, dsl.coder, subtype)
|
29
|
-
end
|
30
|
-
store_accessor(store_attribute, dsl.accessors)
|
31
|
-
|
32
|
-
dsl.accessors.each do |accessor_name|
|
33
|
-
define_method("#{accessor_name}_changed?") do
|
34
|
-
send("#{store_attribute}_changed?") &&
|
35
|
-
send(store_attribute)[accessor_name] != send("#{store_attribute}_was")[accessor_name]
|
36
|
-
end
|
37
|
-
|
38
|
-
define_method("#{accessor_name}_was") do
|
39
|
-
send("#{store_attribute}_was")[accessor_name]
|
40
|
-
end
|
17
|
+
dsl = DSL.new(store_attribute, options, &block)
|
18
|
+
self.typed_stores = (self.typed_stores || {}).merge(store_attribute => dsl)
|
19
|
+
self.store_accessors = typed_stores.each_value.flat_map(&:accessors).map { |a| -a.to_s }.to_set
|
41
20
|
|
42
|
-
|
43
|
-
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
21
|
+
typed_klass = TypedHash.create(dsl.fields.values)
|
22
|
+
const_set("#{store_attribute}_hash".camelize, typed_klass)
|
47
23
|
|
48
|
-
|
49
|
-
|
50
|
-
define_typed_store_attribute_methods
|
24
|
+
decorate_attribute_type(store_attribute, :typed_store) do |subtype|
|
25
|
+
Type.new(typed_klass, dsl.coder, subtype)
|
51
26
|
end
|
27
|
+
store_accessor(store_attribute, dsl.accessors)
|
52
28
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
def define_typed_store_attribute_methods
|
59
|
-
return if @typed_store_attribute_methods_generated
|
60
|
-
store_accessors.each do |attribute|
|
61
|
-
define_attribute_method(attribute.to_s)
|
62
|
-
undefine_before_type_cast_method(attribute)
|
29
|
+
dsl.accessors.each do |accessor_name|
|
30
|
+
define_method("#{accessor_name}_changed?") do
|
31
|
+
send("#{store_attribute}_changed?") &&
|
32
|
+
send(store_attribute)[accessor_name] != send("#{store_attribute}_was")[accessor_name]
|
63
33
|
end
|
64
|
-
@typed_store_attribute_methods_generated = true
|
65
|
-
end
|
66
34
|
|
67
|
-
|
68
|
-
|
69
|
-
method = "#{attribute}_before_type_cast"
|
70
|
-
undef_method(method) if method_defined?(method)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def changes
|
75
|
-
changes = super
|
76
|
-
self.class.store_accessors.each do |attr|
|
77
|
-
if send("#{attr}_changed?")
|
78
|
-
changes[attr] = [send("#{attr}_was"), send(attr)]
|
35
|
+
define_method("#{accessor_name}_was") do
|
36
|
+
send("#{store_attribute}_was")[accessor_name]
|
79
37
|
end
|
80
|
-
end
|
81
|
-
changes
|
82
|
-
end
|
83
|
-
|
84
|
-
def clear_attribute_change(attr_name)
|
85
|
-
return if self.class.store_accessors.include?(normalize_attribute(attr_name))
|
86
|
-
super
|
87
|
-
end
|
88
38
|
|
89
|
-
|
90
|
-
|
91
|
-
return public_send(attr_name)
|
92
|
-
end
|
93
|
-
super
|
94
|
-
end
|
95
|
-
|
96
|
-
def query_attribute(attr_name)
|
97
|
-
if self.class.store_accessors.include?(attr_name.to_sym)
|
98
|
-
value = public_send(attr_name)
|
99
|
-
|
100
|
-
case value
|
101
|
-
when true then true
|
102
|
-
when false, nil then false
|
103
|
-
else
|
104
|
-
if value.respond_to?(:zero?)
|
105
|
-
!value.zero?
|
106
|
-
else
|
107
|
-
!value.blank?
|
108
|
-
end
|
39
|
+
define_method("restore_#{accessor_name}!") do
|
40
|
+
send("#{accessor_name}=", send("#{accessor_name}_was"))
|
109
41
|
end
|
110
|
-
else
|
111
|
-
super
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def normalize_attribute(attr)
|
116
|
-
case attr
|
117
|
-
when Symbol
|
118
|
-
attr
|
119
|
-
else
|
120
|
-
attr.to_s.to_sym
|
121
42
|
end
|
122
43
|
end
|
123
44
|
end
|
@@ -70,20 +70,11 @@ shared_examples 'any model' do
|
|
70
70
|
}.to change { !!model.age_changed? }.from(true).to(false)
|
71
71
|
end
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
}.to change { model.age }.from(24).to(12)
|
79
|
-
end
|
80
|
-
else
|
81
|
-
it 'can be reset individually' do
|
82
|
-
model.age = 24
|
83
|
-
expect {
|
84
|
-
model.reset_age!
|
85
|
-
}.to change { model.age }.from(24).to(12)
|
86
|
-
end
|
73
|
+
it 'can be restored individually' do
|
74
|
+
model.age = 24
|
75
|
+
expect {
|
76
|
+
model.restore_age!
|
77
|
+
}.to change { model.age }.from(24).to(12)
|
87
78
|
end
|
88
79
|
|
89
80
|
it 'does not dirty track assigning the same boolean' do
|
@@ -339,13 +330,13 @@ shared_examples 'any model' do
|
|
339
330
|
describe 'decimal attributes' do
|
340
331
|
|
341
332
|
it 'has the defined default as initial value' do
|
342
|
-
expect(model.total_price).to be == BigDecimal
|
333
|
+
expect(model.total_price).to be == BigDecimal('4.2')
|
343
334
|
expect(model.total_price).to be_a BigDecimal
|
344
335
|
end
|
345
336
|
|
346
337
|
it 'properly cast assigned value to decimal' do
|
347
338
|
model.shipping_cost = 4.2
|
348
|
-
expect(model.shipping_cost).to be == BigDecimal
|
339
|
+
expect(model.shipping_cost).to be == BigDecimal('4.2')
|
349
340
|
expect(model.shipping_cost).to be_a BigDecimal
|
350
341
|
end
|
351
342
|
|
@@ -357,7 +348,7 @@ shared_examples 'any model' do
|
|
357
348
|
|
358
349
|
it 'retreive a BigDecimal instance' do
|
359
350
|
model.update(shipping_cost: 4.2)
|
360
|
-
expect(model.reload.shipping_cost).to be == BigDecimal
|
351
|
+
expect(model.reload.shipping_cost).to be == BigDecimal('4.2')
|
361
352
|
expect(model.reload.shipping_cost).to be_a BigDecimal
|
362
353
|
end
|
363
354
|
|
@@ -367,17 +358,17 @@ shared_examples 'any model' do
|
|
367
358
|
end
|
368
359
|
|
369
360
|
it 'positive values are considered present' do
|
370
|
-
model.shipping_cost = BigDecimal
|
361
|
+
model.shipping_cost = BigDecimal('4.2')
|
371
362
|
expect(model.shipping_cost?).to be true
|
372
363
|
end
|
373
364
|
|
374
365
|
it 'negative values are considered present' do
|
375
|
-
model.shipping_cost = BigDecimal
|
366
|
+
model.shipping_cost = BigDecimal('-4.2')
|
376
367
|
expect(model.shipping_cost?).to be true
|
377
368
|
end
|
378
369
|
|
379
370
|
it '0 is not considered present' do
|
380
|
-
model.shipping_cost = BigDecimal
|
371
|
+
model.shipping_cost = BigDecimal('0')
|
381
372
|
expect(model.shipping_cost?).to be false
|
382
373
|
end
|
383
374
|
|
@@ -432,48 +423,26 @@ shared_examples 'any model' do
|
|
432
423
|
let(:time) { time_string.respond_to?(:in_time_zone) ? time_string.in_time_zone : Time.parse(time_string) }
|
433
424
|
|
434
425
|
context "with ActiveRecord #{ActiveRecord::VERSION::STRING}" do
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
end
|
426
|
+
it 'has the defined default as initial value' do
|
427
|
+
model.save
|
428
|
+
expect(model.reload.published_at).to be == time
|
429
|
+
end
|
440
430
|
|
431
|
+
it 'retreive a time instance' do
|
432
|
+
model.update(published_at: time)
|
433
|
+
expect(model.reload.published_at).to be == time
|
434
|
+
end
|
435
|
+
|
436
|
+
if ActiveRecord::Base.time_zone_aware_attributes
|
441
437
|
it 'properly cast assigned value to time' do
|
442
438
|
model.remind_at = time_string
|
443
439
|
expect(model.remind_at).to be == time
|
444
440
|
end
|
445
|
-
|
441
|
+
else
|
442
|
+
it 'properly cast assigned value to time' do
|
446
443
|
model.remind_at = time_string
|
447
|
-
model.save
|
448
|
-
model.reload
|
449
444
|
expect(model.remind_at).to be == time
|
450
445
|
end
|
451
|
-
it 'retreive a Time instance' do
|
452
|
-
model.update(published_at: time)
|
453
|
-
expect(model.reload.published_at).to be == time
|
454
|
-
end
|
455
|
-
else
|
456
|
-
it 'has the defined default as initial value' do
|
457
|
-
model.save
|
458
|
-
expect(model.reload.published_at).to be == time
|
459
|
-
end
|
460
|
-
|
461
|
-
it 'retreive a time instance' do
|
462
|
-
model.update(published_at: time)
|
463
|
-
expect(model.reload.published_at).to be == time
|
464
|
-
end
|
465
|
-
|
466
|
-
if ActiveRecord::Base.time_zone_aware_attributes
|
467
|
-
it 'properly cast assigned value to time' do
|
468
|
-
model.remind_at = time_string
|
469
|
-
expect(model.remind_at).to be == time
|
470
|
-
end
|
471
|
-
else
|
472
|
-
it 'properly cast assigned value to time' do
|
473
|
-
model.remind_at = time_string
|
474
|
-
expect(model.remind_at).to be == time
|
475
|
-
end
|
476
|
-
end
|
477
446
|
end
|
478
447
|
end
|
479
448
|
end
|
@@ -485,61 +454,27 @@ shared_examples 'any model' do
|
|
485
454
|
let(:time) { datetime_string.respond_to?(:in_time_zone) ? datetime_string.in_time_zone : Time.parse(datetime_string) }
|
486
455
|
|
487
456
|
context "with ActiveRecord #{ActiveRecord::VERSION::STRING}" do
|
457
|
+
it 'has the defined default as initial value' do
|
458
|
+
model.save
|
459
|
+
expect(model.reload.published_at).to be == datetime
|
460
|
+
end
|
488
461
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
expect(model.published_at).to be == time
|
494
|
-
end
|
462
|
+
it 'retreive a DateTime instance' do
|
463
|
+
model.update(published_at: datetime)
|
464
|
+
expect(model.reload.published_at).to be == datetime
|
465
|
+
end
|
495
466
|
|
467
|
+
if ActiveRecord::Base.time_zone_aware_attributes
|
496
468
|
it 'properly cast assigned value to time' do
|
497
469
|
model.remind_at = datetime_string
|
498
470
|
expect(model.remind_at).to be == time
|
499
471
|
end
|
500
|
-
|
501
|
-
it 'properly cast assigned value to time on save' do
|
502
|
-
model.remind_at = datetime_string
|
503
|
-
model.save
|
504
|
-
model.reload
|
505
|
-
expect(model.remind_at).to be == time
|
506
|
-
end
|
507
|
-
|
508
|
-
it 'retreive a Time instance' do
|
509
|
-
model.update(published_at: datetime)
|
510
|
-
expect(model.reload.published_at).to be == time
|
511
|
-
end
|
512
|
-
|
513
472
|
else
|
514
|
-
|
515
|
-
|
516
|
-
model.
|
517
|
-
expect(model.reload.published_at).to be == datetime
|
518
|
-
end
|
519
|
-
|
520
|
-
it 'retreive a DateTime instance' do
|
521
|
-
model.update(published_at: datetime)
|
522
|
-
expect(model.reload.published_at).to be == datetime
|
523
|
-
end
|
524
|
-
|
525
|
-
if ActiveRecord::Base.time_zone_aware_attributes
|
526
|
-
|
527
|
-
it 'properly cast assigned value to time' do
|
528
|
-
model.remind_at = datetime_string
|
529
|
-
expect(model.remind_at).to be == time
|
530
|
-
end
|
531
|
-
|
532
|
-
else
|
533
|
-
|
534
|
-
it 'properly cast assigned value to datetime' do
|
535
|
-
model.remind_at = datetime_string
|
536
|
-
expect(model.remind_at).to be == datetime
|
537
|
-
end
|
538
|
-
|
473
|
+
it 'properly cast assigned value to datetime' do
|
474
|
+
model.remind_at = datetime_string
|
475
|
+
expect(model.remind_at).to be == datetime
|
539
476
|
end
|
540
|
-
|
541
477
|
end
|
542
|
-
|
543
478
|
end
|
544
479
|
|
545
480
|
it 'nillify unparsable datetimes' do
|
@@ -896,15 +831,6 @@ describe PostgresqlRegularARModel do
|
|
896
831
|
it_should_behave_like 'a model supporting arrays', true
|
897
832
|
end if defined?(PostgresqlRegularARModel)
|
898
833
|
|
899
|
-
describe PostgresHstoreTypedStoreModel do
|
900
|
-
if AR_VERSION >= AR_4_1
|
901
|
-
pending('TODO: Rails edge HStore compatibiliy')
|
902
|
-
else
|
903
|
-
it_should_behave_like 'any model'
|
904
|
-
it_should_behave_like 'a store', false
|
905
|
-
end
|
906
|
-
end if defined?(PostgresHstoreTypedStoreModel)
|
907
|
-
|
908
834
|
describe PostgresJsonTypedStoreModel do
|
909
835
|
it_should_behave_like 'any model'
|
910
836
|
it_should_behave_like 'a store', true, :json
|
data/spec/support/models.rb
CHANGED
@@ -2,12 +2,6 @@ require 'active_record'
|
|
2
2
|
require 'json'
|
3
3
|
require 'yaml'
|
4
4
|
|
5
|
-
AR_VERSION = Gem::Version.new(ActiveRecord::VERSION::STRING)
|
6
|
-
AR_4_0 = Gem::Version.new('4.0')
|
7
|
-
AR_4_1 = Gem::Version.new('4.1.0.beta')
|
8
|
-
AR_4_2 = Gem::Version.new('4.2.0-rc1')
|
9
|
-
AR_5_0 = Gem::Version.new('5.0.0')
|
10
|
-
|
11
5
|
ActiveRecord::Base.time_zone_aware_attributes = ENV['TIMEZONE_AWARE'] != '0'
|
12
6
|
ActiveRecord::Base.configurations = {
|
13
7
|
'test_sqlite3' => { 'adapter' => 'sqlite3', 'database' => '/tmp/typed_store.db' },
|
@@ -80,7 +74,7 @@ def define_store_with_attributes(**options)
|
|
80
74
|
end
|
81
75
|
end
|
82
76
|
|
83
|
-
MigrationClass =
|
77
|
+
MigrationClass = ActiveRecord::Migration["5.0"]
|
84
78
|
class CreateAllTables < MigrationClass
|
85
79
|
|
86
80
|
def self.recreate_table(name, *args, &block)
|
@@ -98,13 +92,11 @@ class CreateAllTables < MigrationClass
|
|
98
92
|
ActiveRecord::Base.establish_connection(ENV['POSTGRES_URL'] || :test_postgresql)
|
99
93
|
recreate_table(:postgresql_regular_ar_models) { |t| define_columns(t); t.text :untyped_settings }
|
100
94
|
|
101
|
-
if
|
102
|
-
|
103
|
-
recreate_table(:postgres_hstore_typed_store_models) { |t| t.hstore :settings; t.text :untyped_settings }
|
95
|
+
execute "create extension if not exists hstore"
|
96
|
+
recreate_table(:postgres_hstore_typed_store_models) { |t| t.hstore :settings; t.text :untyped_settings }
|
104
97
|
|
105
|
-
|
106
|
-
|
107
|
-
end
|
98
|
+
if ENV['POSTGRES_JSON']
|
99
|
+
recreate_table(:postgres_json_typed_store_models) { |t| t.json :settings; t.text :explicit_settings; t.text :partial_settings; t.text :untyped_settings }
|
108
100
|
end
|
109
101
|
end
|
110
102
|
|
@@ -163,9 +155,8 @@ if ENV['POSTGRES']
|
|
163
155
|
store :untyped_settings, accessors: [:title]
|
164
156
|
end
|
165
157
|
|
166
|
-
if
|
167
|
-
|
168
|
-
class PostgresHstoreTypedStoreModel < ActiveRecord::Base
|
158
|
+
if ENV['POSTGRES_JSON']
|
159
|
+
class PostgresJsonTypedStoreModel < ActiveRecord::Base
|
169
160
|
establish_connection ENV['POSTGRES_URL'] || :test_postgresql
|
170
161
|
store :untyped_settings, accessors: [:title]
|
171
162
|
|
@@ -173,35 +164,6 @@ if ENV['POSTGRES']
|
|
173
164
|
define_store_with_no_attributes(coder: ColumnCoder.new(AsJson))
|
174
165
|
define_store_with_partial_attributes(coder: ColumnCoder.new(AsJson))
|
175
166
|
end
|
176
|
-
|
177
|
-
if ENV['POSTGRES_JSON']
|
178
|
-
|
179
|
-
if AR_VERSION >= AR_4_2
|
180
|
-
|
181
|
-
class PostgresJsonTypedStoreModel < ActiveRecord::Base
|
182
|
-
establish_connection ENV['POSTGRES_URL'] || :test_postgresql
|
183
|
-
store :untyped_settings, accessors: [:title]
|
184
|
-
|
185
|
-
define_store_with_attributes(coder: ColumnCoder.new(AsJson))
|
186
|
-
define_store_with_no_attributes(coder: ColumnCoder.new(AsJson))
|
187
|
-
define_store_with_partial_attributes(coder: ColumnCoder.new(AsJson))
|
188
|
-
end
|
189
|
-
|
190
|
-
else
|
191
|
-
|
192
|
-
class PostgresJsonTypedStoreModel < ActiveRecord::Base
|
193
|
-
establish_connection ENV['POSTGRES_URL'] || :test_postgresql
|
194
|
-
store :untyped_settings, accessors: [:title]
|
195
|
-
|
196
|
-
define_store_with_attributes(coder: ColumnCoder.new(AsJson))
|
197
|
-
define_store_with_no_attributes(coder: ColumnCoder.new(AsJson))
|
198
|
-
define_store_with_partial_attributes(coder: ColumnCoder.new(AsJson))
|
199
|
-
end
|
200
|
-
|
201
|
-
end
|
202
|
-
|
203
|
-
end
|
204
|
-
|
205
167
|
end
|
206
168
|
end
|
207
169
|
|
@@ -267,5 +229,4 @@ Models = [
|
|
267
229
|
]
|
268
230
|
Models << MysqlRegularARModel if defined?(MysqlRegularARModel)
|
269
231
|
Models << PostgresqlRegularARModel if defined?(PostgresqlRegularARModel)
|
270
|
-
Models << PostgresHstoreTypedStoreModel if defined?(PostgresHstoreTypedStoreModel)
|
271
232
|
Models << PostgresJsonTypedStoreModel if defined?(PostgresJsonTypedStoreModel)
|
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: 1.
|
4
|
+
version: 1.3.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: 2019-
|
11
|
+
date: 2019-12-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '5.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,12 +151,12 @@ files:
|
|
151
151
|
- README.md
|
152
152
|
- Rakefile
|
153
153
|
- activerecord-typedstore.gemspec
|
154
|
-
- gemfiles/Gemfile.ar-4.2
|
155
154
|
- gemfiles/Gemfile.ar-5.0
|
156
|
-
- gemfiles/Gemfile.ar-5.1
|
157
155
|
- gemfiles/Gemfile.ar-5.2
|
156
|
+
- gemfiles/Gemfile.ar-6.0
|
158
157
|
- gemfiles/Gemfile.ar-master
|
159
158
|
- lib/active_record/typed_store.rb
|
159
|
+
- lib/active_record/typed_store/behavior.rb
|
160
160
|
- lib/active_record/typed_store/dsl.rb
|
161
161
|
- lib/active_record/typed_store/extension.rb
|
162
162
|
- lib/active_record/typed_store/field.rb
|
@@ -189,8 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
189
189
|
- !ruby/object:Gem::Version
|
190
190
|
version: '0'
|
191
191
|
requirements: []
|
192
|
-
|
193
|
-
rubygems_version: 2.5.1
|
192
|
+
rubygems_version: 3.0.4
|
194
193
|
signing_key:
|
195
194
|
specification_version: 4
|
196
195
|
summary: Add type casting and full method attributes support to АctiveRecord store
|