jsonb_accessor-1.4/ 0000755 0000041 0000041 00000000000 14531041247 014404 5 ustar www-data www-data jsonb_accessor-1.4/UPGRADE_GUIDE.md 0000644 0000041 0000041 00000003773 14531041247 016744 0 ustar www-data www-data # Upgrading from 0.X.X to 1.0.0
## Jsonb Accessor declaration
In 0.X.X you would write:
```ruby
class Product < ActiveRecord::Base
jsonb_accessor :data,
:count, # doesn't specify a type
title: :string,
external_id: :integer,
reviewed_at: :date_time, # snake cased
previous_rankings: :integer_array, # `:type_array` key
external_rankings: :array # plain array
end
```
In 1.0.0 you would write:
```ruby
class Product < ActiveRecord::Base
jsonb_accessor :data,
count: :value, # all fields must specify a type
title: :string,
external_id: :integer,
reviewed_at: :datetime, # `:date_time` is now `:datetime`
previous_rankings: [:integer, array: true], # now just the type followed by `array: true`
external_rankings: [:value, array: true] # now the value type is specified as well as `array: true`
end
```
There are several important differences. All fields must now specify a type, `:date_time` is now `:datetime`, and arrays are specified using a type and `array: true` instead of `type_array`.
Also, in order to use the `value` type you need to register it:
```ruby
# in an initializer
ActiveRecord::Type.register(:value, ActiveRecord::Type::Value)
```
### Deeply nested objects
In 0.X.X you could write:
```ruby
class Product < ActiveRecord::Base
jsonb_accessor :data,
ranking_info: {
original_rank: :integer,
current_rank: :integer,
metadata: {
ranked_on: :date
}
}
end
```
Which would allow you to use getter and setter methods at any point in the structure.
```ruby
Product.new(ranking_info: { original_rank: 3, current_rank: 5, metadata: { ranked_on: Date.today } })
product.ranking_info.original_rank # 3
product.ranking_info.metadata.ranked_on # Date.today
```
1.0.0 does not support this syntax. If you need these sort of methods, you can create your own type `class` and register it with `ActiveRecord::Type`. [Here's an example](http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute).
jsonb_accessor-1.4/Makefile 0000644 0000041 0000041 00000000715 14531041247 016047 0 ustar www-data www-data build-gem:
@docker build --build-arg RUBY_PLATFORM=ruby --build-arg RUBY_VERSION=3.2.2 -t jsonb_accessor-ruby:3.2.2 .
@docker run --rm -v $(PWD):/usr/src/app -w /usr/src/app jsonb_accessor-ruby:3.2.2 gem build
build-gem-java:
@docker build --build-arg RUBY_PLATFORM=jruby --build-arg RUBY_VERSION=9.4.2-jdk -t jsonb_accessor-jruby:9.4.2-jdk .
@docker run --rm -v $(PWD):/usr/src/app -w /usr/src/app jsonb_accessor-jruby:9.4.2-jdk gem build --platform java
jsonb_accessor-1.4/.rspec 0000644 0000041 0000041 00000000032 14531041247 015514 0 ustar www-data www-data --format progress
--color
jsonb_accessor-1.4/README.md 0000644 0000041 0000041 00000026563 14531041247 015677 0 ustar www-data www-data # JSONb Accessor
Created by [
](https://www.madeintandem.com/)
[](http://badge.fury.io/rb/jsonb_accessor) 
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.
It also adds generic scopes for querying `jsonb` columns.
## Table of Contents
- [Installation](#installation)
- [Usage](#usage)
- [Scopes](#scopes)
- [Single-Table Inheritance](#single-table-inheritance)
- [Dependencies](#dependencies)
- [Validations](#validations)
- [Upgrading](#upgrading)
- [Development](#development)
- [Contributing](#contributing)
## Installation
Add this line to your application's `Gemfile`:
```ruby
gem "jsonb_accessor"
```
And then execute:
$ bundle install
## Usage
First we must create a model which has a `jsonb` column available to store data into it:
```ruby
class CreateProducts < ActiveRecord::Migration
def change
create_table :products do |t|
t.jsonb :data
end
end
end
```
We can then declare the `jsonb` fields we wish to expose via the accessor:
```ruby
class Product < ActiveRecord::Base
jsonb_accessor :data,
title: :string,
external_id: :integer,
reviewed_at: :datetime
end
```
Any type the [`attribute` API](http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute) supports. You can also implement your own type by following the example in the `attribute` documentation.
To pass through options like `default` and `array` to the `attribute` API, just put them in an array.
```ruby
class Product < ActiveRecord::Base
jsonb_accessor :data,
title: [:string, default: "Untitled"],
previous_titles: [:string, array: true, default: []]
end
```
The `default` option works pretty much as you would expect in practice; if no values are set for the attributes, a hash of the specified default values is saved to the jsonb column.
You can also pass in a `store_key` option.
```ruby
class Product < ActiveRecord::Base
jsonb_accessor :data, title: [:string, store_key: :t]
end
```
This allows you to use `title` for your getters and setters, but use `t` as the key in the `jsonb` column.
```ruby
product = Product.new(title: "Foo")
product.title #=> "Foo"
product.data #=> { "t" => "Foo" }
```
## Scopes
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.
If a class does have a `jsonb_accessor` declaration, then we define one custom scope. So, let's say we have a class that looks like this:
```ruby
class Product < ActiveRecord::Base
jsonb_accessor :data,
name: :string,
price: [:integer, store_key: :p],
price_in_cents: :integer,
reviewed_at: :datetime
end
```
Jsonb Accessor will add a `scope` to `Product` called like the json column with `_where` suffix, in our case `data_where`.
```ruby
Product.all.data_where(name: "Granite Towel", price: 17)
```
Similarly, it will also add a `data_where_not` `scope` to `Product`.
```ruby
Product.all.data_where_not(name: "Plasma Fork")
```
For number fields you can query using `<` or `>`or use plain english if that's what you prefer.
```ruby
Product.all.data_where(price: { <: 15 })
Product.all.data_where(price: { <=: 15 })
Product.all.data_where(price: { less_than: 15 })
Product.all.data_where(price: { less_than_or_equal_to: 15 })
Product.all.data_where(price: { >: 15 })
Product.all.data_where(price: { >=: 15 })
Product.all.data_where(price: { greater_than: 15 })
Product.all.data_where(price: { greater_than_or_equal_to: 15 })
Product.all.data_where(price: { greater_than: 15, less_than: 30 })
```
For time related fields you can query using `before` and `after`.
```ruby
Product.all.data_where(reviewed_at: { before: Time.current.beginning_of_week, after: 4.weeks.ago })
```
If you want to search for records within a certain time, date, or number range, just pass in the range (Note: this is just shorthand for the above mentioned `before`/`after`/`less_than`/`less_than_or_equal_to`/`greater_than_or_equal_to`/etc options).
```ruby
Product.all.data_where(price: 10..20)
Product.all.data_where(price: 10...20)
Product.all.data_where(reviewed_at: Time.current..3.days.from_now)
```
This scope is a convenient wrapper around the `jsonb_where` `scope` that saves you from having to convert the given keys to the store keys and from specifying the column.
### `jsonb_where`
Works just like the [`scope` above](#scopes) except that it does not convert the given keys to store keys and you must specify the column name. For example:
```ruby
Product.all.jsonb_where(:data, reviewed_at: { before: Time.current }, p: { greater_than: 5 })
# instead of
Product.all.data_where(reviewed_at: { before: Time.current }, price: { greater_than: 5 })
```
This scope makes use of the `jsonb_contains`, `jsonb_number_where`, and `jsonb_time_where` `scope`s.
### `jsonb_where_not`
Just the opposite of `jsonb_where`. Note that this will automatically exclude all records that contain `null` in their jsonb column (the `data` column, in the example below).
```ruby
Product.all.jsonb_where_not(:data, reviewed_at: { before: Time.current }, p: { greater_than: 5 })
```
### `_order`
Orders your query according to values in the Jsonb Accessor fields similar to ActiveRecord's `order`.
```ruby
Product.all.data_order(:price)
Product.all.data_order(:price, :reviewed_at)
Product.all.data_order(:price, reviewed_at: :desc)
```
It will convert your given keys into store keys if necessary.
### `jsonb_order`
Allows you to order by a Jsonb Accessor field.
```ruby
Product.all.jsonb_order(:data, :price, :asc)
Product.all.jsonb_order(:data, :price, :desc)
```
### `jsonb_contains`
Returns all records that contain the given JSON paths.
```ruby
Product.all.jsonb_contains(:data, title: "foo")
Product.all.jsonb_contains(:data, reviewed_at: 10.minutes.ago, p: 12) # Using the store key
```
**Note:** Under the hood, `jsonb_contains` uses the [`@>` operator in Postgres](https://www.postgresql.org/docs/9.5/static/functions-json.html) so when you include an array query, the stored array and the array used for the query do not need to match exactly. For example, when queried with `[1, 2]`, records that have arrays of `[2, 1, 3]` will be returned.
### `jsonb_excludes`
Returns all records that exclude the given JSON paths. Pretty much the opposite of `jsonb_contains`. Note that this will automatically exclude all records that contain `null` in their jsonb column (the `data` column, in the example below).
```ruby
Product.all.jsonb_excludes(:data, title: "foo")
Product.all.jsonb_excludes(:data, reviewed_at: 10.minutes.ago, p: 12) # Using the store key
```
### `jsonb_number_where`
Returns all records that match the given criteria.
```ruby
Product.all.jsonb_number_where(:data, :price_in_cents, :greater_than, 300)
```
It supports:
- `>`
- `>=`
- `greater_than`
- `greater_than_or_equal_to`
- `<`
- `<=`
- `less_than`
- `less_than_or_equal_to`
and it is indifferent to strings/symbols.
### `jsonb_number_where_not`
Returns all records that do not match the given criteria. It's the opposite of `jsonb_number_where`. Note that this will automatically exclude all records that contain `null` in their jsonb column (the `data` column, in the example below).
```ruby
Product.all.jsonb_number_where_not(:data, :price_in_cents, :greater_than, 300)
```
### `jsonb_time_where`
Returns all records that match the given criteria.
```ruby
Product.all.jsonb_time_where(:data, :reviewed_at, :before, 2.days.ago)
```
It supports `before` and `after` and is indifferent to strings/symbols.
### `jsonb_time_where_not`
Returns all records that match the given criteria. The opposite of `jsonb_time_where`. Note that this will automatically exclude all records that contain `null` in their jsonb column (the `data` column, in the example below).
```ruby
Product.all.jsonb_time_where_not(:data, :reviewed_at, :before, 2.days.ago)
```
## Single-Table Inheritance
One of the big issues with `ActiveRecord` single-table inheritance (STI)
is sparse columns. Essentially, as sub-types of the original table
diverge further from their parent more columns are left empty in a given
table. Postgres' `jsonb` type provides part of the solution in that
the values in an `jsonb` column does not impose a structure - different
rows can have different values.
We set up our table with an `jsonb` field:
```ruby
# db/migration/_create_players.rb
class CreateVehicles < ActiveRecord::Migration
def change
create_table :vehicles do |t|
t.string :make
t.string :model
t.integer :model_year
t.string :type
t.jsonb :data
end
end
end
```
And for our models:
```ruby
# app/models/vehicle.rb
class Vehicle < ActiveRecord::Base
end
# app/models/vehicles/automobile.rb
class Automobile < Vehicle
jsonb_accessor :data,
axle_count: :integer,
weight: :float
end
# app/models/vehicles/airplane.rb
class Airplane < Vehicle
jsonb_accessor :data,
engine_type: :string,
safety_rating: :integer
end
```
From here any attributes specific to any sub-class can be stored in the
`jsonb` column avoiding sparse data. Indices can also be created on
individual fields in an `jsonb` column.
This approach was originally conceived by Joe Hirn in [this blog
post](https://madeintandem.com/blog/2013-3-single-table-inheritance-hstore-lovely-combination/).
## Validations
Because this gem promotes attributes nested into the JSON column to first level attributes, most validations should just work. Please leave us feedback if they're not working as expected.
## Dependencies
- Ruby > 3. Lower versions are not tested.
- ActiveRecord >= 6.1
- Postgres >= 9.4 (in order to use the [jsonb column type](http://www.postgresql.org/docs/9.4/static/datatype-json.html)).
## Upgrading
See the [upgrade guide](UPGRADE_GUIDE.md).
## Development
### On your local machine
After checking out the repo, run `bin/setup` to install dependencies (make sure postgres is running first).
Run `bin/console` for an interactive prompt that will allow you to experiment.
`rake` will run Rubocop and the specs.
### With Docker
```
# setup
docker-compose build
docker-compose run ruby rake db:migrate
# run test suite
docker-compose run ruby rake spec
```
## Contributing
1. [Fork it](https://github.com/madeintandem/jsonb_accessor/fork)
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Add tests and changes (run the tests with `rake`)
4. Commit your changes (`git commit -am 'Add some feature'`)
5. Push to the branch (`git push origin my-new-feature`)
6. Create a new Pull Request
## Alternatives
- https://github.com/DmitryTsepelev/store_model 💪
- https://github.com/palkan/store_attribute ❤️
- https://github.com/jrochkind/attr_json 🤩
jsonb_accessor-1.4/bin/ 0000755 0000041 0000041 00000000000 14531041247 015154 5 ustar www-data www-data jsonb_accessor-1.4/bin/console 0000755 0000041 0000041 00000000673 14531041247 016552 0 ustar www-data www-data #!/usr/bin/env ruby
# frozen_string_literal: true
require "bundler/setup"
require "jsonb_accessor"
require "rspec"
require File.expand_path("../spec/spec_helper.rb", __dir__)
dbconfig = YAML.safe_load(ERB.new(File.read(File.join("db", "config.yml"))).result, aliases: true)
ActiveRecord::Base.establish_connection(dbconfig["test"])
# rubocop:disable Lint/UselessAssignment
x = Product.new
# rubocop:enable Lint/UselessAssignment
Pry.start
jsonb_accessor-1.4/bin/setup 0000755 0000041 0000041 00000000122 14531041247 016235 0 ustar www-data www-data #!/bin/bash
set -euo pipefail
IFS=$'\n\t'
bundle
rake db:create
rake db:migrate
jsonb_accessor-1.4/gemfiles/ 0000755 0000041 0000041 00000000000 14531041247 016177 5 ustar www-data www-data jsonb_accessor-1.4/gemfiles/activerecord_6.1.gemfile 0000644 0000041 0000041 00000000171 14531041247 022566 0 ustar www-data www-data # This file was generated by Appraisal
source "https://rubygems.org"
gem "activerecord", "~> 6.1"
gemspec path: "../"
jsonb_accessor-1.4/gemfiles/activerecord_7.0.gemfile 0000644 0000041 0000041 00000000173 14531041247 022570 0 ustar www-data www-data # This file was generated by Appraisal
source "https://rubygems.org"
gem "activerecord", "~> 7.0.8"
gemspec path: "../"
jsonb_accessor-1.4/gemfiles/activerecord_7.1.gemfile 0000644 0000041 0000041 00000000171 14531041247 022567 0 ustar www-data www-data # This file was generated by Appraisal
source "https://rubygems.org"
gem "activerecord", "~> 7.1"
gemspec path: "../"
jsonb_accessor-1.4/CHANGELOG.md 0000644 0000041 0000041 00000003636 14531041247 016225 0 ustar www-data www-data # Changelog
## [Unreleased]
## [1.4] - 2023-10-15
### Breaking change
- `jsonb_accessor` dropped support for Ruby 2 and Rails versions lower than 6.1. Support for ActiveRecord::Enum was also
dropped because ActiveRecord 7.1 now requires each enum field to be backed by a database column. Enums will still work
when using AR versions lower than 7.1. This is a limitation of Rails, not of this gem.
### Fixed
- Bug fix: An array of datetimes previously caused an error. https://github.com/madeintandem/jsonb_accessor/pull/169. Thanks @bekicot.
- Rails 7.1 is officially supported and tested against.
## [1.3.10] - 2023-05-30
### No changes
A new release was necessary to fix the corrupted 1.3.9 Java release on RubyGems.
## [1.3.9] - 2023-05-30
### No changes
A new release was necessary to fix the corrupted 1.3.8 Java release on RubyGems.
## [1.3.8] - 2023-05-29
### Fixes
- Support for ActiveRecord::Enum. [#163](https://github.com/madeintandem/jsonb_accessor/pull/163)
## [1.3.7] - 2022-12-29
- jruby support. jsonb_accessor now depends on `activerecord-jdbcpostgresql-adapter` instead of `pg` when the RUBY_PLATFORM is java. [#157](https://github.com/madeintandem/jsonb_accessor/pull/157)
## [1.3.6] - 2022-09-23
### Fixed
- Bug fix: Datetime values were not properly deserialized [#155](https://github.com/madeintandem/jsonb_accessor/pull/155)
## [1.3.5] - 2022-07-23
### Fixed
- Bug fix: Attributes defined outside of jsonb_accessor are not written [#149](https://github.com/madeintandem/jsonb_accessor/pull/149)
## [1.3.4] - 2022-02-02
### Fixed
- Bug fix: Raised ActiveModel::MissingAttributeError when model was initialized without the jsonb_accessor field [#145](https://github.com/madeintandem/jsonb_accessor/issues/145)
## [1.3.3] - 2022-01-29
### Fixed
- Bug fix: DateTime objects are now correctly written without timezone
information [#137](https://github.com/madeintandem/jsonb_accessor/pull/137).
Thanks @caiohsramos
jsonb_accessor-1.4/.rubocop.yml 0000644 0000041 0000041 00000002466 14531041247 016666 0 ustar www-data www-data AllCops:
NewCops: enable
TargetRubyVersion: 2.7.2
SuggestExtensions: false
Exclude:
- "db/**/*"
- "gemfiles/**/*"
- "vendor/**/*"
Layout/SpaceBeforeFirstArg:
Enabled: false
Layout/LineLength:
Enabled: false
Layout/SpaceAroundEqualsInParameterDefault:
Enabled: false
Lint/UnusedBlockArgument:
Enabled: false
Lint/UnusedMethodArgument:
Enabled: false
Metrics/AbcSize:
Enabled: false
Metrics/ClassLength:
Enabled: false
Metrics/CyclomaticComplexity:
Enabled: false
Metrics/MethodLength:
Enabled: false
Metrics/ModuleLength:
Enabled: false
Metrics/PerceivedComplexity:
Enabled: false
Metrics/BlockLength:
Enabled: false
Style/ClassAndModuleChildren:
Enabled: false
Style/ClassVars:
Enabled: false
Style/Documentation:
Enabled: false
Style/DoubleNegation:
Enabled: false
Naming/FileName:
Enabled: false
Style/GuardClause:
Enabled: false
Style/NilComparison:
Enabled: false
Style/RescueModifier:
Enabled: false
Style/SignalException:
Enabled: false
Style/SingleLineMethods:
Enabled: false
Style/StringLiterals:
EnforcedStyle: double_quotes
Naming/BinaryOperatorParameterName:
Enabled: false
Naming/VariableNumber:
Enabled: false
Gemspec/RequiredRubyVersion:
Enabled: false
Gemspec/RequireMFA:
Enabled: false
Gemspec/DevelopmentDependencies:
EnforcedStyle: gemspec
jsonb_accessor-1.4/Appraisals 0000644 0000041 0000041 00000000351 14531041247 016425 0 ustar www-data www-data # frozen_string_literal: true
appraise "activerecord-6.1" do
gem "activerecord", "~> 6.1"
end
appraise "activerecord-7.0" do
gem "activerecord", "~> 7.0.8"
end
appraise "activerecord-7.1" do
gem "activerecord", "~> 7.1"
end
jsonb_accessor-1.4/.gitignore 0000644 0000041 0000041 00000000200 14531041247 016364 0 ustar www-data www-data /.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
gemfiles/.bundle
gemfiles/*.gemfile.lock
jsonb_accessor-1.4/CODE_OF_CONDUCT.md 0000644 0000041 0000041 00000002615 14531041247 017207 0 ustar www-data www-data # Contributor Code of Conduct
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
jsonb_accessor-1.4/db/ 0000755 0000041 0000041 00000000000 14531041247 014771 5 ustar www-data www-data jsonb_accessor-1.4/db/config.yml 0000644 0000041 0000041 00000000320 14531041247 016754 0 ustar www-data www-data default: &default
adapter: postgresql
database: jsonb_accessor
host: <%= ENV.fetch("DATABASE_HOST") { "127.0.0.1" } %>
username: <%= ENV.fetch("DATABASE_USER") { "postgres" } %>
test:
<<: *default
jsonb_accessor-1.4/db/schema.rb 0000644 0000041 0000041 00000002524 14531041247 016561 0 ustar www-data www-data # This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2015_04_07_031737) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "product_categories", id: :serial, force: :cascade do |t|
t.jsonb "options"
end
create_table "products", id: :serial, force: :cascade do |t|
t.jsonb "options"
t.jsonb "data"
t.string "string_type"
t.integer "integer_type"
t.integer "product_category_id"
t.boolean "boolean_type"
t.float "float_type"
t.time "time_type"
t.date "date_type"
t.datetime "datetime_type", precision: nil
t.decimal "decimal_type"
end
end
jsonb_accessor-1.4/db/migrate/ 0000755 0000041 0000041 00000000000 14531041247 016421 5 ustar www-data www-data jsonb_accessor-1.4/db/migrate/20150407031737_set_up_testing_db.rb 0000644 0000041 0000041 00000001021 14531041247 024110 0 ustar www-data www-data # frozen_string_literal: true
class SetUpTestingDb < ActiveRecord::Migration[5.0]
def change
create_table :products do |t|
t.jsonb :options
t.jsonb :data
t.string :string_type
t.integer :integer_type
t.integer :product_category_id
t.boolean :boolean_type
t.float :float_type
t.time :time_type
t.date :date_type
t.datetime :datetime_type
t.decimal :decimal_type
end
create_table :product_categories do |t|
t.jsonb :options
end
end
end
jsonb_accessor-1.4/docker-compose.yml 0000644 0000041 0000041 00000001344 14531041247 020043 0 ustar www-data www-data version: '3'
services:
ruby:
environment:
- DATABASE_HOST=postgres
build:
args:
- RUBY_VERSION=${RUBY_VERSION:-3.2.2}
- RUBY_PLATFORM=${RUBY_PLATFORM:-ruby}
context: .
volumes:
- '.:/usr/src/app'
depends_on:
- postgres
postgres:
image: postgres
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
- POSTGRES_DB=jsonb_accessor
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- pg_data:/var/lib/postgresql/data/pgdata
ports:
- 5432:5432
volumes:
pg_data:
jsonb_accessor-1.4/Rakefile 0000644 0000041 0000041 00000001645 14531041247 016057 0 ustar www-data www-data # frozen_string_literal: true
require "rubygems"
require "bundler/setup"
require "bundler/gem_tasks"
require "rspec/core/rake_task"
require "rubocop/rake_task"
require "active_record"
require "erb"
RSpec::Core::RakeTask.new
RuboCop::RakeTask.new
# rubocop:disable Style/MixinUsage
include ActiveRecord::Tasks
# rubocop:enable Style/MixinUsage
root = File.expand_path __dir__
db_dir = File.join(root, "db")
DatabaseTasks.root = root
DatabaseTasks.db_dir = db_dir
DatabaseTasks.database_configuration = YAML.safe_load(ERB.new(File.read(File.join(db_dir, "config.yml"))).result, aliases: true)
DatabaseTasks.migrations_paths = [File.join(db_dir, "migrate")]
DatabaseTasks.env = "test"
task :environment do
ActiveRecord::Base.configurations = DatabaseTasks.database_configuration
ActiveRecord::Base.establish_connection DatabaseTasks.env.to_sym
end
load "active_record/railties/databases.rake"
task(default: %i[rubocop spec])
jsonb_accessor-1.4/lib/ 0000755 0000041 0000041 00000000000 14531041247 015152 5 ustar www-data www-data jsonb_accessor-1.4/lib/jsonb_accessor/ 0000755 0000041 0000041 00000000000 14531041247 020147 5 ustar www-data www-data jsonb_accessor-1.4/lib/jsonb_accessor/attribute_query_methods.rb 0000644 0000041 0000041 00000003125 14531041247 025450 0 ustar www-data www-data # frozen_string_literal: true
module JsonbAccessor
class AttributeQueryMethods
def initialize(klass)
@klass = klass
end
def define(store_key_mapping_method_name, jsonb_attribute)
return if klass.superclass.respond_to? store_key_mapping_method_name
# _where scope
klass.define_singleton_method "#{jsonb_attribute}_where" do |attributes|
store_key_attributes = JsonbAccessor::Helpers.convert_keys_to_store_keys(attributes, all.model.public_send(store_key_mapping_method_name))
jsonb_where(jsonb_attribute, store_key_attributes)
end
# _where_not scope
klass.define_singleton_method "#{jsonb_attribute}_where_not" do |attributes|
store_key_attributes = JsonbAccessor::Helpers.convert_keys_to_store_keys(attributes, all.model.public_send(store_key_mapping_method_name))
jsonb_where_not(jsonb_attribute, store_key_attributes)
end
# _order scope
klass.define_singleton_method "#{jsonb_attribute}_order" do |*args|
ordering_options = args.extract_options!
order_by_defaults = args.each_with_object({}) { |attribute, config| config[attribute] = :asc }
store_key_mapping = all.model.public_send(store_key_mapping_method_name)
order_by_defaults.merge(ordering_options).reduce(all) do |query, (name, direction)|
key = store_key_mapping[name.to_s]
order_query = jsonb_order(jsonb_attribute, key, direction)
query.merge(order_query)
end
end
end
private
attr_reader :klass
end
end
jsonb_accessor-1.4/lib/jsonb_accessor/query_helper.rb 0000644 0000041 0000041 00000007357 14531041247 023214 0 ustar www-data www-data # frozen_string_literal: true
module JsonbAccessor
module QueryHelper
# Errors
InvalidColumnName = Class.new(StandardError)
InvalidFieldName = Class.new(StandardError)
InvalidDirection = Class.new(StandardError)
NotSupported = Class.new(StandardError)
# Constants
GREATER_THAN = ">"
GREATER_THAN_OR_EQUAL_TO = ">="
LESS_THAN = "<"
LESS_THAN_OR_EQUAL_TO = "<="
NUMBER_OPERATORS_MAP = {
GREATER_THAN => GREATER_THAN,
"greater_than" => GREATER_THAN,
"gt" => GREATER_THAN,
GREATER_THAN_OR_EQUAL_TO => GREATER_THAN_OR_EQUAL_TO,
"greater_than_or_equal_to" => GREATER_THAN_OR_EQUAL_TO,
"gte" => GREATER_THAN_OR_EQUAL_TO,
LESS_THAN => LESS_THAN,
"less_than" => LESS_THAN,
"lt" => LESS_THAN,
LESS_THAN_OR_EQUAL_TO => LESS_THAN_OR_EQUAL_TO,
"less_than_or_equal_to" => LESS_THAN_OR_EQUAL_TO,
"lte" => LESS_THAN_OR_EQUAL_TO
}.freeze
NUMBER_OPERATORS = NUMBER_OPERATORS_MAP.keys.freeze
TIME_OPERATORS_MAP = {
"after" => GREATER_THAN,
"before" => LESS_THAN
}.freeze
TIME_OPERATORS = TIME_OPERATORS_MAP.keys.freeze
ORDER_DIRECTIONS = [:asc, :desc, "asc", "desc"].freeze
class << self
def validate_column_name!(query, column_name)
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 }
end
def validate_field_name!(query, column_name, field_name)
store_keys = query.model.public_send("jsonb_store_key_mapping_for_#{column_name}").values
if store_keys.exclude?(field_name.to_s)
valid_field_names = store_keys.map { |key| "`#{key}`" }.join(", ")
raise InvalidFieldName, "`#{field_name}` is not a valid field name, valid field names include: #{valid_field_names}"
end
end
def validate_direction!(option)
raise InvalidDirection, "`#{option}` is not a valid direction for ordering, only `asc` and `desc` are accepted" if ORDER_DIRECTIONS.exclude?(option)
end
def number_query_arguments?(arg)
arg.is_a?(Hash) && arg.keys.map(&:to_s).all? { |key| NUMBER_OPERATORS.include?(key) }
end
def time_query_arguments?(arg)
arg.is_a?(Hash) && arg.keys.map(&:to_s).all? { |key| TIME_OPERATORS.include?(key) }
end
def convert_number_ranges(attributes)
attributes.each_with_object({}) do |(name, value), new_attributes|
is_range = value.is_a?(Range)
new_attributes[name] = if is_range && value.first.is_a?(Numeric) && value.exclude_end?
{ greater_than_or_equal_to: value.first, less_than: value.end }
elsif is_range && value.first.is_a?(Numeric)
{ greater_than_or_equal_to: value.first, less_than_or_equal_to: value.end }
else
value
end
end
end
def convert_time_ranges(attributes)
attributes.each_with_object({}) do |(name, value), new_attributes|
is_range = value.is_a?(Range)
if is_range && (value.first.is_a?(Time) || value.first.is_a?(Date))
start_time = value.first
end_time = value.end
new_attributes[name] = { before: end_time, after: start_time }
else
new_attributes[name] = value
end
end
end
def convert_ranges(attributes)
%i[convert_number_ranges convert_time_ranges].reduce(attributes) do |new_attributes, converter_method|
public_send(converter_method, new_attributes)
end
end
end
end
end
jsonb_accessor-1.4/lib/jsonb_accessor/version.rb 0000644 0000041 0000041 00000000357 14531041247 022166 0 ustar www-data www-data # frozen_string_literal: true
module JsonbAccessor
VERSION = "1.4"
def self.enum_support?
# From AR 7.1 on, enums require a database column.
Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new("7.1")
end
end
jsonb_accessor-1.4/lib/jsonb_accessor/macro.rb 0000644 0000041 0000041 00000013625 14531041247 021604 0 ustar www-data www-data # frozen_string_literal: true
module JsonbAccessor
module Macro
module ClassMethods
def jsonb_accessor(jsonb_attribute, field_types)
names_and_store_keys = field_types.each_with_object({}) do |(name, type), mapping|
_type, options = Array(type)
mapping[name.to_s] = (options.try(:delete, :store_key) || name).to_s
end
# Defines virtual attributes for each jsonb field.
field_types.each do |name, type|
next attribute name, type unless type.is_a?(Array)
next attribute name, *type unless type.last.is_a?(Hash)
*args, keyword_args = type
attribute name, *args, **keyword_args
end
store_key_mapping_method_name = "jsonb_store_key_mapping_for_#{jsonb_attribute}"
# Defines methods on the model class
class_methods = Module.new do
# Allows us to get a mapping of field names to store keys scoped to the column
define_method(store_key_mapping_method_name) do
superclass_mapping = superclass.try(store_key_mapping_method_name) || {}
superclass_mapping.merge(names_and_store_keys)
end
end
# We extend with class methods here so we can use the results of methods it defines to define more useful methods later
extend class_methods
# Get field names to default values mapping
names_and_defaults = field_types.each_with_object({}) do |(name, type), mapping|
_type, options = Array(type)
field_default = options.try(:delete, :default)
mapping[name.to_s] = field_default unless field_default.nil?
end
# Get store keys to default values mapping
store_keys_and_defaults = JsonbAccessor::Helpers.convert_keys_to_store_keys(names_and_defaults, public_send(store_key_mapping_method_name))
# Define jsonb_defaults_mapping_for_
defaults_mapping_method_name = "jsonb_defaults_mapping_for_#{jsonb_attribute}"
class_methods.instance_eval do
define_method(defaults_mapping_method_name) do
superclass_mapping = superclass.try(defaults_mapping_method_name) || {}
superclass_mapping.merge(store_keys_and_defaults)
end
end
all_defaults_mapping = public_send(defaults_mapping_method_name)
# Fields may have procs as default value. This means `all_defaults_mapping` may contain procs as values. To make this work
# with the attributes API, we need to wrap `all_defaults_mapping` with a proc itself, making sure it returns a plain hash
# each time it is evaluated.
all_defaults_mapping_proc =
if all_defaults_mapping.present?
-> { all_defaults_mapping.transform_values { |value| value.respond_to?(:call) ? value.call : value }.to_h.compact }
end
attribute jsonb_attribute, :jsonb, default: all_defaults_mapping_proc if all_defaults_mapping_proc.present?
# Setters are in a module to allow users to override them and still be able to use `super`.
setters = Module.new do
# Overrides the setter created by `attribute` above to make sure the jsonb attribute is kept in sync.
names_and_store_keys.each do |name, store_key|
define_method("#{name}=") do |value|
super(value)
# If enum was defined, take the value from the enum and not what comes out directly from the getter
attribute_value = defined_enums[name].present? ? defined_enums[name][value] : public_send(name)
# Rails always saves time based on `default_timezone`. Since #as_json considers timezone, manual conversion is needed
if attribute_value.acts_like?(:time)
attribute_value = (JsonbAccessor::Helpers.active_record_default_timezone == :utc ? attribute_value.utc : attribute_value.in_time_zone).strftime("%F %R:%S.%L")
end
new_values = (public_send(jsonb_attribute) || {}).merge(store_key => attribute_value)
write_attribute(jsonb_attribute, new_values)
end
end
# Overrides the jsonb attribute setter to make sure the jsonb fields are kept in sync.
define_method("#{jsonb_attribute}=") do |value|
value ||= {}
names_to_store_keys = self.class.public_send(store_key_mapping_method_name)
# this is the raw hash we want to save in the jsonb_attribute
value_with_store_keys = JsonbAccessor::Helpers.convert_keys_to_store_keys(value, names_to_store_keys)
write_attribute(jsonb_attribute, value_with_store_keys)
# this maps attributes to values
value_with_named_keys = JsonbAccessor::Helpers.convert_store_keys_to_keys(value, names_to_store_keys)
empty_named_attributes = names_to_store_keys.transform_values { nil }
empty_named_attributes.merge(value_with_named_keys).each do |name, attribute_value|
# Only proceed if this attribute has been defined using `jsonb_accessor`.
next unless names_to_store_keys.key?(name)
write_attribute(name, attribute_value)
end
end
end
include setters
# Makes sure new objects have the appropriate values in their jsonb fields.
after_initialize do
next unless has_attribute? jsonb_attribute
jsonb_values = public_send(jsonb_attribute) || {}
jsonb_values.each do |store_key, value|
name = names_and_store_keys.key(store_key)
next unless name
write_attribute(
name,
JsonbAccessor::Helpers.deserialize_value(value, self.class.type_for_attribute(name).type)
)
clear_attribute_change(name) if persisted?
end
end
JsonbAccessor::AttributeQueryMethods.new(self).define(store_key_mapping_method_name, jsonb_attribute)
end
end
end
end
jsonb_accessor-1.4/lib/jsonb_accessor/helpers.rb 0000644 0000041 0000041 00000002450 14531041247 022137 0 ustar www-data www-data # frozen_string_literal: true
module JsonbAccessor
module Helpers
module_function
def active_record_default_timezone
ActiveRecord.try(:default_timezone) || ActiveRecord::Base.default_timezone
end
# Replaces all keys in `attributes` that have a defined store_key with the store_key
def convert_keys_to_store_keys(attributes, store_key_mapping)
attributes.stringify_keys.transform_keys do |key|
store_key_mapping[key] || key
end
end
# Replaces all keys in `attributes` that have a defined store_key with the named key (alias)
def convert_store_keys_to_keys(attributes, store_key_mapping)
convert_keys_to_store_keys(attributes, store_key_mapping.invert)
end
def deserialize_value(value, attribute_type)
return value if value.blank?
if attribute_type == :datetime
value = if value.is_a?(Array)
value.map { |v| parse_date(v) }
else
parse_date(value)
end
end
value
end
# Parse datetime based on the configured default_timezone
def parse_date(datetime)
if active_record_default_timezone == :utc
Time.find_zone("UTC").parse(datetime).in_time_zone
else
Time.zone.parse(datetime)
end
end
end
end
jsonb_accessor-1.4/lib/jsonb_accessor/query_builder.rb 0000644 0000041 0000041 00000010147 14531041247 023352 0 ustar www-data www-data # frozen_string_literal: true
module JsonbAccessor
module QueryBuilder
extend ActiveSupport::Concern
included do
scope(:jsonb_contains, lambda do |column_name, attributes|
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
where("#{table_name}.#{column_name} @> (?)::jsonb", attributes.to_json)
end)
scope(:jsonb_excludes, lambda do |column_name, attributes|
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
where.not("#{table_name}.#{column_name} @> (?)::jsonb", attributes.to_json)
end)
scope(:jsonb_number_where, lambda do |column_name, field_name, given_operator, value|
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
operator = JsonbAccessor::QueryHelper::NUMBER_OPERATORS_MAP.fetch(given_operator.to_s)
where("(#{table_name}.#{column_name} ->> ?)::float #{operator} ?", field_name, value)
end)
scope(:jsonb_number_where_not, lambda do |column_name, field_name, given_operator, value|
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
operator = JsonbAccessor::QueryHelper::NUMBER_OPERATORS_MAP.fetch(given_operator.to_s)
where.not("(#{table_name}.#{column_name} ->> ?)::float #{operator} ?", field_name, value)
end)
scope(:jsonb_time_where, lambda do |column_name, field_name, given_operator, value|
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
operator = JsonbAccessor::QueryHelper::TIME_OPERATORS_MAP.fetch(given_operator.to_s)
where("(#{table_name}.#{column_name} ->> ?)::timestamp #{operator} ?", field_name, value)
end)
scope(:jsonb_time_where_not, lambda do |column_name, field_name, given_operator, value|
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
operator = JsonbAccessor::QueryHelper::TIME_OPERATORS_MAP.fetch(given_operator.to_s)
where.not("(#{table_name}.#{column_name} ->> ?)::timestamp #{operator} ?", field_name, value)
end)
scope(:jsonb_where, lambda do |column_name, attributes|
query = all
contains_attributes = {}
JsonbAccessor::QueryHelper.convert_ranges(attributes).each do |name, value|
if JsonbAccessor::QueryHelper.number_query_arguments?(value)
value.each { |operator, query_value| query = query.jsonb_number_where(column_name, name, operator, query_value) }
elsif JsonbAccessor::QueryHelper.time_query_arguments?(value)
value.each { |operator, query_value| query = query.jsonb_time_where(column_name, name, operator, query_value) }
else
contains_attributes[name] = value
end
end
query.jsonb_contains(column_name, contains_attributes)
end)
scope(:jsonb_where_not, lambda do |column_name, attributes|
query = all
excludes_attributes = {}
attributes.each do |name, value|
raise JsonbAccessor::QueryHelper::NotSupported, "`jsonb_where_not` scope does not accept ranges as arguments. Given `#{value}` for `#{name}` field" if value.is_a?(Range)
if JsonbAccessor::QueryHelper.number_query_arguments?(value)
value.each { |operator, query_value| query = query.jsonb_number_where_not(column_name, name, operator, query_value) }
elsif JsonbAccessor::QueryHelper.time_query_arguments?(value)
value.each { |operator, query_value| query = query.jsonb_time_where_not(column_name, name, operator, query_value) }
else
excludes_attributes[name] = value
end
end
excludes_attributes.empty? ? query : query.jsonb_excludes(column_name, excludes_attributes)
end)
scope(:jsonb_order, lambda do |column_name, field_name, direction|
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
JsonbAccessor::QueryHelper.validate_field_name!(all, column_name, field_name)
JsonbAccessor::QueryHelper.validate_direction!(direction)
order(Arel.sql("(#{table_name}.#{column_name} -> '#{field_name}') #{direction}"))
end)
end
end
end
jsonb_accessor-1.4/lib/jsonb_accessor.rb 0000644 0000041 0000041 00000001063 14531041247 020474 0 ustar www-data www-data # frozen_string_literal: true
require "active_record"
require "active_record/connection_adapters/postgresql_adapter"
require "jsonb_accessor/version"
require "jsonb_accessor/helpers"
require "jsonb_accessor/macro"
require "jsonb_accessor/query_helper"
require "jsonb_accessor/query_builder"
require "jsonb_accessor/attribute_query_methods"
module JsonbAccessor
extend ActiveSupport::Concern
include Macro
end
ActiveSupport.on_load(:active_record) do
ActiveRecord::Base.include JsonbAccessor
ActiveRecord::Base.include JsonbAccessor::QueryBuilder
end
jsonb_accessor-1.4/jsonb_accessor.gemspec 0000644 0000041 0000041 00000003635 14531041247 020755 0 ustar www-data www-data # frozen_string_literal: true
lib = File.expand_path("lib", __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "jsonb_accessor/version"
is_java = RUBY_PLATFORM == "java"
Gem::Specification.new do |spec|
spec.name = "jsonb_accessor"
spec.version = JsonbAccessor::VERSION
spec.authors = ["Michael Crismali", "Joe Hirn", "Jason Haruska"]
spec.email = ["michael@crismali.com", "joe@devmynd.com", "jason@haruska.com"]
spec.platform = "java" if is_java
spec.summary = "Adds typed jsonb backed fields to your ActiveRecord models."
spec.description = "Adds typed jsonb backed fields to your ActiveRecord models."
spec.homepage = "https://github.com/devmynd/jsonb_accessor"
spec.license = "MIT"
spec.required_ruby_version = ">= 3"
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) || f.match(/png\z/) }
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_dependency "activerecord", ">= 6.1"
spec.add_dependency "activesupport", ">= 6.1"
if is_java
spec.add_dependency "activerecord-jdbcpostgresql-adapter", ">= 50.0"
else
spec.add_dependency "pg", ">= 0.18.1"
end
spec.add_development_dependency "appraisal", "~> 2.5"
spec.add_development_dependency "awesome_print"
spec.add_development_dependency "database_cleaner-active_record", "~> 2.1"
spec.add_development_dependency "pry"
spec.add_development_dependency "pry-doc"
spec.add_development_dependency "pry-nav"
spec.add_development_dependency "psych", "~> 3"
spec.add_development_dependency "rake", ">= 12.3.3"
spec.add_development_dependency "rspec", "~> 3.6.0"
spec.add_development_dependency "rubocop", "~> 1"
end
jsonb_accessor-1.4/Gemfile 0000644 0000041 0000041 00000000202 14531041247 015671 0 ustar www-data www-data # frozen_string_literal: true
source "https://rubygems.org"
# Specify your gem's dependencies in jsonb_accessor.gemspec
gemspec
jsonb_accessor-1.4/.ruby-version 0000644 0000041 0000041 00000000006 14531041247 017045 0 ustar www-data www-data 3.2.2
jsonb_accessor-1.4/.github/ 0000755 0000041 0000041 00000000000 14531041247 015744 5 ustar www-data www-data jsonb_accessor-1.4/.github/workflows/ 0000755 0000041 0000041 00000000000 14531041247 020001 5 ustar www-data www-data jsonb_accessor-1.4/.github/workflows/ci.yml 0000644 0000041 0000041 00000003547 14531041247 021130 0 ustar www-data www-data name: CI
on:
push:
branches: [master]
pull_request:
branches: ['**']
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Rubocop
run: bundle exec rubocop
tests:
needs: lint
services:
db:
image: postgres
env:
POSTGRES_HOST_AUTH_METHOD: trust
POSTGRES_DB: jsonb_accessor
ports: ['5432:5432']
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- gemfile: activerecord_6.1
ruby: '3.0'
- gemfile: activerecord_6.1
ruby: '3.1'
- gemfile: activerecord_6.1
ruby: '3.2'
- gemfile: activerecord_7.0
ruby: '3.0'
- gemfile: activerecord_7.0
ruby: '3.1'
- gemfile: activerecord_7.0
ruby: '3.2'
- gemfile: activerecord_7.1
ruby: '3.0'
- gemfile: activerecord_7.1
ruby: '3.1'
- gemfile: activerecord_7.1
ruby: '3.2'
- gemfile: activerecord_7.0
ruby: 'jruby-9.4'
name: ${{ matrix.gemfile }}, ruby ${{ matrix.ruby }}
env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Bundle install
run: |
bundle install
- name: Setup DB
run: |
bundle exec rake db:schema:load
- name: Run tests
run: |
bundle exec rake spec
jsonb_accessor-1.4/LICENSE.txt 0000644 0000041 0000041 00000002073 14531041247 016231 0 ustar www-data www-data The MIT License (MIT)
Copyright (c) 2015 Michael Crismali
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
jsonb_accessor-1.4/Dockerfile 0000644 0000041 0000041 00000000455 14531041247 016402 0 ustar www-data www-data ARG RUBY_VERSION
ARG RUBY_PLATFORM
FROM ${RUBY_PLATFORM}:${RUBY_VERSION}
RUN apt-get update && apt-get install -y --no-install-recommends git
WORKDIR /usr/src/app
COPY lib/jsonb_accessor/version.rb ./lib/jsonb_accessor/version.rb
COPY jsonb_accessor.gemspec Gemfile ./
RUN bundle install
COPY . ./