jsonb_accessor 1.3.7-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []