activerecord-typedstore 1.5.0 → 1.5.1
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 +4 -4
- data/activerecord-typedstore.gemspec +1 -1
- data/gemfiles/{Gemfile.ar-master → Gemfile.ar-edge} +0 -0
- data/lib/active_record/typed_store/behavior.rb +19 -0
- data/lib/active_record/typed_store/type.rb +1 -6
- data/lib/active_record/typed_store/version.rb +1 -1
- data/spec/active_record/typed_store_spec.rb +21 -1
- data/spec/spec_helper.rb +6 -0
- data/spec/support/models.rb +35 -10
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f56fb7b6456937890a85e139a296727a04b2c87a2452f45810782849378357a
|
4
|
+
data.tar.gz: 17e694f93e4db21a4b5a08c7795285fd10aaf9bc203f74376a14356873c84802
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02d3ce60427903e2c039818c4c77368a42b20c4f9fbf5bf167357e0e932d01c717f5eea6172ea03170b018a468b6b8f0a00d59fd49073a38eb620a27e05870c3
|
7
|
+
data.tar.gz: 96ff55688ac6c1b2d9f56d9a45e796b4c633e6d3d1dd89cdbdb14025044d97c9f5deefce7a53494f35ff5a227f340e8ec9d9fba70b7d861fe488ee6f52ad98fe
|
data/.github/workflows/ruby.yml
CHANGED
@@ -5,22 +5,22 @@ on: [push, pull_request]
|
|
5
5
|
jobs:
|
6
6
|
build:
|
7
7
|
runs-on: ubuntu-latest
|
8
|
-
name:
|
8
|
+
name: ${{ matrix.ruby }} / Rails ${{ matrix.rails }} / TZ ${{ matrix.timezone_aware }}
|
9
9
|
strategy:
|
10
10
|
fail-fast: false
|
11
11
|
matrix:
|
12
12
|
ruby: ['2.7', '3.0', '3.1']
|
13
|
-
|
13
|
+
rails: ['6.1', '7.0', 'edge']
|
14
14
|
timezone_aware: [0, 1]
|
15
15
|
env:
|
16
|
-
BUNDLE_GEMFILE: gemfiles
|
16
|
+
BUNDLE_GEMFILE: gemfiles/Gemfile.ar-${{ matrix.rails }}
|
17
17
|
TIMEZONE_AWARE: ${{ matrix.timezone_aware }}
|
18
18
|
POSTGRES: 1
|
19
19
|
MYSQL: 1
|
20
20
|
POSTGRES_JSON: 1
|
21
21
|
steps:
|
22
22
|
- name: Check out code
|
23
|
-
uses: actions/checkout@
|
23
|
+
uses: actions/checkout@v3
|
24
24
|
- name: Set up Ruby ${{ matrix.ruby }}
|
25
25
|
uses: ruby/setup-ruby@v1
|
26
26
|
with:
|
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_dependency 'activerecord', '>= 6.1'
|
22
22
|
|
23
23
|
spec.add_development_dependency 'bundler'
|
24
|
-
spec.add_development_dependency 'rake'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
25
|
spec.add_development_dependency 'rspec', '~> 3'
|
26
26
|
spec.add_development_dependency 'sqlite3', '~> 1'
|
27
27
|
spec.add_development_dependency 'database_cleaner', '~> 1'
|
File without changes
|
@@ -71,5 +71,24 @@ module ActiveRecord::TypedStore
|
|
71
71
|
super
|
72
72
|
end
|
73
73
|
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def attribute_names_for_partial_inserts
|
78
|
+
# Contrary to all vanilla Rails types, typedstore attribute have an inherent default
|
79
|
+
# value that doesn't match the database column default.
|
80
|
+
# As such we need to insert them on partial inserts even if they weren't changed.
|
81
|
+
super | self.class.typed_stores.keys.map(&:to_s)
|
82
|
+
end
|
83
|
+
|
84
|
+
def attribute_names_for_partial_updates
|
85
|
+
# On partial updates we shouldn't need to force stores to be persisted. However since
|
86
|
+
# we weren't persisting them for a while on insertion, we now need to gracefully deal
|
87
|
+
# with existing records that may have been persisted with a `NULL` store
|
88
|
+
# We use `blank?` as an heuristic to detect these.
|
89
|
+
super | self.class.typed_stores.keys.map(&:to_s).select do |store|
|
90
|
+
@attributes.key?(store) && @attributes[store].value_before_type_cast.blank?
|
91
|
+
end
|
92
|
+
end
|
74
93
|
end
|
75
94
|
end
|
@@ -41,12 +41,7 @@ module ActiveRecord::TypedStore
|
|
41
41
|
|
42
42
|
def changed_in_place?(raw_old_value, value)
|
43
43
|
return false if value.nil?
|
44
|
-
|
45
|
-
raw_new_value = serialize(value)
|
46
|
-
else
|
47
|
-
# 4.2 capability
|
48
|
-
raw_new_value = type_cast_for_database(value)
|
49
|
-
end
|
44
|
+
raw_new_value = serialize(value)
|
50
45
|
raw_old_value.nil? != raw_new_value.nil? || raw_old_value != raw_new_value
|
51
46
|
end
|
52
47
|
end
|
@@ -925,7 +925,7 @@ describe YamlTypedStoreModel do
|
|
925
925
|
|
926
926
|
it 'nested hashes are not serialized as HashWithIndifferentAccess' do
|
927
927
|
model = described_class.create!
|
928
|
-
expect(model.settings_before_type_cast).not_to include('HashWithIndifferentAccess')
|
928
|
+
expect(model.settings_before_type_cast.to_s).not_to include('HashWithIndifferentAccess')
|
929
929
|
end
|
930
930
|
end
|
931
931
|
|
@@ -954,3 +954,23 @@ describe InheritedTypedStoreModel do
|
|
954
954
|
expect(model.settings[:new_attribute]).to be == '42'
|
955
955
|
end
|
956
956
|
end
|
957
|
+
|
958
|
+
describe DirtyTrackingModel do
|
959
|
+
it 'stores the default on creation' do
|
960
|
+
model = DirtyTrackingModel.create!
|
961
|
+
expect(model.settings_before_type_cast).to_not be_blank
|
962
|
+
end
|
963
|
+
|
964
|
+
it 'handles loaded records having uninitialized defaults' do
|
965
|
+
model = DirtyTrackingModel.create!
|
966
|
+
DirtyTrackingModel.update_all("settings = NULL") # bypass validation
|
967
|
+
model = DirtyTrackingModel.find(model.id)
|
968
|
+
expect(model.settings_changed?).to be false
|
969
|
+
expect(model.changes).to be_empty
|
970
|
+
|
971
|
+
model.update!(title: "Hello")
|
972
|
+
|
973
|
+
expect(model.settings_changed?).to be false
|
974
|
+
expect(model.changes).to be_empty
|
975
|
+
end
|
976
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -8,6 +8,12 @@ Dir[File.expand_path(File.join(File.dirname(__FILE__), 'support', '**', '*.rb'))
|
|
8
8
|
|
9
9
|
Time.zone = 'UTC'
|
10
10
|
|
11
|
+
if ActiveRecord.respond_to?(:yaml_column_permitted_classes)
|
12
|
+
ActiveRecord.yaml_column_permitted_classes |= ['Date', 'Time', 'BigDecimal']
|
13
|
+
elsif ActiveRecord::Base.respond_to?(:yaml_column_permitted_classes)
|
14
|
+
ActiveRecord::Base.yaml_column_permitted_classes |= ['Date', 'Time', 'BigDecimal']
|
15
|
+
end
|
16
|
+
|
11
17
|
RSpec.configure do |config|
|
12
18
|
config.order = 'random'
|
13
19
|
end
|
data/spec/support/models.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_record'
|
2
|
+
require 'base64'
|
2
3
|
require 'json'
|
3
4
|
require 'yaml'
|
4
5
|
|
@@ -12,7 +13,7 @@ ActiveRecord::Base.configurations = {
|
|
12
13
|
}
|
13
14
|
}
|
14
15
|
|
15
|
-
def define_columns(t)
|
16
|
+
def define_columns(t, array: false)
|
16
17
|
t.integer :no_default
|
17
18
|
|
18
19
|
t.string :name, default: '', null: false
|
@@ -40,11 +41,12 @@ def define_columns(t)
|
|
40
41
|
t.decimal :total_price, default: 4.2, null: false, precision: 16, scale: 2
|
41
42
|
t.decimal :shipping_cost, precision: 16, scale: 2
|
42
43
|
|
43
|
-
t.
|
44
|
+
if t.is_a?(ActiveRecord::TypedStore::DSL)
|
45
|
+
t.integer :grades, array: true
|
46
|
+
t.string :tags, array: true, null: false, default: [].to_yaml
|
44
47
|
|
45
|
-
|
46
|
-
|
47
|
-
t.string :nickname, blank: false, default: 'Please enter your nickname'
|
48
|
+
t.string :nickname, blank: false, default: 'Please enter your nickname'
|
49
|
+
end
|
48
50
|
end
|
49
51
|
|
50
52
|
def define_store_with_no_attributes(**options)
|
@@ -79,15 +81,21 @@ def define_stores_with_prefix_and_suffix(**options)
|
|
79
81
|
typed_store(:custom_suffixed_settings, suffix: :custom, **options) { |t| t.any :language }
|
80
82
|
end
|
81
83
|
|
82
|
-
MigrationClass = ActiveRecord::Migration["
|
84
|
+
MigrationClass = ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"]
|
83
85
|
class CreateAllTables < MigrationClass
|
84
|
-
|
85
86
|
def self.up
|
86
87
|
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations.configs_for(env_name: "test", name: :test_sqlite3))
|
87
88
|
create_table(:sqlite3_regular_ar_models, force: true) { |t| define_columns(t); t.text :untyped_settings }
|
88
|
-
create_table(:yaml_typed_store_models, force: true) { |t| %i[settings explicit_settings partial_settings untyped_settings prefixed_settings suffixed_settings custom_prefixed_settings custom_suffixed_settings].each { |column| t.text column} }
|
89
|
-
create_table(:json_typed_store_models, force: true) { |t| %i[settings explicit_settings partial_settings untyped_settings prefixed_settings suffixed_settings custom_prefixed_settings custom_suffixed_settings].each { |column| t.text column} }
|
90
|
-
create_table(:marshal_typed_store_models, force: true) { |t| %i[settings explicit_settings partial_settings untyped_settings prefixed_settings suffixed_settings custom_prefixed_settings custom_suffixed_settings].each { |column| t.text column} }
|
89
|
+
create_table(:yaml_typed_store_models, force: true) { |t| %i[settings explicit_settings partial_settings untyped_settings prefixed_settings suffixed_settings custom_prefixed_settings custom_suffixed_settings].each { |column| t.text column}; t.string :regular_column }
|
90
|
+
create_table(:json_typed_store_models, force: true) { |t| %i[settings explicit_settings partial_settings untyped_settings prefixed_settings suffixed_settings custom_prefixed_settings custom_suffixed_settings].each { |column| t.text column}; t.string :regular_column }
|
91
|
+
create_table(:marshal_typed_store_models, force: true) { |t| %i[settings explicit_settings partial_settings untyped_settings prefixed_settings suffixed_settings custom_prefixed_settings custom_suffixed_settings].each { |column| t.text column}; t.string :regular_column }
|
92
|
+
|
93
|
+
create_table(:dirty_tracking_models, force: true) do |t|
|
94
|
+
t.string :title
|
95
|
+
t.text :settings
|
96
|
+
|
97
|
+
t.timestamps
|
98
|
+
end
|
91
99
|
end
|
92
100
|
end
|
93
101
|
ActiveRecord::Migration.verbose = true
|
@@ -121,6 +129,11 @@ class YamlTypedStoreModel < ActiveRecord::Base
|
|
121
129
|
establish_connection :test_sqlite3
|
122
130
|
store :untyped_settings, accessors: [:title]
|
123
131
|
|
132
|
+
after_update :read_active
|
133
|
+
def read_active
|
134
|
+
enabled
|
135
|
+
end
|
136
|
+
|
124
137
|
define_store_with_attributes
|
125
138
|
define_store_with_no_attributes
|
126
139
|
define_store_with_partial_attributes
|
@@ -175,3 +188,15 @@ Models = [
|
|
175
188
|
JsonTypedStoreModel,
|
176
189
|
MarshalTypedStoreModel
|
177
190
|
]
|
191
|
+
|
192
|
+
class DirtyTrackingModel < ActiveRecord::Base
|
193
|
+
after_update :read_active
|
194
|
+
|
195
|
+
typed_store(:settings) do |f|
|
196
|
+
f.boolean :active, default: false, null: false
|
197
|
+
end
|
198
|
+
|
199
|
+
def read_active
|
200
|
+
active
|
201
|
+
end
|
202
|
+
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: 1.5.
|
4
|
+
version: 1.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jean Boussier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -42,16 +42,16 @@ dependencies:
|
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,7 +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-
|
114
|
+
- gemfiles/Gemfile.ar-edge
|
115
115
|
- lib/active_record/typed_store.rb
|
116
116
|
- lib/active_record/typed_store/behavior.rb
|
117
117
|
- lib/active_record/typed_store/dsl.rb
|