jsonb_accessor 1.3.7-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JsonbAccessor
4
+ VERSION = "1.3.7"
5
+ 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: []