jsonb_accessor 1.3.10 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5593f84fe3d0e2038beeac5377fef22f4d1b1b18daf78b3f65dc4c55362592e0
4
- data.tar.gz: 3421f8ce790d9ca3db6f93007ce3a0ca327a749073f6f8df36f7fb922f5485af
3
+ metadata.gz: ddb7db7a9ab5930ae31cac0fa871289638b0c5a3ba2f3486b4731a39e5d8f3aa
4
+ data.tar.gz: 8c279fcfd16e6c5d490f31a45b0734f06fe70ee500c2a72cae1204d4d6a93e29
5
5
  SHA512:
6
- metadata.gz: a1433289f8c96cd0105f9b49922a4771c99a886f593b79225c835850d6875fad420fd91c60f6c05844464ae757ff597ec1a287245c75bf1afb823fff457eb33a
7
- data.tar.gz: 9b3af34ed491b630e2e0f5859e263cbd157a2d7c6d29713d8536a7e389a21dc356a70e2b70ec3b207cb42c26814736e1fe984e3201acd34e58b08813d5a1a2fd
6
+ metadata.gz: 8a9b59f77d798b4e4134ccf5305a107bd220c89f1a377b7c6899273ba62c0c75ad697cb527c60f9a7a6e81dff52087c286cd8518859f00da4a2e8c37e3094531
7
+ data.tar.gz: 733ee774842a1f4c2b734913fd1af2c02b43a892b27a955e64f44c46ca6bff93466436fd5e9d651e0ad081a09dc7d2a704302e6f5039b4db49e00d38544030f6
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: 'github-actions'
4
+ directory: '/'
5
+ schedule:
6
+ interval: 'weekly'
@@ -4,149 +4,67 @@ on:
4
4
  push:
5
5
  branches: [master]
6
6
  pull_request:
7
- branches: ['**']
7
+ branches: [master]
8
8
 
9
9
  jobs:
10
10
  lint:
11
- runs-on: ubuntu-latest
11
+ runs-on: ubuntu-24.04
12
12
  steps:
13
- - uses: actions/checkout@v3
14
-
15
- - name: Set up Ruby
16
- uses: ruby/setup-ruby@v1
13
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
14
+
15
+ - uses: ruby/setup-ruby@80740b3b13bf9857e28854481ca95a84e78a2bdf # v1.284.0
17
16
  with:
17
+ ruby-version: "3.4"
18
18
  bundler-cache: true
19
-
20
- - name: Rubocop
21
- run: bundle exec rubocop
19
+
20
+ - run: bundle exec rubocop
22
21
 
23
22
  tests:
24
23
  needs: lint
24
+ runs-on: ubuntu-24.04
25
+ strategy:
26
+ fail-fast: false
27
+ matrix:
28
+ ruby: ["ruby-3.2", "ruby-3.3", "ruby-3.4", "ruby-4.0", "jruby-9.4", "jruby-10.0"]
29
+ activerecord: ["6.1", "7.0", "7.1", "7.2", "8.0", "8.1"]
30
+ postgresql: ["13", "14", "15", "16", "17", "18"]
31
+ exclude:
32
+ # fails due to "ArgumentError: when initializing an Active Record adapter with a config hash, that should be the only argument" in db:schema:load
33
+ - ruby: "jruby-9.4"
34
+ activerecord: "7.2"
35
+ - ruby: "jruby-9.4"
36
+ activerecord: "8.0"
37
+ # fails due to "Because activerecord >= 8.0.0.beta1 depends on Ruby >= 3.2.0 and Gemfile depends on activerecord ~> 8.1, Ruby >= 3.2.0 is required. So, because current Ruby version is = 3.1.7, version solving has failed."
38
+ - ruby: "jruby-9.4"
39
+ activerecord: "8.1"
40
+ # https://github.com/jruby/activerecord-jdbc-adapter/issues/1173
41
+ - ruby: "jruby-10.0"
42
+ activerecord: "8.0"
43
+ # https://github.com/jruby/activerecord-jdbc-adapter/issues/1184
44
+ - ruby: "jruby-10.0"
45
+ activerecord: "8.1"
46
+ name: "Active Record ${{ matrix.activerecord }} with PostgreSQL ${{ matrix.postgresql }} on ${{ matrix.ruby }}"
25
47
  services:
26
48
  db:
27
- image: postgres:9.4
49
+ image: postgres:${{ matrix.postgresql }}
28
50
  env:
29
51
  POSTGRES_HOST_AUTH_METHOD: trust
30
52
  POSTGRES_DB: jsonb_accessor
31
53
  ports: ['5432:5432']
32
54
  options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
55
+ steps:
56
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
33
57
 
34
- runs-on: ubuntu-latest
35
- strategy:
36
- fail-fast: false
37
- matrix:
38
- include:
39
- - gemfile: activerecord_5.0.0
40
- ruby: '2.4'
41
-
42
- - gemfile: activerecord_5.1.0
43
- ruby: '2.4'
44
-
45
- - gemfile: activerecord_5.2.0
46
- ruby: '2.4'
47
-
48
- - gemfile: activerecord_5.0.0
49
- ruby: '2.5'
50
-
51
- - gemfile: activerecord_5.1.0
52
- ruby: '2.5'
53
-
54
- - gemfile: activerecord_5.2.0
55
- ruby: '2.5'
56
-
57
- - gemfile: activerecord_6.0.0
58
- ruby: '2.5'
59
-
60
- - gemfile: activerecord_6.1.0
61
- ruby: '2.5'
62
-
63
- - gemfile: activerecord_5.0.0
64
- ruby: '2.6'
65
-
66
- - gemfile: activerecord_5.1.0
67
- ruby: '2.6'
68
-
69
- - gemfile: activerecord_5.2.0
70
- ruby: '2.6'
71
-
72
- - gemfile: activerecord_6.0.0
73
- ruby: '2.6'
74
-
75
- - gemfile: activerecord_6.1.0
76
- ruby: '2.6'
77
-
78
- - gemfile: activerecord_5.0.0
79
- ruby: '2.7'
80
-
81
- - gemfile: activerecord_5.1.0
82
- ruby: '2.7'
83
-
84
- - gemfile: activerecord_5.2.0
85
- ruby: '2.7'
86
-
87
- - gemfile: activerecord_6.0.0
88
- ruby: '2.7'
89
-
90
- - gemfile: activerecord_6.1.0
91
- ruby: '2.7'
92
-
93
- - gemfile: activerecord_7.0.1
94
- ruby: '2.7'
95
-
96
- - gemfile: activerecord_6.1.0
97
- ruby: '3.0'
98
-
99
- - gemfile: activerecord_6.1.0
100
- ruby: '3.1'
101
-
102
- - gemfile: activerecord_6.1.0
103
- ruby: '3.2'
104
-
105
- - gemfile: activerecord_7.0.1
106
- ruby: '3.0'
107
-
108
- - gemfile: activerecord_7.0.1
109
- ruby: '3.1'
110
-
111
- - gemfile: activerecord_7.0.1
112
- ruby: '3.2'
113
-
114
- - gemfile: activerecord_5.1.0
115
- ruby: 'jruby-9.3'
116
-
117
- - gemfile: activerecord_5.2.0
118
- ruby: 'jruby-9.3'
119
-
120
- - gemfile: activerecord_6.0.0
121
- ruby: 'jruby-9.3'
122
-
123
- - gemfile: activerecord_6.1.0
124
- ruby: 'jruby-9.3'
125
-
126
- # waiting for https://github.com/jruby/activerecord-jdbc-adapter/issues/1125 to be addressed
127
- # - gemfile: activerecord_7.0.1
128
- # ruby: 'jruby-9.4'
58
+ - run: echo "gem 'activerecord', '~> ${{ matrix.activerecord }}.0'" > Gemfile.local
129
59
 
130
- name: ${{ matrix.gemfile }}, ruby ${{ matrix.ruby }}
60
+ - if: matrix.activerecord == '6.1' # see https://github.com/rails/rails/pull/54264#issuecomment-2596149819 and https://www.ruby-lang.org/en/news/2024/12/25/ruby-3-4-0-released/#standard-library-updates and https://www.ruby-lang.org/en/news/2025/12/25/ruby-4-0-0-released/#stdlib-updates
61
+ run: printf "gem 'concurrent-ruby', '< 1.3.5'\ngem 'mutex_m'\ngem 'base64'\ngem 'bigdecimal'\ngem 'logger'\n" >> Gemfile.local
131
62
 
132
- steps:
133
- - uses: actions/checkout@v3
134
-
135
- - name: Set up Ruby
136
- uses: ruby/setup-ruby@v1
63
+ - uses: ruby/setup-ruby@80740b3b13bf9857e28854481ca95a84e78a2bdf # v1.284.0
137
64
  with:
138
65
  ruby-version: ${{ matrix.ruby }}
139
66
  bundler-cache: true
140
67
 
141
- - name: Bundle install
142
- run: |
143
- bundle config set gemfile "${GITHUB_WORKSPACE}/gemfiles/${{ matrix.gemfile }}.gemfile"
144
- bundle install --jobs 4 --retry 3
145
-
146
- - name: Setup DB
147
- run: |
148
- bundle exec rake db:schema:load
68
+ - run: bundle exec rake db:schema:load
149
69
 
150
- - name: Run tests
151
- run: |
152
- bundle exec rake spec
70
+ - run: bundle exec rake spec
@@ -0,0 +1,43 @@
1
+ name: Publish gem to rubygems.org
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ push:
13
+ if: github.repository == 'madeintandem/jsonb_accessor'
14
+ runs-on: ubuntu-24.04
15
+
16
+ permissions:
17
+ contents: write
18
+ id-token: write
19
+
20
+ strategy:
21
+ matrix:
22
+ ruby: ["ruby-3.4", "jruby-9.4"]
23
+
24
+ steps:
25
+ - uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
26
+ with:
27
+ egress-policy: audit
28
+
29
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
30
+
31
+ - if: matrix.ruby == 'jruby-9.4' # cribbed from https://github.com/ruby/psych/blob/v5.2.4/.github/workflows/push_gem.yml
32
+ run: |
33
+ sudo apt install default-jdk maven
34
+ gem update --system
35
+ gem install ruby-maven rake-compiler --no-document
36
+ rake compile
37
+
38
+ - uses: ruby/setup-ruby@80740b3b13bf9857e28854481ca95a84e78a2bdf # v1.284.0
39
+ with:
40
+ bundler-cache: true
41
+ ruby-version: ${{ matrix.ruby }}
42
+
43
+ - uses: rubygems/release-gem@1c162a739e8b4cb21a676e97b087e8268d8fc40b # v1.1.2
data/.rubocop.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
- TargetRubyVersion: 2.7.2
3
+ TargetRubyVersion: 3.2.8
4
4
  SuggestExtensions: false
5
5
  Exclude:
6
6
  - "db/**/*"
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.1
1
+ 3.4.3
data/CHANGELOG.md CHANGED
@@ -1,6 +1,21 @@
1
1
  # Changelog
2
2
  ## [Unreleased]
3
3
 
4
+ ## [1.4.1] - 2026-01-22
5
+ ### Added
6
+ - Support for `prefix` and `suffix` options to customize attribute accessor names while preserving original keys in the JSONB column. [#173](https://github.com/madeintandem/jsonb_accessor/issues/173)
7
+
8
+ ## [1.4] - 2023-10-15
9
+ ### Breaking change
10
+ - `jsonb_accessor` dropped support for Ruby 2 and Rails versions lower than 6.1. Support for ActiveRecord::Enum was also
11
+ dropped because ActiveRecord 7.1 now requires each enum field to be backed by a database column. Enums will still work
12
+ when using AR versions lower than 7.1. This is a limitation of Rails, not of this gem.
13
+
14
+ ### Fixed
15
+
16
+ - Bug fix: An array of datetimes previously caused an error. https://github.com/madeintandem/jsonb_accessor/pull/169. Thanks @bekicot.
17
+ - Rails 7.1 is officially supported and tested against.
18
+
4
19
  ## [1.3.10] - 2023-05-30
5
20
  ### No changes
6
21
  A new release was necessary to fix the corrupted 1.3.9 Java release on RubyGems.
data/Gemfile CHANGED
@@ -4,3 +4,6 @@ source "https://rubygems.org"
4
4
 
5
5
  # Specify your gem's dependencies in jsonb_accessor.gemspec
6
6
  gemspec
7
+
8
+ local_gemfile = File.expand_path("Gemfile.local", __dir__)
9
+ eval_gemfile local_gemfile if File.exist?(local_gemfile)
data/README.md CHANGED
@@ -8,6 +8,10 @@ Adds typed `jsonb` backed fields as first class citizens to your `ActiveRecord`
8
8
 
9
9
  It also adds generic scopes for querying `jsonb` columns.
10
10
 
11
+ ## ⚠️ Status
12
+
13
+ This gem is in maintenance mode and no active development of new features is planned. The major focus is to keep it working with new Ruby/Rails versions and fix any bugs reported. Any PRs for feature requests or enhancements will be reviewed and merged -- so contributions are encouraged!
14
+
11
15
  ## Table of Contents
12
16
 
13
17
  - [Installation](#installation)
@@ -87,6 +91,58 @@ product.title #=> "Foo"
87
91
  product.data #=> { "t" => "Foo" }
88
92
  ```
89
93
 
94
+ You can also pass in a `prefix` or `suffix` option.
95
+
96
+ ```ruby
97
+ class Product < ActiveRecord::Base
98
+ jsonb_accessor :data,
99
+ title: [:string, prefix: :data],
100
+ external_id: [:integer, suffix: :attr]
101
+ end
102
+ ```
103
+
104
+ This allows you to use `data_title` and `external_id_attr` for your getters and setters, but use `title` and `external_id` as the key in the `jsonb`.
105
+ Also, you can pass `true` as a value for `prefix` or `suffix` to use the json_accessor name.
106
+
107
+ ```ruby
108
+ product = Product.new(data_title: "Foo", external_id_attr: 12314122)
109
+ product.data_title #=> "Foo"
110
+ product.external_id_attr #=> 12314122
111
+ product.data #=> { "title" => "Foo", "external_id" => 12314122 }
112
+ ```
113
+
114
+ ### Global Options
115
+
116
+ You can apply options to all fields by passing an options hash as the second parameter:
117
+
118
+ ```ruby
119
+ class Product < ActiveRecord::Base
120
+ jsonb_accessor :data, { prefix: true },
121
+ title: :string,
122
+ external_id: :integer,
123
+ price: :decimal
124
+ end
125
+ ```
126
+
127
+ This applies the `prefix` to all fields. You can still override it for individual fields:
128
+
129
+ ```ruby
130
+ class Product < ActiveRecord::Base
131
+ jsonb_accessor :data, { prefix: :product },
132
+ title: :string,
133
+ external_id: [:integer, prefix: :custom],
134
+ price: :decimal
135
+ end
136
+
137
+ product = Product.new(product_title: "Widget", custom_external_id: 123, product_price: 19.99)
138
+ product.product_title #=> "Widget"
139
+ product.custom_external_id #=> 123
140
+ product.product_price #=> 19.99
141
+ product.data #=> { "title" => "Widget", "external_id" => 123, "price" => 19.99 }
142
+ ```
143
+
144
+ Global options currently support `:prefix` and `:suffix`.
145
+
90
146
  ## Scopes
91
147
 
92
148
  Jsonb Accessor provides several scopes to make it easier to query `jsonb` columns. `jsonb_contains`, `jsonb_number_where`, `jsonb_time_where`, and `jsonb_where` are available on all `ActiveRecord::Base` subclasses and don't require that you make use of the `jsonb_accessor` declaration.
@@ -318,33 +374,22 @@ Because this gem promotes attributes nested into the JSON column to first level
318
374
 
319
375
  ## Dependencies
320
376
 
321
- - ActiveRecord >= 5.0
322
- - Postgres >= 9.4 (in order to use the [jsonb column type](http://www.postgresql.org/docs/9.4/static/datatype-json.html)).
377
+ We actively test the following in CI, older versions may work but are **not** supported:
323
378
 
324
- ## Upgrading
379
+ - Ruby >= 3.2 or JRuby >= 9.4
380
+ - Rails >= 6.1
381
+ - PostgreSQL >= 13
325
382
 
326
- See the [upgrade guide](UPGRADE_GUIDE.md).
383
+ JRuby isn't fully supported due to errors, see the CI matrix -- contributions to improve support are welcome!
327
384
 
328
385
  ## Development
329
386
 
330
- ### On your local machine
331
-
332
387
  After checking out the repo, run `bin/setup` to install dependencies (make sure postgres is running first).
333
388
 
334
389
  Run `bin/console` for an interactive prompt that will allow you to experiment.
335
390
 
336
391
  `rake` will run Rubocop and the specs.
337
392
 
338
- ### With Docker
339
-
340
- ```
341
- # setup
342
- docker-compose build
343
- docker-compose run ruby rake db:migrate
344
- # run test suite
345
- docker-compose run ruby rake spec
346
- ```
347
-
348
393
  ## Contributing
349
394
 
350
395
  1. [Fork it](https://github.com/madeintandem/jsonb_accessor/fork)
data/bin/console CHANGED
@@ -7,7 +7,7 @@ require "rspec"
7
7
  require File.expand_path("../spec/spec_helper.rb", __dir__)
8
8
 
9
9
  dbconfig = YAML.safe_load(ERB.new(File.read(File.join("db", "config.yml"))).result, aliases: true)
10
- ActiveRecord::Base.establish_connection(dbconfig["development"])
10
+ ActiveRecord::Base.establish_connection(dbconfig["test"])
11
11
 
12
12
  # rubocop:disable Lint/UselessAssignment
13
13
  x = Product.new
data/db/config.yml CHANGED
@@ -2,7 +2,7 @@ default: &default
2
2
  adapter: postgresql
3
3
  database: jsonb_accessor
4
4
  host: <%= ENV.fetch("DATABASE_HOST") { "127.0.0.1" } %>
5
- user: postgres
5
+ username: <%= ENV.fetch("DATABASE_USER") { "postgres" } %>
6
6
 
7
7
  test:
8
8
  <<: *default
data/db/schema.rb CHANGED
@@ -1,18 +1,16 @@
1
- # frozen_string_literal: true
2
-
3
1
  # This file is auto-generated from the current state of the database. Instead
4
2
  # of editing this file, please use the migrations feature of Active Record to
5
3
  # incrementally modify your database, and then regenerate this schema definition.
6
4
  #
7
- # Note that this schema.rb definition is the authoritative source for your
8
- # database schema. If you need to create the application database on another
9
- # system, you should be using db:schema:load, not running all the migrations
10
- # from scratch. The latter is a flawed and unsustainable approach (the more migrations
11
- # you'll amass, the slower it'll run and the greater likelihood for issues).
5
+ # This file is the source Rails uses to define your schema when running `bin/rails
6
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
12
10
  #
13
11
  # It's strongly recommended that you check this file into your version control system.
14
12
 
15
- ActiveRecord::Schema.define(version: 20_150_407_031_737) do
13
+ ActiveRecord::Schema.define(version: 2015_04_07_031737) do
16
14
  # These are extensions that must be enabled in order to support this database
17
15
  enable_extension "plpgsql"
18
16
 
@@ -30,7 +28,8 @@ ActiveRecord::Schema.define(version: 20_150_407_031_737) do
30
28
  t.float "float_type"
31
29
  t.time "time_type"
32
30
  t.date "date_type"
33
- t.datetime "datetime_type"
31
+ t.datetime "datetime_type", precision: nil
34
32
  t.decimal "decimal_type"
35
33
  end
34
+
36
35
  end
@@ -15,31 +15,32 @@ Gem::Specification.new do |spec|
15
15
 
16
16
  spec.summary = "Adds typed jsonb backed fields to your ActiveRecord models."
17
17
  spec.description = "Adds typed jsonb backed fields to your ActiveRecord models."
18
- spec.homepage = "https://github.com/devmynd/jsonb_accessor"
18
+ spec.homepage = "https://github.com/madeintandem/jsonb_accessor"
19
19
  spec.license = "MIT"
20
- spec.required_ruby_version = ">= 2"
20
+ spec.required_ruby_version = ">= 3"
21
21
 
22
22
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) || f.match(/png\z/) }
23
23
  spec.bindir = "exe"
24
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
25
  spec.require_paths = ["lib"]
26
26
 
27
- spec.add_dependency "activerecord", ">= 5.0"
28
- spec.add_dependency "activesupport", ">= 5.0"
27
+ spec.add_dependency "activerecord", ">= 6.1"
28
+ spec.add_dependency "activesupport", ">= 6.1"
29
29
  if is_java
30
30
  spec.add_dependency "activerecord-jdbcpostgresql-adapter", ">= 50.0"
31
31
  else
32
32
  spec.add_dependency "pg", ">= 0.18.1"
33
33
  end
34
34
 
35
- spec.add_development_dependency "appraisal", "~> 2.2.0"
36
35
  spec.add_development_dependency "awesome_print"
37
- spec.add_development_dependency "database_cleaner", "~> 1.6.0"
36
+ spec.add_development_dependency "benchmark" # for Ruby 4.0
37
+ spec.add_development_dependency "database_cleaner-active_record", ">= 2.1"
38
+ spec.add_development_dependency "ostruct" # for Ruby 4.0
38
39
  spec.add_development_dependency "pry"
39
40
  spec.add_development_dependency "pry-doc"
40
41
  spec.add_development_dependency "pry-nav"
41
- spec.add_development_dependency "psych", "~> 3"
42
+ spec.add_development_dependency "psych", ">= 3"
42
43
  spec.add_development_dependency "rake", ">= 12.3.3"
43
- spec.add_development_dependency "rspec", "~> 3.6.0"
44
- spec.add_development_dependency "rubocop", "~> 1"
44
+ spec.add_development_dependency "rspec", ">= 3.6.0"
45
+ spec.add_development_dependency "rubocop", ">= 1.0"
45
46
  end
@@ -24,14 +24,46 @@ module JsonbAccessor
24
24
  return value if value.blank?
25
25
 
26
26
  if attribute_type == :datetime
27
- value = if active_record_default_timezone == :utc
28
- Time.find_zone("UTC").parse(value).in_time_zone
27
+ value = if value.is_a?(Array)
28
+ value.map { |v| parse_date(v) }
29
29
  else
30
- Time.zone.parse(value)
30
+ parse_date(value)
31
31
  end
32
32
  end
33
33
 
34
34
  value
35
35
  end
36
+
37
+ # Parse datetime based on the configured default_timezone
38
+ def parse_date(datetime)
39
+ if active_record_default_timezone == :utc
40
+ Time.find_zone("UTC").parse(datetime).in_time_zone
41
+ else
42
+ Time.zone.parse(datetime)
43
+ end
44
+ end
45
+
46
+ def define_attribute_name(json_attribute, name, prefix, suffix)
47
+ accessor_prefix =
48
+ case prefix
49
+ when String, Symbol
50
+ "#{prefix}_"
51
+ when TrueClass
52
+ "#{json_attribute}_"
53
+ else
54
+ ""
55
+ end
56
+ accessor_suffix =
57
+ case suffix
58
+ when String, Symbol
59
+ "_#{suffix}"
60
+ when TrueClass
61
+ "_#{json_attribute}"
62
+ else
63
+ ""
64
+ end
65
+
66
+ "#{accessor_prefix}#{name}#{accessor_suffix}"
67
+ end
36
68
  end
37
69
  end
@@ -3,22 +3,30 @@
3
3
  module JsonbAccessor
4
4
  module Macro
5
5
  module ClassMethods
6
- def jsonb_accessor(jsonb_attribute, field_types)
7
- names_and_store_keys = field_types.each_with_object({}) do |(name, type), mapping|
8
- _type, options = Array(type)
9
- mapping[name.to_s] = (options.try(:delete, :store_key) || name).to_s
10
- end
11
-
12
- # Defines virtual attributes for each jsonb field.
13
- field_types.each do |name, type|
14
- next attribute name, type unless type.is_a?(Array)
15
- next attribute name, *type unless type.last.is_a?(Hash)
16
-
17
- *args, keyword_args = type
18
- attribute name, *args, **keyword_args
6
+ def jsonb_accessor(jsonb_attribute, global_options = {}, **definitions)
7
+ names_and_store_keys = {}
8
+ names_and_defaults = {}
9
+ names_and_attribute_names = {}
10
+
11
+ definitions.each do |name, value|
12
+ args = Array(value)
13
+ options = args.last.is_a?(Hash) ? args.pop : {}
14
+
15
+ # Determine store keys and default values for each field
16
+ names_and_store_keys[name.to_s] = (options.delete(:store_key) || name).to_s
17
+ names_and_defaults[name.to_s] = options.delete(:default) unless options[:default].nil?
18
+
19
+ prefix = options.delete(:prefix) || global_options[:prefix]
20
+ suffix = options.delete(:suffix) || global_options[:suffix]
21
+ attribute_name = JsonbAccessor::Helpers.define_attribute_name(jsonb_attribute, name, prefix, suffix)
22
+
23
+ # Define virtual attributes for each field
24
+ names_and_attribute_names[name.to_s] = attribute_name
25
+ attribute attribute_name, *args, **options
19
26
  end
20
27
 
21
28
  store_key_mapping_method_name = "jsonb_store_key_mapping_for_#{jsonb_attribute}"
29
+ attribute_name_mapping_method_name = "jsonb_attribute_name_mapping_for_#{jsonb_attribute}"
22
30
  # Defines methods on the model class
23
31
  class_methods = Module.new do
24
32
  # Allows us to get a mapping of field names to store keys scoped to the column
@@ -26,17 +34,16 @@ module JsonbAccessor
26
34
  superclass_mapping = superclass.try(store_key_mapping_method_name) || {}
27
35
  superclass_mapping.merge(names_and_store_keys)
28
36
  end
37
+
38
+ # Allows us to get a mapping of field names to attribute names scoped to the column
39
+ define_method(attribute_name_mapping_method_name) do
40
+ superclass_mapping = superclass.try(attribute_name_mapping_method_name) || {}
41
+ superclass_mapping.merge(names_and_attribute_names)
42
+ end
29
43
  end
30
44
  # We extend with class methods here so we can use the results of methods it defines to define more useful methods later
31
45
  extend class_methods
32
46
 
33
- # Get field names to default values mapping
34
- names_and_defaults = field_types.each_with_object({}) do |(name, type), mapping|
35
- _type, options = Array(type)
36
- field_default = options.try(:delete, :default)
37
- mapping[name.to_s] = field_default unless field_default.nil?
38
- end
39
-
40
47
  # Get store keys to default values mapping
41
48
  store_keys_and_defaults = JsonbAccessor::Helpers.convert_keys_to_store_keys(names_and_defaults, public_send(store_key_mapping_method_name))
42
49
 
@@ -63,11 +70,13 @@ module JsonbAccessor
63
70
  setters = Module.new do
64
71
  # Overrides the setter created by `attribute` above to make sure the jsonb attribute is kept in sync.
65
72
  names_and_store_keys.each do |name, store_key|
66
- define_method("#{name}=") do |value|
73
+ attribute_name = names_and_attribute_names[name]
74
+
75
+ define_method("#{attribute_name}=") do |value|
67
76
  super(value)
68
77
 
69
78
  # If enum was defined, take the value from the enum and not what comes out directly from the getter
70
- attribute_value = defined_enums[name].present? ? defined_enums[name][value] : public_send(name)
79
+ attribute_value = defined_enums[attribute_name].present? ? defined_enums[attribute_name][value] : public_send(attribute_name)
71
80
 
72
81
  # Rails always saves time based on `default_timezone`. Since #as_json considers timezone, manual conversion is needed
73
82
  if attribute_value.acts_like?(:time)
@@ -83,6 +92,7 @@ module JsonbAccessor
83
92
  define_method("#{jsonb_attribute}=") do |value|
84
93
  value ||= {}
85
94
  names_to_store_keys = self.class.public_send(store_key_mapping_method_name)
95
+ names_to_attribute_names = self.class.public_send(attribute_name_mapping_method_name)
86
96
 
87
97
  # this is the raw hash we want to save in the jsonb_attribute
88
98
  value_with_store_keys = JsonbAccessor::Helpers.convert_keys_to_store_keys(value, names_to_store_keys)
@@ -96,7 +106,8 @@ module JsonbAccessor
96
106
  # Only proceed if this attribute has been defined using `jsonb_accessor`.
97
107
  next unless names_to_store_keys.key?(name)
98
108
 
99
- write_attribute(name, attribute_value)
109
+ attribute_name = names_to_attribute_names[name]
110
+ write_attribute(attribute_name, attribute_value)
100
111
  end
101
112
  end
102
113
  end
@@ -109,13 +120,15 @@ module JsonbAccessor
109
120
  jsonb_values = public_send(jsonb_attribute) || {}
110
121
  jsonb_values.each do |store_key, value|
111
122
  name = names_and_store_keys.key(store_key)
112
- next unless name
123
+ attribute_name = names_and_attribute_names[name]
124
+
125
+ next unless attribute_name
113
126
 
114
127
  write_attribute(
115
- name,
116
- JsonbAccessor::Helpers.deserialize_value(value, self.class.type_for_attribute(name).type)
128
+ attribute_name,
129
+ JsonbAccessor::Helpers.deserialize_value(value, self.class.type_for_attribute(attribute_name).type)
117
130
  )
118
- clear_attribute_change(name) if persisted?
131
+ clear_attribute_change(attribute_name) if persisted?
119
132
  end
120
133
  end
121
134
 
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JsonbAccessor
4
- VERSION = "1.3.10"
4
+ VERSION = "1.4.1"
5
+
6
+ def self.enum_support?
7
+ # From AR 7.1 on, enums require a database column.
8
+ Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("7.1")
9
+ end
5
10
  end
metadata CHANGED
@@ -1,16 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonb_accessor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.10
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Crismali
8
8
  - Joe Hirn
9
9
  - Jason Haruska
10
- autorequire:
11
10
  bindir: exe
12
11
  cert_chain: []
13
- date: 2023-05-31 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: activerecord
@@ -18,28 +17,28 @@ dependencies:
18
17
  requirements:
19
18
  - - ">="
20
19
  - !ruby/object:Gem::Version
21
- version: '5.0'
20
+ version: '6.1'
22
21
  type: :runtime
23
22
  prerelease: false
24
23
  version_requirements: !ruby/object:Gem::Requirement
25
24
  requirements:
26
25
  - - ">="
27
26
  - !ruby/object:Gem::Version
28
- version: '5.0'
27
+ version: '6.1'
29
28
  - !ruby/object:Gem::Dependency
30
29
  name: activesupport
31
30
  requirement: !ruby/object:Gem::Requirement
32
31
  requirements:
33
32
  - - ">="
34
33
  - !ruby/object:Gem::Version
35
- version: '5.0'
34
+ version: '6.1'
36
35
  type: :runtime
37
36
  prerelease: false
38
37
  version_requirements: !ruby/object:Gem::Requirement
39
38
  requirements:
40
39
  - - ">="
41
40
  - !ruby/object:Gem::Version
42
- version: '5.0'
41
+ version: '6.1'
43
42
  - !ruby/object:Gem::Dependency
44
43
  name: pg
45
44
  requirement: !ruby/object:Gem::Requirement
@@ -55,21 +54,21 @@ dependencies:
55
54
  - !ruby/object:Gem::Version
56
55
  version: 0.18.1
57
56
  - !ruby/object:Gem::Dependency
58
- name: appraisal
57
+ name: awesome_print
59
58
  requirement: !ruby/object:Gem::Requirement
60
59
  requirements:
61
- - - "~>"
60
+ - - ">="
62
61
  - !ruby/object:Gem::Version
63
- version: 2.2.0
62
+ version: '0'
64
63
  type: :development
65
64
  prerelease: false
66
65
  version_requirements: !ruby/object:Gem::Requirement
67
66
  requirements:
68
- - - "~>"
67
+ - - ">="
69
68
  - !ruby/object:Gem::Version
70
- version: 2.2.0
69
+ version: '0'
71
70
  - !ruby/object:Gem::Dependency
72
- name: awesome_print
71
+ name: benchmark
73
72
  requirement: !ruby/object:Gem::Requirement
74
73
  requirements:
75
74
  - - ">="
@@ -83,19 +82,33 @@ dependencies:
83
82
  - !ruby/object:Gem::Version
84
83
  version: '0'
85
84
  - !ruby/object:Gem::Dependency
86
- name: database_cleaner
85
+ name: database_cleaner-active_record
87
86
  requirement: !ruby/object:Gem::Requirement
88
87
  requirements:
89
- - - "~>"
88
+ - - ">="
90
89
  - !ruby/object:Gem::Version
91
- version: 1.6.0
90
+ version: '2.1'
92
91
  type: :development
93
92
  prerelease: false
94
93
  version_requirements: !ruby/object:Gem::Requirement
95
94
  requirements:
96
- - - "~>"
95
+ - - ">="
97
96
  - !ruby/object:Gem::Version
98
- version: 1.6.0
97
+ version: '2.1'
98
+ - !ruby/object:Gem::Dependency
99
+ name: ostruct
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
99
112
  - !ruby/object:Gem::Dependency
100
113
  name: pry
101
114
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +155,14 @@ dependencies:
142
155
  name: psych
143
156
  requirement: !ruby/object:Gem::Requirement
144
157
  requirements:
145
- - - "~>"
158
+ - - ">="
146
159
  - !ruby/object:Gem::Version
147
160
  version: '3'
148
161
  type: :development
149
162
  prerelease: false
150
163
  version_requirements: !ruby/object:Gem::Requirement
151
164
  requirements:
152
- - - "~>"
165
+ - - ">="
153
166
  - !ruby/object:Gem::Version
154
167
  version: '3'
155
168
  - !ruby/object:Gem::Dependency
@@ -170,30 +183,30 @@ dependencies:
170
183
  name: rspec
171
184
  requirement: !ruby/object:Gem::Requirement
172
185
  requirements:
173
- - - "~>"
186
+ - - ">="
174
187
  - !ruby/object:Gem::Version
175
188
  version: 3.6.0
176
189
  type: :development
177
190
  prerelease: false
178
191
  version_requirements: !ruby/object:Gem::Requirement
179
192
  requirements:
180
- - - "~>"
193
+ - - ">="
181
194
  - !ruby/object:Gem::Version
182
195
  version: 3.6.0
183
196
  - !ruby/object:Gem::Dependency
184
197
  name: rubocop
185
198
  requirement: !ruby/object:Gem::Requirement
186
199
  requirements:
187
- - - "~>"
200
+ - - ">="
188
201
  - !ruby/object:Gem::Version
189
- version: '1'
202
+ version: '1.0'
190
203
  type: :development
191
204
  prerelease: false
192
205
  version_requirements: !ruby/object:Gem::Requirement
193
206
  requirements:
194
- - - "~>"
207
+ - - ">="
195
208
  - !ruby/object:Gem::Version
196
- version: '1'
209
+ version: '1.0'
197
210
  description: Adds typed jsonb backed fields to your ActiveRecord models.
198
211
  email:
199
212
  - michael@crismali.com
@@ -203,15 +216,15 @@ executables: []
203
216
  extensions: []
204
217
  extra_rdoc_files: []
205
218
  files:
219
+ - ".github/dependabot.yml"
206
220
  - ".github/workflows/ci.yml"
221
+ - ".github/workflows/push_gem.yml"
207
222
  - ".gitignore"
208
223
  - ".rspec"
209
224
  - ".rubocop.yml"
210
225
  - ".ruby-version"
211
- - Appraisals
212
226
  - CHANGELOG.md
213
227
  - CODE_OF_CONDUCT.md
214
- - Dockerfile
215
228
  - Gemfile
216
229
  - LICENSE.txt
217
230
  - Makefile
@@ -223,13 +236,6 @@ files:
223
236
  - db/config.yml
224
237
  - db/migrate/20150407031737_set_up_testing_db.rb
225
238
  - db/schema.rb
226
- - docker-compose.yml
227
- - gemfiles/activerecord_5.0.0.gemfile
228
- - gemfiles/activerecord_5.1.0.gemfile
229
- - gemfiles/activerecord_5.2.0.gemfile
230
- - gemfiles/activerecord_6.0.0.gemfile
231
- - gemfiles/activerecord_6.1.0.gemfile
232
- - gemfiles/activerecord_7.0.1.gemfile
233
239
  - jsonb_accessor.gemspec
234
240
  - lib/jsonb_accessor.rb
235
241
  - lib/jsonb_accessor/attribute_query_methods.rb
@@ -238,11 +244,10 @@ files:
238
244
  - lib/jsonb_accessor/query_builder.rb
239
245
  - lib/jsonb_accessor/query_helper.rb
240
246
  - lib/jsonb_accessor/version.rb
241
- homepage: https://github.com/devmynd/jsonb_accessor
247
+ homepage: https://github.com/madeintandem/jsonb_accessor
242
248
  licenses:
243
249
  - MIT
244
250
  metadata: {}
245
- post_install_message:
246
251
  rdoc_options: []
247
252
  require_paths:
248
253
  - lib
@@ -250,15 +255,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
250
255
  requirements:
251
256
  - - ">="
252
257
  - !ruby/object:Gem::Version
253
- version: '2'
258
+ version: '3'
254
259
  required_rubygems_version: !ruby/object:Gem::Requirement
255
260
  requirements:
256
261
  - - ">="
257
262
  - !ruby/object:Gem::Version
258
263
  version: '0'
259
264
  requirements: []
260
- rubygems_version: 3.4.10
261
- signing_key:
265
+ rubygems_version: 3.6.7
262
266
  specification_version: 4
263
267
  summary: Adds typed jsonb backed fields to your ActiveRecord models.
264
268
  test_files: []
data/Appraisals DELETED
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- appraise "activerecord-5.0.0" do
4
- gem "activerecord", "~> 5.0.0"
5
- end
6
-
7
- appraise "activerecord-5.1.0" do
8
- gem "activerecord", "~> 5.1.3"
9
- end
10
-
11
- appraise "activerecord-5.2.0" do
12
- gem "activerecord", "~> 5.2.8"
13
- end
14
-
15
- appraise "activerecord-6.0.0" do
16
- gem "activerecord", "~> 6.0.6"
17
- end
18
-
19
- appraise "activerecord-6.1.0" do
20
- gem "activerecord", "~> 6.1"
21
- end
22
-
23
- appraise "activerecord-7.0.1" do
24
- gem "activerecord", "~> 7.0.1"
25
- end
data/Dockerfile DELETED
@@ -1,12 +0,0 @@
1
- ARG RUBY_VERSION
2
- ARG RUBY_PLATFORM
3
- FROM ${RUBY_PLATFORM}:${RUBY_VERSION}
4
-
5
- RUN apt-get update && apt-get install -y --no-install-recommends git
6
-
7
- WORKDIR /usr/src/app
8
-
9
- COPY lib/jsonb_accessor/version.rb ./lib/jsonb_accessor/version.rb
10
- COPY jsonb_accessor.gemspec Gemfile ./
11
- # RUN bundle install
12
- COPY . ./
data/docker-compose.yml DELETED
@@ -1,30 +0,0 @@
1
- version: '3'
2
-
3
- services:
4
- ruby:
5
- environment:
6
- - DATABASE_HOST=postgres
7
- build:
8
- args:
9
- - RUBY_VERSION=${RUBY_VERSION:-3.2.2}
10
- - RUBY_PLATFORM=${RUBY_PLATFORM:-ruby}
11
- context: .
12
- volumes:
13
- - '.:/usr/src/app'
14
- depends_on:
15
- - postgres
16
-
17
-
18
- postgres:
19
- image: postgres:12
20
- environment:
21
- - POSTGRES_HOST_AUTH_METHOD=trust
22
- - POSTGRES_DB=jsonb_accessor
23
- - PGDATA=/var/lib/postgresql/data/pgdata
24
- volumes:
25
- - pg_data:/var/lib/postgresql/data/pgdata
26
- ports:
27
- - 5432:5432
28
-
29
- volumes:
30
- pg_data:
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 5.0.0"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 5.1.3"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 5.2.8"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 6.0.6"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 6.1"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 7.0.1"
6
-
7
- gemspec path: "../"