jsonb_accessor 1.0.0.beta.5 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/.travis.yml +7 -4
- data/Appraisals +1 -3
- data/README.md +35 -10
- data/gemfiles/activerecord_5.0.0.gemfile +0 -1
- data/gemfiles/activerecord_5.1.0.gemfile +1 -2
- data/jsonb_accessor.gemspec +7 -7
- data/lib/jsonb_accessor.rb +1 -0
- data/lib/jsonb_accessor/macro.rb +31 -11
- data/lib/jsonb_accessor/query_builder.rb +23 -92
- data/lib/jsonb_accessor/query_helper.rb +114 -0
- data/lib/jsonb_accessor/version.rb +1 -1
- metadata +38 -39
- data/gemfiles/activerecord_5.0.0.gemfile.lock +0 -141
- data/gemfiles/activerecord_5.1.0.gemfile.lock +0 -141
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80ed7aa0b3f529122a97b2a00b4f81011ef18014
|
4
|
+
data.tar.gz: 407d572cea056870ce66d7b92c89d1b3e15bdb2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be4ffe5fc2318edc84b98ffee5296d30d2a9d03817540c4622f04875d0a41c19022c19c0c998357f6730cad37103ce79c43b46c5aa08a46dce8078b77f03752d
|
7
|
+
data.tar.gz: c02e7189b7354d5d112aa9414e9cb4e5329d57b97b75b4d07a7e64da1abab04c63a0419509335fd557728eb48df1183d2a2d00c9c84ed7216ac4461205ec1c4d
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.4.1
|
data/.travis.yml
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
|
-
- 2.
|
4
|
-
- 2.
|
3
|
+
- 2.3.8
|
4
|
+
- 2.4.5
|
5
|
+
- 2.5.3
|
6
|
+
- 2.6.1
|
5
7
|
addons:
|
6
|
-
postgresql:
|
8
|
+
postgresql: "9.4"
|
7
9
|
before_install:
|
8
10
|
- gem update --system
|
9
11
|
- gem --version
|
10
|
-
- gem install bundler
|
12
|
+
- gem install bundler:2.1.4
|
11
13
|
before_script:
|
12
14
|
- bundle exec rake db:create
|
13
15
|
- bundle exec rake db:migrate
|
16
|
+
install: bundle _2.1.4_ install --jobs=3 --retry=3 --path=${BUNDLE_PATH:-vendor/bundle}
|
14
17
|
cache: bundler
|
15
18
|
gemfile:
|
16
19
|
- gemfiles/activerecord_5.0.0.gemfile
|
data/Appraisals
CHANGED
data/README.md
CHANGED
@@ -1,17 +1,13 @@
|
|
1
1
|
# JSONb Accessor
|
2
2
|
|
3
|
-
Created by [<img src="https://raw.githubusercontent.com/
|
3
|
+
Created by [<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) [![Build Status](https://travis-ci.org/
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/jsonb_accessor.svg)](http://badge.fury.io/rb/jsonb_accessor) [![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" />
|
6
6
|
|
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/
|
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
|
|
9
9
|
It also adds generic scopes for querying `jsonb` columns.
|
10
10
|
|
11
|
-
## 1.0 Beta
|
12
|
-
|
13
|
-
This README reflects the most recent 1.0 beta. Method names and interfaces may still change.
|
14
|
-
|
15
11
|
## Table of Contents
|
16
12
|
|
17
13
|
* [Installation](#installation)
|
@@ -29,7 +25,7 @@ This README reflects the most recent 1.0 beta. Method names and interfaces may s
|
|
29
25
|
Add this line to your application's `Gemfile`:
|
30
26
|
|
31
27
|
```ruby
|
32
|
-
gem "jsonb_accessor", "1
|
28
|
+
gem "jsonb_accessor", "~> 1"
|
33
29
|
```
|
34
30
|
|
35
31
|
And then execute:
|
@@ -141,6 +137,14 @@ For time related fields you can query using `before` and `after`.
|
|
141
137
|
Product.all.data_where(reviewed_at: { before: Time.current.beginning_of_week, after: 4.weeks.ago })
|
142
138
|
```
|
143
139
|
|
140
|
+
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).
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
Product.all.data_where(price: 10..20)
|
144
|
+
Product.all.data_where(price: 10...20)
|
145
|
+
Product.all.data_where(reviewed_at: Time.current..3.days.from_now)
|
146
|
+
```
|
147
|
+
|
144
148
|
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.
|
145
149
|
|
146
150
|
### `jsonb_where`
|
@@ -164,6 +168,27 @@ Just the opposite of `jsonb_where`. Note that this will automatically exclude al
|
|
164
168
|
Product.all.jsonb_where_not(:data, reviewed_at: { before: Time.current }, p: { greater_than: 5 })
|
165
169
|
```
|
166
170
|
|
171
|
+
### `<jsonb_attribute>_order`
|
172
|
+
|
173
|
+
Orders your query according to values in the Jsonb Accessor fields similar to ActiveRecord's `order`.
|
174
|
+
|
175
|
+
```ruby
|
176
|
+
Product.all.data_order(:price)
|
177
|
+
Product.all.data_order(:price, :reviewed_at)
|
178
|
+
Product.all.data_order(:price, reviewed_at: :desc)
|
179
|
+
```
|
180
|
+
|
181
|
+
It will convert your given keys into store keys if necessary.
|
182
|
+
|
183
|
+
### `jsonb_order`
|
184
|
+
|
185
|
+
Allows you to order by a Jsonb Accessor field.
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
Product.all.jsonb_order(:data, :price, :asc)
|
189
|
+
Product.all.jsonb_order(:data, :price, :desc)
|
190
|
+
```
|
191
|
+
|
167
192
|
### `jsonb_contains`
|
168
193
|
|
169
194
|
Returns all records that contain the given JSON paths.
|
@@ -284,7 +309,7 @@ From here any attributes specific to any sub-class can be stored in the
|
|
284
309
|
individual fields in an `jsonb` column.
|
285
310
|
|
286
311
|
This approach was originally conceived by Joe Hirn in [this blog
|
287
|
-
post](
|
312
|
+
post](https://madeintandem.com/blog/2013-3-single-table-inheritance-hstore-lovely-combination/).
|
288
313
|
|
289
314
|
## Validations
|
290
315
|
|
@@ -309,7 +334,7 @@ Run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
309
334
|
|
310
335
|
## Contributing
|
311
336
|
|
312
|
-
1. [Fork it](https://github.com/
|
337
|
+
1. [Fork it](https://github.com/madeintandem/jsonb_accessor/fork)
|
313
338
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
314
339
|
3. Add tests and changes (run the tests with `rake`)
|
315
340
|
4. Commit your changes (`git commit -am 'Add some feature'`)
|
data/jsonb_accessor.gemspec
CHANGED
@@ -23,18 +23,18 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
25
|
spec.add_dependency "activerecord", ">= 5.0"
|
26
|
+
spec.add_dependency "activesupport", ">= 5.0"
|
26
27
|
spec.add_dependency "pg", ">= 0.18.1"
|
27
28
|
|
28
|
-
spec.add_development_dependency "appraisal"
|
29
|
-
spec.add_development_dependency "bundler", "~> 1.
|
30
|
-
spec.add_development_dependency "database_cleaner", "~> 1.
|
29
|
+
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"
|
31
32
|
spec.add_development_dependency "awesome_print"
|
32
33
|
spec.add_development_dependency "pry"
|
33
34
|
spec.add_development_dependency "pry-doc"
|
34
35
|
spec.add_development_dependency "pry-nav"
|
35
|
-
spec.add_development_dependency "rake", "
|
36
|
-
spec.add_development_dependency "rspec", "~> 3.
|
36
|
+
spec.add_development_dependency "rake", ">= 12.3.3"
|
37
|
+
spec.add_development_dependency "rspec", "~> 3.6.0"
|
37
38
|
spec.add_development_dependency "rubocop", "~> 0.48.1"
|
38
|
-
spec.add_development_dependency "
|
39
|
-
spec.add_development_dependency "standalone_migrations"
|
39
|
+
spec.add_development_dependency "standalone_migrations", "~> 5.2.0"
|
40
40
|
end
|
data/lib/jsonb_accessor.rb
CHANGED
data/lib/jsonb_accessor/macro.rb
CHANGED
@@ -11,7 +11,11 @@ module JsonbAccessor
|
|
11
11
|
|
12
12
|
# Defines virtual attributes for each jsonb field.
|
13
13
|
field_types.each do |name, type|
|
14
|
-
attribute name,
|
14
|
+
next attribute name, type unless type.is_a?(Array)
|
15
|
+
next attribute name, *type unless type.last.is_a?(Hash)
|
16
|
+
|
17
|
+
*args, keyword_args = type
|
18
|
+
attribute name, *args, **keyword_args
|
15
19
|
end
|
16
20
|
|
17
21
|
store_key_mapping_method_name = "jsonb_store_key_mapping_for_#{jsonb_attribute}"
|
@@ -34,7 +38,7 @@ module JsonbAccessor
|
|
34
38
|
end
|
35
39
|
|
36
40
|
# Get store keys to default values mapping
|
37
|
-
store_keys_and_defaults = ::JsonbAccessor::
|
41
|
+
store_keys_and_defaults = ::JsonbAccessor::QueryHelper.convert_keys_to_store_keys(names_and_defaults, public_send(store_key_mapping_method_name))
|
38
42
|
|
39
43
|
# Define jsonb_defaults_mapping_for_<jsonb_attribute>
|
40
44
|
defaults_mapping_method_name = "jsonb_defaults_mapping_for_#{jsonb_attribute}"
|
@@ -46,7 +50,14 @@ module JsonbAccessor
|
|
46
50
|
end
|
47
51
|
|
48
52
|
all_defaults_mapping = public_send(defaults_mapping_method_name)
|
49
|
-
|
53
|
+
# Fields may have procs as default value. This means `all_defaults_mapping` may contain procs as values. To make this work
|
54
|
+
# with the attributes API, we need to wrap `all_defaults_mapping` with a proc itself, making sure it returns a plain hash
|
55
|
+
# each time it is evaluated.
|
56
|
+
all_defaults_mapping_proc =
|
57
|
+
if all_defaults_mapping.present?
|
58
|
+
-> { all_defaults_mapping.map { |key, value| [key, value.respond_to?(:call) ? value.call : value] }.to_h }
|
59
|
+
end
|
60
|
+
attribute jsonb_attribute, :jsonb, default: all_defaults_mapping_proc if all_defaults_mapping_proc.present?
|
50
61
|
|
51
62
|
# Setters are in a module to allow users to override them and still be able to use `super`.
|
52
63
|
setters = Module.new do
|
@@ -67,7 +78,7 @@ module JsonbAccessor
|
|
67
78
|
empty_store_key_attributes = names_to_store_keys.values.each_with_object({}) { |name, defaults| defaults[name] = nil }
|
68
79
|
empty_named_attributes = names_to_store_keys.keys.each_with_object({}) { |name, defaults| defaults[name] = nil }
|
69
80
|
|
70
|
-
store_key_attributes = ::JsonbAccessor::
|
81
|
+
store_key_attributes = ::JsonbAccessor::QueryHelper.convert_keys_to_store_keys(value, names_to_store_keys)
|
71
82
|
write_attribute(jsonb_attribute, empty_store_key_attributes.merge(store_key_attributes))
|
72
83
|
|
73
84
|
empty_named_attributes.merge(value).each { |name, attribute_value| write_attribute(name, attribute_value) }
|
@@ -81,28 +92,37 @@ module JsonbAccessor
|
|
81
92
|
jsonb_values = public_send(jsonb_attribute) || {}
|
82
93
|
jsonb_values.each do |store_key, value|
|
83
94
|
name = names_and_store_keys.key(store_key)
|
84
|
-
|
95
|
+
next unless name
|
96
|
+
|
97
|
+
write_attribute(name, value)
|
98
|
+
clear_attribute_change(name) if persisted?
|
85
99
|
end
|
86
|
-
clear_changes_information if persisted?
|
87
100
|
end
|
88
101
|
end
|
89
102
|
|
90
103
|
# <jsonb_attribute>_where scope
|
91
104
|
scope("#{jsonb_attribute}_where", lambda do |attributes|
|
92
|
-
store_key_attributes = ::JsonbAccessor::
|
105
|
+
store_key_attributes = ::JsonbAccessor::QueryHelper.convert_keys_to_store_keys(attributes, all.model.public_send(store_key_mapping_method_name))
|
93
106
|
jsonb_where(jsonb_attribute, store_key_attributes)
|
94
107
|
end)
|
95
108
|
|
96
109
|
# <jsonb_attribute>_where_not scope
|
97
110
|
scope("#{jsonb_attribute}_where_not", lambda do |attributes|
|
98
|
-
store_key_attributes = ::JsonbAccessor::
|
111
|
+
store_key_attributes = ::JsonbAccessor::QueryHelper.convert_keys_to_store_keys(attributes, all.model.public_send(store_key_mapping_method_name))
|
99
112
|
jsonb_where_not(jsonb_attribute, store_key_attributes)
|
100
113
|
end)
|
101
114
|
|
102
115
|
# <jsonb_attribute>_order scope
|
103
|
-
scope("#{jsonb_attribute}_order", lambda do |
|
104
|
-
|
105
|
-
|
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
|
106
126
|
end)
|
107
127
|
end
|
108
128
|
end
|
@@ -1,112 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module JsonbAccessor
|
4
|
-
GREATER_THAN = ">"
|
5
|
-
GREATER_THAN_OR_EQUAL_TO = ">="
|
6
|
-
LESS_THAN = "<"
|
7
|
-
LESS_THAN_OR_EQUAL_TO = "<="
|
8
|
-
|
9
|
-
NUMBER_OPERATORS_MAP = {
|
10
|
-
GREATER_THAN => GREATER_THAN,
|
11
|
-
"greater_than" => GREATER_THAN,
|
12
|
-
"gt" => GREATER_THAN,
|
13
|
-
GREATER_THAN_OR_EQUAL_TO => GREATER_THAN_OR_EQUAL_TO,
|
14
|
-
"greater_than_or_equal_to" => GREATER_THAN_OR_EQUAL_TO,
|
15
|
-
"gte" => GREATER_THAN_OR_EQUAL_TO,
|
16
|
-
LESS_THAN => LESS_THAN,
|
17
|
-
"less_than" => LESS_THAN,
|
18
|
-
"lt" => LESS_THAN,
|
19
|
-
LESS_THAN_OR_EQUAL_TO => LESS_THAN_OR_EQUAL_TO,
|
20
|
-
"less_than_or_equal_to" => LESS_THAN_OR_EQUAL_TO,
|
21
|
-
"lte" => LESS_THAN_OR_EQUAL_TO
|
22
|
-
}.freeze
|
23
|
-
|
24
|
-
NUMBER_OPERATORS = NUMBER_OPERATORS_MAP.keys.freeze
|
25
|
-
|
26
|
-
TIME_OPERATORS_MAP = {
|
27
|
-
"after" => GREATER_THAN,
|
28
|
-
"before" => LESS_THAN
|
29
|
-
}.freeze
|
30
|
-
|
31
|
-
TIME_OPERATORS = TIME_OPERATORS_MAP.keys.freeze
|
32
|
-
|
33
|
-
IS_NUMBER_QUERY_ARGUMENTS = lambda do |arg|
|
34
|
-
arg.is_a?(Hash) &&
|
35
|
-
arg.keys.map(&:to_s).all? { |key| JsonbAccessor::NUMBER_OPERATORS.include?(key) }
|
36
|
-
end
|
37
|
-
|
38
|
-
IS_TIME_QUERY_ARGUMENTS = lambda do |arg|
|
39
|
-
arg.is_a?(Hash) &&
|
40
|
-
arg.keys.map(&:to_s).all? { |key| JsonbAccessor::TIME_OPERATORS.include?(key) }
|
41
|
-
end
|
42
|
-
|
43
|
-
ORDER_DIRECTIONS = [:asc, :desc, "asc", "desc"].freeze
|
44
|
-
|
45
4
|
module QueryBuilder
|
46
5
|
extend ActiveSupport::Concern
|
47
|
-
InvalidColumnName = Class.new(StandardError)
|
48
|
-
InvalidFieldName = Class.new(StandardError)
|
49
|
-
InvalidDirection = Class.new(StandardError)
|
50
|
-
|
51
|
-
def self.validate_column_name!(query, column_name)
|
52
|
-
if query.model.columns.none? { |column| column.name == column_name.to_s }
|
53
|
-
raise InvalidColumnName, "a column named `#{column_name}` does not exist on the `#{query.model.table_name}` table"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.validate_field_name!(query, column_name, field_name)
|
58
|
-
store_keys = query.model.public_send("jsonb_store_key_mapping_for_#{column_name}").values
|
59
|
-
if store_keys.exclude?(field_name.to_s)
|
60
|
-
valid_field_names = store_keys.map { |key| "`#{key}`" }.join(", ")
|
61
|
-
raise InvalidFieldName, "`#{field_name}` is not a valid field name, valid field names include: #{valid_field_names}"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.validate_direction!(option)
|
66
|
-
if ORDER_DIRECTIONS.exclude?(option)
|
67
|
-
raise InvalidDirection, "`#{option}` is not a valid direction for ordering, only `asc` and `desc` are accepted"
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.convert_keys_to_store_keys(attributes, store_key_mapping)
|
72
|
-
attributes.each_with_object({}) do |(name, value), new_attributes|
|
73
|
-
store_key = store_key_mapping[name.to_s]
|
74
|
-
new_attributes[store_key] = value
|
75
|
-
end
|
76
|
-
end
|
77
6
|
|
78
7
|
included do
|
79
8
|
scope(:jsonb_contains, lambda do |column_name, attributes|
|
80
|
-
JsonbAccessor::
|
9
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
81
10
|
where("#{table_name}.#{column_name} @> (?)::jsonb", attributes.to_json)
|
82
11
|
end)
|
83
12
|
|
84
13
|
scope(:jsonb_excludes, lambda do |column_name, attributes|
|
85
|
-
JsonbAccessor::
|
14
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
86
15
|
where.not("#{table_name}.#{column_name} @> (?)::jsonb", attributes.to_json)
|
87
16
|
end)
|
88
17
|
|
89
18
|
scope(:jsonb_number_where, lambda do |column_name, field_name, given_operator, value|
|
90
|
-
JsonbAccessor::
|
91
|
-
operator = JsonbAccessor::NUMBER_OPERATORS_MAP.fetch(given_operator.to_s)
|
19
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
20
|
+
operator = JsonbAccessor::QueryHelper::NUMBER_OPERATORS_MAP.fetch(given_operator.to_s)
|
92
21
|
where("(#{table_name}.#{column_name} ->> ?)::float #{operator} ?", field_name, value)
|
93
22
|
end)
|
94
23
|
|
95
24
|
scope(:jsonb_number_where_not, lambda do |column_name, field_name, given_operator, value|
|
96
|
-
JsonbAccessor::
|
97
|
-
operator = JsonbAccessor::NUMBER_OPERATORS_MAP.fetch(given_operator.to_s)
|
25
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
26
|
+
operator = JsonbAccessor::QueryHelper::NUMBER_OPERATORS_MAP.fetch(given_operator.to_s)
|
98
27
|
where.not("(#{table_name}.#{column_name} ->> ?)::float #{operator} ?", field_name, value)
|
99
28
|
end)
|
100
29
|
|
101
30
|
scope(:jsonb_time_where, lambda do |column_name, field_name, given_operator, value|
|
102
|
-
JsonbAccessor::
|
103
|
-
operator = JsonbAccessor::TIME_OPERATORS_MAP.fetch(given_operator.to_s)
|
31
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
32
|
+
operator = JsonbAccessor::QueryHelper::TIME_OPERATORS_MAP.fetch(given_operator.to_s)
|
104
33
|
where("(#{table_name}.#{column_name} ->> ?)::timestamp #{operator} ?", field_name, value)
|
105
34
|
end)
|
106
35
|
|
107
36
|
scope(:jsonb_time_where_not, lambda do |column_name, field_name, given_operator, value|
|
108
|
-
JsonbAccessor::
|
109
|
-
operator = JsonbAccessor::TIME_OPERATORS_MAP.fetch(given_operator.to_s)
|
37
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
38
|
+
operator = JsonbAccessor::QueryHelper::TIME_OPERATORS_MAP.fetch(given_operator.to_s)
|
110
39
|
where.not("(#{table_name}.#{column_name} ->> ?)::timestamp #{operator} ?", field_name, value)
|
111
40
|
end)
|
112
41
|
|
@@ -114,11 +43,10 @@ module JsonbAccessor
|
|
114
43
|
query = all
|
115
44
|
contains_attributes = {}
|
116
45
|
|
117
|
-
attributes.each do |name, value|
|
118
|
-
|
119
|
-
when IS_NUMBER_QUERY_ARGUMENTS
|
46
|
+
JsonbAccessor::QueryHelper.convert_ranges(attributes).each do |name, value|
|
47
|
+
if JsonbAccessor::QueryHelper.number_query_arguments?(value)
|
120
48
|
value.each { |operator, query_value| query = query.jsonb_number_where(column_name, name, operator, query_value) }
|
121
|
-
|
49
|
+
elsif JsonbAccessor::QueryHelper.time_query_arguments?(value)
|
122
50
|
value.each { |operator, query_value| query = query.jsonb_time_where(column_name, name, operator, query_value) }
|
123
51
|
else
|
124
52
|
contains_attributes[name] = value
|
@@ -133,10 +61,13 @@ module JsonbAccessor
|
|
133
61
|
excludes_attributes = {}
|
134
62
|
|
135
63
|
attributes.each do |name, value|
|
136
|
-
|
137
|
-
|
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
|
67
|
+
|
68
|
+
if JsonbAccessor::QueryHelper.number_query_arguments?(value)
|
138
69
|
value.each { |operator, query_value| query = query.jsonb_number_where_not(column_name, name, operator, query_value) }
|
139
|
-
|
70
|
+
elsif JsonbAccessor::QueryHelper.time_query_arguments?(value)
|
140
71
|
value.each { |operator, query_value| query = query.jsonb_time_where_not(column_name, name, operator, query_value) }
|
141
72
|
else
|
142
73
|
excludes_attributes[name] = value
|
@@ -147,10 +78,10 @@ module JsonbAccessor
|
|
147
78
|
end)
|
148
79
|
|
149
80
|
scope(:jsonb_order, lambda do |column_name, field_name, direction|
|
150
|
-
JsonbAccessor::
|
151
|
-
JsonbAccessor::
|
152
|
-
JsonbAccessor::
|
153
|
-
order("(#{table_name}.#{column_name} -> '#{field_name}') #{direction}")
|
81
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
82
|
+
JsonbAccessor::QueryHelper.validate_field_name!(all, column_name, field_name)
|
83
|
+
JsonbAccessor::QueryHelper.validate_direction!(direction)
|
84
|
+
order(Arel.sql("(#{table_name}.#{column_name} -> '#{field_name}') #{direction}"))
|
154
85
|
end)
|
155
86
|
end
|
156
87
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JsonbAccessor
|
4
|
+
module QueryHelper
|
5
|
+
# Errors
|
6
|
+
InvalidColumnName = Class.new(StandardError)
|
7
|
+
InvalidFieldName = Class.new(StandardError)
|
8
|
+
InvalidDirection = Class.new(StandardError)
|
9
|
+
NotSupported = Class.new(StandardError)
|
10
|
+
|
11
|
+
# Constants
|
12
|
+
GREATER_THAN = ">"
|
13
|
+
GREATER_THAN_OR_EQUAL_TO = ">="
|
14
|
+
LESS_THAN = "<"
|
15
|
+
LESS_THAN_OR_EQUAL_TO = "<="
|
16
|
+
|
17
|
+
NUMBER_OPERATORS_MAP = {
|
18
|
+
GREATER_THAN => GREATER_THAN,
|
19
|
+
"greater_than" => GREATER_THAN,
|
20
|
+
"gt" => GREATER_THAN,
|
21
|
+
GREATER_THAN_OR_EQUAL_TO => GREATER_THAN_OR_EQUAL_TO,
|
22
|
+
"greater_than_or_equal_to" => GREATER_THAN_OR_EQUAL_TO,
|
23
|
+
"gte" => GREATER_THAN_OR_EQUAL_TO,
|
24
|
+
LESS_THAN => LESS_THAN,
|
25
|
+
"less_than" => LESS_THAN,
|
26
|
+
"lt" => LESS_THAN,
|
27
|
+
LESS_THAN_OR_EQUAL_TO => LESS_THAN_OR_EQUAL_TO,
|
28
|
+
"less_than_or_equal_to" => LESS_THAN_OR_EQUAL_TO,
|
29
|
+
"lte" => LESS_THAN_OR_EQUAL_TO
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
NUMBER_OPERATORS = NUMBER_OPERATORS_MAP.keys.freeze
|
33
|
+
|
34
|
+
TIME_OPERATORS_MAP = {
|
35
|
+
"after" => GREATER_THAN,
|
36
|
+
"before" => LESS_THAN
|
37
|
+
}.freeze
|
38
|
+
|
39
|
+
TIME_OPERATORS = TIME_OPERATORS_MAP.keys.freeze
|
40
|
+
|
41
|
+
ORDER_DIRECTIONS = [:asc, :desc, "asc", "desc"].freeze
|
42
|
+
|
43
|
+
class << self
|
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
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate_field_name!(query, column_name, field_name)
|
51
|
+
store_keys = query.model.public_send("jsonb_store_key_mapping_for_#{column_name}").values
|
52
|
+
if store_keys.exclude?(field_name.to_s)
|
53
|
+
valid_field_names = store_keys.map { |key| "`#{key}`" }.join(", ")
|
54
|
+
raise InvalidFieldName, "`#{field_name}` is not a valid field name, valid field names include: #{valid_field_names}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
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
|
69
|
+
end
|
70
|
+
|
71
|
+
def number_query_arguments?(arg)
|
72
|
+
arg.is_a?(Hash) && arg.keys.map(&:to_s).all? { |key| NUMBER_OPERATORS.include?(key) }
|
73
|
+
end
|
74
|
+
|
75
|
+
def time_query_arguments?(arg)
|
76
|
+
arg.is_a?(Hash) && arg.keys.map(&:to_s).all? { |key| TIME_OPERATORS.include?(key) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def convert_number_ranges(attributes)
|
80
|
+
attributes.each_with_object({}) do |(name, value), new_attributes|
|
81
|
+
is_range = value.is_a?(Range)
|
82
|
+
|
83
|
+
new_attributes[name] = if is_range && value.first.is_a?(Numeric) && value.exclude_end?
|
84
|
+
{ greater_than_or_equal_to: value.first, less_than: value.end }
|
85
|
+
elsif is_range && value.first.is_a?(Numeric)
|
86
|
+
{ greater_than_or_equal_to: value.first, less_than_or_equal_to: value.end }
|
87
|
+
else
|
88
|
+
value
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def convert_time_ranges(attributes)
|
94
|
+
attributes.each_with_object({}) do |(name, value), new_attributes|
|
95
|
+
is_range = value.is_a?(Range)
|
96
|
+
|
97
|
+
if is_range && (value.first.is_a?(Time) || value.first.is_a?(Date))
|
98
|
+
start_time = value.first
|
99
|
+
end_time = value.end
|
100
|
+
new_attributes[name] = { before: end_time, after: start_time }
|
101
|
+
else
|
102
|
+
new_attributes[name] = value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def convert_ranges(attributes)
|
108
|
+
%i[convert_number_ranges convert_time_ranges].reduce(attributes) do |new_attributes, converter_method|
|
109
|
+
public_send(converter_method, new_attributes)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
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.
|
4
|
+
version: 1.2.0
|
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:
|
13
|
+
date: 2021-05-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -26,6 +26,20 @@ dependencies:
|
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: '5.0'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: activesupport
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '5.0'
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '5.0'
|
29
43
|
- !ruby/object:Gem::Dependency
|
30
44
|
name: pg
|
31
45
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,44 +58,44 @@ dependencies:
|
|
44
58
|
name: appraisal
|
45
59
|
requirement: !ruby/object:Gem::Requirement
|
46
60
|
requirements:
|
47
|
-
- - "
|
61
|
+
- - "~>"
|
48
62
|
- !ruby/object:Gem::Version
|
49
|
-
version:
|
63
|
+
version: 2.2.0
|
50
64
|
type: :development
|
51
65
|
prerelease: false
|
52
66
|
version_requirements: !ruby/object:Gem::Requirement
|
53
67
|
requirements:
|
54
|
-
- - "
|
68
|
+
- - "~>"
|
55
69
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
70
|
+
version: 2.2.0
|
57
71
|
- !ruby/object:Gem::Dependency
|
58
72
|
name: bundler
|
59
73
|
requirement: !ruby/object:Gem::Requirement
|
60
74
|
requirements:
|
61
75
|
- - "~>"
|
62
76
|
- !ruby/object:Gem::Version
|
63
|
-
version:
|
77
|
+
version: 2.1.4
|
64
78
|
type: :development
|
65
79
|
prerelease: false
|
66
80
|
version_requirements: !ruby/object:Gem::Requirement
|
67
81
|
requirements:
|
68
82
|
- - "~>"
|
69
83
|
- !ruby/object:Gem::Version
|
70
|
-
version:
|
84
|
+
version: 2.1.4
|
71
85
|
- !ruby/object:Gem::Dependency
|
72
86
|
name: database_cleaner
|
73
87
|
requirement: !ruby/object:Gem::Requirement
|
74
88
|
requirements:
|
75
89
|
- - "~>"
|
76
90
|
- !ruby/object:Gem::Version
|
77
|
-
version: 1.
|
91
|
+
version: 1.6.0
|
78
92
|
type: :development
|
79
93
|
prerelease: false
|
80
94
|
version_requirements: !ruby/object:Gem::Requirement
|
81
95
|
requirements:
|
82
96
|
- - "~>"
|
83
97
|
- !ruby/object:Gem::Version
|
84
|
-
version: 1.
|
98
|
+
version: 1.6.0
|
85
99
|
- !ruby/object:Gem::Dependency
|
86
100
|
name: awesome_print
|
87
101
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,30 +156,30 @@ dependencies:
|
|
142
156
|
name: rake
|
143
157
|
requirement: !ruby/object:Gem::Requirement
|
144
158
|
requirements:
|
145
|
-
- - "
|
159
|
+
- - ">="
|
146
160
|
- !ruby/object:Gem::Version
|
147
|
-
version:
|
161
|
+
version: 12.3.3
|
148
162
|
type: :development
|
149
163
|
prerelease: false
|
150
164
|
version_requirements: !ruby/object:Gem::Requirement
|
151
165
|
requirements:
|
152
|
-
- - "
|
166
|
+
- - ">="
|
153
167
|
- !ruby/object:Gem::Version
|
154
|
-
version:
|
168
|
+
version: 12.3.3
|
155
169
|
- !ruby/object:Gem::Dependency
|
156
170
|
name: rspec
|
157
171
|
requirement: !ruby/object:Gem::Requirement
|
158
172
|
requirements:
|
159
173
|
- - "~>"
|
160
174
|
- !ruby/object:Gem::Version
|
161
|
-
version:
|
175
|
+
version: 3.6.0
|
162
176
|
type: :development
|
163
177
|
prerelease: false
|
164
178
|
version_requirements: !ruby/object:Gem::Requirement
|
165
179
|
requirements:
|
166
180
|
- - "~>"
|
167
181
|
- !ruby/object:Gem::Version
|
168
|
-
version:
|
182
|
+
version: 3.6.0
|
169
183
|
- !ruby/object:Gem::Dependency
|
170
184
|
name: rubocop
|
171
185
|
requirement: !ruby/object:Gem::Requirement
|
@@ -180,34 +194,20 @@ dependencies:
|
|
180
194
|
- - "~>"
|
181
195
|
- !ruby/object:Gem::Version
|
182
196
|
version: 0.48.1
|
183
|
-
- !ruby/object:Gem::Dependency
|
184
|
-
name: shoulda-matchers
|
185
|
-
requirement: !ruby/object:Gem::Requirement
|
186
|
-
requirements:
|
187
|
-
- - ">="
|
188
|
-
- !ruby/object:Gem::Version
|
189
|
-
version: '0'
|
190
|
-
type: :development
|
191
|
-
prerelease: false
|
192
|
-
version_requirements: !ruby/object:Gem::Requirement
|
193
|
-
requirements:
|
194
|
-
- - ">="
|
195
|
-
- !ruby/object:Gem::Version
|
196
|
-
version: '0'
|
197
197
|
- !ruby/object:Gem::Dependency
|
198
198
|
name: standalone_migrations
|
199
199
|
requirement: !ruby/object:Gem::Requirement
|
200
200
|
requirements:
|
201
|
-
- - "
|
201
|
+
- - "~>"
|
202
202
|
- !ruby/object:Gem::Version
|
203
|
-
version:
|
203
|
+
version: 5.2.0
|
204
204
|
type: :development
|
205
205
|
prerelease: false
|
206
206
|
version_requirements: !ruby/object:Gem::Requirement
|
207
207
|
requirements:
|
208
|
-
- - "
|
208
|
+
- - "~>"
|
209
209
|
- !ruby/object:Gem::Version
|
210
|
-
version:
|
210
|
+
version: 5.2.0
|
211
211
|
description: Adds typed jsonb backed fields to your ActiveRecord models.
|
212
212
|
email:
|
213
213
|
- michael@crismali.com
|
@@ -235,13 +235,12 @@ files:
|
|
235
235
|
- db/migrate/20150407031737_set_up_testing_db.rb
|
236
236
|
- db/schema.rb
|
237
237
|
- gemfiles/activerecord_5.0.0.gemfile
|
238
|
-
- gemfiles/activerecord_5.0.0.gemfile.lock
|
239
238
|
- gemfiles/activerecord_5.1.0.gemfile
|
240
|
-
- gemfiles/activerecord_5.1.0.gemfile.lock
|
241
239
|
- jsonb_accessor.gemspec
|
242
240
|
- lib/jsonb_accessor.rb
|
243
241
|
- lib/jsonb_accessor/macro.rb
|
244
242
|
- lib/jsonb_accessor/query_builder.rb
|
243
|
+
- lib/jsonb_accessor/query_helper.rb
|
245
244
|
- lib/jsonb_accessor/version.rb
|
246
245
|
homepage: https://github.com/devmynd/jsonb_accessor
|
247
246
|
licenses:
|
@@ -258,12 +257,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
258
257
|
version: '2.0'
|
259
258
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
260
259
|
requirements:
|
261
|
-
- - "
|
260
|
+
- - ">="
|
262
261
|
- !ruby/object:Gem::Version
|
263
|
-
version:
|
262
|
+
version: '0'
|
264
263
|
requirements: []
|
265
264
|
rubyforge_project:
|
266
|
-
rubygems_version: 2.
|
265
|
+
rubygems_version: 2.6.11
|
267
266
|
signing_key:
|
268
267
|
specification_version: 4
|
269
268
|
summary: Adds typed jsonb backed fields to your ActiveRecord models.
|
@@ -1,141 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ..
|
3
|
-
specs:
|
4
|
-
jsonb_accessor (1.0.0.beta.5)
|
5
|
-
activerecord (>= 5.0)
|
6
|
-
pg (>= 0.18.1)
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
actionpack (5.0.2)
|
12
|
-
actionview (= 5.0.2)
|
13
|
-
activesupport (= 5.0.2)
|
14
|
-
rack (~> 2.0)
|
15
|
-
rack-test (~> 0.6.3)
|
16
|
-
rails-dom-testing (~> 2.0)
|
17
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
18
|
-
actionview (5.0.2)
|
19
|
-
activesupport (= 5.0.2)
|
20
|
-
builder (~> 3.1)
|
21
|
-
erubis (~> 2.7.0)
|
22
|
-
rails-dom-testing (~> 2.0)
|
23
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
24
|
-
activemodel (5.0.2)
|
25
|
-
activesupport (= 5.0.2)
|
26
|
-
activerecord (5.0.2)
|
27
|
-
activemodel (= 5.0.2)
|
28
|
-
activesupport (= 5.0.2)
|
29
|
-
arel (~> 7.0)
|
30
|
-
activesupport (5.0.2)
|
31
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
32
|
-
i18n (~> 0.7)
|
33
|
-
minitest (~> 5.1)
|
34
|
-
tzinfo (~> 1.1)
|
35
|
-
appraisal (2.1.0)
|
36
|
-
bundler
|
37
|
-
rake
|
38
|
-
thor (>= 0.14.0)
|
39
|
-
arel (7.1.4)
|
40
|
-
ast (2.3.0)
|
41
|
-
awesome_print (1.7.0)
|
42
|
-
builder (3.2.3)
|
43
|
-
coderay (1.1.1)
|
44
|
-
concurrent-ruby (1.0.5)
|
45
|
-
database_cleaner (1.5.3)
|
46
|
-
diff-lcs (1.3)
|
47
|
-
erubis (2.7.0)
|
48
|
-
i18n (0.8.1)
|
49
|
-
loofah (2.0.3)
|
50
|
-
nokogiri (>= 1.5.9)
|
51
|
-
method_source (0.8.2)
|
52
|
-
mini_portile2 (2.1.0)
|
53
|
-
minitest (5.10.1)
|
54
|
-
nokogiri (1.7.0.1)
|
55
|
-
mini_portile2 (~> 2.1.0)
|
56
|
-
parser (2.4.0.0)
|
57
|
-
ast (~> 2.2)
|
58
|
-
pg (0.20.0)
|
59
|
-
powerpack (0.1.1)
|
60
|
-
pry (0.10.4)
|
61
|
-
coderay (~> 1.1.0)
|
62
|
-
method_source (~> 0.8.1)
|
63
|
-
slop (~> 3.4)
|
64
|
-
pry-doc (0.10.0)
|
65
|
-
pry (~> 0.9)
|
66
|
-
yard (~> 0.9)
|
67
|
-
pry-nav (0.2.4)
|
68
|
-
pry (>= 0.9.10, < 0.11.0)
|
69
|
-
rack (2.0.1)
|
70
|
-
rack-test (0.6.3)
|
71
|
-
rack (>= 1.0)
|
72
|
-
rails-dom-testing (2.0.2)
|
73
|
-
activesupport (>= 4.2.0, < 6.0)
|
74
|
-
nokogiri (~> 1.6)
|
75
|
-
rails-html-sanitizer (1.0.3)
|
76
|
-
loofah (~> 2.0)
|
77
|
-
railties (5.0.2)
|
78
|
-
actionpack (= 5.0.2)
|
79
|
-
activesupport (= 5.0.2)
|
80
|
-
method_source
|
81
|
-
rake (>= 0.8.7)
|
82
|
-
thor (>= 0.18.1, < 2.0)
|
83
|
-
rainbow (2.2.2)
|
84
|
-
rake
|
85
|
-
rake (10.5.0)
|
86
|
-
rspec (3.5.0)
|
87
|
-
rspec-core (~> 3.5.0)
|
88
|
-
rspec-expectations (~> 3.5.0)
|
89
|
-
rspec-mocks (~> 3.5.0)
|
90
|
-
rspec-core (3.5.4)
|
91
|
-
rspec-support (~> 3.5.0)
|
92
|
-
rspec-expectations (3.5.0)
|
93
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
94
|
-
rspec-support (~> 3.5.0)
|
95
|
-
rspec-mocks (3.5.0)
|
96
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
97
|
-
rspec-support (~> 3.5.0)
|
98
|
-
rspec-support (3.5.0)
|
99
|
-
rubocop (0.48.1)
|
100
|
-
parser (>= 2.3.3.1, < 3.0)
|
101
|
-
powerpack (~> 0.1)
|
102
|
-
rainbow (>= 1.99.1, < 3.0)
|
103
|
-
ruby-progressbar (~> 1.7)
|
104
|
-
unicode-display_width (~> 1.0, >= 1.0.1)
|
105
|
-
ruby-progressbar (1.8.1)
|
106
|
-
shoulda-matchers (3.1.1)
|
107
|
-
activesupport (>= 4.0.0)
|
108
|
-
slop (3.6.0)
|
109
|
-
standalone_migrations (5.0.0)
|
110
|
-
activerecord (>= 4.2.7, < 5.1.0)
|
111
|
-
railties (>= 4.2.7, < 5.1.0)
|
112
|
-
rake (~> 10.0)
|
113
|
-
thor (0.19.4)
|
114
|
-
thread_safe (0.3.6)
|
115
|
-
tzinfo (1.2.2)
|
116
|
-
thread_safe (~> 0.1)
|
117
|
-
unicode-display_width (1.2.1)
|
118
|
-
yard (0.9.8)
|
119
|
-
|
120
|
-
PLATFORMS
|
121
|
-
ruby
|
122
|
-
|
123
|
-
DEPENDENCIES
|
124
|
-
activerecord (~> 5.0.0)
|
125
|
-
appraisal
|
126
|
-
awesome_print
|
127
|
-
bundler (~> 1.9)
|
128
|
-
database_cleaner (~> 1.5.3)
|
129
|
-
jsonb_accessor!
|
130
|
-
pg
|
131
|
-
pry
|
132
|
-
pry-doc
|
133
|
-
pry-nav
|
134
|
-
rake (~> 10.0)
|
135
|
-
rspec (~> 3.2)
|
136
|
-
rubocop (~> 0.48.1)
|
137
|
-
shoulda-matchers
|
138
|
-
standalone_migrations
|
139
|
-
|
140
|
-
BUNDLED WITH
|
141
|
-
1.14.6
|
@@ -1,141 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ..
|
3
|
-
specs:
|
4
|
-
jsonb_accessor (1.0.0.beta.5)
|
5
|
-
activerecord (>= 5.0)
|
6
|
-
pg (>= 0.18.1)
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
actionpack (5.1.0)
|
12
|
-
actionview (= 5.1.0)
|
13
|
-
activesupport (= 5.1.0)
|
14
|
-
rack (~> 2.0)
|
15
|
-
rack-test (~> 0.6.3)
|
16
|
-
rails-dom-testing (~> 2.0)
|
17
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
18
|
-
actionview (5.1.0)
|
19
|
-
activesupport (= 5.1.0)
|
20
|
-
builder (~> 3.1)
|
21
|
-
erubi (~> 1.4)
|
22
|
-
rails-dom-testing (~> 2.0)
|
23
|
-
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
24
|
-
activemodel (5.1.0)
|
25
|
-
activesupport (= 5.1.0)
|
26
|
-
activerecord (5.1.0)
|
27
|
-
activemodel (= 5.1.0)
|
28
|
-
activesupport (= 5.1.0)
|
29
|
-
arel (~> 8.0)
|
30
|
-
activesupport (5.1.0)
|
31
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
32
|
-
i18n (~> 0.7)
|
33
|
-
minitest (~> 5.1)
|
34
|
-
tzinfo (~> 1.1)
|
35
|
-
appraisal (2.2.0)
|
36
|
-
bundler
|
37
|
-
rake
|
38
|
-
thor (>= 0.14.0)
|
39
|
-
arel (8.0.0)
|
40
|
-
ast (2.3.0)
|
41
|
-
awesome_print (1.7.0)
|
42
|
-
builder (3.2.3)
|
43
|
-
coderay (1.1.1)
|
44
|
-
concurrent-ruby (1.0.5)
|
45
|
-
database_cleaner (1.5.3)
|
46
|
-
diff-lcs (1.3)
|
47
|
-
erubi (1.6.0)
|
48
|
-
i18n (0.8.1)
|
49
|
-
loofah (2.0.3)
|
50
|
-
nokogiri (>= 1.5.9)
|
51
|
-
method_source (0.8.2)
|
52
|
-
mini_portile2 (2.1.0)
|
53
|
-
minitest (5.10.1)
|
54
|
-
nokogiri (1.7.1)
|
55
|
-
mini_portile2 (~> 2.1.0)
|
56
|
-
parser (2.4.0.0)
|
57
|
-
ast (~> 2.2)
|
58
|
-
pg (0.20.0)
|
59
|
-
powerpack (0.1.1)
|
60
|
-
pry (0.10.4)
|
61
|
-
coderay (~> 1.1.0)
|
62
|
-
method_source (~> 0.8.1)
|
63
|
-
slop (~> 3.4)
|
64
|
-
pry-doc (0.10.0)
|
65
|
-
pry (~> 0.9)
|
66
|
-
yard (~> 0.9)
|
67
|
-
pry-nav (0.2.4)
|
68
|
-
pry (>= 0.9.10, < 0.11.0)
|
69
|
-
rack (2.0.1)
|
70
|
-
rack-test (0.6.3)
|
71
|
-
rack (>= 1.0)
|
72
|
-
rails-dom-testing (2.0.2)
|
73
|
-
activesupport (>= 4.2.0, < 6.0)
|
74
|
-
nokogiri (~> 1.6)
|
75
|
-
rails-html-sanitizer (1.0.3)
|
76
|
-
loofah (~> 2.0)
|
77
|
-
railties (5.1.0)
|
78
|
-
actionpack (= 5.1.0)
|
79
|
-
activesupport (= 5.1.0)
|
80
|
-
method_source
|
81
|
-
rake (>= 0.8.7)
|
82
|
-
thor (>= 0.18.1, < 2.0)
|
83
|
-
rainbow (2.2.2)
|
84
|
-
rake
|
85
|
-
rake (10.5.0)
|
86
|
-
rspec (3.5.0)
|
87
|
-
rspec-core (~> 3.5.0)
|
88
|
-
rspec-expectations (~> 3.5.0)
|
89
|
-
rspec-mocks (~> 3.5.0)
|
90
|
-
rspec-core (3.5.4)
|
91
|
-
rspec-support (~> 3.5.0)
|
92
|
-
rspec-expectations (3.5.0)
|
93
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
94
|
-
rspec-support (~> 3.5.0)
|
95
|
-
rspec-mocks (3.5.0)
|
96
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
97
|
-
rspec-support (~> 3.5.0)
|
98
|
-
rspec-support (3.5.0)
|
99
|
-
rubocop (0.48.1)
|
100
|
-
parser (>= 2.3.3.1, < 3.0)
|
101
|
-
powerpack (~> 0.1)
|
102
|
-
rainbow (>= 1.99.1, < 3.0)
|
103
|
-
ruby-progressbar (~> 1.7)
|
104
|
-
unicode-display_width (~> 1.0, >= 1.0.1)
|
105
|
-
ruby-progressbar (1.8.1)
|
106
|
-
shoulda-matchers (3.1.1)
|
107
|
-
activesupport (>= 4.0.0)
|
108
|
-
slop (3.6.0)
|
109
|
-
standalone_migrations (5.2.1)
|
110
|
-
activerecord (>= 4.2.7, < 5.2.0)
|
111
|
-
railties (>= 4.2.7, < 5.2.0)
|
112
|
-
rake (~> 10.0)
|
113
|
-
thor (0.19.4)
|
114
|
-
thread_safe (0.3.6)
|
115
|
-
tzinfo (1.2.3)
|
116
|
-
thread_safe (~> 0.1)
|
117
|
-
unicode-display_width (1.2.1)
|
118
|
-
yard (0.9.9)
|
119
|
-
|
120
|
-
PLATFORMS
|
121
|
-
ruby
|
122
|
-
|
123
|
-
DEPENDENCIES
|
124
|
-
activerecord (~> 5.1.0)
|
125
|
-
appraisal
|
126
|
-
awesome_print
|
127
|
-
bundler (~> 1.9)
|
128
|
-
database_cleaner (~> 1.5.3)
|
129
|
-
jsonb_accessor!
|
130
|
-
pg
|
131
|
-
pry
|
132
|
-
pry-doc
|
133
|
-
pry-nav
|
134
|
-
rake (~> 10.0)
|
135
|
-
rspec (~> 3.2)
|
136
|
-
rubocop (~> 0.48.1)
|
137
|
-
shoulda-matchers
|
138
|
-
standalone_migrations
|
139
|
-
|
140
|
-
BUNDLED WITH
|
141
|
-
1.14.6
|