attr_json 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|