attr_json 0.7.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +87 -0
- data/.github/workflows/future_rails_ci.yml +66 -0
- data/Appraisals +26 -11
- data/CHANGELOG.md +67 -0
- data/Gemfile +15 -8
- data/README.md +123 -34
- data/attr_json.gemspec +20 -4
- data/gemfiles/rails_5_0.gemfile +4 -3
- data/gemfiles/rails_5_1.gemfile +4 -3
- data/gemfiles/rails_5_2.gemfile +4 -3
- data/gemfiles/rails_6_0.gemfile +6 -5
- data/gemfiles/rails_6_1.gemfile +19 -0
- data/gemfiles/rails_7_0.gemfile +19 -0
- data/gemfiles/{rails_edge_6.gemfile → rails_edge.gemfile} +6 -6
- data/lib/attr_json/attribute_definition.rb +6 -0
- data/lib/attr_json/config.rb +12 -2
- data/lib/attr_json/model.rb +97 -37
- data/lib/attr_json/record/dirty.rb +7 -1
- data/lib/attr_json/record/query_builder.rb +15 -3
- data/lib/attr_json/record/query_scopes.rb +6 -0
- data/lib/attr_json/record.rb +20 -4
- data/lib/attr_json/serialization_coder_from_type.rb +40 -0
- data/lib/attr_json/type/model.rb +35 -8
- data/lib/attr_json/type/polymorphic_model.rb +7 -0
- data/lib/attr_json/version.rb +1 -1
- data/lib/attr_json.rb +0 -1
- metadata +40 -22
- data/.travis.yml +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3cd2566fed014325bee56f5c062080d3c929a790dbb3b287e92b086c2fa3180f
|
4
|
+
data.tar.gz: ffa8e7b471dce27a2708b12e6a2bf27edb5b20d1345656ca026ecc4b263a01a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8db6d4211a2dd9f4b9d8a5482b723597958082617e139157c325e8e3b9dddf15216d21bd56daece5d5b3674acdc8e099a22998ad452473a4bf0834774b7a21f
|
7
|
+
data.tar.gz: 13e2cd5b4b10f67f4ecfc1be8732c6a33a7f7a7fdb561b6d8f4f89ae39c74e4b0b153ae10fdf5d650a239534f5b28cd33750aaff90009eeec8877677e765a935
|
@@ -0,0 +1,87 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ '**' ]
|
8
|
+
# UTC Tuesdays 0900. note, no notifications will be sent for failed scheduled builds. :(
|
9
|
+
schedule:
|
10
|
+
- cron: '0 9 * * TUE'
|
11
|
+
|
12
|
+
|
13
|
+
env:
|
14
|
+
POSTGRES_USER: postgres
|
15
|
+
POSTGRES_PASSWORD: postgres
|
16
|
+
|
17
|
+
jobs:
|
18
|
+
tests:
|
19
|
+
services:
|
20
|
+
db:
|
21
|
+
image: postgres:9.4
|
22
|
+
env:
|
23
|
+
POSTGRES_USER: postgres
|
24
|
+
POSTGRES_PASSWORD: postgres
|
25
|
+
ports: ['5432:5432']
|
26
|
+
|
27
|
+
runs-on: ubuntu-latest
|
28
|
+
strategy:
|
29
|
+
fail-fast: false
|
30
|
+
matrix:
|
31
|
+
include:
|
32
|
+
- gemfile: rails_5_0
|
33
|
+
ruby: 2.4
|
34
|
+
|
35
|
+
- gemfile: rails_5_0
|
36
|
+
ruby: 2.5
|
37
|
+
|
38
|
+
- gemfile: rails_5_1
|
39
|
+
ruby: 2.4
|
40
|
+
|
41
|
+
- gemfile: rails_5_2
|
42
|
+
ruby: 2.4
|
43
|
+
|
44
|
+
- gemfile: rails_5_2
|
45
|
+
ruby: 2.6
|
46
|
+
|
47
|
+
- gemfile: rails_6_0
|
48
|
+
ruby: 2.6
|
49
|
+
|
50
|
+
- gemfile: rails_6_0
|
51
|
+
ruby: 2.7
|
52
|
+
|
53
|
+
- gemfile: rails_6_1
|
54
|
+
ruby: 2.7
|
55
|
+
|
56
|
+
- gemfile: rails_6_1
|
57
|
+
ruby: '3.0'
|
58
|
+
|
59
|
+
- gemfile: rails_7_0
|
60
|
+
ruby: '3.0'
|
61
|
+
|
62
|
+
- gemfile: rails_7_0
|
63
|
+
ruby: 3.1
|
64
|
+
|
65
|
+
- gemfile: rails_7_0
|
66
|
+
ruby: 3.2
|
67
|
+
|
68
|
+
|
69
|
+
name: ${{ matrix.gemfile }}, ruby ${{ matrix.ruby }}
|
70
|
+
|
71
|
+
steps:
|
72
|
+
- uses: actions/checkout@v3
|
73
|
+
|
74
|
+
- name: Set up Ruby
|
75
|
+
uses: ruby/setup-ruby@v1
|
76
|
+
with:
|
77
|
+
ruby-version: ${{ matrix.ruby }}
|
78
|
+
bundler-cache: false
|
79
|
+
|
80
|
+
- name: Bundle install
|
81
|
+
run: |
|
82
|
+
bundle config set gemfile "${GITHUB_WORKSPACE}/gemfiles/${{ matrix.gemfile }}.gemfile"
|
83
|
+
bundle install --jobs 4 --retry 3
|
84
|
+
|
85
|
+
- name: Run tests
|
86
|
+
run: |
|
87
|
+
bundle exec rspec
|
@@ -0,0 +1,66 @@
|
|
1
|
+
name: CI on Future Rails Versions
|
2
|
+
|
3
|
+
# Experimenting with separate github actions workflow
|
4
|
+
# for gemfiles for FUTURE Rails vesions, we'd like to keep an eye on
|
5
|
+
# if they pass, but they aren't required to do so.
|
6
|
+
#
|
7
|
+
# This has to just be a copy-and-paste copy of our main ci.yml,
|
8
|
+
# but with different gemfiles in the matrix. That is not great.
|
9
|
+
# We also choose NOT to run this one on pull_request, we just
|
10
|
+
# run it on master, see how that works.
|
11
|
+
#
|
12
|
+
# These jobs can be left out of "required" for merge in github settings
|
13
|
+
# for "Branch Protection Rules" at https://github.com/jrochkind/attr_json/settings/branches
|
14
|
+
#
|
15
|
+
# You can move a Rails version between this file and ci.yml, and (un)check it in those
|
16
|
+
# github settings. (I wish whether it was required to pass could be in this file
|
17
|
+
# too, to keep things together)
|
18
|
+
|
19
|
+
on:
|
20
|
+
push:
|
21
|
+
branches: [ master ]
|
22
|
+
# UTC Sundays 0900. note, no notifications will be sent for failed scheduled builds. :(
|
23
|
+
schedule:
|
24
|
+
- cron: '0 9 * * SUN'
|
25
|
+
|
26
|
+
env:
|
27
|
+
POSTGRES_USER: postgres
|
28
|
+
POSTGRES_PASSWORD: postgres
|
29
|
+
|
30
|
+
jobs:
|
31
|
+
tests:
|
32
|
+
services:
|
33
|
+
db:
|
34
|
+
image: postgres:9.4
|
35
|
+
env:
|
36
|
+
POSTGRES_USER: postgres
|
37
|
+
POSTGRES_PASSWORD: postgres
|
38
|
+
ports: ['5432:5432']
|
39
|
+
|
40
|
+
runs-on: ubuntu-latest
|
41
|
+
|
42
|
+
strategy:
|
43
|
+
fail-fast: false
|
44
|
+
matrix:
|
45
|
+
include:
|
46
|
+
|
47
|
+
- gemfile: rails_edge
|
48
|
+
ruby: '3.1'
|
49
|
+
|
50
|
+
name: ${{ matrix.gemfile }}, ruby ${{ matrix.ruby }}
|
51
|
+
|
52
|
+
steps:
|
53
|
+
- uses: actions/checkout@v3
|
54
|
+
|
55
|
+
- name: Set up Ruby
|
56
|
+
uses: ruby/setup-ruby@v1
|
57
|
+
with:
|
58
|
+
ruby-version: ${{ matrix.ruby }}
|
59
|
+
|
60
|
+
- name: Bundle install
|
61
|
+
run: |
|
62
|
+
bundle config set gemfile "${GITHUB_WORKSPACE}/gemfiles/${{ matrix.gemfile }}.gemfile"
|
63
|
+
bundle install --jobs 4 --retry 3
|
64
|
+
|
65
|
+
- name: Run tests
|
66
|
+
run: bundle exec rspec
|
data/Appraisals
CHANGED
@@ -26,22 +26,37 @@ appraise "rails-5-2" do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
appraise "rails-6-0" do
|
29
|
-
gem 'combustion',
|
29
|
+
gem 'combustion', "~> 1.0"
|
30
30
|
|
31
|
-
gem "rails", ">= 6.0.0
|
31
|
+
gem "rails", ">= 6.0.0", "< 6.1"
|
32
32
|
gem "pg", "~> 1.0"
|
33
33
|
end
|
34
34
|
|
35
|
-
appraise "rails-
|
36
|
-
|
37
|
-
# https://github.com/pat/combustion/issues/92
|
38
|
-
gem 'combustion', git: "https://github.com/pat/combustion.git"
|
35
|
+
appraise "rails-6-1" do
|
36
|
+
gem 'combustion', "~> 1.0"
|
39
37
|
|
40
|
-
gem "rails",
|
38
|
+
gem "rails", "~> 6.1.0"
|
41
39
|
gem "pg", "~> 1.0"
|
42
40
|
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
gem
|
41
|
+
# sprockets-rails is already a rails 6.1 dependency, but combustion is failing
|
42
|
+
# to require it, this is one way to get it required.
|
43
|
+
# https://github.com/pat/combustion/issues/128
|
44
|
+
gem "sprockets-rails"
|
45
|
+
end
|
46
|
+
|
47
|
+
appraise "rails-7-0" do
|
48
|
+
gem 'combustion', "~> 1.0"
|
49
|
+
|
50
|
+
gem "rails", "~> 7.0.0"
|
51
|
+
gem "pg", "~> 1.0"
|
52
|
+
end
|
53
|
+
|
54
|
+
appraise "rails-edge" do
|
55
|
+
# need combustion edge to work with rails edge, will no longer
|
56
|
+
# be true on next combustion release, probably no later than Rails 7.1
|
57
|
+
# https://github.com/pat/combustion/pull/126
|
58
|
+
gem 'combustion', "~> 1.0", github: "pat/combustion"
|
59
|
+
|
60
|
+
gem "rails", git: "https://github.com/rails/rails.git", branch: "main"
|
61
|
+
gem "pg", "~> 1.0"
|
47
62
|
end
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Changelog
|
2
|
+
Notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
|
+
|
7
|
+
## [Unreleased](https://github.com/jrochkind/attr_json/compare/v1.4.1...HEAD)
|
8
|
+
|
9
|
+
|
10
|
+
## [1.5.0](https://github.com/jrochkind/attr_json/compare/v1.4.1...v1.5.0)
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
* AttrJson::Model#dup will properly deep-dup attributes https://github.com/jrochkind/attr_json/pull/169
|
15
|
+
|
16
|
+
* AttrJson::Model#freeze will freeze attributes -- but not deep-freeze. https://github.com/jrochkind/attr_json/pull/169
|
17
|
+
|
18
|
+
* AttrJson::Model has some methods conventional in ActiveModel classes: Klass.attribute_types, Klass.attribute_names, and instance.attribute_names. https://github.com/jrochkind/attr_json/pull/169
|
19
|
+
|
20
|
+
## [1.4.1](https://github.com/jrochkind/attr_json/compare/v1.4.0...v1.4.1)
|
21
|
+
|
22
|
+
### Fixed
|
23
|
+
|
24
|
+
* Fixed an obscure bug involving a conflict between attribute defaults and accepts_nested_attributes, in which defaults could overwrite assigned attributes. The `.fill_in_defaults` class method, which was never intended as public API and was commented accordingly, is gone. https://github.com/jrochkind/attr_json/pull/160
|
25
|
+
|
26
|
+
## [1.4.0](https://github.com/jrochkind/attr_json/compare/v1.3.0...v1.4.0)
|
27
|
+
|
28
|
+
### Changed
|
29
|
+
|
30
|
+
* When using store_key feature on an AttrJson::Model, you should not be able to pass in the store_key as a key in initializer or assign_attributes. It was really a bug that this ended up mapped to attribute this way, which could cause a problem in some cases; but calling it out in Changed section because if you were accidentally relying on it, it may appear as a backwards incompat to you. https://github.com/jrochkind/attr_json/pull/125
|
31
|
+
|
32
|
+
* Rails 7.0.0 allowed by gemspec and tested in CI
|
33
|
+
|
34
|
+
### Fixed
|
35
|
+
|
36
|
+
* polymorphic single type can be set to nil https://github.com/jrochkind/attr_json/pull/115
|
37
|
+
* polymorphic models can be serialized from hash in container attribute. Thanks @machty. https://github.com/jrochkind/attr_json/pull/123
|
38
|
+
* fix bug with deserialization of nested attributes that have types that apply different serialization vs cast logic. Thanks @bradleesand. https://github.com/jrochkind/attr_json/pull/125
|
39
|
+
|
40
|
+
## [1.3.0](https://github.com/jrochkind/attr_json/compare/v1.2.0...v1.3.0)
|
41
|
+
|
42
|
+
### Added
|
43
|
+
|
44
|
+
* Gemspec allows use with ActiveRecord 6.1.x
|
45
|
+
|
46
|
+
## [1.2.0](https://github.com/jrochkind/attr_json/compare/v1.1.0...v1.2.0)
|
47
|
+
|
48
|
+
### Added
|
49
|
+
|
50
|
+
* attr_json_config(bad_cast: :as_nil) to avoid raising on data that can't be cast to a
|
51
|
+
AttrJson::Model, instead just casting to nil. https://github.com/jrochkind/attr_json/pull/95
|
52
|
+
|
53
|
+
* Documented and tested support for using ActiveRecord serialize to map one AttrJson::Model
|
54
|
+
to an entire column on it's own. https://github.com/jrochkind/attr_json/pull/89 and
|
55
|
+
https://github.com/jrochkind/attr_json/pull/93
|
56
|
+
|
57
|
+
* Better synchronization with ActiveRecord attributes when using rails_attribute:true, and a configurable true default_rails_attribute. Thanks @volkanunsal . https://github.com/jrochkind/attr_json/pull/94
|
58
|
+
|
59
|
+
### Changed
|
60
|
+
|
61
|
+
* AttrJson::Model#== now requires same class for equality. And doesn't raise on certain arguments. https://github.com/jrochkind/attr_json/pull/90 Thanks @caiofilipemr for related bug report.
|
62
|
+
|
63
|
+
## [1.1.0](https://github.com/jrochkind/attr_json/compare/v1.0.0...v1.1.0)
|
64
|
+
|
65
|
+
### Added
|
66
|
+
|
67
|
+
* not_jsonb_contains query method, like `jsonb_contains` but negated. https://github.com/jrochkind/attr_json/pull/85
|
data/Gemfile
CHANGED
@@ -10,7 +10,7 @@ gemspec
|
|
10
10
|
# We also have these development dependencies here in the Gemfile instead of the
|
11
11
|
# gemspec so appraisal can override them from our Appraisal file.
|
12
12
|
|
13
|
-
gem 'combustion', '~>
|
13
|
+
gem 'combustion', '~> 1.1'
|
14
14
|
|
15
15
|
# all of rails is NOT a dependency, just activerecord.
|
16
16
|
# But we use it for integration testing with combustion. Hmm, a bit annoying
|
@@ -18,19 +18,26 @@ gem 'combustion', '~> 0.9.0'
|
|
18
18
|
# be the way to do it.
|
19
19
|
gem 'rails'
|
20
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
21
|
gem "pg"
|
27
|
-
gem "rspec-rails", "~>
|
22
|
+
gem "rspec-rails", "~> 6.0"
|
28
23
|
gem "simple_form", ">= 4.0"
|
29
24
|
gem 'cocoon', ">= 1.2"
|
30
25
|
gem 'jquery-rails'
|
31
26
|
|
27
|
+
# Even though we don't use coffee-script, when running specs, some part of rails
|
28
|
+
# or other part of our stack is still insisting on requiring it, for reasons we
|
29
|
+
# don't understand, so we need to depend on it.
|
30
|
+
gem "coffee-rails"
|
31
|
+
|
32
|
+
# We do some tests using cocoon via sprockets, which needs sprockets-rails,
|
33
|
+
# which is not automatically available in Rails 7. We add it explicitly,
|
34
|
+
# which will duplciate dependences in rails pre-7, but add for rails 7. Not sure
|
35
|
+
# the future of cocoon in general. https://github.com/nathanvda/cocoon/issues/555
|
36
|
+
gem "sprockets-rails"
|
37
|
+
|
38
|
+
|
32
39
|
gem 'capybara', "~> 3.0"
|
33
|
-
gem 'webdrivers', '~>
|
40
|
+
gem 'webdrivers', '~> 5.0'
|
34
41
|
gem "selenium-webdriver"
|
35
42
|
|
36
43
|
gem "byebug"
|
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# AttrJson
|
2
|
-
[![
|
2
|
+
[![CI Status](https://github.com/jrochkind/attr_json/workflows/CI/badge.svg?branch=master)](https://github.com/jrochkind/attr_json/actions?query=workflow%3ACI+branch%3Amaster)
|
3
|
+
[![CI Status](https://github.com/jrochkind/attr_json/workflows/CI%20on%20Future%20Rails%20Versions/badge.svg?branch=master)](https://github.com/jrochkind/attr_json/actions?query=workflow%3A%22CI+on+Future+Rails+Versions%22+branch%3Amaster)
|
3
4
|
[![Gem Version](https://badge.fury.io/rb/attr_json.svg)](https://badge.fury.io/rb/attr_json)
|
4
5
|
|
5
6
|
|
6
|
-
ActiveRecord attributes stored serialized in a json column, super smooth. For Rails 5.0
|
7
|
+
ActiveRecord attributes stored serialized in a json column, super smooth. For Rails 5.0 through 7.0. Ruby 2.4+.
|
7
8
|
|
8
9
|
Typed and cast like Active Record. Supporting [nested models](#nested), [dirty tracking](#dirty), some [querying](#querying) (with postgres [jsonb](https://www.postgresql.org/docs/9.5/static/datatype-json.html) contains), and [working smoothy with form builders](#forms).
|
9
10
|
|
@@ -11,8 +12,6 @@ Typed and cast like Active Record. Supporting [nested models](#nested), [dirty t
|
|
11
12
|
|
12
13
|
[Why might you want or not want this?](#why)
|
13
14
|
|
14
|
-
AttrJson is pre-1.0. The functionality that is documented here _is_ already implemented (these docs are real, not vaporware) and seems pretty solid. It may still have backwards-incompat changes before 1.0 release. Review and feedback is very welcome.
|
15
|
-
|
16
15
|
Developed for postgres, but most features should work with MySQL json columns too, although
|
17
16
|
has not yet been tested with MySQL.
|
18
17
|
|
@@ -140,6 +139,9 @@ MyModel.jsonb_contains(my_string: "foo", my_integer: 100).first
|
|
140
139
|
# Implemented with scopes, this is an ordinary relation, you can
|
141
140
|
# combine it with whatever, just like ordinary `where`.
|
142
141
|
|
142
|
+
MyModel.not_jsonb_contains(my:string: "foo", my_integer: 100).to_sql
|
143
|
+
# SELECT "products".* FROM "products" WHERE NOT (products.json_attributes @> ('{"my_string":"foo","my_integer":100}')::jsonb)
|
144
|
+
|
143
145
|
# typecasts much like ActiveRecord on query too:
|
144
146
|
MyModel.jsonb_contains(my_string: "foo", my_integer: "100")
|
145
147
|
# no problem
|
@@ -227,6 +229,26 @@ m.attr_jsons_before_type_cast
|
|
227
229
|
|
228
230
|
You can nest AttrJson::Model objects inside each other, as deeply as you like.
|
229
231
|
|
232
|
+
### Model-type defaults
|
233
|
+
|
234
|
+
If you want to set a default for an AttrJson::Model type, you should use a proc argument for
|
235
|
+
the default, to avoid accidentally re-using a shared global default value, similar to issues
|
236
|
+
people have with ruby Hash default.
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
attr_json :lang_and_value, LangAndValue.to_type, default: -> { LangAndValue.new(lang: "en", value: "default") }
|
240
|
+
```
|
241
|
+
|
242
|
+
You can also use a Hash value that will be cast to your model, no need for proc argument
|
243
|
+
in this case.
|
244
|
+
|
245
|
+
```ruby
|
246
|
+
attr_json :lang_and_value, LangAndValue.to_type, default: { lang: "en", value: "default" }
|
247
|
+
```
|
248
|
+
|
249
|
+
|
250
|
+
### Polymorphic model types
|
251
|
+
|
230
252
|
There is some support for "polymorphic" attributes that can hetereogenously contain instances of different AttrJson::Model classes, see comment docs at [AttrJson::Type::PolymorphicModel](./lib/attr_json/type/polymorphic_model.rb).
|
231
253
|
|
232
254
|
|
@@ -285,6 +307,63 @@ always mean 'contains' -- the previous query needs a `my_labels.hello`
|
|
285
307
|
which is a hash that includes the key/value, `lang: en`, it can have
|
286
308
|
other key/values in it too. String values will need to match exactly.
|
287
309
|
|
310
|
+
## Single AttrJson::Model serialized to an entire json column
|
311
|
+
|
312
|
+
The main use case of the gem is set up to let you combine multiple primitives and nested models
|
313
|
+
under different keys combined in a single json or jsonb column.
|
314
|
+
|
315
|
+
But you may also want to have one AttrJson::Model class that serializes to map one model class, as
|
316
|
+
a hash, to an entire json column on it's own.
|
317
|
+
|
318
|
+
`AttrJson::Model` can supply a simple coder for the [ActiveRecord serialization](https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html)
|
319
|
+
feature to easily do that.
|
320
|
+
|
321
|
+
```ruby
|
322
|
+
class MyModel
|
323
|
+
include AttrJson::Model
|
324
|
+
|
325
|
+
attr_json :some_string, :string
|
326
|
+
attr_json :some_int, :int
|
327
|
+
end
|
328
|
+
|
329
|
+
class MyTable < ApplicationRecord
|
330
|
+
serialize :some_json_column, MyModel.to_serialization_coder
|
331
|
+
end
|
332
|
+
|
333
|
+
MyTable.create(some_json_column: MyModel.new(some_string: "string"))
|
334
|
+
|
335
|
+
# will cast from hash for you
|
336
|
+
MyTable.create(some_json_column: { some_int: 12 })
|
337
|
+
|
338
|
+
# etc
|
339
|
+
```
|
340
|
+
|
341
|
+
To avoid errors raised at inconvenient times, we recommend you set these settings to make 'bad'
|
342
|
+
data turn into `nil`, consistent with most ActiveRecord types:
|
343
|
+
|
344
|
+
```ruby
|
345
|
+
class MyModel
|
346
|
+
include AttrJson::Model
|
347
|
+
|
348
|
+
attr_json_config(bad_cast: :as_nil, unknown_key: :strip)
|
349
|
+
# ...
|
350
|
+
end
|
351
|
+
```
|
352
|
+
|
353
|
+
And/or define a setter method to cast, and raise early on data problems:
|
354
|
+
|
355
|
+
```ruby
|
356
|
+
class MyTable < ApplicationRecord
|
357
|
+
serialize :some_json_column, MyModel.to_serialization_coder
|
358
|
+
|
359
|
+
def some_json_column=(val)
|
360
|
+
super( )
|
361
|
+
end
|
362
|
+
end
|
363
|
+
```
|
364
|
+
|
365
|
+
Serializing a model to an entire json column is a relatively recent feature, please let us know how it's working for you.
|
366
|
+
|
288
367
|
<a name="arbitrary-json-data"></a>
|
289
368
|
## Storing Arbitrary JSON data
|
290
369
|
|
@@ -307,7 +386,7 @@ Use with Rails form builders is supported pretty painlessly. Including with [sim
|
|
307
386
|
|
308
387
|
If you have nested AttrJson::Models you'd like to use in your forms much like Rails associated records: Where you would use Rails `accepts_nested_attributes_for`, instead `include AttrJson::NestedAttributes` and use `attr_json_accepts_nested_attributes_for`. Multiple levels of nesting are supported.
|
309
388
|
|
310
|
-
To get simple_form to properly detect your attribute types, define your attributes with `rails_attribute: true`.
|
389
|
+
To get simple_form to properly detect your attribute types, define your attributes with `rails_attribute: true`. You can default rails_attribute to true with `attr_json_config(default_rails_attribute: true)`
|
311
390
|
|
312
391
|
For more info, see doc page on [Use with Forms and Form Builders](doc_src/forms.md).
|
313
392
|
|
@@ -319,27 +398,29 @@ Rails 5.1+ on `attr_json`s on your ActiveRecord classes that include
|
|
319
398
|
`AttrJson::Record`, by including `AttrJson::Record::Dirty`.
|
320
399
|
Change-tracking methods are available off the `attr_json_changes` method.
|
321
400
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
attr_json :str, :string
|
327
|
-
end
|
328
|
-
|
329
|
-
model = MyModel.new
|
330
|
-
model.str = "old"
|
331
|
-
model.save
|
332
|
-
model.str = "new"
|
401
|
+
```ruby
|
402
|
+
class MyModel < ActiveRecord::Base
|
403
|
+
include AttrJson::Record
|
404
|
+
include AttrJson::Record::Dirty
|
333
405
|
|
334
|
-
|
335
|
-
|
406
|
+
attr_json :str, :string
|
407
|
+
end
|
336
408
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
409
|
+
model = MyModel.new
|
410
|
+
model.str = "old"
|
411
|
+
model.save
|
412
|
+
model.str = "new"
|
413
|
+
|
414
|
+
# All and only "new" style dirty tracking methods (Raisl 5.1+)
|
415
|
+
# are available:
|
416
|
+
|
417
|
+
model.attr_json_changes.saved_changes
|
418
|
+
model.attr_json_changes.changes_to_save
|
419
|
+
model.attr_json_changes.saved_change_to_str?
|
420
|
+
model.attr_json_changes.saved_change_to_str
|
421
|
+
model.attr_json_changes.will_save_change_to_str?
|
422
|
+
# etc
|
423
|
+
```
|
343
424
|
|
344
425
|
More options are available, including merging changes from 'ordinary'
|
345
426
|
ActiveRecord attributes in. See docs on [Dirty Tracking](./doc_src/dirty_tracking.md)
|
@@ -397,38 +478,46 @@ to prevent overwriting other updates from processes.
|
|
397
478
|
|
398
479
|
## State of Code, and To Be Done
|
399
480
|
|
400
|
-
This is
|
481
|
+
This code is solid and stable and is being used in production by at least a handful of people, including the primary maintainer, jrochkind.
|
482
|
+
|
483
|
+
The project is currently getting very little maintainance -- and is still working reliably through Rails releases. It is tested on edge rails and ruby (and has needed very few if any changes with subsequent releases), and I endeavor to keep it working as Rails keeps releasing.
|
401
484
|
|
402
|
-
|
485
|
+
In order to keep the low-maintenace scenario sustainable, I am *very* cautious accepting new features, especially if they increase code complexity at all. Even if you have a working PR, I may be reluctant to accept it. I'm prioritizing sustainability and stability over new features, and so far this is working out well. However, discussion is always welcome! Especially when paired with code (failing tests for the bugfix or feature you want are super helpful on their own!).
|
403
486
|
|
404
|
-
|
487
|
+
We are committed to [semantic versioning](https://semver.org/) and will endeavor to release no backwards breaking changes without a major version. We are also serious about minimizing backwards incompat releases altogether (ie minimiing major version releases).
|
405
488
|
|
406
|
-
Feedback of any kind of _very welcome_, please feel free to use the issue tracker.
|
489
|
+
Feedback of any kind of _very welcome_, please feel free to use the issue tracker. It is hard to get a sense of how many people are actually using this, which is helpful both for my own sense of reward and for anyone to get a sense of the size of the userbase -- feel free to say hi and let us know how you are using it!
|
407
490
|
|
408
491
|
Except for the jsonb_contains stuff using postgres jsonb contains operator, I don't believe any postgres-specific features are used. It ought to work with MySQL, testing and feedback welcome. (Or a PR to test on MySQL?). My own interest is postgres.
|
409
492
|
|
493
|
+
This is still mostly a single-maintainer operation, so has all the sustainability risks of that. Although there are other people using and contributing to it, check out the Github Issues and Pull Request tabs yourself to get a sense.
|
494
|
+
|
410
495
|
### Possible future features:
|
411
496
|
|
412
|
-
*
|
497
|
+
* Make AttrJson::Model lean more heavily on ActiveModel::Attributes API that did not fully exist in first version of attr_json [hope for a future attr_json 2.0 release]
|
498
|
+
|
499
|
+
* Make AttrJson::Record insist on creating rails cover attributes (no longer optional) and integrating more fully into rails, including rails dirty tricking, eliminating need for custom dirty tracking implementation. Overall decrease in lines of code. Can use jsonb_accessor as guide for some aspects. [hope for inclusion in future attr_json 2.0 release]
|
500
|
+
|
501
|
+
* partial updates for json hashes would be really nice: Using postgres jsonb merge operators to only overwrite what changed. In my initial attempts, AR doesn't make it easy to customize this. [update: this is hard, probably not coming soon]
|
413
502
|
|
414
|
-
* seamless compatibility with ransack
|
503
|
+
* seamless compatibility with ransack [update: not necessarily prioritized]
|
415
504
|
|
416
505
|
* Should we give AttrJson::Model a before_serialize hook that you might
|
417
506
|
want to use similar to AR before_save? Should AttrJson::Models
|
418
|
-
raise on trying to serialize an invalid model?
|
507
|
+
raise on trying to serialize an invalid model? [update: eh, hasn't really come up]
|
419
508
|
|
420
509
|
* There are limits to what you can do with just jsonb_contains
|
421
510
|
queries. We could support operations like `>`, `<`, `<>`
|
422
511
|
as [jsonb_accessor](https://github.com/devmynd/jsonb_accessor),
|
423
512
|
even accross keypaths. (At present, you could use a
|
424
513
|
before_savee to denormalize/renormalize copy your data into
|
425
|
-
ordinary AR columns/associations for searching. Or perhaps a postgres ts_vector for text searching. Needs to be worked out.)
|
514
|
+
ordinary AR columns/associations for searching. Or perhaps a postgres ts_vector for text searching. Needs to be worked out.) [update: interested, but not necessarily prioritized. This one would be interesting for a third-party PR draft!]
|
426
515
|
|
427
516
|
* We could/should probably support `jsonb_order` clauses, even
|
428
|
-
accross key paths, like jsonb_accessor.
|
517
|
+
accross key paths, like jsonb_accessor. [update: interested but not necessarily prioritized]
|
429
518
|
|
430
519
|
* Could we make these attributes work in ordinary AR where, same
|
431
|
-
as they do in jsonb_contains? Maybe.
|
520
|
+
as they do in jsonb_contains? Maybe. [update: probably not]
|
432
521
|
|
433
522
|
## Development
|
434
523
|
|
data/attr_json.gemspec
CHANGED
@@ -44,14 +44,30 @@ attributes use as much of the existing ActiveRecord architecture as we can.}
|
|
44
44
|
|
45
45
|
# Only to get CI to work on versions of Rails other than we release with,
|
46
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", "<
|
47
|
+
unless ENV['APPRAISAL_INITIALIZED'] || ENV["TRAVIS"] || ENV['CI']
|
48
|
+
spec.add_runtime_dependency "activerecord", ">= 5.0.0", "< 7.1"
|
49
49
|
end
|
50
50
|
|
51
|
-
spec.add_development_dependency "bundler"
|
51
|
+
spec.add_development_dependency "bundler"
|
52
52
|
spec.add_development_dependency "rake", ">= 10.0"
|
53
53
|
spec.add_development_dependency "rspec", "~> 3.7"
|
54
|
-
spec.add_development_dependency "database_cleaner", "~> 1.5"
|
55
54
|
spec.add_development_dependency "yard-activesupport-concern"
|
56
55
|
spec.add_development_dependency "appraisal", "~> 2.2"
|
56
|
+
|
57
|
+
# Working around annoying issue in selenium 3.x with ruby 3.0.
|
58
|
+
# we don't actually use rexml ourselves. selenium 3 is a dependency
|
59
|
+
# of webdrivers, and tries to use rexml without depending on it
|
60
|
+
# as is needed in ruby 3.
|
61
|
+
#
|
62
|
+
# https://github.com/SeleniumHQ/selenium/issues/9001
|
63
|
+
#
|
64
|
+
# if in the future you can remove this dependecy and still have tests pass
|
65
|
+
# under ruby 3.x, you're good.
|
66
|
+
spec.add_development_dependency "rexml"
|
67
|
+
|
68
|
+
# Used only for Capybara.server in our spec_helper.rb.
|
69
|
+
# webrick is no longer included in ruby 3.0, so has to
|
70
|
+
# be expressed as a dependecy, unless we switch
|
71
|
+
# capybara to use alternate webserver.
|
72
|
+
spec.add_development_dependency "webrick", "~> 1.0"
|
57
73
|
end
|
data/gemfiles/rails_5_0.gemfile
CHANGED
@@ -4,14 +4,15 @@ source "https://rubygems.org"
|
|
4
4
|
|
5
5
|
gem "combustion", "~> 0.9.0"
|
6
6
|
gem "rails", "~> 5.0.0"
|
7
|
-
gem "railties"
|
8
7
|
gem "pg", "~> 0.18"
|
9
|
-
gem "rspec-rails", "~>
|
8
|
+
gem "rspec-rails", "~> 4.0"
|
10
9
|
gem "simple_form", ">= 4.0"
|
11
10
|
gem "cocoon", ">= 1.2"
|
12
11
|
gem "jquery-rails"
|
12
|
+
gem "coffee-rails"
|
13
|
+
gem "sprockets-rails"
|
13
14
|
gem "capybara", "~> 3.0"
|
14
|
-
gem "webdrivers", "~>
|
15
|
+
gem "webdrivers", "~> 4.0"
|
15
16
|
gem "selenium-webdriver"
|
16
17
|
gem "byebug"
|
17
18
|
gem "rails-ujs", require: false
|
data/gemfiles/rails_5_1.gemfile
CHANGED
@@ -4,14 +4,15 @@ source "https://rubygems.org"
|
|
4
4
|
|
5
5
|
gem "combustion", "~> 0.9.0"
|
6
6
|
gem "rails", "~> 5.1.0"
|
7
|
-
gem "railties"
|
8
7
|
gem "pg", "~> 1.0"
|
9
|
-
gem "rspec-rails", "~>
|
8
|
+
gem "rspec-rails", "~> 4.0"
|
10
9
|
gem "simple_form", ">= 4.0"
|
11
10
|
gem "cocoon", ">= 1.2"
|
12
11
|
gem "jquery-rails"
|
12
|
+
gem "coffee-rails"
|
13
|
+
gem "sprockets-rails"
|
13
14
|
gem "capybara", "~> 3.0"
|
14
|
-
gem "webdrivers", "~>
|
15
|
+
gem "webdrivers", "~> 4.0"
|
15
16
|
gem "selenium-webdriver"
|
16
17
|
gem "byebug"
|
17
18
|
|
data/gemfiles/rails_5_2.gemfile
CHANGED
@@ -4,14 +4,15 @@ source "https://rubygems.org"
|
|
4
4
|
|
5
5
|
gem "combustion", "~> 0.9.0"
|
6
6
|
gem "rails", "~> 5.2.0"
|
7
|
-
gem "railties"
|
8
7
|
gem "pg", "~> 1.0"
|
9
|
-
gem "rspec-rails", "~>
|
8
|
+
gem "rspec-rails", "~> 4.0"
|
10
9
|
gem "simple_form", ">= 4.0"
|
11
10
|
gem "cocoon", ">= 1.2"
|
12
11
|
gem "jquery-rails"
|
12
|
+
gem "coffee-rails"
|
13
|
+
gem "sprockets-rails"
|
13
14
|
gem "capybara", "~> 3.0"
|
14
|
-
gem "webdrivers", "~>
|
15
|
+
gem "webdrivers", "~> 4.0"
|
15
16
|
gem "selenium-webdriver"
|
16
17
|
gem "byebug"
|
17
18
|
|