associate_jsonb 0.0.10 → 6.1.4.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 847b6c8d5410dca5511a9ab2537ea3d2d9ba5c40e681ad42a63f0e752604d1ff
4
- data.tar.gz: 935adff8c21a94b4d7593a236c9e56eec29c31340a897c82851b3662b0da880e
3
+ metadata.gz: f26470e30b277fe8ef0189ca4bef7eacf8cf7d4fa22008a879f5c1b187f9c476
4
+ data.tar.gz: 28ca2bd98358795e4e9d6a59e14738536e7a2696e0b4eacb11612e5bc33840a6
5
5
  SHA512:
6
- metadata.gz: c614936df446af3b0bd1301037954214e973cc4522637c3578f47f775065eb9085f08b668b11bf619ba3ca7968b14c078e192579be56eee489d5bf0780097552
7
- data.tar.gz: 5243289a848da4cc15d03204a6d5bc6a502d810e6f839fb2b26aabc264bea63553b040a8508cf6f6d0722d82be5ea905c9bb75caa5e9ac1038b2e9d85e535122
6
+ metadata.gz: 6475d5e18d9c67d1b4b13a4770640ba79031357317dd185d77b8c959b8fdf1f59b52d6ee12fe1bed2e18652ed36747ce22c33af390bd63a3dbb87249c81479d2
7
+ data.tar.gz: 300b6fb1c2385bab73823765ee42d27e2b0a047efcf10b58727ad5e2973672910ca07a57ae76b64ff4ab32f006bf934d6376ddd975b9380600404d6264860955
@@ -1,28 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
- # module AssociateJsonb
5
- # module ArelNodes
6
- # class SqlCastedEquality < ::Arel::Nodes::Equality
7
- # attr_reader :original_left
8
- # def initialize(left, cast_as, right)
9
- # @original_left = left
10
- # super(
11
- # ::Arel::Nodes::NamedFunction.new(
12
- # "CAST",
13
- # [ left.as(cast_as) ]
14
- # ),
15
- # right
16
- # )
17
- # end
18
- # end
19
- # end
20
- # end
21
-
22
-
23
- # encoding: utf-8
24
- # frozen_string_literal: true
25
-
26
4
  module AssociateJsonb
27
5
  module ArelNodes
28
6
  class SqlCastedEquality < AssociateJsonb::ArelNodes::SqlCastedBinary
@@ -5,8 +5,8 @@ require "active_support/core_ext/string/conversions"
5
5
  module AssociateJsonb
6
6
  module Associations
7
7
  module AliasTracker # :nodoc:
8
- def aliased_table_for(table_name, aliased_name, type_caster, store_tracker = nil)
9
- super(table_name, aliased_name, type_caster).with_store_tracker(store_tracker)
8
+ def aliased_table_for(arel_table, table_name = nil, store_tracker: nil)
9
+ super(arel_table, table_name).with_store_tracker(store_tracker)
10
10
  end
11
11
  end
12
12
  end
@@ -12,28 +12,14 @@ module AssociateJsonb
12
12
  assigned_keys = record.changed_attribute_names_to_save
13
13
  assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
14
14
  attributes = scope_for_create.except!(*(assigned_keys - skip_assign))
15
+
15
16
  if attributes.key?(reflection.foreign_store_key.to_s)
16
- v = attributes.delete(reflection.foreign_store_key.to_s)
17
- attributes[reflection.foreign_key.to_s] = v
17
+ attributes[reflection.foreign_key.to_s] = attributes.delete(reflection.foreign_store_key.to_s)
18
18
  end
19
+
19
20
  record.send(:_assign_attributes, attributes) if attributes.any?
20
21
  set_inverse_instance(record)
21
22
  end
22
-
23
- private
24
- def creation_attributes
25
- return super if reflection.belongs_to?
26
- return super unless reflection.foreign_store?
27
-
28
- attributes = {}
29
-
30
- jsonb_store = reflection.foreign_store_attr
31
- attributes[jsonb_store] ||= {}
32
- attributes[jsonb_store][reflection.foreign_store_key] =
33
- owner[reflection.active_record_primary_key]
34
-
35
- attributes
36
- end
37
23
  end
38
24
  end
39
25
  end
@@ -4,17 +4,13 @@
4
4
  module AssociateJsonb
5
5
  module Associations
6
6
  module AssociationScope #:nodoc:
7
-
8
7
  def get_chain(reflection, association, tracker)
9
8
  name = reflection.name
10
9
  chain = [ActiveRecord::Reflection::RuntimeReflection.new(reflection, association)]
11
10
  reflection.chain.drop(1).each do |refl|
12
- aliased_table = tracker.aliased_table_for(
13
- refl.table_name,
14
- refl.alias_candidate(name),
15
- refl.klass.type_caster,
16
- refl.klass.store_column_attribute_tracker
17
- )
11
+ aliased_table = tracker.aliased_table_for(refl.klass.arel_table, store_tracker: refl.klass.store_column_attribute_tracker) do
12
+ refl.alias_candidate(name)
13
+ end
18
14
  chain << ActiveRecord::Associations::AssociationScope::ReflectionProxy.new(refl, aliased_table)
19
15
  end
20
16
  chain
@@ -25,18 +21,19 @@ module AssociateJsonb
25
21
  reflection = owner_reflection.instance_variable_get(:@reflection)
26
22
  return super unless reflection&.foreign_store?
27
23
 
24
+ primary_key = reflection.join_primary_key
25
+ foreign_key = reflection.join_foreign_key
26
+ store_key = reflection.foreign_store_key || primary_key
28
27
 
29
- join_keys = owner_reflection.join_keys
30
28
  table = owner_reflection.aliased_table
31
- key = reflection.foreign_store_key || join_keys.key
32
- value = transform_value(owner[join_keys.foreign_key])
29
+ value = transform_value(owner[foreign_key])
33
30
 
34
31
  apply_jsonb_equality(
35
32
  scope,
36
33
  table,
37
34
  reflection.foreign_store_attr,
38
- key.to_s,
39
- join_keys.foreign_key,
35
+ store_key.to_s,
36
+ owner_reflection.join_foreign_key,
40
37
  value,
41
38
  reflection.active_record
42
39
  )
@@ -5,6 +5,29 @@ module AssociateJsonb
5
5
  module Associations
6
6
  module Builder
7
7
  module BelongsTo #:nodoc:
8
+ # Maybe convert to builder callbacks here in next iteration
9
+ # def define_callbacks(model, reflection)
10
+ # super
11
+ # add_after_jsonb_initialize_callbacks(model, reflection) if reflection.jsonb_store?
12
+ # add_after_foreign_store_initialize_callbacks(model, reflection) if reflection.foreign_store?
13
+ # end
14
+ #
15
+ # def add_after_jsonb_initialize_callbacks(model, reflection)
16
+ # model.after_initialize lambda {|record|
17
+ # association = association(reflection.name)
18
+ # p model, reflection.join_primary_key, reflection.join_foreign_key, reflection.options
19
+ # p record.attributes
20
+ # # record.attributes._write_attribute()
21
+ # }
22
+ # end
23
+ #
24
+ # def add_after_foreign_store_initialize_callbacks(model, reflection)
25
+ # model.after_initialize lambda {|record|
26
+ # association = association(reflection.name)
27
+ # # record.attributes._write_attribute()
28
+ # }
29
+ # end
30
+
8
31
  def valid_options(options)
9
32
  super + %i[ store store_key ]
10
33
  end
@@ -18,7 +41,7 @@ module AssociateJsonb
18
41
  end
19
42
 
20
43
  def add_association_accessor_methods(mixin, reflection)
21
- foreign_key = reflection.foreign_key.to_s
44
+ foreign_key = reflection.join_foreign_key.to_s
22
45
  key = (reflection.jsonb_store_key || foreign_key).to_s
23
46
  store = reflection.jsonb_store_attr
24
47
 
@@ -35,8 +58,8 @@ module AssociateJsonb
35
58
  foreign_type = :integer
36
59
  sql_type = "numeric"
37
60
  begin
38
- primary_key = reflection.active_record_primary_key.to_s
39
- primary_column = reflection.klass.columns.find {|col| col.name == primary_key }
61
+ primary_key = reflection.join_primary_key.to_s
62
+ primary_column = reflection.klass.columns_hash[primary_key]
40
63
 
41
64
  if primary_column
42
65
  foreign_type = primary_column.type
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module AssociateJsonb
5
+ module Associations
6
+ module ForeignAssociation # :nodoc:
7
+ private
8
+ # Sets the owner attributes on the given record
9
+ def set_owner_attributes(record)
10
+ return if options[:through]
11
+ return super unless reflection.foreign_store?
12
+
13
+ jsonb_store = reflection.foreign_store_attr.to_s
14
+ value = record._read_attribute(jsonb_store).presence || {}
15
+ fk_value = owner._read_attribute(reflection.join_foreign_key)
16
+ value[reflection.foreign_store_key] = fk_value
17
+
18
+ record._write_attribute(reflection.join_primary_key, fk_value)
19
+ record._write_attribute(jsonb_store, value)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -6,15 +6,28 @@ module AssociateJsonb
6
6
  module Associations
7
7
  module JoinDependency # :nodoc:
8
8
  private
9
- def table_aliases_for(parent, node)
10
- node.reflection.chain.map { |reflection|
11
- alias_tracker.aliased_table_for(
12
- reflection.table_name,
13
- table_alias_for(reflection, parent, reflection != node.reflection),
14
- reflection.klass.type_caster,
15
- reflection.klass.store_column_attribute_tracker
16
- )
17
- }
9
+ def make_constraints(parent, child, join_type)
10
+ foreign_table = parent.table
11
+ foreign_klass = parent.base_klass
12
+ child.join_constraints(foreign_table, foreign_klass, join_type, alias_tracker) do |reflection|
13
+ table, terminated = @joined_tables[reflection]
14
+ root = reflection == child.reflection
15
+
16
+ if table && (!root || !terminated)
17
+ @joined_tables[reflection] = [table, root] if root
18
+ next table, true
19
+ end
20
+
21
+ table_name = @references[reflection.name.to_sym]&.to_s
22
+
23
+ table = alias_tracker.aliased_table_for(reflection.klass.arel_table, table_name, store_tracker: reflection.klass.store_column_attribute_tracker) do
24
+ name = reflection.alias_candidate(parent.table_name)
25
+ root ? name : "#{name}_join"
26
+ end
27
+
28
+ @joined_tables[reflection] ||= [table, root] if join_type == Arel::Nodes::OuterJoin
29
+ table
30
+ end.concat child.children.flat_map { |c| make_constraints(child, c, join_type) }
18
31
  end
19
32
  end
20
33
  end
@@ -18,6 +18,30 @@ module AssociateJsonb
18
18
  ).intersects_with(ids)
19
19
  )
20
20
  end
21
+
22
+ private
23
+ def load_records
24
+ return super unless reflection.foreign_store?
25
+ # owners can be duplicated when a relation has a collection association join
26
+ # #compare_by_identity makes such owners different hash keys
27
+ @records_by_owner = {}.compare_by_identity
28
+ raw_records = owner_keys.empty? ? [] : records_for(owner_keys)
29
+
30
+ @preloaded_records = raw_records.select do |record|
31
+ assignments = false
32
+
33
+ owners_by_key[convert_key(record[association_key_name])].each do |owner|
34
+ entries = (@records_by_owner[owner] ||= [])
35
+
36
+ if reflection.collection? || entries.empty?
37
+ entries << record
38
+ assignments = true
39
+ end
40
+ end
41
+
42
+ assignments
43
+ end
44
+ end
21
45
  end
22
46
  end
23
47
  end
@@ -11,8 +11,8 @@ module AssociateJsonb
11
11
 
12
12
  private
13
13
  def attributes_with_info(attribute_names)
14
- attribute_names.each_with_object({}) do |name, attrs|
15
- attrs[name] = _fetch_attribute(name)
14
+ attribute_names.index_with do |name|
15
+ _fetch_attribute(name)
16
16
  end
17
17
  end
18
18
  end
@@ -30,7 +30,7 @@ module AssociateJsonb
30
30
  end
31
31
 
32
32
  create_sql << "(#{statements.join(', ')})" if statements.present?
33
- add_table_options!(create_sql, table_options(o))
33
+ add_table_options!(create_sql, o)
34
34
  create_sql << " AS #{to_sql(o.as)}" if o.as
35
35
  create_sql
36
36
  end
@@ -12,38 +12,43 @@ module AssociateJsonb
12
12
  execute schema_creation.accept(AddJsonbForeignKeyFunction.new)
13
13
  end
14
14
 
15
- def create_table(table_name, **options)
16
- td = create_table_definition(table_name, **options)
15
+ def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options)
16
+ td = create_table_definition(table_name, **extract_table_options!(options))
17
17
 
18
- if options[:id] != false && !options[:as]
19
- pk = options.fetch(:primary_key) do
20
- ActiveRecord::Base.get_primary_key table_name.to_s.singularize
18
+ if id && !td.as
19
+ pk = primary_key || ActiveRecord::Base.get_primary_key(table_name.to_s.singularize)
20
+
21
+ if id.is_a?(Hash)
22
+ options.merge!(id.except(:type))
23
+ id = id.fetch(:type, :primary_key)
21
24
  end
22
25
 
23
26
  if pk.is_a?(Array)
24
27
  td.primary_keys pk
25
28
  else
26
- td.primary_key pk, options.fetch(:id, :primary_key), **options.except(:comment)
29
+ td.primary_key pk, id, **options
27
30
  end
28
31
  end
29
32
 
30
33
  yield td if block_given?
31
34
 
32
- if options[:force]
33
- drop_table(table_name, **options, if_exists: true)
35
+ if force
36
+ drop_table(table_name, force: force, if_exists: true)
37
+ else
38
+ schema_cache.clear_data_source_cache!(table_name.to_s)
34
39
  end
35
40
 
36
41
  result = execute schema_creation.accept td
37
42
 
38
43
  td.indexes.each do |column_name, index_options|
39
- add_index(table_name, column_name, index_options)
44
+ add_index(table_name, column_name, **index_options, if_not_exists: td.if_not_exists)
40
45
  end
41
46
 
42
47
  td.constraints.each do |ct|
43
48
  add_constraint(table_name, **ct)
44
49
  end
45
50
 
46
- if table_comment = options[:comment].presence
51
+ if table_comment = td.comment.presence
47
52
  change_table_comment(table_name, table_comment)
48
53
  end
49
54
 
@@ -18,7 +18,7 @@ module AssociateJsonb
18
18
  end
19
19
 
20
20
  def jsonb_store_key
21
- options[:store_key].presence || join_keys.foreign_key
21
+ options[:store_key].presence || join_foreign_key
22
22
  end
23
23
 
24
24
  def foreign_store?
@@ -36,7 +36,7 @@ module AssociateJsonb
36
36
  end
37
37
 
38
38
  def foreign_store_key
39
- options[:foreign_store_key].presence || join_keys.key
39
+ options[:foreign_store_key].presence || join_primary_key
40
40
  end
41
41
 
42
42
  def join_scope(table, foreign_table, foreign_klass)
@@ -52,8 +52,8 @@ module AssociateJsonb
52
52
 
53
53
  scope_chain_items.inject(klass_scope, &:merge!)
54
54
 
55
- key = join_keys.key
56
- foreign_key = join_keys.foreign_key
55
+ key = join_primary_key
56
+ foreign_key = join_foreign_key
57
57
 
58
58
  if foreign_store?
59
59
  klass_scope.where!(
@@ -4,36 +4,14 @@
4
4
  module AssociateJsonb
5
5
  module Relation
6
6
  module WhereClause
7
- def to_h(table_name = nil)
8
- equalities = equalities(predicates)
9
- if table_name
10
- equalities = equalities.select do |node|
11
- node.original_left.relation.name == table_name
12
- end
13
- end
14
-
15
- equalities.map { |node|
7
+ def to_h(table_name = nil, equality_only: false)
8
+ equalities(predicates, equality_only).each_with_object({}) do |node, hash|
9
+ next if table_name&.!= node.original_left.relation.name
16
10
  name = node.original_left.name.to_s
17
11
  value = extract_node_value(node.right)
18
- [name, value]
19
- }.to_h
20
- end
21
-
22
- private
23
- def equalities(predicates)
24
- equalities = []
25
-
26
- predicates.each do |node|
27
- case node
28
- when Arel::Nodes::Equality, Arel::Nodes::SqlCastedEquality
29
- equalities << node
30
- when Arel::Nodes::And
31
- equalities.concat equalities(node.children)
32
- end
33
- end
34
-
35
- equalities
12
+ hash[name] = value
36
13
  end
14
+ end
37
15
  end
38
16
  end
39
17
  end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module AssociateJsonb
5
- SUPPORTED_RAILS_VERSION = "6.0.3.2"
5
+ SUPPORTED_RAILS_VERSION = "6.1.4.1"
6
6
  end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module AssociateJsonb
5
- VERSION = "0.0.10"
5
+ VERSION = "6.1.4.1.1"
6
6
  end
@@ -99,15 +99,15 @@ module AssociateJsonb
99
99
  end
100
100
 
101
101
  def store_column_attribute(store, attr, cast_type = ActiveRecord::Type::Value.new, sql_type: nil, key: nil, **attribute_opts)
102
- store = store.to_sym
103
- attr = attr.to_sym
102
+ store = store.to_s
103
+ attr = attr.to_s
104
104
  key ||= attr
105
105
  key = key.to_s
106
106
  array = attribute_opts[:array]
107
107
  attribute attr, cast_type, **attribute_opts
108
108
 
109
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 })
110
+ add_store_column_attribute_name(attr, store, key, { sql_type: sql_type, type: cast_type, opts: attribute_opts })
111
111
  CODE
112
112
 
113
113
  include WithStoreAttribute::InstanceMethodsOnActivation.new(self, store, attr, key, array)
@@ -120,9 +120,9 @@ module AssociateJsonb
120
120
 
121
121
  array_or_attr = ->(value) {
122
122
  is_array \
123
- ? %Q(Array(#{value})) \
124
- : %Q(#{value})
125
- }
123
+ ? %Q(Array(#{value})) \
124
+ : %Q(#{value})
125
+ }
126
126
 
127
127
  on_store_change = "_write_attribute(:#{attribute}, #{array_or_attr.call %Q(#{store}["#{key}"])})"
128
128
  on_attr_change = "super(#{array_or_attr.call %Q(given)})"
@@ -36,7 +36,7 @@ module AssociateJsonb
36
36
  ##
37
37
  # Enables the use of `jsonb_nested_set` for hash updates
38
38
  #
39
- # if passed a class, or a list of classes, those classes will be added todo
39
+ # if passed a class, or a list of classes, those classes will be added to
40
40
  # the enabled classes. if no argument is given, and the enabled class list is
41
41
  # empty, `ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb` is added
42
42
  # to the list of enabled classes
@@ -187,6 +187,10 @@ ActiveSupport.on_load :active_record do
187
187
  AssociateJsonb::Associations::Preloader::Association
188
188
  )
189
189
 
190
+ ActiveRecord::Associations::ForeignAssociation.prepend(
191
+ AssociateJsonb::Associations::ForeignAssociation
192
+ )
193
+
190
194
  %i[
191
195
  AlterTable
192
196
  ConstraintDefinition
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.10
4
+ version: 6.1.4.1.1
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-09-24 00:00:00.000000000 Z
11
+ date: 2021-09-19 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: 6.0.3
19
+ version: 6.1.4
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 6.0.3.2
22
+ version: 6.1.4.1
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: 6.0.3
29
+ version: 6.1.4
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 6.0.3.2
32
+ version: 6.1.4.1
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: pg
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -149,6 +149,7 @@ files:
149
149
  - lib/associate_jsonb/associations/builder/has_many.rb
150
150
  - lib/associate_jsonb/associations/builder/has_one.rb
151
151
  - lib/associate_jsonb/associations/conflicting_association.rb
152
+ - lib/associate_jsonb/associations/foreign_association.rb
152
153
  - lib/associate_jsonb/associations/has_many_association.rb
153
154
  - lib/associate_jsonb/associations/join_dependency.rb
154
155
  - lib/associate_jsonb/associations/preloader/association.rb
@@ -190,7 +191,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
191
  - !ruby/object:Gem::Version
191
192
  version: '0'
192
193
  requirements: []
193
- rubygems_version: 3.1.4
194
+ rubygems_version: 3.1.6
194
195
  signing_key:
195
196
  specification_version: 4
196
197
  summary: Store database references in PostgreSQL Jsonb columns