store_model 2.0.1 → 2.1.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/README.md +43 -1
- data/lib/store_model/configuration.rb +4 -0
- data/lib/store_model/model.rb +23 -2
- data/lib/store_model/nested_attributes.rb +50 -12
- data/lib/store_model/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61353c039b8274db76c67d73081ce718a5446e392df4bd5987f4dde023d5b244
|
4
|
+
data.tar.gz: 40f5011957af3787650b1f3565468fc0b59a4c1a2e090735e8cbf9926e8b622e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e3065c9503681ac881fe2e2b2194bfc9f9c959c66e4a6430b47160ff4487cc1bdc6f4408dfc72e216f94eae729ce8462e09ae12364e3e37ef5341769588a796
|
7
|
+
data.tar.gz: 427cb2dab39fd79ef74fb3b1a1e48f89003fbb2e00ca25488cea257cc9f87c9aad5eedb4c469252a605e5932420ad6e257898e85ab7622c904c7cec99c75af73
|
data/README.md
CHANGED
@@ -76,7 +76,49 @@ product.save
|
|
76
76
|
_Usage note: Rails and assigning Arrays/Hashes to records_
|
77
77
|
|
78
78
|
- Assigned attributes must be a String, Hash, Array of Hashes, or StoreModel. For example, if the attributes are coming from a controller, be sure to convert any ActionController::Parameters as needed.
|
79
|
-
- Any changes made to a StoreModel instance requires the attribute be
|
79
|
+
- Any changes made to a StoreModel instance requires the attribute be flagged as dirty, either by reassignment (`self.my_stored_models = my_stored_models.map(&:as_json)`) or by `will_change!` (`self.my_stored_models_will_change!`)
|
80
|
+
- Mixing `StoreModel::NestedAttributes` into your model will allow you to use `accepts_nested_attributes_for` in the same way as ActiveRecord.
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
class Supplier < ActiveRecord::Base
|
84
|
+
include StoreModel::NestedAttributes
|
85
|
+
|
86
|
+
has_many :bicycles, dependent: :destroy
|
87
|
+
|
88
|
+
attribute :products, Product.to_array_type
|
89
|
+
|
90
|
+
accepts_nested_attributes_for :bicycles, :products, allow_destroy: true
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
This will allow the form builders to work their magic:
|
95
|
+
|
96
|
+
```erb
|
97
|
+
<%= form_with model: @supplier do |form| %>
|
98
|
+
<%= form.fields_for :products do |product_fields| %>
|
99
|
+
<%= product_fields.text_field :name %>
|
100
|
+
<% end %>
|
101
|
+
<% end %>
|
102
|
+
```
|
103
|
+
|
104
|
+
Resulting in:
|
105
|
+
```html
|
106
|
+
<input type="text" name="supplier[products_attributes][0][name]" id="supplier_products_attributes_0_name">
|
107
|
+
```
|
108
|
+
|
109
|
+
In the controller:
|
110
|
+
```ruby
|
111
|
+
def create
|
112
|
+
@supplier = Supplier.new(supplier_params)
|
113
|
+
@supplier.save
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def supplier_params
|
119
|
+
params.require(:supplier).permit(products_attributes: [:name])
|
120
|
+
end
|
121
|
+
```
|
80
122
|
|
81
123
|
## Documentation
|
82
124
|
|
@@ -15,6 +15,10 @@ module StoreModel
|
|
15
15
|
# @return [Boolean]
|
16
16
|
attr_accessor :serialize_unknown_attributes
|
17
17
|
|
18
|
+
# Controls if the result of `as_json` will serialize enum fiels using `as_json`
|
19
|
+
# @return [Boolean]
|
20
|
+
attr_accessor :serialize_enums_using_as_json
|
21
|
+
|
18
22
|
def initialize
|
19
23
|
@serialize_unknown_attributes = true
|
20
24
|
end
|
data/lib/store_model/model.rb
CHANGED
@@ -31,16 +31,24 @@ module StoreModel
|
|
31
31
|
# @param options [Hash]
|
32
32
|
#
|
33
33
|
# @return [Hash]
|
34
|
-
def as_json(options = {})
|
34
|
+
def as_json(options = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
35
35
|
serialize_unknown_attributes = if options.key?(:serialize_unknown_attributes)
|
36
36
|
options[:serialize_unknown_attributes]
|
37
37
|
else
|
38
38
|
StoreModel.config.serialize_unknown_attributes
|
39
39
|
end
|
40
40
|
|
41
|
+
serialize_enums_using_as_json = if options.key?(:serialize_enums_using_as_json)
|
42
|
+
options[:serialize_enums_using_as_json]
|
43
|
+
else
|
44
|
+
StoreModel.config.serialize_enums_using_as_json
|
45
|
+
end
|
46
|
+
|
41
47
|
result = attributes.with_indifferent_access
|
42
48
|
result.merge!(unknown_attributes) if serialize_unknown_attributes
|
43
|
-
result.as_json(options)
|
49
|
+
result.as_json(options).tap do |json|
|
50
|
+
serialize_enums!(json) if serialize_enums_using_as_json
|
51
|
+
end
|
44
52
|
end
|
45
53
|
|
46
54
|
# Returns an Object, similar to Hash#fetch, raises
|
@@ -186,5 +194,18 @@ module StoreModel
|
|
186
194
|
else value.present?
|
187
195
|
end
|
188
196
|
end
|
197
|
+
|
198
|
+
def serialize_enums!(json)
|
199
|
+
enum_mappings =
|
200
|
+
self.class
|
201
|
+
.attribute_types
|
202
|
+
.select { |_, type| type.is_a?(StoreModel::Types::EnumType) }
|
203
|
+
|
204
|
+
enum_mappings.each do |name, _|
|
205
|
+
next unless json.key?(name)
|
206
|
+
|
207
|
+
json[name] = public_send(name).as_json unless json[name].nil?
|
208
|
+
end
|
209
|
+
end
|
189
210
|
end
|
190
211
|
end
|
@@ -13,27 +13,54 @@ module StoreModel
|
|
13
13
|
# @param associations [Array] list of associations and options to define attributes, for example:
|
14
14
|
# accepts_nested_attributes_for [:suppliers, allow_destroy: true]
|
15
15
|
#
|
16
|
+
# Alternatively, use the standard Rails syntax:
|
17
|
+
#
|
18
|
+
# @param associations [Array] list of associations and attributes to define getters and setters.
|
19
|
+
#
|
20
|
+
# @param options [Hash] options not supported by StoreModel will still be passed to ActiveRecord.
|
21
|
+
#
|
16
22
|
# Supported options:
|
17
23
|
# [:allow_destroy]
|
18
24
|
# If true, destroys any members from the attributes hash with a
|
19
25
|
# <tt>_destroy</tt> key and a value that evaluates to +true+
|
20
26
|
# (e.g. 1, '1', true, or 'true'). This option is off by default.
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
#
|
28
|
+
# [:reject_if]
|
29
|
+
# Allows you to specify a Proc or a Symbol pointing to a method that
|
30
|
+
# checks whether a record should be built for a certain attribute hash.
|
31
|
+
# The hash is passed to the supplied Proc or the method and it should
|
32
|
+
# return either true or false. Passing <tt>:all_blank</tt> instead of a Proc
|
33
|
+
# will create a proc that will reject a record where all the attributes
|
34
|
+
# are blank excluding any value for <tt>_destroy</tt>.
|
35
|
+
#
|
36
|
+
# See https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#method-i-accepts_nested_attributes_for
|
37
|
+
def accepts_nested_attributes_for(*attributes)
|
38
|
+
global_options = attributes.extract_options!
|
30
39
|
|
31
|
-
|
40
|
+
attributes.each do |attribute, options|
|
41
|
+
case attribute_types[attribute.to_s]
|
42
|
+
when Types::OneBase, Types::ManyBase
|
43
|
+
define_store_model_attr_accessors(attribute, options || global_options)
|
44
|
+
else
|
45
|
+
super(attribute, options || global_options)
|
46
|
+
end
|
32
47
|
end
|
33
48
|
end
|
34
49
|
|
35
50
|
private
|
36
51
|
|
52
|
+
def define_store_model_attr_accessors(attribute, options)
|
53
|
+
case attribute_types[attribute.to_s]
|
54
|
+
when Types::OneBase
|
55
|
+
define_association_setter_for_single(attribute, options)
|
56
|
+
alias_method "#{attribute}_attributes=", "#{attribute}="
|
57
|
+
when Types::ManyBase
|
58
|
+
define_association_setter_for_many(attribute, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
define_attr_accessor_for_destroy(attribute, options)
|
62
|
+
end
|
63
|
+
|
37
64
|
def define_attr_accessor_for_destroy(association, options)
|
38
65
|
return unless options&.dig(:allow_destroy)
|
39
66
|
|
@@ -61,8 +88,6 @@ module StoreModel
|
|
61
88
|
end
|
62
89
|
end
|
63
90
|
|
64
|
-
private
|
65
|
-
|
66
91
|
def assign_nested_attributes_for_collection_association(association, attributes, options)
|
67
92
|
attributes = attributes.values if attributes.is_a?(Hash)
|
68
93
|
|
@@ -72,7 +97,20 @@ module StoreModel
|
|
72
97
|
end
|
73
98
|
end
|
74
99
|
|
100
|
+
attributes.reject! { |attribute| call_reject_if(attribute, options[:reject_if]) } if options&.dig(:reject_if)
|
101
|
+
|
75
102
|
send("#{association}=", attributes)
|
76
103
|
end
|
104
|
+
|
105
|
+
def call_reject_if(attributes, callback)
|
106
|
+
callback = ActiveRecord::NestedAttributes::ClassMethods::REJECT_ALL_BLANK_PROC if callback == :all_blank
|
107
|
+
|
108
|
+
case callback
|
109
|
+
when Symbol
|
110
|
+
method(callback).arity.zero? ? send(callback) : send(callback, attributes)
|
111
|
+
when Proc
|
112
|
+
callback.call(attributes)
|
113
|
+
end
|
114
|
+
end
|
77
115
|
end
|
78
116
|
end
|
data/lib/store_model/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: store_model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- DmitryTsepelev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|