associate_jsonb 0.0.4 → 0.0.5
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 +3 -1
- data/lib/associate_jsonb.rb +14 -1
- data/lib/associate_jsonb/arel_extensions/table.rb +1 -1
- data/lib/associate_jsonb/arel_extensions/visitors/postgresql.rb +73 -0
- data/lib/associate_jsonb/associations/association_scope.rb +2 -4
- data/lib/associate_jsonb/associations/belongs_to_association.rb +8 -8
- 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/reference_definition.rb +37 -19
- data/lib/associate_jsonb/connection_adapters/schema_creation.rb +63 -0
- data/lib/associate_jsonb/connection_adapters/schema_creation/alter_table.rb +35 -0
- data/lib/associate_jsonb/connection_adapters/schema_statements.rb +13 -0
- data/lib/associate_jsonb/connection_adapters/table_definition.rb +9 -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 +3 -0
- data/lib/associate_jsonb/version.rb +1 -1
- data/lib/associate_jsonb/with_store_attribute.rb +11 -8
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2488f59e2d11f0055e7bf0f619397eb949517e61110d8e5b5a81409231f6f6fe
|
4
|
+
data.tar.gz: dbebbe5383f20bdb95e359210df22161eecf1819d0148bede5e587b4a62b3f7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db5297d3d3557fef9ca21a7aceaebc13788006e3e1597156cfc108308ce902af258435b9c820bad6a9df88735f8f778774ad4fe198e6189067ae223dd0cf4ab4
|
7
|
+
data.tar.gz: 8bf8a3a056de12214579f8ca8a8cf0a471bde370f531abd86da7d239802ccdb673e058484f4998d6fc0aec2082932b07431013cb222361e4af3c696f1bb8dc81
|
data/README.md
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/associate_jsonb)
|
4
4
|
|
5
|
-
|
5
|
+
#### PostgreSQL JSONB extensions including:
|
6
|
+
- Basic ActiveRecord Associations using PostgreSQL JSONB columns, with built-in accessors and column indexes
|
7
|
+
- Thread-Safe JSONB updates (well, as safe as they can be) using `jsonb_set`
|
6
8
|
|
7
9
|
<!-- This gem was created as a solution to this [task](http://cultofmartians.com/tasks/active-record-jsonb-associations.html) from [EvilMartians](http://evilmartians.com).
|
8
10
|
|
data/lib/associate_jsonb.rb
CHANGED
@@ -12,10 +12,16 @@ require "mutex_m"
|
|
12
12
|
|
13
13
|
require "zeitwerk"
|
14
14
|
loader = Zeitwerk::Loader.for_gem
|
15
|
-
loader.inflector.inflect
|
15
|
+
loader.inflector.inflect(
|
16
|
+
"postgresql" => "PostgreSQL",
|
17
|
+
"supported_rails_version" => "SUPPORTED_RAILS_VERSION"
|
18
|
+
)
|
16
19
|
loader.setup # ready!
|
17
20
|
|
18
21
|
module AssociateJsonb
|
22
|
+
mattr_accessor :safe_hash_classes, default: [
|
23
|
+
ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb
|
24
|
+
]
|
19
25
|
end
|
20
26
|
|
21
27
|
|
@@ -25,6 +31,8 @@ ActiveSupport.on_load :active_record do
|
|
25
31
|
|
26
32
|
ActiveRecord::Base.include AssociateJsonb::WithStoreAttribute
|
27
33
|
ActiveRecord::Base.include AssociateJsonb::Associations
|
34
|
+
ActiveRecord::Base.include AssociateJsonb::AttributeMethods
|
35
|
+
ActiveRecord::Base.include AssociateJsonb::Persistence
|
28
36
|
|
29
37
|
Arel::Nodes.include AssociateJsonb::ArelNodes
|
30
38
|
|
@@ -40,6 +48,10 @@ ActiveSupport.on_load :active_record do
|
|
40
48
|
AssociateJsonb::ArelExtensions::Table
|
41
49
|
)
|
42
50
|
|
51
|
+
Arel::Visitors::PostgreSQL.prepend(
|
52
|
+
AssociateJsonb::ArelExtensions::Visitors::PostgreSQL
|
53
|
+
)
|
54
|
+
|
43
55
|
Arel::Visitors::Visitor.singleton_class.prepend(
|
44
56
|
AssociateJsonb::ArelExtensions::Visitors::Visitor
|
45
57
|
)
|
@@ -86,6 +98,7 @@ ActiveSupport.on_load :active_record do
|
|
86
98
|
# )
|
87
99
|
|
88
100
|
ActiveRecord::Reflection::AbstractReflection.prepend AssociateJsonb::Reflection
|
101
|
+
ActiveRecord::PredicateBuilder.prepend AssociateJsonb::PredicateBuilder
|
89
102
|
ActiveRecord::Relation::WhereClause.prepend AssociateJsonb::Relation::WhereClause
|
90
103
|
|
91
104
|
ActiveRecord::ConnectionAdapters::ReferenceDefinition.prepend(
|
@@ -23,7 +23,7 @@ module AssociateJsonb
|
|
23
23
|
def [](name)
|
24
24
|
return super unless store_col = store_tracker&.get(name)
|
25
25
|
|
26
|
-
attr = ::Arel::Nodes::Jsonb::
|
26
|
+
attr = ::Arel::Nodes::Jsonb::DashDoubleArrow.
|
27
27
|
new(self, self[store_col[:store]], store_col[:key])
|
28
28
|
|
29
29
|
if cast_as = (store_col[:cast] && store_col[:cast][:sql_type])
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module AssociateJsonb
|
2
|
+
module ArelExtensions
|
3
|
+
module Visitors
|
4
|
+
module PostgreSQL
|
5
|
+
private
|
6
|
+
def collect_hash_changes(original, updated, nesting = nil)
|
7
|
+
keys = original.keys.map(&:to_s)
|
8
|
+
updated_keys = updated.keys.map(&:to_s)
|
9
|
+
keys |= updated_keys
|
10
|
+
original = original.with_indifferent_access
|
11
|
+
updated = updated.with_indifferent_access
|
12
|
+
added = []
|
13
|
+
deleted = []
|
14
|
+
finished = {}
|
15
|
+
keys.each do |k|
|
16
|
+
if original[k].is_a?(Hash) && updated[k].is_a?(Hash)
|
17
|
+
finished[k], a, d = collect_hash_changes(original[k], updated[k], nesting ? "#{nesting},#{k}" : k)
|
18
|
+
added |= a
|
19
|
+
deleted |= d
|
20
|
+
else
|
21
|
+
if updated[k].nil?
|
22
|
+
deleted << (nesting ? "{#{nesting},#{k}}" : "{#{k}}") if updated_keys.include?(k)
|
23
|
+
elsif original[k] != updated[k]
|
24
|
+
finished[k] = updated[k]
|
25
|
+
added << [(nesting ? "{#{nesting},#{k}}" : "{#{k}}"), updated[k]]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
[ finished, added, deleted ]
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_hash_update?(o, collector)
|
33
|
+
collector &&
|
34
|
+
Array(collector.value).any? {|v| v.is_a?(String) && (v =~ /UPDATE/) } &&
|
35
|
+
AssociateJsonb.safe_hash_classes.any? {|t| o.value.type.is_a?(t) }
|
36
|
+
rescue
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
def visit_Arel_Nodes_BindParam(o, collector)
|
41
|
+
if is_hash_update?(o, collector)
|
42
|
+
value = o.value
|
43
|
+
|
44
|
+
changes, additions, deletions =
|
45
|
+
collect_hash_changes(
|
46
|
+
value.original_value.presence || {},
|
47
|
+
value.value.presence || {}
|
48
|
+
)
|
49
|
+
|
50
|
+
json = +"COALESCE(#{quote_column_name(o.value.name)}, '{}'::jsonb)"
|
51
|
+
|
52
|
+
deletions.each do |del|
|
53
|
+
json = +"(#{json} #- '#{del}')"
|
54
|
+
end
|
55
|
+
|
56
|
+
additions.each do |add, value|
|
57
|
+
collector.add_bind(o.value.with_value_from_user(value)) do |i|
|
58
|
+
json = +"jsonb_set(#{json},'#{add}', $#{i}, true)"
|
59
|
+
''
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
collector << json
|
64
|
+
|
65
|
+
collector
|
66
|
+
else
|
67
|
+
collector.add_bind(o.value) { |i| "$#{i}" }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -44,23 +44,21 @@ module AssociateJsonb
|
|
44
44
|
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
45
45
|
|
46
46
|
def apply_jsonb_equality(scope, table, jsonb_column, store_key, foreign_key, value, foreign_klass)
|
47
|
-
sql_type = type =
|
47
|
+
sql_type = type = nil
|
48
48
|
begin
|
49
49
|
type = foreign_klass.attribute_types[foreign_key.to_s]
|
50
50
|
raise "type not found" unless type.present?
|
51
51
|
sql_type = foreign_klass.columns_hash[foreign_key.to_s]
|
52
52
|
raise "not a column" unless sql_type.present?
|
53
53
|
sql_type = sql_type.sql_type
|
54
|
-
node_klass = Arel::Nodes::Jsonb::DashArrow
|
55
54
|
rescue
|
56
55
|
type = ActiveModel::Type::String.new
|
57
56
|
sql_type = "text"
|
58
|
-
node_klass = Arel::Nodes::Jsonb::DashDoubleArrow
|
59
57
|
end
|
60
58
|
|
61
59
|
scope.where!(
|
62
60
|
Arel::Nodes::SqlCastedEquality.new(
|
63
|
-
|
61
|
+
Arel::Nodes::Jsonb::DashDoubleArrow.new(table, table[jsonb_column], store_key),
|
64
62
|
sql_type,
|
65
63
|
Arel::Nodes::BindParam.new(
|
66
64
|
ActiveRecord::Relation::QueryAttribute.new(
|
@@ -4,14 +4,14 @@
|
|
4
4
|
module AssociateJsonb
|
5
5
|
module Associations
|
6
6
|
module BelongsToAssociation #:nodoc:
|
7
|
-
def replace_keys(record)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
7
|
+
# def replace_keys(record)
|
8
|
+
# return super unless reflection.options.key?(:store)
|
9
|
+
#
|
10
|
+
# owner[reflection.foreign_key] =
|
11
|
+
# record._read_attribute(
|
12
|
+
# reflection.association_primary_key(record.class)
|
13
|
+
# )
|
14
|
+
# end
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AssociateJsonb
|
5
|
+
module AttributeMethods
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
include Read
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def attributes_with_info(attribute_names)
|
14
|
+
attribute_names.each_with_object({}) do |name, attrs|
|
15
|
+
attrs[name] = _fetch_attribute(name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AssociateJsonb
|
5
|
+
module AttributeMethods
|
6
|
+
module Read
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
def _fetch_attribute(attr_name, &block) # :nodoc
|
10
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
11
|
+
@attributes.fetch(attr_name.to_s, &block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -3,18 +3,25 @@
|
|
3
3
|
module AssociateJsonb
|
4
4
|
module ConnectionAdapters
|
5
5
|
module ReferenceDefinition #:nodoc:
|
6
|
+
ForeignKeyDefinition = ActiveRecord::ConnectionAdapters::ForeignKeyDefinition
|
6
7
|
# rubocop:disable Metrics/ParameterLists
|
7
8
|
def initialize(
|
8
9
|
name,
|
9
10
|
store: false,
|
11
|
+
store_key: false,
|
10
12
|
**options
|
11
13
|
)
|
12
14
|
@store = store && store.to_sym
|
15
|
+
@store_key = store_key && store_key.to_s unless options[:polymorphic]
|
13
16
|
|
14
17
|
super(name, **options)
|
15
18
|
end
|
16
19
|
# rubocop:enable Metrics/ParameterLists
|
17
20
|
|
21
|
+
def column_name
|
22
|
+
store_key || super
|
23
|
+
end
|
24
|
+
|
18
25
|
def add_to(table)
|
19
26
|
return super unless store
|
20
27
|
|
@@ -25,40 +32,51 @@ module AssociateJsonb
|
|
25
32
|
should_add_col = table.columns.none? {|col| col.name.to_sym == store}
|
26
33
|
end
|
27
34
|
|
28
|
-
|
35
|
+
if should_add_col
|
36
|
+
opts = { null: false, default: {} }
|
37
|
+
table.column(store, :jsonb, **opts)
|
38
|
+
end
|
39
|
+
|
40
|
+
if foreign_key && column_names.length == 1
|
41
|
+
fk = ForeignKeyDefinition.new(table.name, foreign_table_name, foreign_key_options)
|
42
|
+
columns.each do |col_name, type, _|
|
43
|
+
value = <<-SQL.squish
|
44
|
+
jsonb_foreign_key(
|
45
|
+
'#{fk.to_table}',
|
46
|
+
'#{fk.active_record_primary_key}',
|
47
|
+
#{store},
|
48
|
+
'#{col_name}',
|
49
|
+
'#{type}'
|
50
|
+
)
|
51
|
+
SQL
|
52
|
+
table.constraint({
|
53
|
+
name: "#{table.name}_#{col_name}_foreign_key",
|
54
|
+
value: value
|
55
|
+
})
|
56
|
+
end
|
57
|
+
end
|
29
58
|
|
30
59
|
return unless index
|
31
60
|
|
32
|
-
|
33
|
-
|
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|
|
61
|
+
columns.each do |col_name, type, opts|
|
62
|
+
type = :text if type == :string
|
45
63
|
table.index(
|
46
|
-
"CAST (\"#{store}\"
|
64
|
+
"CAST (\"#{store}\"->>'#{col_name}' AS #{type || :bigint})",
|
47
65
|
using: :btree,
|
48
|
-
name: "index_#{table.name}_on_#{store}_#{
|
66
|
+
name: "index_#{table.name}_on_#{store}_#{col_name}"
|
49
67
|
)
|
50
68
|
|
51
69
|
table.index(
|
52
|
-
"(#{store}->>'#{
|
70
|
+
"(\"#{store}\"->>'#{col_name}')",
|
53
71
|
using: :btree,
|
54
|
-
name: "index_#{table.name}_on_#{store}_#{
|
72
|
+
name: "index_#{table.name}_on_#{store}_#{col_name}_text"
|
55
73
|
)
|
56
74
|
end
|
57
75
|
end
|
58
76
|
|
59
77
|
protected
|
60
78
|
|
61
|
-
attr_reader :store
|
79
|
+
attr_reader :store, :store_key
|
62
80
|
end
|
63
81
|
end
|
64
82
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AssociateJsonb
|
4
|
+
module ConnectionAdapters
|
5
|
+
module SchemaCreation
|
6
|
+
private
|
7
|
+
def visit_AlterTable(o)
|
8
|
+
sql = super
|
9
|
+
sql << o.constraint_adds.map {|ct| visit_AddConstraint ct }.join(" ")
|
10
|
+
sql << o.constraint_drops.map {|ct| visit_DropConstraint ct }.join(" ")
|
11
|
+
add_jsonb_function(o, sql)
|
12
|
+
end
|
13
|
+
|
14
|
+
def visit_TableDefinition(...)
|
15
|
+
add_jsonb_function(o, super(...))
|
16
|
+
end
|
17
|
+
|
18
|
+
def visit_ColumnDefinition(o)
|
19
|
+
column_sql = super
|
20
|
+
add_column_constraint!(o, column_sql, column_options(o))
|
21
|
+
column_sql
|
22
|
+
end
|
23
|
+
|
24
|
+
def visit_ConstraintDefinition(o)
|
25
|
+
+<<-SQL.squish
|
26
|
+
CONSTRAINT #{o.name} CHECK (#{o.value})
|
27
|
+
SQL
|
28
|
+
end
|
29
|
+
|
30
|
+
def visit_AddConstraint(o)
|
31
|
+
"ADD #{accept(o)}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def visit_DropConstraint(o)
|
35
|
+
"DROP CONSTRAINT #{o.name}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_column_constraint!(o, sql, options)
|
39
|
+
if options[:constraint]
|
40
|
+
name = value = nil
|
41
|
+
if options[:constraint].is_a?(Hash)
|
42
|
+
name = quote_column_name(options[:constraint][:name]).presence
|
43
|
+
value = options[:constraint][:value]
|
44
|
+
else
|
45
|
+
value = options[:constraint]
|
46
|
+
end
|
47
|
+
name ||= quote_column_name("#{o.name}_constraint_#{value.hash}")
|
48
|
+
sql << " CONSTRAINT #{name} CHECK (#{value})"
|
49
|
+
end
|
50
|
+
|
51
|
+
sql
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_jsonb_function(o, sql)
|
55
|
+
if sql =~ /jsonb_foreign_key/
|
56
|
+
visit_AddJsonForeignKeyFunction(o) + sql
|
57
|
+
else
|
58
|
+
sql
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AssociateJsonb
|
4
|
+
module ConnectionAdapters
|
5
|
+
module SchemaCreation
|
6
|
+
class AlterTable # :nodoc:
|
7
|
+
attr_reader :constraint_adds
|
8
|
+
attr_reader :constraint_drops
|
9
|
+
|
10
|
+
def initialize(td)
|
11
|
+
super
|
12
|
+
@constraint_adds = []
|
13
|
+
@constraint_drops = []
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def add_foreign_key(to_table, options)
|
18
|
+
@foreign_key_adds << ForeignKeyDefinition.new(name, to_table, options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def drop_foreign_key(name)
|
22
|
+
@foreign_key_drops << name
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_constraint(options)
|
26
|
+
@foreign_key_adds << ConstraintDefinition.new(name, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def drop_constraint(options)
|
30
|
+
@constraint_drops << ConstraintDefinition.new(name, options)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/migration/join_table"
|
4
|
+
require "active_support/core_ext/string/access"
|
5
|
+
require "active_support/deprecation"
|
6
|
+
require "digest/sha2"
|
7
|
+
|
8
|
+
module AssociateJsonb
|
9
|
+
module ConnectionAdapters
|
10
|
+
module SchemaStatements
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AssociateJsonb
|
5
|
+
module Persistence
|
6
|
+
private
|
7
|
+
def _update_row(attribute_names, attempted_action = "update")
|
8
|
+
self.class._update_record(
|
9
|
+
attributes_with_info(attribute_names),
|
10
|
+
@primary_key => id_in_database
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AssociateJsonb
|
5
|
+
module PredicateBuilder # :nodoc:
|
6
|
+
def build_bind_attribute(column_name, value)
|
7
|
+
if value.respond_to?(:value_before_type_cast)
|
8
|
+
attr = ActiveRecord::Relation::QueryAttribute.new(column_name.to_s, value.value_before_type_cast, table.type(column_name), value)
|
9
|
+
else
|
10
|
+
attr = ActiveRecord::Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name))
|
11
|
+
end
|
12
|
+
Arel::Nodes::BindParam.new(attr)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -60,7 +60,7 @@ module AssociateJsonb
|
|
60
60
|
Arel::Nodes::NamedFunction.new(
|
61
61
|
"CAST",
|
62
62
|
[
|
63
|
-
Arel::Nodes::Jsonb::
|
63
|
+
Arel::Nodes::Jsonb::DashDoubleArrow.
|
64
64
|
new(table, table[foreign_store_attr], foreign_store_key || key).
|
65
65
|
as(foreign_klass.columns_hash[foreign_key.to_s].sql_type)
|
66
66
|
]
|
@@ -83,7 +83,7 @@ module AssociateJsonb
|
|
83
83
|
Arel::Nodes::NamedFunction.new(
|
84
84
|
"CAST",
|
85
85
|
[
|
86
|
-
Arel::Nodes::Jsonb::
|
86
|
+
Arel::Nodes::Jsonb::DashDoubleArrow.
|
87
87
|
new(foreign_table, foreign_table[jsonb_store_attr], jsonb_store_key || foreign_key).
|
88
88
|
as(klass.columns_hash[key.to_s].sql_type)
|
89
89
|
]
|
@@ -140,20 +140,23 @@ module AssociateJsonb
|
|
140
140
|
|
141
141
|
mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
142
142
|
def #{store}=(given)
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
143
|
+
if !given
|
144
|
+
given = {}
|
145
|
+
#{store}.keys.each do |k|
|
146
|
+
given[k] = nil
|
147
|
+
end
|
148
|
+
end
|
149
|
+
super(#{store}.deep_merge(given.deep_stringify_keys))
|
150
|
+
if #{store}.key?("#{key}")
|
151
|
+
write_attribute(:#{attribute}, #{on_store_change.call %Q(#{store}["#{key}"])})
|
152
|
+
#{store}["#{key}"] = #{attribute}.presence
|
149
153
|
end
|
150
154
|
#{store}
|
151
155
|
end
|
152
156
|
|
153
157
|
def #{attribute}=(given)
|
154
158
|
#{on_attr_change}
|
155
|
-
value = #{store}["#{key}"] = #{attribute}
|
156
|
-
#{store}.delete("#{key}") if value.nil?
|
159
|
+
value = #{store}["#{key}"] = #{attribute}.presence
|
157
160
|
_write_attribute(:#{store}, #{store})
|
158
161
|
value
|
159
162
|
end
|
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.5
|
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-07-
|
11
|
+
date: 2020-07-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -125,6 +125,7 @@ files:
|
|
125
125
|
- lib/associate_jsonb/arel_extensions/nodes/binary.rb
|
126
126
|
- lib/associate_jsonb/arel_extensions/nodes/table_alias.rb
|
127
127
|
- lib/associate_jsonb/arel_extensions/table.rb
|
128
|
+
- lib/associate_jsonb/arel_extensions/visitors/postgresql.rb
|
128
129
|
- lib/associate_jsonb/arel_extensions/visitors/visitor.rb
|
129
130
|
- lib/associate_jsonb/arel_nodes/jsonb/at_arrow.rb
|
130
131
|
- lib/associate_jsonb/arel_nodes/jsonb/attribute.rb
|
@@ -147,8 +148,16 @@ files:
|
|
147
148
|
- lib/associate_jsonb/associations/has_many_association.rb
|
148
149
|
- lib/associate_jsonb/associations/join_dependency.rb
|
149
150
|
- lib/associate_jsonb/associations/preloader/association.rb
|
151
|
+
- lib/associate_jsonb/attribute_methods.rb
|
152
|
+
- lib/associate_jsonb/attribute_methods/read.rb
|
150
153
|
- lib/associate_jsonb/connection_adapters.rb
|
151
154
|
- lib/associate_jsonb/connection_adapters/reference_definition.rb
|
155
|
+
- lib/associate_jsonb/connection_adapters/schema_creation.rb
|
156
|
+
- lib/associate_jsonb/connection_adapters/schema_creation/alter_table.rb
|
157
|
+
- lib/associate_jsonb/connection_adapters/schema_statements.rb
|
158
|
+
- lib/associate_jsonb/connection_adapters/table_definition.rb
|
159
|
+
- lib/associate_jsonb/persistence.rb
|
160
|
+
- lib/associate_jsonb/predicate_builder.rb
|
152
161
|
- lib/associate_jsonb/reflection.rb
|
153
162
|
- lib/associate_jsonb/relation/where_clause.rb
|
154
163
|
- lib/associate_jsonb/supported_rails_version.rb
|