jsonb_accessor 1.2.0 → 1.3.3

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
- SHA1:
3
- metadata.gz: 80ed7aa0b3f529122a97b2a00b4f81011ef18014
4
- data.tar.gz: 407d572cea056870ce66d7b92c89d1b3e15bdb2d
2
+ SHA256:
3
+ metadata.gz: f098f30fabf2c5bbbe39acaecc6487c84516837bb8f55ff1ecfcde0bdda24e2f
4
+ data.tar.gz: 9dd89e98ec2937007ca3a11794ad3c0b3d48f8510a8f2836e0a1276b9ba8d5e0
5
5
  SHA512:
6
- metadata.gz: be4ffe5fc2318edc84b98ffee5296d30d2a9d03817540c4622f04875d0a41c19022c19c0c998357f6730cad37103ce79c43b46c5aa08a46dce8078b77f03752d
7
- data.tar.gz: c02e7189b7354d5d112aa9414e9cb4e5329d57b97b75b4d07a7e64da1abab04c63a0419509335fd557728eb48df1183d2a2d00c9c84ed7216ac4461205ec1c4d
6
+ metadata.gz: 2f7ca35afa36d13d4907b7e81ccf9c380c9eba36d7a18c6b6a10a1dcc6e423096fd39ab7c69ef372d9a217a01f31530b271e2f5a72ed482be1faa4dcc43806ea
7
+ data.tar.gz: 7389bebb7a9f7d6d4fcbde9cecc339f8505ae5cda68a6dbdd0489f10bcb1172919c9bd60d8bddee9be9a1053867ba99eefafce0be7cbf0022a151f9207fac069
@@ -0,0 +1,92 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: ['**']
8
+
9
+ jobs:
10
+ tests:
11
+ services:
12
+ db:
13
+ image: postgres:9.4
14
+ env:
15
+ POSTGRES_HOST_AUTH_METHOD: trust
16
+ POSTGRES_DB: jsonb_accessor
17
+ ports: ['5432:5432']
18
+ options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
19
+
20
+ runs-on: ubuntu-latest
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ include:
25
+ - gemfile: activerecord_5.0.0
26
+ ruby: 2.4.5
27
+
28
+ - gemfile: activerecord_5.1.0
29
+ ruby: 2.4.5
30
+
31
+ - gemfile: activerecord_5.0.0
32
+ ruby: 2.5.3
33
+
34
+ - gemfile: activerecord_5.1.0
35
+ ruby: 2.5.3
36
+
37
+ - gemfile: activerecord_6.1.0
38
+ ruby: 2.5.3
39
+
40
+ - gemfile: activerecord_5.0.0
41
+ ruby: 2.6.1
42
+
43
+ - gemfile: activerecord_5.1.0
44
+ ruby: 2.6.1
45
+
46
+ - gemfile: activerecord_6.1.0
47
+ ruby: 2.6.1
48
+
49
+ - gemfile: activerecord_5.0.0
50
+ ruby: 2.7.2
51
+
52
+ - gemfile: activerecord_5.1.0
53
+ ruby: 2.7.2
54
+
55
+ - gemfile: activerecord_6.1.0
56
+ ruby: 2.7.2
57
+
58
+ - gemfile: activerecord_7.0.1
59
+ ruby: 2.7.2
60
+
61
+ - gemfile: activerecord_6.1.0
62
+ ruby: 3.0.0
63
+
64
+ - gemfile: activerecord_7.0.1
65
+ ruby: 3.0.0
66
+
67
+ - gemfile: activerecord_7.0.1
68
+ ruby: 3.1.0
69
+
70
+ name: ${{ matrix.gemfile }}, ruby ${{ matrix.ruby }}
71
+
72
+ steps:
73
+ - uses: actions/checkout@v2
74
+
75
+ - name: Set up Ruby
76
+ uses: ruby/setup-ruby@v1
77
+ with:
78
+ ruby-version: ${{ matrix.ruby }}
79
+ bundler-cache: true
80
+
81
+ - name: Bundle install
82
+ run: |
83
+ bundle config set gemfile "${GITHUB_WORKSPACE}/gemfiles/${{ matrix.gemfile }}.gemfile"
84
+ bundle install --jobs 4 --retry 3
85
+
86
+ - name: Setup DB
87
+ run: |
88
+ bundle exec rake db:create db:schema:load
89
+
90
+ - name: Run tests
91
+ run: |
92
+ 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
@@ -7,3 +7,11 @@ end
7
7
  appraise "activerecord-5.1.0" do
8
8
  gem "activerecord", "~> 5.1.3"
9
9
  end
10
+
11
+ appraise "activerecord-6.1.0" do
12
+ gem "activerecord", "~> 6.1"
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,9 @@
1
+ # Changelog
2
+ ## [Unreleased]
3
+
4
+ ## [1.3.3] - 2022-01-29
5
+ ### Fixed
6
+
7
+ - Bug fix: DateTime objects are now correctly written without timezone
8
+ information [#137](https://github.com/madeintandem/jsonb_accessor/pull/137).
9
+ 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,10 +5,29 @@ require "bundler/setup"
5
5
  require "bundler/gem_tasks"
6
6
  require "rspec/core/rake_task"
7
7
  require "rubocop/rake_task"
8
- require "standalone_migrations"
9
- StandaloneMigrations::Tasks.load_tasks
8
+ require "active_record"
9
+ require "erb"
10
10
 
11
11
  RSpec::Core::RakeTask.new
12
12
  RuboCop::RakeTask.new
13
13
 
14
+ # rubocop:disable Style/MixinUsage
15
+ include ActiveRecord::Tasks
16
+ # rubocop:enable Style/MixinUsage
17
+
18
+ root = File.expand_path __dir__
19
+ db_dir = File.join(root, "db")
20
+ DatabaseTasks.root = root
21
+ DatabaseTasks.db_dir = db_dir
22
+ DatabaseTasks.database_configuration = YAML.safe_load(ERB.new(File.read(File.join(db_dir, "config.yml"))).result, aliases: true)
23
+ DatabaseTasks.migrations_paths = [File.join(db_dir, "migrate")]
24
+ DatabaseTasks.env = "test"
25
+
26
+ task :environment do
27
+ ActiveRecord::Base.configurations = DatabaseTasks.database_configuration
28
+ ActiveRecord::Base.establish_connection DatabaseTasks.env.to_sym
29
+ end
30
+
31
+ load "active_record/railties/databases.rake"
32
+
14
33
  task(default: %i[rubocop spec])
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,9 +1,8 @@
1
1
  default: &default
2
2
  adapter: postgresql
3
3
  database: jsonb_accessor
4
-
5
- development:
6
- <<: *default
4
+ host: <%= ENV.fetch("DATABASE_HOST") { "127.0.0.1" } %>
5
+ user: postgres
7
6
 
8
7
  test:
9
8
  <<: *default
@@ -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,3 +1,5 @@
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.
@@ -10,8 +12,7 @@
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: 20150407031737) 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: 20150407031737) 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", "~> 6.1"
7
+
8
+ gemspec path: "../"
@@ -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
 
@@ -15,7 +14,7 @@ Gem::Specification.new do |spec|
15
14
  spec.description = "Adds typed jsonb backed fields to your ActiveRecord models."
16
15
  spec.homepage = "https://github.com/devmynd/jsonb_accessor"
17
16
  spec.license = "MIT"
18
- spec.required_ruby_version = "~> 2.0"
17
+ spec.required_ruby_version = ">= 2"
19
18
 
20
19
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) || f.match(/png\z/) }
21
20
  spec.bindir = "exe"
@@ -27,14 +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 "bundler", "~> 2.1.4"
31
- spec.add_development_dependency "database_cleaner", "~> 1.6.0"
32
29
  spec.add_development_dependency "awesome_print"
30
+ spec.add_development_dependency "database_cleaner", "~> 1.6.0"
33
31
  spec.add_development_dependency "pry"
34
32
  spec.add_development_dependency "pry-doc"
35
33
  spec.add_development_dependency "pry-nav"
34
+ spec.add_development_dependency "psych", "~> 3"
36
35
  spec.add_development_dependency "rake", ">= 12.3.3"
37
36
  spec.add_development_dependency "rspec", "~> 3.6.0"
38
- spec.add_development_dependency "rubocop", "~> 0.48.1"
39
- spec.add_development_dependency "standalone_migrations", "~> 5.2.0"
37
+ spec.add_development_dependency "rubocop", "~> 1"
40
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::QueryHelper.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::QueryHelper.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,9 @@
1
+ module JsonbAccessor
2
+ module Helpers
3
+ module_function
4
+
5
+ def active_record_default_timezone
6
+ ActiveRecord.try(:default_timezone) || ActiveRecord::Base.default_timezone
7
+ end
8
+ end
9
+ end
@@ -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::QueryHelper.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::QueryHelper.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 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,18 +54,21 @@ 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
57
+ raise InvalidDirection, "`#{option}` is not a valid direction for ordering, only `asc` and `desc` are accepted" if ORDER_DIRECTIONS.exclude?(option)
62
58
  end
63
59
 
60
+ # Replaces all keys in `attributes` that have a defined store_key with the store_key
64
61
  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
62
+ attributes.stringify_keys.transform_keys do |key|
63
+ store_key_mapping[key] || key
68
64
  end
69
65
  end
70
66
 
67
+ # Replaces all keys in `attributes` that have a defined store_key with the named key (alias)
68
+ def convert_store_keys_to_keys(attributes, store_key_mapping)
69
+ convert_keys_to_store_keys(attributes, store_key_mapping.invert)
70
+ end
71
+
71
72
  def number_query_arguments?(arg)
72
73
  arg.is_a?(Hash) && arg.keys.map(&:to_s).all? { |key| NUMBER_OPERATORS.include?(key) }
73
74
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JsonbAccessor
4
- VERSION = "1.2.0"
4
+ VERSION = "1.3.3"
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,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonb_accessor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Crismali
8
8
  - Joe Hirn
9
9
  - Jason Haruska
10
- autorequire:
10
+ autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2021-05-03 00:00:00.000000000 Z
13
+ date: 2022-01-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -69,19 +69,19 @@ dependencies:
69
69
  - !ruby/object:Gem::Version
70
70
  version: 2.2.0
71
71
  - !ruby/object:Gem::Dependency
72
- name: bundler
72
+ name: awesome_print
73
73
  requirement: !ruby/object:Gem::Requirement
74
74
  requirements:
75
- - - "~>"
75
+ - - ">="
76
76
  - !ruby/object:Gem::Version
77
- version: 2.1.4
77
+ version: '0'
78
78
  type: :development
79
79
  prerelease: false
80
80
  version_requirements: !ruby/object:Gem::Requirement
81
81
  requirements:
82
- - - "~>"
82
+ - - ">="
83
83
  - !ruby/object:Gem::Version
84
- version: 2.1.4
84
+ version: '0'
85
85
  - !ruby/object:Gem::Dependency
86
86
  name: database_cleaner
87
87
  requirement: !ruby/object:Gem::Requirement
@@ -97,7 +97,7 @@ dependencies:
97
97
  - !ruby/object:Gem::Version
98
98
  version: 1.6.0
99
99
  - !ruby/object:Gem::Dependency
100
- name: awesome_print
100
+ name: pry
101
101
  requirement: !ruby/object:Gem::Requirement
102
102
  requirements:
103
103
  - - ">="
@@ -111,7 +111,7 @@ dependencies:
111
111
  - !ruby/object:Gem::Version
112
112
  version: '0'
113
113
  - !ruby/object:Gem::Dependency
114
- name: pry
114
+ name: pry-doc
115
115
  requirement: !ruby/object:Gem::Requirement
116
116
  requirements:
117
117
  - - ">="
@@ -125,7 +125,7 @@ dependencies:
125
125
  - !ruby/object:Gem::Version
126
126
  version: '0'
127
127
  - !ruby/object:Gem::Dependency
128
- name: pry-doc
128
+ name: pry-nav
129
129
  requirement: !ruby/object:Gem::Requirement
130
130
  requirements:
131
131
  - - ">="
@@ -139,19 +139,19 @@ dependencies:
139
139
  - !ruby/object:Gem::Version
140
140
  version: '0'
141
141
  - !ruby/object:Gem::Dependency
142
- name: pry-nav
142
+ name: psych
143
143
  requirement: !ruby/object:Gem::Requirement
144
144
  requirements:
145
- - - ">="
145
+ - - "~>"
146
146
  - !ruby/object:Gem::Version
147
- version: '0'
147
+ version: '3'
148
148
  type: :development
149
149
  prerelease: false
150
150
  version_requirements: !ruby/object:Gem::Requirement
151
151
  requirements:
152
- - - ">="
152
+ - - "~>"
153
153
  - !ruby/object:Gem::Version
154
- version: '0'
154
+ version: '3'
155
155
  - !ruby/object:Gem::Dependency
156
156
  name: rake
157
157
  requirement: !ruby/object:Gem::Requirement
@@ -186,28 +186,14 @@ dependencies:
186
186
  requirements:
187
187
  - - "~>"
188
188
  - !ruby/object:Gem::Version
189
- version: 0.48.1
190
- type: :development
191
- prerelease: false
192
- version_requirements: !ruby/object:Gem::Requirement
193
- requirements:
194
- - - "~>"
195
- - !ruby/object:Gem::Version
196
- version: 0.48.1
197
- - !ruby/object:Gem::Dependency
198
- name: standalone_migrations
199
- requirement: !ruby/object:Gem::Requirement
200
- requirements:
201
- - - "~>"
202
- - !ruby/object:Gem::Version
203
- version: 5.2.0
189
+ version: '1'
204
190
  type: :development
205
191
  prerelease: false
206
192
  version_requirements: !ruby/object:Gem::Requirement
207
193
  requirements:
208
194
  - - "~>"
209
195
  - !ruby/object:Gem::Version
210
- version: 5.2.0
196
+ version: '1'
211
197
  description: Adds typed jsonb backed fields to your ActiveRecord models.
212
198
  email:
213
199
  - michael@crismali.com
@@ -217,13 +203,15 @@ executables: []
217
203
  extensions: []
218
204
  extra_rdoc_files: []
219
205
  files:
206
+ - ".github/workflows/ci.yml"
220
207
  - ".gitignore"
221
208
  - ".rspec"
222
209
  - ".rubocop.yml"
223
210
  - ".ruby-version"
224
- - ".travis.yml"
225
211
  - Appraisals
212
+ - CHANGELOG.md
226
213
  - CODE_OF_CONDUCT.md
214
+ - Dockerfile
227
215
  - Gemfile
228
216
  - LICENSE.txt
229
217
  - README.md
@@ -234,10 +222,15 @@ files:
234
222
  - db/config.yml
235
223
  - db/migrate/20150407031737_set_up_testing_db.rb
236
224
  - db/schema.rb
225
+ - docker-compose.yml
237
226
  - gemfiles/activerecord_5.0.0.gemfile
238
227
  - gemfiles/activerecord_5.1.0.gemfile
228
+ - gemfiles/activerecord_6.1.0.gemfile
229
+ - gemfiles/activerecord_7.0.1.gemfile
239
230
  - jsonb_accessor.gemspec
240
231
  - lib/jsonb_accessor.rb
232
+ - lib/jsonb_accessor/attribute_query_methods.rb
233
+ - lib/jsonb_accessor/helpers.rb
241
234
  - lib/jsonb_accessor/macro.rb
242
235
  - lib/jsonb_accessor/query_builder.rb
243
236
  - lib/jsonb_accessor/query_helper.rb
@@ -246,24 +239,23 @@ homepage: https://github.com/devmynd/jsonb_accessor
246
239
  licenses:
247
240
  - MIT
248
241
  metadata: {}
249
- post_install_message:
242
+ post_install_message:
250
243
  rdoc_options: []
251
244
  require_paths:
252
245
  - lib
253
246
  required_ruby_version: !ruby/object:Gem::Requirement
254
247
  requirements:
255
- - - "~>"
248
+ - - ">="
256
249
  - !ruby/object:Gem::Version
257
- version: '2.0'
250
+ version: '2'
258
251
  required_rubygems_version: !ruby/object:Gem::Requirement
259
252
  requirements:
260
253
  - - ">="
261
254
  - !ruby/object:Gem::Version
262
255
  version: '0'
263
256
  requirements: []
264
- rubyforge_project:
265
- rubygems_version: 2.6.11
266
- signing_key:
257
+ rubygems_version: 3.1.4
258
+ signing_key:
267
259
  specification_version: 4
268
260
  summary: Adds typed jsonb backed fields to your ActiveRecord models.
269
261
  test_files: []
data/.travis.yml DELETED
@@ -1,20 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.3.8
4
- - 2.4.5
5
- - 2.5.3
6
- - 2.6.1
7
- addons:
8
- postgresql: "9.4"
9
- before_install:
10
- - gem update --system
11
- - gem --version
12
- - gem install bundler:2.1.4
13
- before_script:
14
- - bundle exec rake db:create
15
- - bundle exec rake db:migrate
16
- install: bundle _2.1.4_ install --jobs=3 --retry=3 --path=${BUNDLE_PATH:-vendor/bundle}
17
- cache: bundler
18
- gemfile:
19
- - gemfiles/activerecord_5.0.0.gemfile
20
- - gemfiles/activerecord_5.1.0.gemfile