jsonb_accessor 1.3.7-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +153 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.rubocop.yml +62 -0
- data/.ruby-version +1 -0
- data/Appraisals +25 -0
- data/CHANGELOG.md +28 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Dockerfile +12 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +355 -0
- data/Rakefile +33 -0
- data/UPGRADE_GUIDE.md +67 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/db/config.yml +8 -0
- data/db/migrate/20150407031737_set_up_testing_db.rb +24 -0
- data/db/schema.rb +36 -0
- data/docker-compose.yml +29 -0
- data/gemfiles/activerecord_5.0.0.gemfile +7 -0
- data/gemfiles/activerecord_5.1.0.gemfile +7 -0
- data/gemfiles/activerecord_5.2.0.gemfile +7 -0
- data/gemfiles/activerecord_6.0.0.gemfile +7 -0
- data/gemfiles/activerecord_6.1.0.gemfile +7 -0
- data/gemfiles/activerecord_7.0.1.gemfile +7 -0
- data/jsonb_accessor.gemspec +45 -0
- data/lib/jsonb_accessor/attribute_query_methods.rb +42 -0
- data/lib/jsonb_accessor/helpers.rb +37 -0
- data/lib/jsonb_accessor/macro.rb +124 -0
- data/lib/jsonb_accessor/query_builder.rb +86 -0
- data/lib/jsonb_accessor/query_helper.rb +103 -0
- data/lib/jsonb_accessor/version.rb +5 -0
- data/lib/jsonb_accessor.rb +22 -0
- metadata +263 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JsonbAccessor
|
4
|
+
class AttributeQueryMethods
|
5
|
+
def initialize(klass)
|
6
|
+
@klass = klass
|
7
|
+
end
|
8
|
+
|
9
|
+
def define(store_key_mapping_method_name, jsonb_attribute)
|
10
|
+
return if klass.superclass.respond_to? store_key_mapping_method_name
|
11
|
+
|
12
|
+
# <jsonb_attribute>_where scope
|
13
|
+
klass.define_singleton_method "#{jsonb_attribute}_where" do |attributes|
|
14
|
+
store_key_attributes = JsonbAccessor::Helpers.convert_keys_to_store_keys(attributes, all.model.public_send(store_key_mapping_method_name))
|
15
|
+
jsonb_where(jsonb_attribute, store_key_attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
# <jsonb_attribute>_where_not scope
|
19
|
+
klass.define_singleton_method "#{jsonb_attribute}_where_not" do |attributes|
|
20
|
+
store_key_attributes = JsonbAccessor::Helpers.convert_keys_to_store_keys(attributes, all.model.public_send(store_key_mapping_method_name))
|
21
|
+
jsonb_where_not(jsonb_attribute, store_key_attributes)
|
22
|
+
end
|
23
|
+
|
24
|
+
# <jsonb_attribute>_order scope
|
25
|
+
klass.define_singleton_method "#{jsonb_attribute}_order" do |*args|
|
26
|
+
ordering_options = args.extract_options!
|
27
|
+
order_by_defaults = args.each_with_object({}) { |attribute, config| config[attribute] = :asc }
|
28
|
+
store_key_mapping = all.model.public_send(store_key_mapping_method_name)
|
29
|
+
|
30
|
+
order_by_defaults.merge(ordering_options).reduce(all) do |query, (name, direction)|
|
31
|
+
key = store_key_mapping[name.to_s]
|
32
|
+
order_query = jsonb_order(jsonb_attribute, key, direction)
|
33
|
+
query.merge(order_query)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :klass
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JsonbAccessor
|
4
|
+
module Helpers
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def active_record_default_timezone
|
8
|
+
ActiveRecord.try(:default_timezone) || ActiveRecord::Base.default_timezone
|
9
|
+
end
|
10
|
+
|
11
|
+
# Replaces all keys in `attributes` that have a defined store_key with the store_key
|
12
|
+
def convert_keys_to_store_keys(attributes, store_key_mapping)
|
13
|
+
attributes.stringify_keys.transform_keys do |key|
|
14
|
+
store_key_mapping[key] || key
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Replaces all keys in `attributes` that have a defined store_key with the named key (alias)
|
19
|
+
def convert_store_keys_to_keys(attributes, store_key_mapping)
|
20
|
+
convert_keys_to_store_keys(attributes, store_key_mapping.invert)
|
21
|
+
end
|
22
|
+
|
23
|
+
def deserialize_value(value, attribute_type)
|
24
|
+
return value if value.blank?
|
25
|
+
|
26
|
+
if attribute_type == :datetime
|
27
|
+
value = if active_record_default_timezone == :utc
|
28
|
+
Time.find_zone("UTC").parse(value).in_time_zone
|
29
|
+
else
|
30
|
+
Time.zone.parse(value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JsonbAccessor
|
4
|
+
module Macro
|
5
|
+
module ClassMethods
|
6
|
+
def jsonb_accessor(jsonb_attribute, field_types)
|
7
|
+
names_and_store_keys = field_types.each_with_object({}) do |(name, type), mapping|
|
8
|
+
_type, options = Array(type)
|
9
|
+
mapping[name.to_s] = (options.try(:delete, :store_key) || name).to_s
|
10
|
+
end
|
11
|
+
|
12
|
+
# Defines virtual attributes for each jsonb field.
|
13
|
+
field_types.each do |name, type|
|
14
|
+
next attribute name, type unless type.is_a?(Array)
|
15
|
+
next attribute name, *type unless type.last.is_a?(Hash)
|
16
|
+
|
17
|
+
*args, keyword_args = type
|
18
|
+
attribute name, *args, **keyword_args
|
19
|
+
end
|
20
|
+
|
21
|
+
store_key_mapping_method_name = "jsonb_store_key_mapping_for_#{jsonb_attribute}"
|
22
|
+
# Defines methods on the model class
|
23
|
+
class_methods = Module.new do
|
24
|
+
# Allows us to get a mapping of field names to store keys scoped to the column
|
25
|
+
define_method(store_key_mapping_method_name) do
|
26
|
+
superclass_mapping = superclass.try(store_key_mapping_method_name) || {}
|
27
|
+
superclass_mapping.merge(names_and_store_keys)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
# We extend with class methods here so we can use the results of methods it defines to define more useful methods later
|
31
|
+
extend class_methods
|
32
|
+
|
33
|
+
# Get field names to default values mapping
|
34
|
+
names_and_defaults = field_types.each_with_object({}) do |(name, type), mapping|
|
35
|
+
_type, options = Array(type)
|
36
|
+
field_default = options.try(:delete, :default)
|
37
|
+
mapping[name.to_s] = field_default unless field_default.nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
# Get store keys to default values mapping
|
41
|
+
store_keys_and_defaults = JsonbAccessor::Helpers.convert_keys_to_store_keys(names_and_defaults, public_send(store_key_mapping_method_name))
|
42
|
+
|
43
|
+
# Define jsonb_defaults_mapping_for_<jsonb_attribute>
|
44
|
+
defaults_mapping_method_name = "jsonb_defaults_mapping_for_#{jsonb_attribute}"
|
45
|
+
class_methods.instance_eval do
|
46
|
+
define_method(defaults_mapping_method_name) do
|
47
|
+
superclass_mapping = superclass.try(defaults_mapping_method_name) || {}
|
48
|
+
superclass_mapping.merge(store_keys_and_defaults)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
all_defaults_mapping = public_send(defaults_mapping_method_name)
|
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.transform_values { |value| value.respond_to?(:call) ? value.call : value }.to_h.compact }
|
59
|
+
end
|
60
|
+
attribute jsonb_attribute, :jsonb, default: all_defaults_mapping_proc if all_defaults_mapping_proc.present?
|
61
|
+
|
62
|
+
# Setters are in a module to allow users to override them and still be able to use `super`.
|
63
|
+
setters = Module.new do
|
64
|
+
# Overrides the setter created by `attribute` above to make sure the jsonb attribute is kept in sync.
|
65
|
+
names_and_store_keys.each do |name, store_key|
|
66
|
+
define_method("#{name}=") do |value|
|
67
|
+
super(value)
|
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)
|
76
|
+
write_attribute(jsonb_attribute, new_values)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Overrides the jsonb attribute setter to make sure the jsonb fields are kept in sync.
|
81
|
+
define_method("#{jsonb_attribute}=") do |value|
|
82
|
+
value ||= {}
|
83
|
+
names_to_store_keys = self.class.public_send(store_key_mapping_method_name)
|
84
|
+
|
85
|
+
# this is the raw hash we want to save in the jsonb_attribute
|
86
|
+
value_with_store_keys = JsonbAccessor::Helpers.convert_keys_to_store_keys(value, names_to_store_keys)
|
87
|
+
write_attribute(jsonb_attribute, value_with_store_keys)
|
88
|
+
|
89
|
+
# this maps attributes to values
|
90
|
+
value_with_named_keys = JsonbAccessor::Helpers.convert_store_keys_to_keys(value, names_to_store_keys)
|
91
|
+
|
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
|
+
# Only proceed if this attribute has been defined using `jsonb_accessor`.
|
95
|
+
next unless names_to_store_keys.key?(name)
|
96
|
+
|
97
|
+
write_attribute(name, attribute_value)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
include setters
|
102
|
+
|
103
|
+
# Makes sure new objects have the appropriate values in their jsonb fields.
|
104
|
+
after_initialize do
|
105
|
+
next unless has_attribute? jsonb_attribute
|
106
|
+
|
107
|
+
jsonb_values = public_send(jsonb_attribute) || {}
|
108
|
+
jsonb_values.each do |store_key, value|
|
109
|
+
name = names_and_store_keys.key(store_key)
|
110
|
+
next unless name
|
111
|
+
|
112
|
+
write_attribute(
|
113
|
+
name,
|
114
|
+
JsonbAccessor::Helpers.deserialize_value(value, self.class.type_for_attribute(name).type)
|
115
|
+
)
|
116
|
+
clear_attribute_change(name) if persisted?
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
JsonbAccessor::AttributeQueryMethods.new(self).define(store_key_mapping_method_name, jsonb_attribute)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module JsonbAccessor
|
4
|
+
module QueryBuilder
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
scope(:jsonb_contains, lambda do |column_name, attributes|
|
9
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
10
|
+
where("#{table_name}.#{column_name} @> (?)::jsonb", attributes.to_json)
|
11
|
+
end)
|
12
|
+
|
13
|
+
scope(:jsonb_excludes, lambda do |column_name, attributes|
|
14
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
15
|
+
where.not("#{table_name}.#{column_name} @> (?)::jsonb", attributes.to_json)
|
16
|
+
end)
|
17
|
+
|
18
|
+
scope(:jsonb_number_where, lambda do |column_name, field_name, given_operator, value|
|
19
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
20
|
+
operator = JsonbAccessor::QueryHelper::NUMBER_OPERATORS_MAP.fetch(given_operator.to_s)
|
21
|
+
where("(#{table_name}.#{column_name} ->> ?)::float #{operator} ?", field_name, value)
|
22
|
+
end)
|
23
|
+
|
24
|
+
scope(:jsonb_number_where_not, lambda do |column_name, field_name, given_operator, value|
|
25
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
26
|
+
operator = JsonbAccessor::QueryHelper::NUMBER_OPERATORS_MAP.fetch(given_operator.to_s)
|
27
|
+
where.not("(#{table_name}.#{column_name} ->> ?)::float #{operator} ?", field_name, value)
|
28
|
+
end)
|
29
|
+
|
30
|
+
scope(:jsonb_time_where, lambda do |column_name, field_name, given_operator, value|
|
31
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
32
|
+
operator = JsonbAccessor::QueryHelper::TIME_OPERATORS_MAP.fetch(given_operator.to_s)
|
33
|
+
where("(#{table_name}.#{column_name} ->> ?)::timestamp #{operator} ?", field_name, value)
|
34
|
+
end)
|
35
|
+
|
36
|
+
scope(:jsonb_time_where_not, lambda do |column_name, field_name, given_operator, value|
|
37
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
38
|
+
operator = JsonbAccessor::QueryHelper::TIME_OPERATORS_MAP.fetch(given_operator.to_s)
|
39
|
+
where.not("(#{table_name}.#{column_name} ->> ?)::timestamp #{operator} ?", field_name, value)
|
40
|
+
end)
|
41
|
+
|
42
|
+
scope(:jsonb_where, lambda do |column_name, attributes|
|
43
|
+
query = all
|
44
|
+
contains_attributes = {}
|
45
|
+
|
46
|
+
JsonbAccessor::QueryHelper.convert_ranges(attributes).each do |name, value|
|
47
|
+
if JsonbAccessor::QueryHelper.number_query_arguments?(value)
|
48
|
+
value.each { |operator, query_value| query = query.jsonb_number_where(column_name, name, operator, query_value) }
|
49
|
+
elsif JsonbAccessor::QueryHelper.time_query_arguments?(value)
|
50
|
+
value.each { |operator, query_value| query = query.jsonb_time_where(column_name, name, operator, query_value) }
|
51
|
+
else
|
52
|
+
contains_attributes[name] = value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
query.jsonb_contains(column_name, contains_attributes)
|
57
|
+
end)
|
58
|
+
|
59
|
+
scope(:jsonb_where_not, lambda do |column_name, attributes|
|
60
|
+
query = all
|
61
|
+
excludes_attributes = {}
|
62
|
+
|
63
|
+
attributes.each do |name, value|
|
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)
|
65
|
+
|
66
|
+
if JsonbAccessor::QueryHelper.number_query_arguments?(value)
|
67
|
+
value.each { |operator, query_value| query = query.jsonb_number_where_not(column_name, name, operator, query_value) }
|
68
|
+
elsif JsonbAccessor::QueryHelper.time_query_arguments?(value)
|
69
|
+
value.each { |operator, query_value| query = query.jsonb_time_where_not(column_name, name, operator, query_value) }
|
70
|
+
else
|
71
|
+
excludes_attributes[name] = value
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
excludes_attributes.empty? ? query : query.jsonb_excludes(column_name, excludes_attributes)
|
76
|
+
end)
|
77
|
+
|
78
|
+
scope(:jsonb_order, lambda do |column_name, field_name, direction|
|
79
|
+
JsonbAccessor::QueryHelper.validate_column_name!(all, column_name)
|
80
|
+
JsonbAccessor::QueryHelper.validate_field_name!(all, column_name, field_name)
|
81
|
+
JsonbAccessor::QueryHelper.validate_direction!(direction)
|
82
|
+
order(Arel.sql("(#{table_name}.#{column_name} -> '#{field_name}') #{direction}"))
|
83
|
+
end)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,103 @@
|
|
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
|
+
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 }
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_field_name!(query, column_name, field_name)
|
49
|
+
store_keys = query.model.public_send("jsonb_store_key_mapping_for_#{column_name}").values
|
50
|
+
if store_keys.exclude?(field_name.to_s)
|
51
|
+
valid_field_names = store_keys.map { |key| "`#{key}`" }.join(", ")
|
52
|
+
raise InvalidFieldName, "`#{field_name}` is not a valid field name, valid field names include: #{valid_field_names}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_direction!(option)
|
57
|
+
raise InvalidDirection, "`#{option}` is not a valid direction for ordering, only `asc` and `desc` are accepted" if ORDER_DIRECTIONS.exclude?(option)
|
58
|
+
end
|
59
|
+
|
60
|
+
def number_query_arguments?(arg)
|
61
|
+
arg.is_a?(Hash) && arg.keys.map(&:to_s).all? { |key| NUMBER_OPERATORS.include?(key) }
|
62
|
+
end
|
63
|
+
|
64
|
+
def time_query_arguments?(arg)
|
65
|
+
arg.is_a?(Hash) && arg.keys.map(&:to_s).all? { |key| TIME_OPERATORS.include?(key) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def convert_number_ranges(attributes)
|
69
|
+
attributes.each_with_object({}) do |(name, value), new_attributes|
|
70
|
+
is_range = value.is_a?(Range)
|
71
|
+
|
72
|
+
new_attributes[name] = if is_range && value.first.is_a?(Numeric) && value.exclude_end?
|
73
|
+
{ greater_than_or_equal_to: value.first, less_than: value.end }
|
74
|
+
elsif is_range && value.first.is_a?(Numeric)
|
75
|
+
{ greater_than_or_equal_to: value.first, less_than_or_equal_to: value.end }
|
76
|
+
else
|
77
|
+
value
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def convert_time_ranges(attributes)
|
83
|
+
attributes.each_with_object({}) do |(name, value), new_attributes|
|
84
|
+
is_range = value.is_a?(Range)
|
85
|
+
|
86
|
+
if is_range && (value.first.is_a?(Time) || value.first.is_a?(Date))
|
87
|
+
start_time = value.first
|
88
|
+
end_time = value.end
|
89
|
+
new_attributes[name] = { before: end_time, after: start_time }
|
90
|
+
else
|
91
|
+
new_attributes[name] = value
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def convert_ranges(attributes)
|
97
|
+
%i[convert_number_ranges convert_time_ranges].reduce(attributes) do |new_attributes, converter_method|
|
98
|
+
public_send(converter_method, new_attributes)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record"
|
4
|
+
|
5
|
+
require "active_record/connection_adapters/postgresql_adapter"
|
6
|
+
|
7
|
+
require "jsonb_accessor/version"
|
8
|
+
require "jsonb_accessor/helpers"
|
9
|
+
require "jsonb_accessor/macro"
|
10
|
+
require "jsonb_accessor/query_helper"
|
11
|
+
require "jsonb_accessor/query_builder"
|
12
|
+
require "jsonb_accessor/attribute_query_methods"
|
13
|
+
|
14
|
+
module JsonbAccessor
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
include Macro
|
17
|
+
end
|
18
|
+
|
19
|
+
ActiveSupport.on_load(:active_record) do
|
20
|
+
ActiveRecord::Base.include JsonbAccessor
|
21
|
+
ActiveRecord::Base.include JsonbAccessor::QueryBuilder
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jsonb_accessor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.7
|
5
|
+
platform: java
|
6
|
+
authors:
|
7
|
+
- Michael Crismali
|
8
|
+
- Joe Hirn
|
9
|
+
- Jason Haruska
|
10
|
+
autorequire:
|
11
|
+
bindir: exe
|
12
|
+
cert_chain: []
|
13
|
+
date: 2022-12-29 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '5.0'
|
21
|
+
name: activerecord
|
22
|
+
prerelease: false
|
23
|
+
type: :runtime
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '5.0'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '5.0'
|
35
|
+
name: activesupport
|
36
|
+
prerelease: false
|
37
|
+
type: :runtime
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '5.0'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '50.0'
|
49
|
+
name: activerecord-jdbcpostgresql-adapter
|
50
|
+
prerelease: false
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '50.0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 2.2.0
|
63
|
+
name: appraisal
|
64
|
+
prerelease: false
|
65
|
+
type: :development
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - "~>"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 2.2.0
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
name: awesome_print
|
78
|
+
prerelease: false
|
79
|
+
type: :development
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 1.6.0
|
91
|
+
name: database_cleaner
|
92
|
+
prerelease: false
|
93
|
+
type: :development
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - "~>"
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 1.6.0
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
name: pry
|
106
|
+
prerelease: false
|
107
|
+
type: :development
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
name: pry-doc
|
120
|
+
prerelease: false
|
121
|
+
type: :development
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
name: pry-nav
|
134
|
+
prerelease: false
|
135
|
+
type: :development
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - "~>"
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '3'
|
147
|
+
name: psych
|
148
|
+
prerelease: false
|
149
|
+
type: :development
|
150
|
+
version_requirements: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - "~>"
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '3'
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: 12.3.3
|
161
|
+
name: rake
|
162
|
+
prerelease: false
|
163
|
+
type: :development
|
164
|
+
version_requirements: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: 12.3.3
|
169
|
+
- !ruby/object:Gem::Dependency
|
170
|
+
requirement: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - "~>"
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: 3.6.0
|
175
|
+
name: rspec
|
176
|
+
prerelease: false
|
177
|
+
type: :development
|
178
|
+
version_requirements: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - "~>"
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: 3.6.0
|
183
|
+
- !ruby/object:Gem::Dependency
|
184
|
+
requirement: !ruby/object:Gem::Requirement
|
185
|
+
requirements:
|
186
|
+
- - "~>"
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: '1'
|
189
|
+
name: rubocop
|
190
|
+
prerelease: false
|
191
|
+
type: :development
|
192
|
+
version_requirements: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - "~>"
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '1'
|
197
|
+
description: Adds typed jsonb backed fields to your ActiveRecord models.
|
198
|
+
email:
|
199
|
+
- michael@crismali.com
|
200
|
+
- joe@devmynd.com
|
201
|
+
- jason@haruska.com
|
202
|
+
executables: []
|
203
|
+
extensions: []
|
204
|
+
extra_rdoc_files: []
|
205
|
+
files:
|
206
|
+
- ".github/workflows/ci.yml"
|
207
|
+
- ".gitignore"
|
208
|
+
- ".rspec"
|
209
|
+
- ".rubocop.yml"
|
210
|
+
- ".ruby-version"
|
211
|
+
- Appraisals
|
212
|
+
- CHANGELOG.md
|
213
|
+
- CODE_OF_CONDUCT.md
|
214
|
+
- Dockerfile
|
215
|
+
- Gemfile
|
216
|
+
- LICENSE.txt
|
217
|
+
- README.md
|
218
|
+
- Rakefile
|
219
|
+
- UPGRADE_GUIDE.md
|
220
|
+
- bin/console
|
221
|
+
- bin/setup
|
222
|
+
- db/config.yml
|
223
|
+
- db/migrate/20150407031737_set_up_testing_db.rb
|
224
|
+
- db/schema.rb
|
225
|
+
- docker-compose.yml
|
226
|
+
- gemfiles/activerecord_5.0.0.gemfile
|
227
|
+
- gemfiles/activerecord_5.1.0.gemfile
|
228
|
+
- gemfiles/activerecord_5.2.0.gemfile
|
229
|
+
- gemfiles/activerecord_6.0.0.gemfile
|
230
|
+
- gemfiles/activerecord_6.1.0.gemfile
|
231
|
+
- gemfiles/activerecord_7.0.1.gemfile
|
232
|
+
- jsonb_accessor.gemspec
|
233
|
+
- lib/jsonb_accessor.rb
|
234
|
+
- lib/jsonb_accessor/attribute_query_methods.rb
|
235
|
+
- lib/jsonb_accessor/helpers.rb
|
236
|
+
- lib/jsonb_accessor/macro.rb
|
237
|
+
- lib/jsonb_accessor/query_builder.rb
|
238
|
+
- lib/jsonb_accessor/query_helper.rb
|
239
|
+
- lib/jsonb_accessor/version.rb
|
240
|
+
homepage: https://github.com/devmynd/jsonb_accessor
|
241
|
+
licenses:
|
242
|
+
- MIT
|
243
|
+
metadata: {}
|
244
|
+
post_install_message:
|
245
|
+
rdoc_options: []
|
246
|
+
require_paths:
|
247
|
+
- lib
|
248
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
249
|
+
requirements:
|
250
|
+
- - ">="
|
251
|
+
- !ruby/object:Gem::Version
|
252
|
+
version: '2'
|
253
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - ">="
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: '0'
|
258
|
+
requirements: []
|
259
|
+
rubygems_version: 3.2.33
|
260
|
+
signing_key:
|
261
|
+
specification_version: 4
|
262
|
+
summary: Adds typed jsonb backed fields to your ActiveRecord models.
|
263
|
+
test_files: []
|