jsonb_accessor 1.3.0 → 1.3.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 12a9ef2a6ecf012dd86338b0962ea0338ac8950f
4
- data.tar.gz: ffb75c6ce59fa8eeb1a6917c822853f0aa63cead
2
+ SHA256:
3
+ metadata.gz: b3b40b7c775b9275c1fe7b6f3f3a8c0b7988dcd995da1b5bd594d0c3469ca372
4
+ data.tar.gz: 68dcf83030c07a537adee9030fd0f209f276e1e80f118c2d3ecc982694be466b
5
5
  SHA512:
6
- metadata.gz: ddb76f1639699f471680602e9d3f7601eca9666e7c3c03d2f3dce80d8e810a22940712668e0190f2469bccb54f9ae10a7f0b2fb7e763ea8818da32c34893ea91
7
- data.tar.gz: 11e77edee1f60874eb313da3301483beb5cc4a962ad14b8f202e923511a1378a10b664fcb00fb4eae161e06f73b4f3c20878871753a693cc5fd733665a0dd2c4
6
+ metadata.gz: 9a136d5a27d25f8ffb29e2f2f06ffb43417b91544836dda70dd40583786512d29d302251c39eb877772e382da5ef4af28afc970a31ae295b5d01933d5f5e33bd
7
+ data.tar.gz: 411147569acaf3f9052e4ccae17063b3b0eaeb00c2738933a520a635861b054889b31b534b8959ae5d38bc3f5709dc0c3ccc9b20f45cf0f1f066b0aa60469e77
@@ -0,0 +1,106 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: ['**']
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: 2.7.2
19
+ bundler-cache: true
20
+ - name: Rubocop
21
+ run: bundle exec rubocop
22
+
23
+ tests:
24
+ needs: lint
25
+ services:
26
+ db:
27
+ image: postgres:9.4
28
+ env:
29
+ POSTGRES_HOST_AUTH_METHOD: trust
30
+ POSTGRES_DB: jsonb_accessor
31
+ ports: ['5432:5432']
32
+ options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
33
+
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.5
41
+
42
+ - gemfile: activerecord_5.1.0
43
+ ruby: 2.4.5
44
+
45
+ - gemfile: activerecord_5.0.0
46
+ ruby: 2.5.3
47
+
48
+ - gemfile: activerecord_5.1.0
49
+ ruby: 2.5.3
50
+
51
+ - gemfile: activerecord_6.1.0
52
+ ruby: 2.5.3
53
+
54
+ - gemfile: activerecord_5.0.0
55
+ ruby: 2.6.1
56
+
57
+ - gemfile: activerecord_5.1.0
58
+ ruby: 2.6.1
59
+
60
+ - gemfile: activerecord_6.1.0
61
+ ruby: 2.6.1
62
+
63
+ - gemfile: activerecord_5.0.0
64
+ ruby: 2.7.2
65
+
66
+ - gemfile: activerecord_5.1.0
67
+ ruby: 2.7.2
68
+
69
+ - gemfile: activerecord_6.1.0
70
+ ruby: 2.7.2
71
+
72
+ - gemfile: activerecord_7.0.1
73
+ ruby: 2.7.2
74
+
75
+ - gemfile: activerecord_6.1.0
76
+ ruby: 3.0.0
77
+
78
+ - gemfile: activerecord_7.0.1
79
+ ruby: 3.0.0
80
+
81
+ - gemfile: activerecord_7.0.1
82
+ ruby: 3.1.0
83
+
84
+ name: ${{ matrix.gemfile }}, ruby ${{ matrix.ruby }}
85
+
86
+ steps:
87
+ - uses: actions/checkout@v2
88
+
89
+ - name: Set up Ruby
90
+ uses: ruby/setup-ruby@v1
91
+ with:
92
+ ruby-version: ${{ matrix.ruby }}
93
+ bundler-cache: true
94
+
95
+ - name: Bundle install
96
+ run: |
97
+ bundle config set gemfile "${GITHUB_WORKSPACE}/gemfiles/${{ matrix.gemfile }}.gemfile"
98
+ bundle install --jobs 4 --retry 3
99
+
100
+ - name: Setup DB
101
+ run: |
102
+ bundle exec rake db:create db:schema:load
103
+
104
+ - name: Run tests
105
+ run: |
106
+ bundle exec rake spec
data/.rubocop.yml CHANGED
@@ -1,11 +1,16 @@
1
1
  AllCops:
2
- Include:
3
- - "**/Rakefile"
2
+ NewCops: enable
3
+ TargetRubyVersion: 2.7.2
4
+ SuggestExtensions: false
4
5
  Exclude:
5
- - db/**/*
6
- - gemfiles/**/*
7
- - vendor/**/*
8
- Style/SpaceBeforeFirstArg:
6
+ - "db/**/*"
7
+ - "gemfiles/**/*"
8
+ - "vendor/**/*"
9
+ Layout/SpaceBeforeFirstArg:
10
+ Enabled: false
11
+ Layout/LineLength:
12
+ Enabled: false
13
+ Layout/SpaceAroundEqualsInParameterDefault:
9
14
  Enabled: false
10
15
  Lint/UnusedBlockArgument:
11
16
  Enabled: false
@@ -17,8 +22,6 @@ Metrics/ClassLength:
17
22
  Enabled: false
18
23
  Metrics/CyclomaticComplexity:
19
24
  Enabled: false
20
- Metrics/LineLength:
21
- Enabled: false
22
25
  Metrics/MethodLength:
23
26
  Enabled: false
24
27
  Metrics/ModuleLength:
@@ -27,10 +30,6 @@ Metrics/PerceivedComplexity:
27
30
  Enabled: false
28
31
  Metrics/BlockLength:
29
32
  Enabled: false
30
- Security/YAMLLoad:
31
- Enabled: false
32
- Style/AlignParameters:
33
- Enabled: false
34
33
  Style/ClassAndModuleChildren:
35
34
  Enabled: false
36
35
  Style/ClassVars:
@@ -39,25 +38,25 @@ Style/Documentation:
39
38
  Enabled: false
40
39
  Style/DoubleNegation:
41
40
  Enabled: false
42
- Style/FileName:
41
+ Naming/FileName:
43
42
  Enabled: false
44
43
  Style/GuardClause:
45
44
  Enabled: false
46
- Style/IndentHash:
47
- Enabled: false
48
45
  Style/NilComparison:
49
46
  Enabled: false
50
- Style/OpMethod:
51
- Enabled: false
52
47
  Style/RescueModifier:
53
48
  Enabled: false
54
49
  Style/SignalException:
55
50
  Enabled: false
56
51
  Style/SingleLineMethods:
57
52
  Enabled: false
58
- Style/SpaceAroundEqualsInParameterDefault:
59
- Enabled: false
60
53
  Style/StringLiterals:
61
54
  EnforcedStyle: double_quotes
62
- Performance/EndWith:
55
+ Naming/BinaryOperatorParameterName:
56
+ Enabled: false
57
+ Naming/VariableNumber:
58
+ Enabled: false
59
+ Gemspec/RequiredRubyVersion:
60
+ Enabled: false
61
+ Gemspec/RequireMFA:
63
62
  Enabled: false
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.4.1
1
+ 2.7.2
data/Appraisals CHANGED
@@ -11,3 +11,7 @@ end
11
11
  appraise "activerecord-6.1.0" do
12
12
  gem "activerecord", "~> 6.1"
13
13
  end
14
+
15
+ appraise "activerecord-7.0.1" do
16
+ gem "activerecord", "~> 7.0.1"
17
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+ ## [Unreleased]
3
+
4
+ ## [1.3.4] - 2022-02-02
5
+ ### Fixed
6
+
7
+ - Bug fix: Raised ActiveModel::MissingAttributeError when model was initialized without the jsonb_accessor field [#145](https://github.com/madeintandem/jsonb_accessor/issues/145)
8
+
9
+ ## [1.3.3] - 2022-01-29
10
+ ### Fixed
11
+
12
+ - Bug fix: DateTime objects are now correctly written without timezone
13
+ information [#137](https://github.com/madeintandem/jsonb_accessor/pull/137).
14
+ Thanks @caiohsramos
data/Dockerfile ADDED
@@ -0,0 +1,12 @@
1
+ ARG RUBY_VERSION=latest
2
+ FROM ruby:${RUBY_VERSION}
3
+
4
+ WORKDIR /usr/src/app
5
+
6
+ RUN mkdir -p lib/jsonb_accessor
7
+ COPY lib/jsonb_accessor/version.rb ./lib/jsonb_accessor/
8
+ COPY *.gemspec Gemfile* ./
9
+
10
+ RUN bundle install
11
+
12
+ COPY . .
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Created by &nbsp;&nbsp;&nbsp; [<img src="https://raw.githubusercontent.com/madeintandem/jsonb_accessor/master/tandem-logo.png" alt="Tandem Logo" />](https://www.madeintandem.com/)
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/jsonb_accessor.svg)](http://badge.fury.io/rb/jsonb_accessor) &nbsp;&nbsp;&nbsp;[![Build Status](https://travis-ci.org/madeintandem/jsonb_accessor.svg)](https://travis-ci.org/madeintandem/jsonb_accessor) <img src="https://raw.githubusercontent.com/madeintandem/jsonb_accessor/master/json-bee.png" alt="JSONb Accessor Logo" align="right" />
5
+ [![Gem Version](https://badge.fury.io/rb/jsonb_accessor.svg)](http://badge.fury.io/rb/jsonb_accessor) &nbsp;&nbsp;&nbsp;![CI](https://github.com/madeintandem/jsonb_accessor/actions/workflows/ci.yml/badge.svg) <img src="https://raw.githubusercontent.com/madeintandem/jsonb_accessor/master/json-bee.png" alt="JSONb Accessor Logo" align="right" />
6
6
 
7
7
  Adds typed `jsonb` backed fields as first class citizens to your `ActiveRecord` models. This gem is similar in spirit to [HstoreAccessor](https://github.com/madeintandem/hstore_accessor), but the `jsonb` column in PostgreSQL has a few distinct advantages, mostly around nested documents and support for collections.
8
8
 
@@ -10,15 +10,15 @@ It also adds generic scopes for querying `jsonb` columns.
10
10
 
11
11
  ## Table of Contents
12
12
 
13
- * [Installation](#installation)
14
- * [Usage](#usage)
15
- * [Scopes](#scopes)
16
- * [Single-Table Inheritance](#single-table-inheritance)
17
- * [Dependencies](#dependencies)
18
- * [Validations](#validations)
19
- * [Upgrading](#upgrading)
20
- * [Development](#development)
21
- * [Contributing](#contributing)
13
+ - [Installation](#installation)
14
+ - [Usage](#usage)
15
+ - [Scopes](#scopes)
16
+ - [Single-Table Inheritance](#single-table-inheritance)
17
+ - [Dependencies](#dependencies)
18
+ - [Validations](#validations)
19
+ - [Upgrading](#upgrading)
20
+ - [Development](#development)
21
+ - [Contributing](#contributing)
22
22
 
23
23
  ## Installation
24
24
 
@@ -158,6 +158,7 @@ Product.all.jsonb_where(:data, reviewed_at: { before: Time.current }, p: { great
158
158
 
159
159
  Product.all.data_where(reviewed_at: { before: Time.current }, price: { greater_than: 5 })
160
160
  ```
161
+
161
162
  This scope makes use of the `jsonb_contains`, `jsonb_number_where`, and `jsonb_time_where` `scope`s.
162
163
 
163
164
  ### `jsonb_where_not`
@@ -219,14 +220,14 @@ Product.all.jsonb_number_where(:data, :price_in_cents, :greater_than, 300)
219
220
 
220
221
  It supports:
221
222
 
222
- * `>`
223
- * `>=`
224
- * `greater_than`
225
- * `greater_than_or_equal_to`
226
- * `<`
227
- * `<=`
228
- * `less_than`
229
- * `less_than_or_equal_to`
223
+ - `>`
224
+ - `>=`
225
+ - `greater_than`
226
+ - `greater_than_or_equal_to`
227
+ - `<`
228
+ - `<=`
229
+ - `less_than`
230
+ - `less_than_or_equal_to`
230
231
 
231
232
  and it is indifferent to strings/symbols.
232
233
 
@@ -259,9 +260,9 @@ Product.all.jsonb_time_where_not(:data, :reviewed_at, :before, 2.days.ago)
259
260
  ## Single-Table Inheritance
260
261
 
261
262
  One of the big issues with `ActiveRecord` single-table inheritance (STI)
262
- is sparse columns. Essentially, as sub-types of the original table
263
+ is sparse columns. Essentially, as sub-types of the original table
263
264
  diverge further from their parent more columns are left empty in a given
264
- table. Postgres' `jsonb` type provides part of the solution in that
265
+ table. Postgres' `jsonb` type provides part of the solution in that
265
266
  the values in an `jsonb` column does not impose a structure - different
266
267
  rows can have different values.
267
268
 
@@ -305,7 +306,7 @@ end
305
306
  ```
306
307
 
307
308
  From here any attributes specific to any sub-class can be stored in the
308
- `jsonb` column avoiding sparse data. Indices can also be created on
309
+ `jsonb` column avoiding sparse data. Indices can also be created on
309
310
  individual fields in an `jsonb` column.
310
311
 
311
312
  This approach was originally conceived by Joe Hirn in [this blog
@@ -326,12 +327,24 @@ See the [upgrade guide](UPGRADE_GUIDE.md).
326
327
 
327
328
  ## Development
328
329
 
330
+ ### On your local machine
331
+
329
332
  After checking out the repo, run `bin/setup` to install dependencies (make sure postgres is running first).
330
333
 
331
334
  Run `bin/console` for an interactive prompt that will allow you to experiment.
332
335
 
333
336
  `rake` will run Rubocop and the specs.
334
337
 
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
+
335
348
  ## Contributing
336
349
 
337
350
  1. [Fork it](https://github.com/madeintandem/jsonb_accessor/fork)
data/Rakefile CHANGED
@@ -5,18 +5,21 @@ require "bundler/setup"
5
5
  require "bundler/gem_tasks"
6
6
  require "rspec/core/rake_task"
7
7
  require "rubocop/rake_task"
8
+ require "active_record"
9
+ require "erb"
8
10
 
9
11
  RSpec::Core::RakeTask.new
10
12
  RuboCop::RakeTask.new
11
13
 
12
- require "active_record"
14
+ # rubocop:disable Style/MixinUsage
13
15
  include ActiveRecord::Tasks
16
+ # rubocop:enable Style/MixinUsage
14
17
 
15
- root = File.expand_path "..", __FILE__
18
+ root = File.expand_path __dir__
16
19
  db_dir = File.join(root, "db")
17
20
  DatabaseTasks.root = root
18
21
  DatabaseTasks.db_dir = db_dir
19
- DatabaseTasks.database_configuration = YAML.load(File.read(File.join(db_dir, "config.yml")))
22
+ DatabaseTasks.database_configuration = YAML.safe_load(ERB.new(File.read(File.join(db_dir, "config.yml"))).result, aliases: true)
20
23
  DatabaseTasks.migrations_paths = [File.join(db_dir, "migrate")]
21
24
  DatabaseTasks.env = "test"
22
25
 
data/bin/console CHANGED
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- # rubocop:disable Lint/UselessAssignment
5
-
6
4
  require "bundler/setup"
7
5
  require "jsonb_accessor"
8
6
  require "rspec"
9
- require File.expand_path("../../spec/spec_helper.rb", __FILE__)
7
+ require File.expand_path("../spec/spec_helper.rb", __dir__)
10
8
 
11
- dbconfig = YAML.load(File.open("db/config.yml"))
9
+ dbconfig = YAML.safe_load(ERB.new(File.read(File.join("db", "config.yml"))).result, aliases: true)
12
10
  ActiveRecord::Base.establish_connection(dbconfig["development"])
13
11
 
12
+ # rubocop:disable Lint/UselessAssignment
14
13
  x = Product.new
14
+ # rubocop:enable Lint/UselessAssignment
15
15
 
16
16
  Pry.start
data/db/config.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  default: &default
2
2
  adapter: postgresql
3
3
  database: jsonb_accessor
4
- host: 127.0.0.1
4
+ host: <%= ENV.fetch("DATABASE_HOST") { "127.0.0.1" } %>
5
5
  user: postgres
6
6
 
7
7
  test:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class SetUpTestingDb < ActiveRecord::Migration[5.0]
2
4
  def change
3
5
  create_table :products do |t|
data/db/schema.rb CHANGED
@@ -1,17 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This file is auto-generated from the current state of the database. Instead
2
4
  # of editing this file, please use the migrations feature of Active Record to
3
5
  # incrementally modify your database, and then regenerate this schema definition.
4
6
  #
5
- # This file is the source Rails uses to define your schema when running `rails
6
- # db:schema:load`. When creating a new database, `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.
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).
10
12
  #
11
13
  # It's strongly recommended that you check this file into your version control system.
12
14
 
13
- ActiveRecord::Schema.define(version: 2015_04_07_031737) do
14
-
15
+ ActiveRecord::Schema.define(version: 20_150_407_031_737) do
15
16
  # These are extensions that must be enabled in order to support this database
16
17
  enable_extension "plpgsql"
17
18
 
@@ -32,5 +33,4 @@ ActiveRecord::Schema.define(version: 2015_04_07_031737) do
32
33
  t.datetime "datetime_type"
33
34
  t.decimal "decimal_type"
34
35
  end
35
-
36
36
  end
@@ -0,0 +1,29 @@
1
+ version: '3'
2
+
3
+ services:
4
+ ruby:
5
+ environment:
6
+ - DATABASE_HOST=postgres
7
+ build:
8
+ args:
9
+ - RUBY_VERSION=${RUBY_VERSION:-2.7.2}
10
+ context: .
11
+ volumes:
12
+ - '.:/usr/src/app'
13
+ depends_on:
14
+ - postgres
15
+
16
+
17
+ postgres:
18
+ image: postgres:12
19
+ environment:
20
+ - POSTGRES_HOST_AUTH_METHOD=trust
21
+ - POSTGRES_DB=jsonb_accessor
22
+ - PGDATA=/var/lib/postgresql/data/pgdata
23
+ volumes:
24
+ - pg_data:/var/lib/postgresql/data/pgdata
25
+ ports:
26
+ - 5432:5432
27
+
28
+ volumes:
29
+ pg_data:
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "pg"
6
+ gem "activerecord", "~> 7.0.1"
7
+
8
+ gemspec path: "../"
@@ -1,7 +1,6 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
- lib = File.expand_path("../lib", __FILE__)
3
+ lib = File.expand_path("lib", __dir__)
5
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
5
  require "jsonb_accessor/version"
7
6
 
@@ -27,12 +26,13 @@ Gem::Specification.new do |spec|
27
26
  spec.add_dependency "pg", ">= 0.18.1"
28
27
 
29
28
  spec.add_development_dependency "appraisal", "~> 2.2.0"
30
- spec.add_development_dependency "database_cleaner", "~> 1.6.0"
31
29
  spec.add_development_dependency "awesome_print"
30
+ spec.add_development_dependency "database_cleaner", "~> 1.6.0"
32
31
  spec.add_development_dependency "pry"
33
32
  spec.add_development_dependency "pry-doc"
34
33
  spec.add_development_dependency "pry-nav"
34
+ spec.add_development_dependency "psych", "~> 3"
35
35
  spec.add_development_dependency "rake", ">= 12.3.3"
36
36
  spec.add_development_dependency "rspec", "~> 3.6.0"
37
- spec.add_development_dependency "rubocop", "~> 0.48.1"
37
+ spec.add_development_dependency "rubocop", "~> 1"
38
38
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonbAccessor
4
+ class AttributeQueryMethods
5
+ def initialize(klass)
6
+ @klass = klass
7
+ end
8
+
9
+ def define(store_key_mapping_method_name, jsonb_attribute)
10
+ return if klass.superclass.respond_to? store_key_mapping_method_name
11
+
12
+ # <jsonb_attribute>_where scope
13
+ klass.define_singleton_method "#{jsonb_attribute}_where" do |attributes|
14
+ store_key_attributes = ::JsonbAccessor::Helpers.convert_keys_to_store_keys(attributes, all.model.public_send(store_key_mapping_method_name))
15
+ jsonb_where(jsonb_attribute, store_key_attributes)
16
+ end
17
+
18
+ # <jsonb_attribute>_where_not scope
19
+ klass.define_singleton_method "#{jsonb_attribute}_where_not" do |attributes|
20
+ store_key_attributes = ::JsonbAccessor::Helpers.convert_keys_to_store_keys(attributes, all.model.public_send(store_key_mapping_method_name))
21
+ jsonb_where_not(jsonb_attribute, store_key_attributes)
22
+ end
23
+
24
+ # <jsonb_attribute>_order scope
25
+ klass.define_singleton_method "#{jsonb_attribute}_order" do |*args|
26
+ ordering_options = args.extract_options!
27
+ order_by_defaults = args.each_with_object({}) { |attribute, config| config[attribute] = :asc }
28
+ store_key_mapping = all.model.public_send(store_key_mapping_method_name)
29
+
30
+ order_by_defaults.merge(ordering_options).reduce(all) do |query, (name, direction)|
31
+ key = store_key_mapping[name.to_s]
32
+ order_query = jsonb_order(jsonb_attribute, key, direction)
33
+ query.merge(order_query)
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :klass
41
+ end
42
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonbAccessor
4
+ module Helpers
5
+ module_function
6
+
7
+ def active_record_default_timezone
8
+ ActiveRecord.try(:default_timezone) || ActiveRecord::Base.default_timezone
9
+ end
10
+
11
+ # Replaces all keys in `attributes` that have a defined store_key with the store_key
12
+ def convert_keys_to_store_keys(attributes, store_key_mapping)
13
+ attributes.stringify_keys.transform_keys do |key|
14
+ store_key_mapping[key] || key
15
+ end
16
+ end
17
+
18
+ # Replaces all keys in `attributes` that have a defined store_key with the named key (alias)
19
+ def convert_store_keys_to_keys(attributes, store_key_mapping)
20
+ convert_keys_to_store_keys(attributes, store_key_mapping.invert)
21
+ end
22
+ end
23
+ end
@@ -38,7 +38,7 @@ module JsonbAccessor
38
38
  end
39
39
 
40
40
  # Get store keys to default values mapping
41
- store_keys_and_defaults = ::JsonbAccessor::QueryHelper.convert_keys_to_store_keys(names_and_defaults, public_send(store_key_mapping_method_name))
41
+ store_keys_and_defaults = ::JsonbAccessor::Helpers.convert_keys_to_store_keys(names_and_defaults, public_send(store_key_mapping_method_name))
42
42
 
43
43
  # Define jsonb_defaults_mapping_for_<jsonb_attribute>
44
44
  defaults_mapping_method_name = "jsonb_defaults_mapping_for_#{jsonb_attribute}"
@@ -55,7 +55,7 @@ module JsonbAccessor
55
55
  # each time it is evaluated.
56
56
  all_defaults_mapping_proc =
57
57
  if all_defaults_mapping.present?
58
- -> { all_defaults_mapping.map { |key, value| [key, value.respond_to?(:call) ? value.call : value] }.to_h }
58
+ -> { all_defaults_mapping.transform_values { |value| value.respond_to?(:call) ? value.call : value }.to_h.compact }
59
59
  end
60
60
  attribute jsonb_attribute, :jsonb, default: all_defaults_mapping_proc if all_defaults_mapping_proc.present?
61
61
 
@@ -65,65 +65,57 @@ module JsonbAccessor
65
65
  names_and_store_keys.each do |name, store_key|
66
66
  define_method("#{name}=") do |value|
67
67
  super(value)
68
- new_values = (public_send(jsonb_attribute) || {}).merge(store_key => public_send(name))
68
+
69
+ attribute_value = public_send(name)
70
+ # Rails always saves time based on `default_timezone`. Since #as_json considers timezone, manual conversion is needed
71
+ if attribute_value.acts_like?(:time)
72
+ attribute_value = (::JsonbAccessor::Helpers.active_record_default_timezone == :utc ? attribute_value.utc : attribute_value.in_time_zone).strftime("%F %R:%S.%L")
73
+ end
74
+
75
+ new_values = (public_send(jsonb_attribute) || {}).merge(store_key => attribute_value)
69
76
  write_attribute(jsonb_attribute, new_values)
70
77
  end
71
78
  end
72
79
 
73
80
  # Overrides the jsonb attribute setter to make sure the jsonb fields are kept in sync.
74
- define_method("#{jsonb_attribute}=") do |given_value|
75
- value = given_value || {}
81
+ define_method("#{jsonb_attribute}=") do |value|
82
+ value ||= {}
76
83
  names_to_store_keys = self.class.public_send(store_key_mapping_method_name)
77
84
 
78
- empty_store_key_attributes = names_to_store_keys.values.each_with_object({}) { |name, defaults| defaults[name] = nil }
79
- empty_named_attributes = names_to_store_keys.keys.each_with_object({}) { |name, defaults| defaults[name] = nil }
85
+ # this is the raw hash we want to save in the jsonb_attribute
86
+ value_with_store_keys = ::JsonbAccessor::Helpers.convert_keys_to_store_keys(value, names_to_store_keys)
87
+ write_attribute(jsonb_attribute, value_with_store_keys)
80
88
 
81
- store_key_attributes = ::JsonbAccessor::QueryHelper.convert_keys_to_store_keys(value, names_to_store_keys)
82
- write_attribute(jsonb_attribute, empty_store_key_attributes.merge(store_key_attributes))
89
+ # this maps attributes to values
90
+ value_with_named_keys = ::JsonbAccessor::Helpers.convert_store_keys_to_keys(value, names_to_store_keys)
83
91
 
84
- empty_named_attributes.merge(value).each { |name, attribute_value| write_attribute(name, attribute_value) }
92
+ empty_named_attributes = names_to_store_keys.transform_values { nil }
93
+ empty_named_attributes.merge(value_with_named_keys).each do |name, attribute_value|
94
+ # Undefined keys: There might be things in the JSON that haven't been defined using jsonb_accessor
95
+ # It should still be possible to save arbitrary data in the JSON
96
+ next unless has_attribute? name
97
+
98
+ write_attribute(name, attribute_value)
99
+ end
85
100
  end
86
101
  end
87
102
  include setters
88
103
 
89
104
  # Makes sure new objects have the appropriate values in their jsonb fields.
90
105
  after_initialize do
91
- if has_attribute?(jsonb_attribute)
92
- jsonb_values = public_send(jsonb_attribute) || {}
93
- jsonb_values.each do |store_key, value|
94
- name = names_and_store_keys.key(store_key)
95
- next unless name
96
-
97
- write_attribute(name, value)
98
- clear_attribute_change(name) if persisted?
99
- end
106
+ next unless has_attribute? jsonb_attribute
107
+
108
+ jsonb_values = public_send(jsonb_attribute) || {}
109
+ jsonb_values.each do |store_key, value|
110
+ name = names_and_store_keys.key(store_key)
111
+ next unless name
112
+
113
+ write_attribute(name, value)
114
+ clear_attribute_change(name) if persisted?
100
115
  end
101
116
  end
102
117
 
103
- # <jsonb_attribute>_where scope
104
- scope("#{jsonb_attribute}_where", lambda do |attributes|
105
- store_key_attributes = ::JsonbAccessor::QueryHelper.convert_keys_to_store_keys(attributes, all.model.public_send(store_key_mapping_method_name))
106
- jsonb_where(jsonb_attribute, store_key_attributes)
107
- end)
108
-
109
- # <jsonb_attribute>_where_not scope
110
- scope("#{jsonb_attribute}_where_not", lambda do |attributes|
111
- store_key_attributes = ::JsonbAccessor::QueryHelper.convert_keys_to_store_keys(attributes, all.model.public_send(store_key_mapping_method_name))
112
- jsonb_where_not(jsonb_attribute, store_key_attributes)
113
- end)
114
-
115
- # <jsonb_attribute>_order scope
116
- scope("#{jsonb_attribute}_order", lambda do |*args|
117
- ordering_options = args.extract_options!
118
- order_by_defaults = args.each_with_object({}) { |attribute, config| config[attribute] = :asc }
119
- store_key_mapping = all.model.public_send(store_key_mapping_method_name)
120
-
121
- order_by_defaults.merge(ordering_options).reduce(all) do |query, (name, direction)|
122
- key = store_key_mapping[name.to_s]
123
- order_query = jsonb_order(jsonb_attribute, key, direction)
124
- query.merge(order_query)
125
- end
126
- end)
118
+ ::JsonbAccessor::AttributeQueryMethods.new(self).define(store_key_mapping_method_name, jsonb_attribute)
127
119
  end
128
120
  end
129
121
  end
@@ -61,9 +61,7 @@ module JsonbAccessor
61
61
  excludes_attributes = {}
62
62
 
63
63
  attributes.each do |name, value|
64
- if value.is_a?(Range)
65
- raise JsonbAccessor::QueryHelper::NotSupported, "`jsonb_where_not` scope does not accept ranges as arguments. Given `#{value}` for `#{name}` field"
66
- end
64
+ raise JsonbAccessor::QueryHelper::NotSupported, "`jsonb_where_not` scope does not accept ranges as arguments. Given `#{value}` for `#{name}` field" if value.is_a?(Range)
67
65
 
68
66
  if JsonbAccessor::QueryHelper.number_query_arguments?(value)
69
67
  value.each { |operator, query_value| query = query.jsonb_number_where_not(column_name, name, operator, query_value) }
@@ -42,9 +42,7 @@ module JsonbAccessor
42
42
 
43
43
  class << self
44
44
  def validate_column_name!(query, column_name)
45
- if query.model.columns.none? { |column| column.name == column_name.to_s }
46
- raise InvalidColumnName, "a column named `#{column_name}` does not exist on the `#{query.model.table_name}` table"
47
- end
45
+ raise InvalidColumnName, "a column named `#{column_name}` does not exist on the `#{query.model.table_name}` table" if query.model.columns.none? { |column| column.name == column_name.to_s }
48
46
  end
49
47
 
50
48
  def validate_field_name!(query, column_name, field_name)
@@ -56,16 +54,7 @@ module JsonbAccessor
56
54
  end
57
55
 
58
56
  def validate_direction!(option)
59
- if ORDER_DIRECTIONS.exclude?(option)
60
- raise InvalidDirection, "`#{option}` is not a valid direction for ordering, only `asc` and `desc` are accepted"
61
- end
62
- end
63
-
64
- def convert_keys_to_store_keys(attributes, store_key_mapping)
65
- attributes.each_with_object({}) do |(name, value), new_attributes|
66
- store_key = store_key_mapping[name.to_s]
67
- new_attributes[store_key] = value
68
- end
57
+ raise InvalidDirection, "`#{option}` is not a valid direction for ordering, only `asc` and `desc` are accepted" if ORDER_DIRECTIONS.exclude?(option)
69
58
  end
70
59
 
71
60
  def number_query_arguments?(arg)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JsonbAccessor
4
- VERSION = "1.3.0"
4
+ VERSION = "1.3.4"
5
5
  end
@@ -5,9 +5,11 @@ require "active_record"
5
5
  require "active_record/connection_adapters/postgresql_adapter"
6
6
 
7
7
  require "jsonb_accessor/version"
8
+ require "jsonb_accessor/helpers"
8
9
  require "jsonb_accessor/macro"
9
10
  require "jsonb_accessor/query_helper"
10
11
  require "jsonb_accessor/query_builder"
12
+ require "jsonb_accessor/attribute_query_methods"
11
13
 
12
14
  module JsonbAccessor
13
15
  extend ActiveSupport::Concern
@@ -15,6 +17,6 @@ module JsonbAccessor
15
17
  end
16
18
 
17
19
  ActiveSupport.on_load(:active_record) do
18
- ActiveRecord::Base.send(:include, JsonbAccessor)
19
- ActiveRecord::Base.send(:include, JsonbAccessor::QueryBuilder)
20
+ ActiveRecord::Base.include JsonbAccessor
21
+ ActiveRecord::Base.include JsonbAccessor::QueryBuilder
20
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonb_accessor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Crismali
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2021-05-12 00:00:00.000000000 Z
13
+ date: 2022-02-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -68,6 +68,20 @@ dependencies:
68
68
  - - "~>"
69
69
  - !ruby/object:Gem::Version
70
70
  version: 2.2.0
71
+ - !ruby/object:Gem::Dependency
72
+ name: awesome_print
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
71
85
  - !ruby/object:Gem::Dependency
72
86
  name: database_cleaner
73
87
  requirement: !ruby/object:Gem::Requirement
@@ -83,7 +97,7 @@ dependencies:
83
97
  - !ruby/object:Gem::Version
84
98
  version: 1.6.0
85
99
  - !ruby/object:Gem::Dependency
86
- name: awesome_print
100
+ name: pry
87
101
  requirement: !ruby/object:Gem::Requirement
88
102
  requirements:
89
103
  - - ">="
@@ -97,7 +111,7 @@ dependencies:
97
111
  - !ruby/object:Gem::Version
98
112
  version: '0'
99
113
  - !ruby/object:Gem::Dependency
100
- name: pry
114
+ name: pry-doc
101
115
  requirement: !ruby/object:Gem::Requirement
102
116
  requirements:
103
117
  - - ">="
@@ -111,7 +125,7 @@ dependencies:
111
125
  - !ruby/object:Gem::Version
112
126
  version: '0'
113
127
  - !ruby/object:Gem::Dependency
114
- name: pry-doc
128
+ name: pry-nav
115
129
  requirement: !ruby/object:Gem::Requirement
116
130
  requirements:
117
131
  - - ">="
@@ -125,19 +139,19 @@ dependencies:
125
139
  - !ruby/object:Gem::Version
126
140
  version: '0'
127
141
  - !ruby/object:Gem::Dependency
128
- name: pry-nav
142
+ name: psych
129
143
  requirement: !ruby/object:Gem::Requirement
130
144
  requirements:
131
- - - ">="
145
+ - - "~>"
132
146
  - !ruby/object:Gem::Version
133
- version: '0'
147
+ version: '3'
134
148
  type: :development
135
149
  prerelease: false
136
150
  version_requirements: !ruby/object:Gem::Requirement
137
151
  requirements:
138
- - - ">="
152
+ - - "~>"
139
153
  - !ruby/object:Gem::Version
140
- version: '0'
154
+ version: '3'
141
155
  - !ruby/object:Gem::Dependency
142
156
  name: rake
143
157
  requirement: !ruby/object:Gem::Requirement
@@ -172,14 +186,14 @@ dependencies:
172
186
  requirements:
173
187
  - - "~>"
174
188
  - !ruby/object:Gem::Version
175
- version: 0.48.1
189
+ version: '1'
176
190
  type: :development
177
191
  prerelease: false
178
192
  version_requirements: !ruby/object:Gem::Requirement
179
193
  requirements:
180
194
  - - "~>"
181
195
  - !ruby/object:Gem::Version
182
- version: 0.48.1
196
+ version: '1'
183
197
  description: Adds typed jsonb backed fields to your ActiveRecord models.
184
198
  email:
185
199
  - michael@crismali.com
@@ -189,13 +203,15 @@ executables: []
189
203
  extensions: []
190
204
  extra_rdoc_files: []
191
205
  files:
206
+ - ".github/workflows/ci.yml"
192
207
  - ".gitignore"
193
208
  - ".rspec"
194
209
  - ".rubocop.yml"
195
210
  - ".ruby-version"
196
- - ".travis.yml"
197
211
  - Appraisals
212
+ - CHANGELOG.md
198
213
  - CODE_OF_CONDUCT.md
214
+ - Dockerfile
199
215
  - Gemfile
200
216
  - LICENSE.txt
201
217
  - README.md
@@ -206,11 +222,15 @@ files:
206
222
  - db/config.yml
207
223
  - db/migrate/20150407031737_set_up_testing_db.rb
208
224
  - db/schema.rb
225
+ - docker-compose.yml
209
226
  - gemfiles/activerecord_5.0.0.gemfile
210
227
  - gemfiles/activerecord_5.1.0.gemfile
211
228
  - gemfiles/activerecord_6.1.0.gemfile
229
+ - gemfiles/activerecord_7.0.1.gemfile
212
230
  - jsonb_accessor.gemspec
213
231
  - lib/jsonb_accessor.rb
232
+ - lib/jsonb_accessor/attribute_query_methods.rb
233
+ - lib/jsonb_accessor/helpers.rb
214
234
  - lib/jsonb_accessor/macro.rb
215
235
  - lib/jsonb_accessor/query_builder.rb
216
236
  - lib/jsonb_accessor/query_helper.rb
@@ -234,8 +254,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
234
254
  - !ruby/object:Gem::Version
235
255
  version: '0'
236
256
  requirements: []
237
- rubyforge_project:
238
- rubygems_version: 2.6.11
257
+ rubygems_version: 3.1.4
239
258
  signing_key:
240
259
  specification_version: 4
241
260
  summary: Adds typed jsonb backed fields to your ActiveRecord models.
data/.travis.yml DELETED
@@ -1,33 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.3.8
4
- - 2.4.5
5
- - 2.5.3
6
- - 2.6.1
7
- - 2.7.2
8
- - 3.0.0
9
- addons:
10
- postgresql: "9.4"
11
- before_install:
12
- - gem update --system
13
- - gem --version
14
- - gem install bundler:2.1.4
15
- before_script:
16
- - bundle exec rake db:create
17
- - bundle exec rake db:migrate
18
- install: bundle _2.1.4_ install --jobs=3 --retry=3 --path=${BUNDLE_PATH:-vendor/bundle}
19
- cache: bundler
20
- gemfile:
21
- - gemfiles/activerecord_5.0.0.gemfile
22
- - gemfiles/activerecord_5.1.0.gemfile
23
- - gemfiles/activerecord_6.1.0.gemfile
24
- jobs:
25
- exclude:
26
- - rvm: 2.3.8
27
- gemfile: gemfiles/activerecord_6.1.0.gemfile
28
- - rvm: 2.4.5
29
- gemfile: gemfiles/activerecord_6.1.0.gemfile
30
- - rvm: 3.0.0
31
- gemfile: gemfiles/activerecord_5.0.0.gemfile
32
- - rvm: 3.0.0
33
- gemfile: gemfiles/activerecord_5.1.0.gemfile