attr_json 0.3.0 → 0.4.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 +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +9 -5
- data/Appraisals +40 -0
- data/Gemfile +31 -35
- data/README.md +11 -1
- data/attr_json.gemspec +7 -2
- data/doc_src/forms.md +75 -13
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/rails_5_0.gemfile +19 -0
- data/gemfiles/rails_5_1.gemfile +18 -0
- data/gemfiles/rails_5_2.gemfile +18 -0
- data/gemfiles/rails_edge_6.gemfile +19 -0
- data/lib/attr_json/config.rb +1 -1
- data/lib/attr_json/nested_attributes.rb +7 -1
- data/lib/attr_json/nested_attributes/writer.rb +26 -1
- data/lib/attr_json/record.rb +10 -3
- data/lib/attr_json/type/array.rb +6 -0
- data/lib/attr_json/version.rb +1 -1
- metadata +25 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 05247aceb96f0df4ce9f36a4f6c56099700a33aeddcc0d2a9596330f0ecb23c9
|
|
4
|
+
data.tar.gz: ed213264805ed42866d00c6e03e5504a63c96763ac1f83a3518302dbb5c51954
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 193073a8b1ac277d2f062bb8fae958ec2be300e53216e29fd7af5cf8e70db96e39da92c23ee2f452907b31e55fca0966dff7dd6e45c270028dd2c400a4f53477
|
|
7
|
+
data.tar.gz: d92e6761a2dfab4db80931a5af85bbad112631b12f0c62536fcd5ff532df41ffb475a0bea3cd10ac7d013b7ab4d779a19e2af980ab00fa320168715840e32fcc
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -8,10 +8,14 @@ language: ruby
|
|
|
8
8
|
cache: bundler
|
|
9
9
|
rvm:
|
|
10
10
|
- 2.4
|
|
11
|
-
- 2.5.
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
11
|
+
- 2.5.1
|
|
12
|
+
gemfile:
|
|
13
|
+
- gemfiles/rails_5_0.gemfile
|
|
14
|
+
- gemfiles/rails_5_1.gemfile
|
|
15
|
+
- gemfiles/rails_5_2.gemfile
|
|
16
|
+
- gemfiles/rails_edge_6.gemfile
|
|
16
17
|
before_install:
|
|
17
18
|
- gem install bundler -v 1.14.6
|
|
19
|
+
matrix:
|
|
20
|
+
allow_failures:
|
|
21
|
+
- gemfile: gemfiles/rails_edge_6.gemfile
|
data/Appraisals
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
appraise "rails-5-0" do
|
|
2
|
+
gem 'combustion', '~> 0.9.0'
|
|
3
|
+
|
|
4
|
+
gem "rails", "~> 5.0.0"
|
|
5
|
+
|
|
6
|
+
# rails 5.1+ includes it by default, but rails 5.0 needs it:
|
|
7
|
+
gem 'rails-ujs', require: false
|
|
8
|
+
|
|
9
|
+
# Rails 5 won't work with pg 1.0 even though it doesn't say so
|
|
10
|
+
gem "pg", "~> 0.18"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
appraise "rails-5-1" do
|
|
14
|
+
gem 'combustion', '~> 0.9.0'
|
|
15
|
+
|
|
16
|
+
gem "rails", "~> 5.1.0"
|
|
17
|
+
|
|
18
|
+
gem "pg", "~> 1.0"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
appraise "rails-5-2" do
|
|
22
|
+
gem 'combustion', '~> 0.9.0'
|
|
23
|
+
|
|
24
|
+
gem "rails", "~> 5.2.0"
|
|
25
|
+
gem "pg", "~> 1.0"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
appraise "rails-edge-6" do
|
|
29
|
+
# Edge rails needs unreleased combustion
|
|
30
|
+
# https://github.com/pat/combustion/issues/92
|
|
31
|
+
gem 'combustion', git: "https://github.com/pat/combustion.git"
|
|
32
|
+
|
|
33
|
+
gem "rails", git: "https://github.com/rails/rails.git", branch: "master"
|
|
34
|
+
gem "pg", "~> 1.0"
|
|
35
|
+
|
|
36
|
+
# We don't actually use coffeescript at all, we need coffee-rails as an explicit
|
|
37
|
+
# dependency just for transitory edge weirdness using current sprockets release
|
|
38
|
+
# with rails 6 edge.
|
|
39
|
+
gem 'coffee-rails'
|
|
40
|
+
end
|
data/Gemfile
CHANGED
|
@@ -3,40 +3,36 @@ source 'https://rubygems.org'
|
|
|
3
3
|
# Specify your gem's dependencies in attr_json.gemspec
|
|
4
4
|
gemspec
|
|
5
5
|
|
|
6
|
-
# for
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# This shouldn't really be needed, but seems to maybe be a bundler bug,
|
|
36
|
-
# this makes standalone_migrations dependencies resolve properly even when our
|
|
37
|
-
# RAILS_REQ is for 5.2.0.rc2. If in the future you delete this and everything
|
|
38
|
-
# still passes, feel free to remove.
|
|
39
|
-
gem "railties", ENV['RAILS_GEM'].split(",")
|
|
40
|
-
end
|
|
6
|
+
# Dependencies for testing and development. To let appraisal override them, we
|
|
7
|
+
# do NOT put them in group :test,:development -- which anyway doesn't make a
|
|
8
|
+
# lot of sense in a gem Gemfile anyway, there is no "production" in a gem Gemfile.
|
|
9
|
+
#
|
|
10
|
+
# We also have these development dependencies here in the Gemfile instead of the
|
|
11
|
+
# gemspec so appraisal can override them from our Appraisal file.
|
|
12
|
+
|
|
13
|
+
gem 'combustion', '~> 0.9.0'
|
|
14
|
+
|
|
15
|
+
# all of rails is NOT a dependency, just activerecord.
|
|
16
|
+
# But we use it for integration testing with combustion. Hmm, a bit annoying
|
|
17
|
+
# that now our other tests can't be sure they're depending, this might not
|
|
18
|
+
# be the way to do it.
|
|
19
|
+
gem 'rails'
|
|
20
|
+
|
|
21
|
+
# We should not really need to mention railties, it's already a dependency of
|
|
22
|
+
# rails, but seems to be necessary to get around some mystery bug in bundler
|
|
23
|
+
# dependency resolution.
|
|
24
|
+
gem 'railties'
|
|
25
|
+
|
|
26
|
+
gem "pg"
|
|
27
|
+
gem "rspec-rails", "~> 3.7"
|
|
28
|
+
gem "simple_form", ">= 4.0"
|
|
29
|
+
gem 'cocoon', ">= 1.2"
|
|
30
|
+
gem 'jquery-rails'
|
|
31
|
+
|
|
32
|
+
gem 'capybara', "~> 3.0"
|
|
33
|
+
gem "chromedriver-helper"
|
|
34
|
+
gem "selenium-webdriver"
|
|
41
35
|
|
|
42
36
|
gem "byebug"
|
|
37
|
+
|
|
38
|
+
|
data/README.md
CHANGED
|
@@ -116,7 +116,13 @@ model.json_attributes_before_type_cast # => string containing: {"__my_string":"f
|
|
|
116
116
|
|
|
117
117
|
You can of course combine `array`, `default`, `store_key`, and `container_attribute`
|
|
118
118
|
params however you like, with whatever types you like: symbols resolvable
|
|
119
|
-
with `
|
|
119
|
+
with `ActiveRecord::Type.lookup`, or any [ActiveModel::Type::Value](https://apidock.com/rails/ActiveRecord/Attributes/ClassMethods/attribute) subclass, built-in or custom.
|
|
120
|
+
|
|
121
|
+
You can register your custom `ActiveModel::Type::Value` in a Rails initializer or early on in your app boot sequence:
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
ActiveRecord::Type.register(:my_type, MyActiveModelTypeSubclass)
|
|
125
|
+
```
|
|
120
126
|
|
|
121
127
|
<a name="querying"></a>
|
|
122
128
|
## Querying
|
|
@@ -418,6 +424,10 @@ At present this does mean that all our automated tests are run in a full Rails e
|
|
|
418
424
|
|
|
419
425
|
Tests are in rspec, run tests simply with `./bin/rspec`.
|
|
420
426
|
|
|
427
|
+
We use [appraisal](https://github.com/thoughtbot/appraisal) to test with multiple rails versions, including on travis. Locally you can run `bundle exec appraisal rspec` to run tests multiple times for each rails version, or eg `bundle exec appraisal rails-5-1 rspec`. If the `Gemfile` _or_ `Appraisal` file changes, you may need to re-run `bundle exec appraisal install` and commit changes. (Try to put dev dependencies in gemspec instead of Gemfile, but sometimes it gets weird.)
|
|
428
|
+
|
|
429
|
+
* If you've been switching between rails versions and you get integration test failures, try `rm -rf spec/internal/tmp/cache`. Rails 6 does some things in there apparently not compatible with Rails 5, at least in our setup, and vice versa.
|
|
430
|
+
|
|
421
431
|
There is a `./bin/console` that will give you a console in the context of attr_json and all it's dependencies, including the combustion rails app, and the models defined there.
|
|
422
432
|
|
|
423
433
|
## Acknowledements and Prior Art
|
data/attr_json.gemspec
CHANGED
|
@@ -42,11 +42,16 @@ attributes use as much of the existing ActiveRecord architecture as we can.}
|
|
|
42
42
|
|
|
43
43
|
spec.required_ruby_version = '>= 2.4.0'
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
# Only to get CI to work on versions of Rails other than we release with,
|
|
46
|
+
# should never release a gem with RAILS_GEM set!
|
|
47
|
+
unless ENV['APPRAISAL_INITIALIZED'] || ENV["TRAVIS"]
|
|
48
|
+
spec.add_runtime_dependency "activerecord", ">= 5.0.0", "< 5.3"
|
|
49
|
+
end
|
|
46
50
|
|
|
47
51
|
spec.add_development_dependency "bundler", "~> 1.14"
|
|
48
52
|
spec.add_development_dependency "rake", ">= 10.0"
|
|
49
|
-
spec.add_development_dependency "rspec", "~> 3.
|
|
53
|
+
spec.add_development_dependency "rspec", "~> 3.7"
|
|
50
54
|
spec.add_development_dependency "database_cleaner", "~> 1.5"
|
|
51
55
|
spec.add_development_dependency "yard-activesupport-concern"
|
|
56
|
+
spec.add_development_dependency "appraisal", "~> 2.2"
|
|
52
57
|
end
|
data/doc_src/forms.md
CHANGED
|
@@ -23,19 +23,6 @@ It _will_ work with the weird rails multi-param setting used for date fields.
|
|
|
23
23
|
|
|
24
24
|
Don't forget you gotta handle strong params same as you would for any ordinary attribute.
|
|
25
25
|
|
|
26
|
-
### Arrays of simple attributes
|
|
27
|
-
|
|
28
|
-
attr_json :string_array, :string, array: true
|
|
29
|
-
|
|
30
|
-
The ActionView+ActiveRecord architecture isn't really setup for an array of "primitives", but you can make it work:
|
|
31
|
-
|
|
32
|
-
<% f.object.string_array.each do |str| %>
|
|
33
|
-
<%= f.text_field(:string_array, value: str, multiple: true) %>
|
|
34
|
-
<% end %>
|
|
35
|
-
|
|
36
|
-
That will display, submit and update fine, although when you try to handle reporting validation errors, you'll probably only be able to report on the array, not the specific element.
|
|
37
|
-
|
|
38
|
-
You may want to [use SimpleForm and create a custom input](https://github.com/plataformatec/simple_form#custom-inputs) to handle arrays of primitives in the way you want. Or you may want to consider an array of AttrJson::Model value types instead -- you can have a model with only one attribute! It can be handled more conventionally, see below.
|
|
39
26
|
|
|
40
27
|
### Embedded/Nested AttrJson::Model attributes
|
|
41
28
|
|
|
@@ -81,6 +68,37 @@ It should just work as you are expecting! You have to handle strong params as no
|
|
|
81
68
|
|
|
82
69
|
Note that the `AttrJsons::NestedAttributes` module also adds convenient rails-style `build_` methods for you. In the case above, you get a `build_one_event` and `build_many_event` (note singularization, cause that's how Rails does) method, which you can use much like Rails' `build_to_one_association` or `to_many_assocication.build` methods. You can turn off creation of the build methods by passing `define_build_method: false` to `attr_json_accepts_nested_attributes_for`.
|
|
83
70
|
|
|
71
|
+
### Shortcuts for attr_json_accepts_nested_attributes_for
|
|
72
|
+
|
|
73
|
+
You can automatically add the 'accepts nested attributes' call when you define your attribute, including with additional arguments like `reject_if`.
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
class SomeRecord < ApplicationRecord
|
|
77
|
+
include AttrJson::Record
|
|
78
|
+
include AttrJson::NestedAttributes
|
|
79
|
+
|
|
80
|
+
attr_json :one_event, Event.to_type, accepts_nested_attributes: true
|
|
81
|
+
attr_json :many_events, Event.to_type, array: true, accepts_nested_attributes: { reject_if: :all_blank }
|
|
82
|
+
end
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
You can also set defaults for the whole class:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
class SomeRecord < ApplicationRecord
|
|
89
|
+
include AttrJson::Record
|
|
90
|
+
include AttrJson::NestedAttributes
|
|
91
|
+
|
|
92
|
+
attr_json_config(default_accepts_nested_attributes_for: { reject_if: :all_blank })
|
|
93
|
+
|
|
94
|
+
attr_json :one_event, Event.to_type, accepts_nested_attributes: false # override default
|
|
95
|
+
attr_json :many_events, Event.to_type, array: true
|
|
96
|
+
end
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If you're doing a lot of rails-style nested attributes form handling, the above probably makes sense. More convenient than having to do it each time, or repeat every param in another
|
|
100
|
+
long call.
|
|
101
|
+
|
|
84
102
|
### Nested multi-level/compound embedded models
|
|
85
103
|
|
|
86
104
|
A model inside a model inside a model? Some single and some array? No problem, should just work.
|
|
@@ -105,6 +123,50 @@ This will use the [ActiveRecord::Base.attribute](http://api.rubyonrails.org/clas
|
|
|
105
123
|
|
|
106
124
|
You don't need to do this in your nested AttrJson::Model classes, SimpleForm will already be able to reflect on their attribute types just fine as is.
|
|
107
125
|
|
|
126
|
+
### Arrays of simple attributes
|
|
127
|
+
|
|
128
|
+
attr_json :string_array, :string, array: true
|
|
129
|
+
|
|
130
|
+
The ActionView+ActiveRecord architecture isn't really setup for an array of "primitives", but we can kind of make it work:
|
|
131
|
+
|
|
132
|
+
<% f.object.string_array.each do |str| %>
|
|
133
|
+
<%= f.text_field(:string_array, value: str, multiple: true) %>
|
|
134
|
+
<% end %>
|
|
135
|
+
|
|
136
|
+
Or with simple_form, perhaps:
|
|
137
|
+
|
|
138
|
+
<%= f.input :string_array do %>
|
|
139
|
+
<% f.object.string_array.each do |str| %>
|
|
140
|
+
<%= f.text_field(:string_array, value: str, class: "form-control", multiple: true) %>
|
|
141
|
+
<% end %>
|
|
142
|
+
<% end %>
|
|
143
|
+
|
|
144
|
+
That will display, submit and update fine, although when you try to handle reporting validation errors, you'll probably only be able to report on the array, not the specific element.
|
|
145
|
+
|
|
146
|
+
The bigger problem is that if you use some javascript to allow people to add/remove elements,
|
|
147
|
+
and they remove _all_ elements, Rails params get no input for this attribute, and instead of setting it to empty array, doesn't touch it as in-memory. This is similar to the problem
|
|
148
|
+
with Rails collection checkboxes, and we can use a similar solution, of a hidden input value
|
|
149
|
+
making sure there's always at least one value.
|
|
150
|
+
|
|
151
|
+
<%= f.hidden_field "string_array[]", "" %>
|
|
152
|
+
<%= f.input :string_array do %>
|
|
153
|
+
<% f.object.string_array.each do |str| %>
|
|
154
|
+
<%= f.text_field(:string_array, value: str, class: "form-control", multiple: true) %>
|
|
155
|
+
<% end %>
|
|
156
|
+
<% end %>
|
|
157
|
+
|
|
158
|
+
But now we'll get an extra empty string added on to our array on every submit! We need to filter
|
|
159
|
+
out empty strings. `attr_json_accepts_nested_attributes_for` has an `_attributes=` method implementation when it recognizes an array of primitives, that simply filteres out empty strings. So! With `attr_json_accepts_nested_attributes_for :string_array`:
|
|
160
|
+
|
|
161
|
+
<%= f.hidden_field "string_array_attributes[]", "" %>
|
|
162
|
+
<%= f.input :string_array do %>
|
|
163
|
+
<% f.object.string_array.each do |str| %>
|
|
164
|
+
<%= f.text_field(:string_array_attributes, value: str, class: "form-control", multiple: true) %>
|
|
165
|
+
<% end %>
|
|
166
|
+
<% end %>
|
|
167
|
+
|
|
168
|
+
This is definitely getting a bit obtuse. You may want to consider an array of AttrJson::Model value types instead -- you can have a model with only one attribute! It can be handled somewhat more conventionally, as above.
|
|
169
|
+
|
|
108
170
|
## Cocoon
|
|
109
171
|
|
|
110
172
|
[Cocoon](https://github.com/nathanvda/cocoon) is one easy way to implement js-powered add- and remove-field functionality for to-many associations nested on a form with Rails.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "combustion", "~> 0.9.0"
|
|
6
|
+
gem "rails", "~> 5.0.0"
|
|
7
|
+
gem "railties"
|
|
8
|
+
gem "pg", "~> 0.18"
|
|
9
|
+
gem "rspec-rails", "~> 3.7"
|
|
10
|
+
gem "simple_form", ">= 4.0"
|
|
11
|
+
gem "cocoon", ">= 1.2"
|
|
12
|
+
gem "jquery-rails"
|
|
13
|
+
gem "capybara", "~> 3.0"
|
|
14
|
+
gem "chromedriver-helper"
|
|
15
|
+
gem "selenium-webdriver"
|
|
16
|
+
gem "byebug"
|
|
17
|
+
gem "rails-ujs", require: false
|
|
18
|
+
|
|
19
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "combustion", "~> 0.9.0"
|
|
6
|
+
gem "rails", "~> 5.1.0"
|
|
7
|
+
gem "railties"
|
|
8
|
+
gem "pg", "~> 1.0"
|
|
9
|
+
gem "rspec-rails", "~> 3.7"
|
|
10
|
+
gem "simple_form", ">= 4.0"
|
|
11
|
+
gem "cocoon", ">= 1.2"
|
|
12
|
+
gem "jquery-rails"
|
|
13
|
+
gem "capybara", "~> 3.0"
|
|
14
|
+
gem "chromedriver-helper"
|
|
15
|
+
gem "selenium-webdriver"
|
|
16
|
+
gem "byebug"
|
|
17
|
+
|
|
18
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "combustion", "~> 0.9.0"
|
|
6
|
+
gem "rails", "~> 5.2.0"
|
|
7
|
+
gem "railties"
|
|
8
|
+
gem "pg", "~> 1.0"
|
|
9
|
+
gem "rspec-rails", "~> 3.7"
|
|
10
|
+
gem "simple_form", ">= 4.0"
|
|
11
|
+
gem "cocoon", ">= 1.2"
|
|
12
|
+
gem "jquery-rails"
|
|
13
|
+
gem "capybara", "~> 3.0"
|
|
14
|
+
gem "chromedriver-helper"
|
|
15
|
+
gem "selenium-webdriver"
|
|
16
|
+
gem "byebug"
|
|
17
|
+
|
|
18
|
+
gemspec path: "../"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "combustion", git: "https://github.com/pat/combustion.git"
|
|
6
|
+
gem "rails", git: "https://github.com/rails/rails.git", branch: "master"
|
|
7
|
+
gem "railties"
|
|
8
|
+
gem "pg", "~> 1.0"
|
|
9
|
+
gem "rspec-rails", "~> 3.7"
|
|
10
|
+
gem "simple_form", ">= 4.0"
|
|
11
|
+
gem "cocoon", ">= 1.2"
|
|
12
|
+
gem "jquery-rails"
|
|
13
|
+
gem "capybara", "~> 3.0"
|
|
14
|
+
gem "chromedriver-helper"
|
|
15
|
+
gem "selenium-webdriver"
|
|
16
|
+
gem "byebug"
|
|
17
|
+
gem "coffee-rails"
|
|
18
|
+
|
|
19
|
+
gemspec path: "../"
|
data/lib/attr_json/config.rb
CHANGED
|
@@ -3,7 +3,7 @@ module AttrJson
|
|
|
3
3
|
# and rails class_attribute. Instead, you set to new Config object
|
|
4
4
|
# changed with {#merge}.
|
|
5
5
|
class Config
|
|
6
|
-
RECORD_ALLOWED_KEYS = %i{default_container_attribute}
|
|
6
|
+
RECORD_ALLOWED_KEYS = %i{default_container_attribute default_accepts_nested_attributes}
|
|
7
7
|
MODEL_ALLOWED_KEYS = %i{unknown_key}
|
|
8
8
|
DEFAULTS = {
|
|
9
9
|
default_container_attribute: "json_attributes",
|
|
@@ -29,6 +29,11 @@ module AttrJson
|
|
|
29
29
|
# * _allow_destroy_, no such option. Effectively always true, doesn't make sense to try to gate this with our implementation.
|
|
30
30
|
# * _update_only_, no such option. Not really relevant to this architecture where you're embedded models have no independent existence.
|
|
31
31
|
#
|
|
32
|
+
# If called on an array of 'primitive' (not AttrJson::Model) objects, it will do a kind of weird
|
|
33
|
+
# thing where it creates an `#{attribute_name}_attributes=` method that does nothing
|
|
34
|
+
# but filter out empty strings and nil values. This can be convenient in hackily form
|
|
35
|
+
# handling array of primitives, see guide doc on forms.
|
|
36
|
+
#
|
|
32
37
|
# @overload attr_json_accepts_nested_attributes_for(define_build_method: true, reject_if: nil, limit: nil)
|
|
33
38
|
# @param define_build_method [Boolean] Default true, provide `build_attribute_name`
|
|
34
39
|
# method that works like you expect. [Cocoon](https://github.com/nathanvda/cocoon),
|
|
@@ -74,7 +79,8 @@ module AttrJson
|
|
|
74
79
|
end
|
|
75
80
|
end
|
|
76
81
|
|
|
77
|
-
|
|
82
|
+
# No build method for our wacky array of primitive type.
|
|
83
|
+
if options[:define_build_method] && !(attr_def.array_type? && attr_def.type.base_type_primitive?)
|
|
78
84
|
_attr_jsons_module.module_eval do
|
|
79
85
|
build_method_name = "build_#{attr_name.to_s.singularize}"
|
|
80
86
|
if method_defined?(build_method_name)
|
|
@@ -16,7 +16,11 @@ module AttrJson
|
|
|
16
16
|
|
|
17
17
|
def assign_nested_attributes(attributes)
|
|
18
18
|
if attr_def.array_type?
|
|
19
|
-
|
|
19
|
+
if attr_def.type.base_type_primitive?
|
|
20
|
+
assign_nested_attributes_for_primitive_array(attributes)
|
|
21
|
+
else
|
|
22
|
+
assign_nested_attributes_for_model_array(attributes)
|
|
23
|
+
end
|
|
20
24
|
else
|
|
21
25
|
assign_nested_attributes_for_single_model(attributes)
|
|
22
26
|
end
|
|
@@ -38,6 +42,27 @@ module AttrJson
|
|
|
38
42
|
end
|
|
39
43
|
end
|
|
40
44
|
|
|
45
|
+
|
|
46
|
+
# Implementation for an `#{attribute_name}_attributes=` method, when the attr_json
|
|
47
|
+
# attribute in question is recognized as an array of primitive values (not nested models)
|
|
48
|
+
#
|
|
49
|
+
# Really just exists to filter out blank/empty strings with reject_if.
|
|
50
|
+
#
|
|
51
|
+
# It will insist on filtering out empty strings and nils from arrays (ignores reject_if argument),
|
|
52
|
+
# since that's the only reason to use it. It will respect limit argument.
|
|
53
|
+
#
|
|
54
|
+
# Filtering out empty strings can be convenient for using a hidden field in a form to
|
|
55
|
+
# make sure an empty array gets set if all individual fields are removed from form using
|
|
56
|
+
# cocoon-like javascript.
|
|
57
|
+
def assign_nested_attributes_for_primitive_array(attributes_array)
|
|
58
|
+
options = nested_attributes_options[attr_name]
|
|
59
|
+
check_record_limit!(options[:limit], attributes_array)
|
|
60
|
+
|
|
61
|
+
attributes_array = attributes_array.reject { |value| value.blank? }
|
|
62
|
+
|
|
63
|
+
model_send("#{attr_name}=", attributes_array)
|
|
64
|
+
end
|
|
65
|
+
|
|
41
66
|
# Copied with signficant modifications from:
|
|
42
67
|
# https://github.com/rails/rails/blob/master/activerecord/lib/active_record/nested_attributes.rb#L407
|
|
43
68
|
def assign_nested_attributes_for_single_model(attributes)
|
data/lib/attr_json/record.rb
CHANGED
|
@@ -93,9 +93,10 @@ module AttrJson
|
|
|
93
93
|
options = {
|
|
94
94
|
rails_attribute: false,
|
|
95
95
|
validate: true,
|
|
96
|
-
container_attribute: self.attr_json_config.default_container_attribute
|
|
96
|
+
container_attribute: self.attr_json_config.default_container_attribute,
|
|
97
|
+
accepts_nested_attributes: self.attr_json_config.default_accepts_nested_attributes
|
|
97
98
|
}.merge!(options)
|
|
98
|
-
options.assert_valid_keys(AttributeDefinition::VALID_OPTIONS + [:validate, :rails_attribute])
|
|
99
|
+
options.assert_valid_keys(AttributeDefinition::VALID_OPTIONS + [:validate, :rails_attribute, :accepts_nested_attributes])
|
|
99
100
|
container_attribute = options[:container_attribute]
|
|
100
101
|
|
|
101
102
|
# TODO arg check container_attribute make sure it exists. Hard cause
|
|
@@ -117,7 +118,7 @@ module AttrJson
|
|
|
117
118
|
end
|
|
118
119
|
|
|
119
120
|
self.attr_json_registry = attr_json_registry.with(
|
|
120
|
-
AttributeDefinition.new(name.to_sym, type, options.except(:rails_attribute, :validate))
|
|
121
|
+
AttributeDefinition.new(name.to_sym, type, options.except(:rails_attribute, :validate, :accepts_nested_attributes))
|
|
121
122
|
)
|
|
122
123
|
|
|
123
124
|
# By default, automatically validate nested models
|
|
@@ -158,6 +159,12 @@ module AttrJson
|
|
|
158
159
|
read_store_attribute(attribute_def.container_attribute, attribute_def.store_key)
|
|
159
160
|
end
|
|
160
161
|
end
|
|
162
|
+
|
|
163
|
+
# Default attr_json_accepts_nested_attributes_for values
|
|
164
|
+
if options[:accepts_nested_attributes]
|
|
165
|
+
options = options[:accepts_nested_attributes] == true ? {} : options[:accepts_nested_attributes]
|
|
166
|
+
self.attr_json_accepts_nested_attributes_for name, **options
|
|
167
|
+
end
|
|
161
168
|
end
|
|
162
169
|
|
|
163
170
|
private
|
data/lib/attr_json/type/array.rb
CHANGED
|
@@ -41,6 +41,12 @@ module AttrJson
|
|
|
41
41
|
]
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
# Hacky, hard-coded classes, but used in our weird primitive implementation in NestedAttributes,
|
|
45
|
+
# better than putting the conditionals there
|
|
46
|
+
def base_type_primitive?
|
|
47
|
+
!(base_type.is_a?(AttrJson::Type::Model) || base_type.is_a?(AttrJson::Type::PolymorphicModel))
|
|
48
|
+
end
|
|
49
|
+
|
|
44
50
|
protected
|
|
45
51
|
def convert_to_array(value)
|
|
46
52
|
if value.kind_of?(Hash)
|
data/lib/attr_json/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: attr_json
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jonathan Rochkind
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-
|
|
11
|
+
date: 2018-10-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -64,14 +64,14 @@ dependencies:
|
|
|
64
64
|
requirements:
|
|
65
65
|
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: '3.
|
|
67
|
+
version: '3.7'
|
|
68
68
|
type: :development
|
|
69
69
|
prerelease: false
|
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: '3.
|
|
74
|
+
version: '3.7'
|
|
75
75
|
- !ruby/object:Gem::Dependency
|
|
76
76
|
name: database_cleaner
|
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -100,6 +100,20 @@ dependencies:
|
|
|
100
100
|
- - ">="
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
102
|
version: '0'
|
|
103
|
+
- !ruby/object:Gem::Dependency
|
|
104
|
+
name: appraisal
|
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '2.2'
|
|
110
|
+
type: :development
|
|
111
|
+
prerelease: false
|
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '2.2'
|
|
103
117
|
description: |-
|
|
104
118
|
ActiveRecord attributes stored serialized in a json column, super smooth.
|
|
105
119
|
For Rails 5.0, 5.1, or 5.2. Typed and cast like Active Record. Supporting nested models,
|
|
@@ -118,6 +132,7 @@ files:
|
|
|
118
132
|
- ".rspec"
|
|
119
133
|
- ".travis.yml"
|
|
120
134
|
- ".yardopts"
|
|
135
|
+
- Appraisals
|
|
121
136
|
- Gemfile
|
|
122
137
|
- LICENSE.txt
|
|
123
138
|
- README.md
|
|
@@ -130,6 +145,11 @@ files:
|
|
|
130
145
|
- config.ru
|
|
131
146
|
- doc_src/dirty_tracking.md
|
|
132
147
|
- doc_src/forms.md
|
|
148
|
+
- gemfiles/.bundle/config
|
|
149
|
+
- gemfiles/rails_5_0.gemfile
|
|
150
|
+
- gemfiles/rails_5_1.gemfile
|
|
151
|
+
- gemfiles/rails_5_2.gemfile
|
|
152
|
+
- gemfiles/rails_edge_6.gemfile
|
|
133
153
|
- lib/attr_json.rb
|
|
134
154
|
- lib/attr_json/attribute_definition.rb
|
|
135
155
|
- lib/attr_json/attribute_definition/registry.rb
|
|
@@ -172,7 +192,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
172
192
|
version: '0'
|
|
173
193
|
requirements: []
|
|
174
194
|
rubyforge_project:
|
|
175
|
-
rubygems_version: 2.
|
|
195
|
+
rubygems_version: 2.7.7
|
|
176
196
|
signing_key:
|
|
177
197
|
specification_version: 4
|
|
178
198
|
summary: ActiveRecord attributes stored serialized in a json column, super smooth.
|