activerecord-typedstore 1.5.1 → 1.6.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 +4 -4
- data/.github/workflows/ruby.yml +11 -2
- data/README.md +1 -1
- data/gemfiles/Gemfile.ar-7.1 +5 -0
- data/lib/active_record/typed_store/behavior.rb +22 -13
- data/lib/active_record/typed_store/extension.rb +6 -1
- data/lib/active_record/typed_store/field.rb +3 -1
- data/lib/active_record/typed_store/version.rb +1 -1
- data/spec/active_record/typed_store_spec.rb +18 -2
- data/spec/spec_helper.rb +2 -2
- data/spec/support/models.rb +3 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9cbd38a8c2df073a4576501953ef2e9debb1d4c36c673c7e5467c04a247ba9cd
|
4
|
+
data.tar.gz: f12be53e1013b2302706e6471bebec9abd0d9edd74efe660d0fcf6d4859368c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e9ff18057af10d974dc456f3ff66633dd2483aae664f6acab881a895ef341b8006a25641441b216189dd61f972fefad067e41351e3cd04020e51d9a7d974272
|
7
|
+
data.tar.gz: 230a6686e806dac2ad28892f2f2f2344f1f7b6b7627f1eb048a1e0e2cce4e4b5f6336e162aa23f37de52197ca41909fa9ac43476a828b4d3fcf5e7ffbdb0dc96
|
data/.github/workflows/ruby.yml
CHANGED
@@ -9,9 +9,18 @@ jobs:
|
|
9
9
|
strategy:
|
10
10
|
fail-fast: false
|
11
11
|
matrix:
|
12
|
-
ruby: ['2.7', '3.0', '3.1']
|
13
|
-
rails: ['6.1', '7.0', 'edge']
|
12
|
+
ruby: ['2.7', '3.0', '3.1', '3.2', '3.3']
|
13
|
+
rails: ['6.1', '7.0', '7.1', 'edge']
|
14
14
|
timezone_aware: [0, 1]
|
15
|
+
exclude:
|
16
|
+
- ruby: '3.2'
|
17
|
+
rails: '6.1'
|
18
|
+
- ruby: '3.3'
|
19
|
+
rails: '6.1'
|
20
|
+
- ruby: '2.7'
|
21
|
+
rails: 'edge'
|
22
|
+
- ruby: '3.0'
|
23
|
+
rails: 'edge'
|
15
24
|
env:
|
16
25
|
BUNDLE_GEMFILE: gemfiles/Gemfile.ar-${{ matrix.rails }}
|
17
26
|
TIMEZONE_AWARE: ${{ matrix.timezone_aware }}
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# ActiveRecord::TypedStore
|
2
2
|
|
3
|
-
[](http://badge.fury.io/rb/activerecord-typedstore)
|
4
4
|
|
5
5
|
[ActiveRecord::Store](http://api.rubyonrails.org/classes/ActiveRecord/Store.html) but with typed attributes.
|
6
6
|
|
@@ -74,20 +74,29 @@ module ActiveRecord::TypedStore
|
|
74
74
|
|
75
75
|
private
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
77
|
+
if ActiveRecord.version.segments.first >= 7
|
78
|
+
def attribute_names_for_partial_inserts
|
79
|
+
# Contrary to all vanilla Rails types, typedstore attribute have an inherent default
|
80
|
+
# value that doesn't match the database column default.
|
81
|
+
# As such we need to insert them on partial inserts even if they weren't changed.
|
82
|
+
super | self.class.typed_stores.keys.map(&:to_s)
|
83
|
+
end
|
83
84
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
85
|
+
def attribute_names_for_partial_updates
|
86
|
+
# On partial updates we shouldn't need to force stores to be persisted. However since
|
87
|
+
# we weren't persisting them for a while on insertion, we now need to gracefully deal
|
88
|
+
# with existing records that may have been persisted with a `NULL` store
|
89
|
+
# We use `blank?` as an heuristic to detect these.
|
90
|
+
super | self.class.typed_stores.keys.map(&:to_s).select do |store|
|
91
|
+
has_attribute?(store) && read_attribute_before_type_cast(store).blank?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
else
|
95
|
+
# Rails 6.1 capability
|
96
|
+
def attribute_names_for_partial_writes
|
97
|
+
super | self.class.typed_stores.keys.map(&:to_s).select do |store|
|
98
|
+
has_attribute?(store) && read_attribute_before_type_cast(store).blank?
|
99
|
+
end
|
91
100
|
end
|
92
101
|
end
|
93
102
|
end
|
@@ -22,7 +22,12 @@ module ActiveRecord::TypedStore
|
|
22
22
|
typed_klass = TypedHash.create(dsl.fields.values)
|
23
23
|
const_set("#{store_attribute}_hash".camelize, typed_klass)
|
24
24
|
|
25
|
-
if ActiveRecord.version >= Gem::Version.new('
|
25
|
+
if ActiveRecord.version >= Gem::Version.new('7.2.0.alpha')
|
26
|
+
decorate_attributes([store_attribute]) do |name, subtype|
|
27
|
+
subtype = subtype.subtype if subtype.is_a?(Type)
|
28
|
+
Type.new(typed_klass, dsl.coder, subtype)
|
29
|
+
end
|
30
|
+
elsif ActiveRecord.version >= Gem::Version.new('6.1.0.alpha')
|
26
31
|
attribute(store_attribute) do |subtype|
|
27
32
|
subtype = subtype.subtype if subtype.is_a?(Type)
|
28
33
|
Type.new(typed_klass, dsl.coder, subtype)
|
@@ -11,12 +11,12 @@ module ActiveRecord::TypedStore
|
|
11
11
|
|
12
12
|
@accessor = options.fetch(:accessor, true)
|
13
13
|
@name = name
|
14
|
+
@array = options.fetch(:array, false)
|
14
15
|
if options.key?(:default)
|
15
16
|
@default = extract_default(options[:default])
|
16
17
|
end
|
17
18
|
@null = options.fetch(:null, true)
|
18
19
|
@blank = options.fetch(:blank, true)
|
19
|
-
@array = options.fetch(:array, false)
|
20
20
|
end
|
21
21
|
|
22
22
|
def has_default?
|
@@ -27,6 +27,8 @@ module ActiveRecord::TypedStore
|
|
27
27
|
casted_value = type_cast(value)
|
28
28
|
if !blank
|
29
29
|
casted_value = default if casted_value.blank?
|
30
|
+
elsif array && has_default?
|
31
|
+
casted_value = default if value.nil?
|
30
32
|
elsif !null
|
31
33
|
casted_value = default if casted_value.nil?
|
32
34
|
end
|
@@ -524,7 +524,7 @@ shared_examples 'a store' do |retain_type = true, settings_type = :text|
|
|
524
524
|
describe 'model.typed_stores' do
|
525
525
|
it "can access keys" do
|
526
526
|
stores = model.class.typed_stores
|
527
|
-
expect(stores[:settings].keys).to eq [:no_default, :name, :email, :cell_phone, :public, :enabled, :age, :max_length, :rate, :price, :published_on, :remind_on, :published_at_time, :remind_at_time, :published_at, :remind_at, :total_price, :shipping_cost, :grades, :tags, :nickname, :author, :source, :signup, :country]
|
527
|
+
expect(stores[:settings].keys).to eq [:no_default, :name, :email, :cell_phone, :public, :enabled, :age, :max_length, :rate, :price, :published_on, :remind_on, :published_at_time, :remind_at_time, :published_at, :remind_at, :total_price, :shipping_cost, :grades, :tags, :subjects, :nickname, :author, :source, :signup, :country]
|
528
528
|
end
|
529
529
|
|
530
530
|
it "can access keys even when accessors are not defined" do
|
@@ -889,9 +889,15 @@ shared_examples 'a model supporting arrays' do |pg_native=false|
|
|
889
889
|
expect(model.reload.grades).to be == [[1, 2], [3, 4, 5]]
|
890
890
|
end
|
891
891
|
|
892
|
+
it 'defaults to [] if provided default is not an array' do
|
893
|
+
model.update(subjects: nil)
|
894
|
+
expect(model.reload.subjects).to be == []
|
895
|
+
end
|
896
|
+
|
897
|
+
# Not sure about pg_native and if this test should be outside of this block.
|
892
898
|
it 'retreive default if assigned null' do
|
893
899
|
model.update(tags: nil)
|
894
|
-
expect(model.reload.tags).to be == []
|
900
|
+
expect(model.reload.tags).to be == ['article']
|
895
901
|
end
|
896
902
|
end
|
897
903
|
end
|
@@ -958,6 +964,7 @@ end
|
|
958
964
|
describe DirtyTrackingModel do
|
959
965
|
it 'stores the default on creation' do
|
960
966
|
model = DirtyTrackingModel.create!
|
967
|
+
model = DirtyTrackingModel.find(model.id)
|
961
968
|
expect(model.settings_before_type_cast).to_not be_blank
|
962
969
|
end
|
963
970
|
|
@@ -973,4 +980,13 @@ describe DirtyTrackingModel do
|
|
973
980
|
expect(model.settings_changed?).to be false
|
974
981
|
expect(model.changes).to be_empty
|
975
982
|
end
|
983
|
+
|
984
|
+
it 'does not update missing attributes in partially loaded records' do
|
985
|
+
model = DirtyTrackingModel.create!(active: true)
|
986
|
+
model = DirtyTrackingModel.select(:id, :title).find(model.id)
|
987
|
+
model.update!(title: "Hello")
|
988
|
+
|
989
|
+
model = DirtyTrackingModel.find(model.id)
|
990
|
+
expect(model.active).to be true
|
991
|
+
end
|
976
992
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -9,9 +9,9 @@ Dir[File.expand_path(File.join(File.dirname(__FILE__), 'support', '**', '*.rb'))
|
|
9
9
|
Time.zone = 'UTC'
|
10
10
|
|
11
11
|
if ActiveRecord.respond_to?(:yaml_column_permitted_classes)
|
12
|
-
ActiveRecord.yaml_column_permitted_classes |= [
|
12
|
+
ActiveRecord.yaml_column_permitted_classes |= [Date, Time, BigDecimal]
|
13
13
|
elsif ActiveRecord::Base.respond_to?(:yaml_column_permitted_classes)
|
14
|
-
ActiveRecord::Base.yaml_column_permitted_classes |= [
|
14
|
+
ActiveRecord::Base.yaml_column_permitted_classes |= [Date, Time, BigDecimal]
|
15
15
|
end
|
16
16
|
|
17
17
|
RSpec.configure do |config|
|
data/spec/support/models.rb
CHANGED
@@ -43,7 +43,8 @@ def define_columns(t, array: false)
|
|
43
43
|
|
44
44
|
if t.is_a?(ActiveRecord::TypedStore::DSL)
|
45
45
|
t.integer :grades, array: true
|
46
|
-
t.string :tags, array: true, null: false, default: []
|
46
|
+
t.string :tags, array: true, null: false, default: ['article']
|
47
|
+
t.string :subjects, array: true, null: false, default: ['mathematics'].to_yaml
|
47
48
|
|
48
49
|
t.string :nickname, blank: false, default: 'Please enter your nickname'
|
49
50
|
end
|
@@ -190,7 +191,7 @@ Models = [
|
|
190
191
|
]
|
191
192
|
|
192
193
|
class DirtyTrackingModel < ActiveRecord::Base
|
193
|
-
after_update :read_active
|
194
|
+
after_update :read_active, if: -> { has_attribute?(:settings) }
|
194
195
|
|
195
196
|
typed_store(:settings) do |f|
|
196
197
|
f.boolean :active, default: false, null: false
|
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.6.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:
|
11
|
+
date: 2024-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -111,6 +111,7 @@ files:
|
|
111
111
|
- activerecord-typedstore.gemspec
|
112
112
|
- gemfiles/Gemfile.ar-6.1
|
113
113
|
- gemfiles/Gemfile.ar-7.0
|
114
|
+
- gemfiles/Gemfile.ar-7.1
|
114
115
|
- gemfiles/Gemfile.ar-edge
|
115
116
|
- lib/active_record/typed_store.rb
|
116
117
|
- lib/active_record/typed_store/behavior.rb
|
@@ -146,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
147
|
- !ruby/object:Gem::Version
|
147
148
|
version: '0'
|
148
149
|
requirements: []
|
149
|
-
rubygems_version: 3.
|
150
|
+
rubygems_version: 3.5.5
|
150
151
|
signing_key:
|
151
152
|
specification_version: 4
|
152
153
|
summary: Add type casting and full method attributes support to АctiveRecord store
|