store_attribute 1.3.1 → 2.0.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/CHANGELOG.md +26 -0
- data/README.md +33 -4
- data/lib/store_attribute/active_record/mutation_tracker.rb +1 -1
- data/lib/store_attribute/active_record/store.rb +32 -17
- data/lib/store_attribute/active_record/type/typed_store.rb +7 -2
- data/lib/store_attribute/version.rb +1 -1
- data/lib/store_attribute.rb +9 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5530282b5ea4488c94d5f90ba1474c9a8b6dd1b153c412cce62a6dca0c69c3d3
|
4
|
+
data.tar.gz: 67f65c84644842ebc7c6cdbcc455f034854d5ada9dd469180cf94a0a4cf02d38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f00159fa7de150635efa6c2d623ab8aacac3b166582fa5b48d623621f38ee79a123903e538faddd8b42d9cca955a9c18ea0fc4ebd32cfaba7de51b233b203891
|
7
|
+
data.tar.gz: f7ee58675bc257f21343054e131b3708ee3d8f5c1f504e814e80e3eb95eb0e506bf69361815736cf50732f8846b1b73671533802854f402bf72881ceaada3de9
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,32 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 2.0.1 (2025-05-09) 🎇
|
6
|
+
|
7
|
+
- Register store_attributes as attributes. ([@rickcsong](https://github.com/rickcsong))
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
class User < ActiveRecord::Base
|
11
|
+
self.store_attribute_register_attributes = true
|
12
|
+
|
13
|
+
store_attribute :extra, :color, :string, default: "grey"
|
14
|
+
end
|
15
|
+
|
16
|
+
User.attribute_types.keys.include?("color") #=> true
|
17
|
+
```
|
18
|
+
|
19
|
+
## 2.0.0 (2024-12-12)
|
20
|
+
|
21
|
+
- **Breaking:** The `store_attribute_unset_values_fallback_to_default` option is now true by default, meaning that the default value will be returned when the attribute key is not present in the serialized value.
|
22
|
+
|
23
|
+
For v1.x behavior, set the option to `false` globally as follows:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
StoreAttribute.store_attribute_unset_values_fallback_to_default = false
|
27
|
+
```
|
28
|
+
|
29
|
+
- Ruby >= 3.0 is required.
|
30
|
+
|
5
31
|
## 1.3.1 (2024-09-19)
|
6
32
|
|
7
33
|
- Populate missing defaults on user input when `store_attribute_unset_values_fallback_to_default` is true. ([@palkan][])
|
data/README.md
CHANGED
@@ -146,15 +146,44 @@ another_user.name #=> nil
|
|
146
146
|
another_user.expired_at #=> nil
|
147
147
|
```
|
148
148
|
|
149
|
-
|
149
|
+
By default, Store Attribute returns the default value even when the record is persisted but the attribute name is not present:
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
user = User.create!(extra: {})
|
153
|
+
user.expired_at #=> 2022-03-19
|
154
|
+
```
|
155
|
+
|
156
|
+
You can disable this behaviour by setting the `store_attribute_unset_values_fallback_to_default` class option to `false` in your model:
|
150
157
|
|
151
158
|
```ruby
|
152
159
|
class User < ApplicationRecord
|
153
|
-
self.store_attribute_unset_values_fallback_to_default =
|
160
|
+
self.store_attribute_unset_values_fallback_to_default = false
|
154
161
|
end
|
155
162
|
|
156
163
|
user = User.create!(extra: {})
|
157
|
-
user.expired_at #=>
|
164
|
+
user.expired_at #=> nil
|
158
165
|
```
|
159
166
|
|
160
|
-
|
167
|
+
You can also configure the global default for this option in an initializer or application configuration:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
# config/initializers/store_attribute.rb
|
171
|
+
# # or
|
172
|
+
# config/application.rb
|
173
|
+
StoreAttribute.store_attribute_unset_values_fallback_to_default = false
|
174
|
+
```
|
175
|
+
|
176
|
+
## Contributing
|
177
|
+
|
178
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/palkan/store_attribute](https://github.com/palkan/store_attribute).
|
179
|
+
|
180
|
+
For local development, you'll need PostgreSQL up and running. You can either install it on your host machine or run via Docker as follows:
|
181
|
+
|
182
|
+
```bash
|
183
|
+
docker run --name store_attribute_postgres -e POSTGRES_HOST_AUTH_METHOD=trust -e POSTGRES_USER=$USER -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres
|
184
|
+
docker exec -it store_attribute_postgres createdb -U $USER store_attribute_test
|
185
|
+
```
|
186
|
+
|
187
|
+
## License
|
188
|
+
|
189
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
@@ -10,6 +10,7 @@ module ActiveRecord
|
|
10
10
|
alias_method :_orig_store_without_types, :store
|
11
11
|
alias_method :_orig_store_accessor_without_types, :store_accessor
|
12
12
|
|
13
|
+
attr_writer :store_attribute_register_attributes
|
13
14
|
attr_writer :store_attribute_unset_values_fallback_to_default
|
14
15
|
|
15
16
|
# Defines store on this model.
|
@@ -133,6 +134,28 @@ module ActiveRecord
|
|
133
134
|
|
134
135
|
_local_typed_stored_attributes[store_name][:owner] = self if options.key?(:default) || !_local_typed_stored_attributes?
|
135
136
|
_local_typed_stored_attributes[store_name][:types][name] = [type, options]
|
137
|
+
|
138
|
+
if store_attribute_register_attributes
|
139
|
+
cast_type =
|
140
|
+
if type == :value
|
141
|
+
ActiveModel::Type::Value.new(**options.except(:default))
|
142
|
+
else
|
143
|
+
ActiveRecord::Type.lookup(type, **options.except(:default))
|
144
|
+
end
|
145
|
+
|
146
|
+
attribute(name, cast_type, **options)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def store_attribute_register_attributes
|
151
|
+
return @store_attribute_register_attributes if instance_variable_defined?(:@store_attribute_register_attributes)
|
152
|
+
|
153
|
+
@store_attribute_register_attributes =
|
154
|
+
if superclass.respond_to?(:store_attribute_register_attributes)
|
155
|
+
superclass.store_attribute_register_attributes
|
156
|
+
else
|
157
|
+
StoreAttribute.store_attribute_register_attributes
|
158
|
+
end
|
136
159
|
end
|
137
160
|
|
138
161
|
def store_attribute_unset_values_fallback_to_default
|
@@ -142,7 +165,7 @@ module ActiveRecord
|
|
142
165
|
if superclass.respond_to?(:store_attribute_unset_values_fallback_to_default)
|
143
166
|
superclass.store_attribute_unset_values_fallback_to_default
|
144
167
|
else
|
145
|
-
|
168
|
+
StoreAttribute.store_attribute_unset_values_fallback_to_default
|
146
169
|
end
|
147
170
|
end
|
148
171
|
|
@@ -170,23 +193,8 @@ module ActiveRecord
|
|
170
193
|
|
171
194
|
owner = self
|
172
195
|
|
173
|
-
# For Rails <6.1
|
174
|
-
if respond_to?(:decorate_attribute_type) && method(:decorate_attribute_type).parameters.count { |type, _| type == :req } == 2
|
175
|
-
decorate_attribute_type(attr_name, "typed_accessor_for_#{attr_name}") do |subtype|
|
176
|
-
subtypes = _local_typed_stored_attributes[attr_name][:types]
|
177
|
-
type = Type::TypedStore.create_from_type(subtype)
|
178
|
-
type.owner = owner
|
179
|
-
defaultik.type = type
|
180
|
-
subtypes.each do |name, (cast_type, options)|
|
181
|
-
type.add_typed_key(name, cast_type, **options.symbolize_keys)
|
182
|
-
end
|
183
|
-
|
184
|
-
define_default_attribute(attr_name, defaultik.proc, type, from_user: true)
|
185
|
-
|
186
|
-
type
|
187
|
-
end
|
188
196
|
# Rails >7.1
|
189
|
-
|
197
|
+
if respond_to?(:decorate_attributes)
|
190
198
|
decorate_attributes([attr_name]) do |_, subtype|
|
191
199
|
subtypes = _local_typed_stored_attributes[attr_name][:types]
|
192
200
|
type = Type::TypedStore.create_from_type(subtype)
|
@@ -215,6 +223,13 @@ module ActiveRecord
|
|
215
223
|
type.add_typed_key(name, cast_type, **options.symbolize_keys)
|
216
224
|
end
|
217
225
|
|
226
|
+
# Make sure default attribute uses the correct type, so #changed? works as expected
|
227
|
+
# This is dirty hack that makes Rails <7.2 works similar to Rails >=7.2. Please, upgrade :)
|
228
|
+
if type.defaults.any? && _default_attributes[attr_name] && !_default_attributes[attr_name].type.is_a?(Type::TypedStore)
|
229
|
+
_default_attributes[attr_name] =
|
230
|
+
ActiveModel::Attribute.from_database(attr_name, _default_attributes[attr_name].value.deep_dup, type)
|
231
|
+
end
|
232
|
+
|
218
233
|
type
|
219
234
|
end
|
220
235
|
end
|
@@ -26,6 +26,7 @@ module ActiveRecord
|
|
26
26
|
end
|
27
27
|
|
28
28
|
attr_writer :owner
|
29
|
+
attr_reader :defaults
|
29
30
|
|
30
31
|
def initialize(subtype)
|
31
32
|
@accessor_types = {}
|
@@ -91,12 +92,16 @@ module ActiveRecord
|
|
91
92
|
self
|
92
93
|
end
|
93
94
|
|
95
|
+
def mutable?
|
96
|
+
true
|
97
|
+
end
|
98
|
+
|
94
99
|
def write(object, attribute, key, value)
|
95
100
|
value = type_for(key).cast(value) if typed?(key)
|
96
101
|
store_accessor.write(object, attribute, key, value)
|
97
102
|
end
|
98
103
|
|
99
|
-
delegate :read, :prepare, to: :store_accessor
|
104
|
+
delegate :get, :read, :prepare, to: :store_accessor
|
100
105
|
|
101
106
|
def build_defaults
|
102
107
|
defaults.transform_values do |val|
|
@@ -140,7 +145,7 @@ module ActiveRecord
|
|
140
145
|
subtype.accessor
|
141
146
|
end
|
142
147
|
|
143
|
-
attr_reader :accessor_types, :
|
148
|
+
attr_reader :accessor_types, :subtype, :owner
|
144
149
|
end
|
145
150
|
end
|
146
151
|
end
|
data/lib/store_attribute.rb
CHANGED
@@ -4,4 +4,13 @@ require "store_attribute/version"
|
|
4
4
|
require "store_attribute/active_record"
|
5
5
|
|
6
6
|
module StoreAttribute
|
7
|
+
class << self
|
8
|
+
# Global default value for `store_attribute_unset_values_fallback_to_default` option.
|
9
|
+
# Must be set before any model is loaded
|
10
|
+
attr_accessor :store_attribute_unset_values_fallback_to_default
|
11
|
+
attr_accessor :store_attribute_register_attributes
|
12
|
+
end
|
13
|
+
|
14
|
+
self.store_attribute_unset_values_fallback_to_default = true
|
15
|
+
self.store_attribute_register_attributes = false
|
7
16
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: store_attribute
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- palkan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-05-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -91,7 +91,7 @@ metadata:
|
|
91
91
|
documentation_uri: http://github.com/palkan/store_attribute
|
92
92
|
homepage_uri: http://github.com/palkan/store_attribute
|
93
93
|
source_code_uri: http://github.com/palkan/store_attribute
|
94
|
-
post_install_message:
|
94
|
+
post_install_message:
|
95
95
|
rdoc_options: []
|
96
96
|
require_paths:
|
97
97
|
- lib
|
@@ -99,7 +99,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
99
99
|
requirements:
|
100
100
|
- - ">="
|
101
101
|
- !ruby/object:Gem::Version
|
102
|
-
version:
|
102
|
+
version: 3.0.0
|
103
103
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
104
|
requirements:
|
105
105
|
- - ">="
|
@@ -107,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
107
|
version: '0'
|
108
108
|
requirements: []
|
109
109
|
rubygems_version: 3.4.19
|
110
|
-
signing_key:
|
110
|
+
signing_key:
|
111
111
|
specification_version: 4
|
112
112
|
summary: ActiveRecord extension which adds typecasting to store accessors
|
113
113
|
test_files: []
|