associate_jsonb 0.0.1 → 0.0.7
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.
- checksums.yaml +4 -4
- data/README.md +81 -1
- data/lib/associate_jsonb.rb +111 -1
- data/lib/associate_jsonb/arel_extensions/nodes/binary.rb +14 -0
- data/lib/associate_jsonb/arel_extensions/nodes/table_alias.rb +38 -0
- data/lib/associate_jsonb/arel_extensions/table.rb +40 -0
- data/lib/associate_jsonb/arel_extensions/visitors/postgresql.rb +113 -0
- data/lib/associate_jsonb/arel_extensions/visitors/visitor.rb +19 -0
- data/lib/associate_jsonb/arel_nodes/jsonb/attribute.rb +38 -0
- data/lib/associate_jsonb/arel_nodes/sql_casted_binary.rb +20 -0
- data/lib/associate_jsonb/arel_nodes/sql_casted_equality.rb +26 -12
- data/lib/associate_jsonb/associations/alias_tracker.rb +13 -0
- data/lib/associate_jsonb/associations/association_scope.rb +18 -45
- data/lib/associate_jsonb/associations/belongs_to_association.rb +8 -8
- data/lib/associate_jsonb/associations/builder/belongs_to.rb +5 -3
- data/lib/associate_jsonb/associations/join_dependency.rb +21 -0
- data/lib/associate_jsonb/attribute_methods.rb +19 -0
- data/lib/associate_jsonb/attribute_methods/read.rb +15 -0
- data/lib/associate_jsonb/connection_adapters/schema_creation.rb +162 -0
- data/lib/associate_jsonb/connection_adapters/schema_definitions/add_jsonb_foreign_key_function.rb +9 -0
- data/lib/associate_jsonb/connection_adapters/schema_definitions/add_jsonb_nested_set_function.rb +9 -0
- data/lib/associate_jsonb/connection_adapters/schema_definitions/alter_table.rb +40 -0
- data/lib/associate_jsonb/connection_adapters/schema_definitions/constraint_definition.rb +60 -0
- data/lib/associate_jsonb/connection_adapters/schema_definitions/reference_definition.rb +88 -0
- data/lib/associate_jsonb/connection_adapters/schema_definitions/table.rb +12 -0
- data/lib/associate_jsonb/connection_adapters/schema_definitions/table_definition.rb +25 -0
- data/lib/associate_jsonb/connection_adapters/schema_statements.rb +116 -0
- data/lib/associate_jsonb/persistence.rb +14 -0
- data/lib/associate_jsonb/predicate_builder.rb +15 -0
- data/lib/associate_jsonb/reflection.rb +2 -2
- data/lib/associate_jsonb/relation/where_clause.rb +19 -0
- data/lib/associate_jsonb/supported_rails_version.rb +6 -0
- data/lib/associate_jsonb/version.rb +1 -1
- data/lib/associate_jsonb/with_store_attribute.rb +59 -23
- metadata +39 -14
- data/lib/associate_jsonb/arel_node_extensions/binary.rb +0 -12
- data/lib/associate_jsonb/connection_adapters/reference_definition.rb +0 -64
@@ -12,18 +12,29 @@ module AssociateJsonb
|
|
12
12
|
@names_list ||= {}
|
13
13
|
end
|
14
14
|
|
15
|
-
def add_name(name, store, key)
|
16
|
-
|
17
|
-
@names_list[name.to_s.freeze] = { store: store, key: key }
|
15
|
+
def add_name(name, store, key, cast)
|
16
|
+
names_list[name.to_s.freeze] = { store: store, key: key, cast: cast }
|
18
17
|
end
|
19
18
|
|
20
19
|
def has_name?(name)
|
21
20
|
names_list.key? name.to_s
|
22
21
|
end
|
22
|
+
|
23
|
+
def get(name)
|
24
|
+
names_list[name.to_s]
|
25
|
+
end
|
26
|
+
|
27
|
+
def store_for(name)
|
28
|
+
(get(name) || {})[:store]
|
29
|
+
end
|
30
|
+
|
31
|
+
def key_for(name)
|
32
|
+
(get(name) || {})[:key]
|
33
|
+
end
|
23
34
|
end
|
24
35
|
|
25
36
|
included do
|
26
|
-
instance_eval
|
37
|
+
instance_eval <<~CODE, __FILE__, __LINE__ + 1
|
27
38
|
initialize_store_column_attribute_tracker
|
28
39
|
|
29
40
|
after_initialize &set_store_column_attribute_values_on_init
|
@@ -37,6 +48,10 @@ module AssociateJsonb
|
|
37
48
|
super
|
38
49
|
end
|
39
50
|
|
51
|
+
def arel_table
|
52
|
+
super.with_store_tracker(store_column_attribute_tracker)
|
53
|
+
end
|
54
|
+
|
40
55
|
def initialize_store_column_attribute_tracker
|
41
56
|
@store_column_attribute_tracker = const_set(:StoreColumnAttributeTracker, StoreColumnAttributeTracker.new)
|
42
57
|
private_constant :StoreColumnAttributeTracker
|
@@ -56,9 +71,9 @@ module AssociateJsonb
|
|
56
71
|
end
|
57
72
|
end
|
58
73
|
|
59
|
-
def add_store_column_attribute_name(name, store, key)
|
74
|
+
def add_store_column_attribute_name(name, store, key, cast_opts)
|
60
75
|
store_column_attribute_tracker.synchronize do
|
61
|
-
store_column_attribute_tracker.add_name(name, store, key)
|
76
|
+
store_column_attribute_tracker.add_name(name, store, key, cast_opts)
|
62
77
|
end
|
63
78
|
end
|
64
79
|
|
@@ -83,16 +98,16 @@ module AssociateJsonb
|
|
83
98
|
store_column_attribute :data, *args, **opts
|
84
99
|
end
|
85
100
|
|
86
|
-
def store_column_attribute(store, attr,
|
101
|
+
def store_column_attribute(store, attr, cast_type = ActiveRecord::Type::Value.new, sql_type: nil, key: nil, **attribute_opts)
|
87
102
|
store = store.to_sym
|
88
103
|
attr = attr.to_sym
|
89
104
|
key ||= attr
|
90
105
|
key = key.to_s
|
91
106
|
array = attribute_opts[:array]
|
92
|
-
attribute attr,
|
107
|
+
attribute attr, cast_type, **attribute_opts
|
93
108
|
|
94
|
-
instance_eval
|
95
|
-
add_store_column_attribute_name("#{attr}", :#{store}, "#{key}")
|
109
|
+
instance_eval <<~CODE, __FILE__, __LINE__ + 1
|
110
|
+
add_store_column_attribute_name("#{attr}", :#{store}, "#{key}", { sql_type: sql_type, type: cast_type, opts: attribute_opts })
|
96
111
|
CODE
|
97
112
|
|
98
113
|
include WithStoreAttribute::InstanceMethodsOnActivation.new(self, store, attr, key, array)
|
@@ -102,31 +117,52 @@ module AssociateJsonb
|
|
102
117
|
class InstanceMethodsOnActivation < Module
|
103
118
|
def initialize(mixin, store, attribute, key, is_array)
|
104
119
|
is_array = !!(is_array && attribute.to_s =~ /_ids$/)
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
120
|
+
|
121
|
+
array_or_attr = ->(value) {
|
122
|
+
is_array \
|
123
|
+
? %Q(Array(#{value})) \
|
124
|
+
: %Q(#{value})
|
125
|
+
}
|
126
|
+
|
127
|
+
on_store_change = "_write_attribute(:#{attribute}, #{array_or_attr.call %Q(#{store}["#{key}"])})"
|
128
|
+
on_attr_change = "super(#{array_or_attr.call %Q(given)})"
|
129
|
+
|
109
130
|
if is_array
|
110
|
-
mixin.class_eval
|
131
|
+
mixin.class_eval <<~CODE, __FILE__, __LINE__ + 1
|
111
132
|
def #{attribute}
|
112
133
|
_read_attribute(:#{attribute}) || []
|
113
134
|
end
|
114
135
|
CODE
|
115
136
|
end
|
116
137
|
|
117
|
-
mixin.class_eval
|
138
|
+
mixin.class_eval <<~CODE, __FILE__, __LINE__ + 1
|
118
139
|
def #{store}=(given)
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
140
|
+
if given.is_a?(::String)
|
141
|
+
given = ActiveSupport::JSON.decode(given) rescue nil
|
142
|
+
end
|
143
|
+
|
144
|
+
if AssociateJsonb.merge_hash?(self.class.attribute_types["#{store}"])
|
145
|
+
if !given
|
146
|
+
given = {}
|
147
|
+
#{store}.keys.each do |k|
|
148
|
+
given[k] = nil
|
149
|
+
end
|
150
|
+
end
|
151
|
+
super(#{store}.deep_merge(given.deep_stringify_keys))
|
152
|
+
|
153
|
+
self.#{attribute}= #{store}["#{key}"] if #{store}.key?("#{key}")
|
154
|
+
else
|
155
|
+
super given || {}
|
156
|
+
self.#{attribute}= #{store}["#{key}"]
|
157
|
+
end
|
158
|
+
|
159
|
+
#{store}
|
123
160
|
end
|
124
161
|
|
125
162
|
def #{attribute}=(given)
|
126
163
|
#{on_attr_change}
|
127
|
-
value = #{store}["#{key}"] = #{attribute}
|
128
|
-
#{store}.delete("#{key}")
|
129
|
-
_write_attribute(:#{store}, #{store})
|
164
|
+
value = #{store}["#{key}"] = #{attribute}.presence
|
165
|
+
#{store}.delete("#{key}") unless !value.nil? || AssociateJsonb.merge_hash?(self.class.attribute_types["#{store}"])
|
130
166
|
value
|
131
167
|
end
|
132
168
|
CODE
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: associate_jsonb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sampson Crowley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 6.0.3
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 6.0.3.
|
22
|
+
version: 6.0.3.2
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 6.0.3
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 6.0.3.
|
32
|
+
version: 6.0.3.2
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: pg
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,14 +104,18 @@ dependencies:
|
|
104
104
|
- - "~>"
|
105
105
|
- !ruby/object:Gem::Version
|
106
106
|
version: 3.7.0
|
107
|
-
description: |
|
108
|
-
|
107
|
+
description: |
|
108
|
+
This gem extends ActiveRecord to add additional functionality to JSONB
|
109
109
|
|
110
|
-
|
111
|
-
|
110
|
+
- use PostgreSQL JSONB data for associations
|
111
|
+
- thread-safe single-key updates to JSONB columns using `jsonb_set`
|
112
|
+
- extended `table#references` for easy migrations and indexes
|
113
|
+
- virtual JSONB foreign keys using check constraints
|
114
|
+
(NOTE: real foreign key constraints are not possible with PostgreSQL JSONB)
|
112
115
|
|
113
|
-
|
114
|
-
|
116
|
+
Inspired by activerecord-jsonb-associations, but for use in Rails 6+ and
|
117
|
+
ruby 2.7+ and with some unnecessary options and features (HABTM) removed
|
118
|
+
and some additional features added
|
115
119
|
email:
|
116
120
|
- sampsonsprojects@gmail.com
|
117
121
|
executables: []
|
@@ -122,15 +126,22 @@ files:
|
|
122
126
|
- README.md
|
123
127
|
- Rakefile
|
124
128
|
- lib/associate_jsonb.rb
|
125
|
-
- lib/associate_jsonb/
|
129
|
+
- lib/associate_jsonb/arel_extensions/nodes/binary.rb
|
130
|
+
- lib/associate_jsonb/arel_extensions/nodes/table_alias.rb
|
131
|
+
- lib/associate_jsonb/arel_extensions/table.rb
|
132
|
+
- lib/associate_jsonb/arel_extensions/visitors/postgresql.rb
|
133
|
+
- lib/associate_jsonb/arel_extensions/visitors/visitor.rb
|
126
134
|
- lib/associate_jsonb/arel_nodes/jsonb/at_arrow.rb
|
135
|
+
- lib/associate_jsonb/arel_nodes/jsonb/attribute.rb
|
127
136
|
- lib/associate_jsonb/arel_nodes/jsonb/bindable_operator.rb
|
128
137
|
- lib/associate_jsonb/arel_nodes/jsonb/dash_arrow.rb
|
129
138
|
- lib/associate_jsonb/arel_nodes/jsonb/dash_double_arrow.rb
|
130
139
|
- lib/associate_jsonb/arel_nodes/jsonb/double_pipe.rb
|
131
140
|
- lib/associate_jsonb/arel_nodes/jsonb/hash_arrow.rb
|
132
141
|
- lib/associate_jsonb/arel_nodes/jsonb/operator.rb
|
142
|
+
- lib/associate_jsonb/arel_nodes/sql_casted_binary.rb
|
133
143
|
- lib/associate_jsonb/arel_nodes/sql_casted_equality.rb
|
144
|
+
- lib/associate_jsonb/associations/alias_tracker.rb
|
134
145
|
- lib/associate_jsonb/associations/association.rb
|
135
146
|
- lib/associate_jsonb/associations/association_scope.rb
|
136
147
|
- lib/associate_jsonb/associations/belongs_to_association.rb
|
@@ -139,11 +150,25 @@ files:
|
|
139
150
|
- lib/associate_jsonb/associations/builder/has_one.rb
|
140
151
|
- lib/associate_jsonb/associations/conflicting_association.rb
|
141
152
|
- lib/associate_jsonb/associations/has_many_association.rb
|
153
|
+
- lib/associate_jsonb/associations/join_dependency.rb
|
142
154
|
- lib/associate_jsonb/associations/preloader/association.rb
|
155
|
+
- lib/associate_jsonb/attribute_methods.rb
|
156
|
+
- lib/associate_jsonb/attribute_methods/read.rb
|
143
157
|
- lib/associate_jsonb/connection_adapters.rb
|
144
|
-
- lib/associate_jsonb/connection_adapters/
|
158
|
+
- lib/associate_jsonb/connection_adapters/schema_creation.rb
|
159
|
+
- lib/associate_jsonb/connection_adapters/schema_definitions/add_jsonb_foreign_key_function.rb
|
160
|
+
- lib/associate_jsonb/connection_adapters/schema_definitions/add_jsonb_nested_set_function.rb
|
161
|
+
- lib/associate_jsonb/connection_adapters/schema_definitions/alter_table.rb
|
162
|
+
- lib/associate_jsonb/connection_adapters/schema_definitions/constraint_definition.rb
|
163
|
+
- lib/associate_jsonb/connection_adapters/schema_definitions/reference_definition.rb
|
164
|
+
- lib/associate_jsonb/connection_adapters/schema_definitions/table.rb
|
165
|
+
- lib/associate_jsonb/connection_adapters/schema_definitions/table_definition.rb
|
166
|
+
- lib/associate_jsonb/connection_adapters/schema_statements.rb
|
167
|
+
- lib/associate_jsonb/persistence.rb
|
168
|
+
- lib/associate_jsonb/predicate_builder.rb
|
145
169
|
- lib/associate_jsonb/reflection.rb
|
146
170
|
- lib/associate_jsonb/relation/where_clause.rb
|
171
|
+
- lib/associate_jsonb/supported_rails_version.rb
|
147
172
|
- lib/associate_jsonb/version.rb
|
148
173
|
- lib/associate_jsonb/with_store_attribute.rb
|
149
174
|
homepage: https://github.com/SampsonCrowley/associate_jsonb
|
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module AssociateJsonb
|
4
|
-
module ConnectionAdapters
|
5
|
-
module ReferenceDefinition #:nodoc:
|
6
|
-
# rubocop:disable Metrics/ParameterLists
|
7
|
-
def initialize(
|
8
|
-
name,
|
9
|
-
store: false,
|
10
|
-
**options
|
11
|
-
)
|
12
|
-
@store = store && store.to_sym
|
13
|
-
|
14
|
-
super(name, **options)
|
15
|
-
end
|
16
|
-
# rubocop:enable Metrics/ParameterLists
|
17
|
-
|
18
|
-
def add_to(table)
|
19
|
-
return super unless store
|
20
|
-
|
21
|
-
should_add_col = false
|
22
|
-
if table.respond_to? :column_exists?
|
23
|
-
should_add_col = !table.column_exists?(store)
|
24
|
-
elsif table.respond_to? :columns
|
25
|
-
should_add_col = table.columns.none? {|col| col.name.to_sym == store}
|
26
|
-
end
|
27
|
-
|
28
|
-
table.column(store, :jsonb, null: false, default: {}) if should_add_col
|
29
|
-
|
30
|
-
return unless index
|
31
|
-
|
32
|
-
# should_add_idx = false
|
33
|
-
# if table.respond_to? :index_exists?
|
34
|
-
# should_add_idx = !table.index_exists?([ store ], using: :gin)
|
35
|
-
# elsif table.respond_to? :indexes
|
36
|
-
# should_add_idx = table.indexes.none? do |idx, opts|
|
37
|
-
# (idx == [ store ]) \
|
38
|
-
# && (opts == { using: :gin })
|
39
|
-
# end
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# table.index([ store ], using: :gin) if should_add_idx
|
43
|
-
|
44
|
-
column_names.each do |column_name|
|
45
|
-
table.index(
|
46
|
-
"CAST (\"#{store}\"->'#{column_name}' AS #{@type || :bigint})",
|
47
|
-
using: :btree,
|
48
|
-
name: "index_#{table.name}_on_#{store}_#{column_name}"
|
49
|
-
)
|
50
|
-
|
51
|
-
table.index(
|
52
|
-
"(#{store}->>'#{column_name}')",
|
53
|
-
using: :btree,
|
54
|
-
name: "index_#{table.name}_on_#{store}_#{column_name}_text"
|
55
|
-
)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
protected
|
60
|
-
|
61
|
-
attr_reader :store
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|