composite_primary_keys 14.0.1 → 14.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,68 +1,68 @@
1
- module ActiveRecord
2
- module Associations
3
- class Preloader
4
- class Association
5
-
6
- class LoaderQuery
7
- def load_records_for_keys(keys, &block)
8
- # CPK
9
- if association_key_name.is_a?(Array)
10
- predicate = cpk_in_predicate(scope.klass.arel_table, association_key_name, keys)
11
- scope.where(predicate).load(&block)
12
- else
13
- scope.where(association_key_name => keys).load(&block)
14
- end
15
- end
16
- end
17
-
18
- # TODO: is records_for needed anymore? Rails' implementation has changed significantly
19
- def records_for(ids)
20
- records = if association_key_name.is_a?(Array)
21
- predicate = cpk_in_predicate(klass.arel_table, association_key_name, ids)
22
- scope.where(predicate)
23
- else
24
- scope.where(association_key_name => ids)
25
- end
26
- records.load do |record|
27
- # Processing only the first owner
28
- # because the record is modified but not an owner
29
- owner = owners_by_key[convert_key(record[association_key_name])].first
30
- association = owner.association(reflection.name)
31
- association.set_inverse_instance(record)
32
- end
33
- end
34
-
35
- def owners_by_key
36
- @owners_by_key ||= owners.each_with_object({}) do |owner, result|
37
- # CPK
38
- # key = convert_key(owner[owner_key_name])
39
- key = if owner_key_name.is_a?(Array)
40
- Array(owner_key_name).map do |key_name|
41
- convert_key(owner[key_name])
42
- end
43
- else
44
- convert_key(owner[owner_key_name])
45
- end
46
- (result[key] ||= []) << owner if key
47
- end
48
- end
49
-
50
- # TODO: is records_by_owner needed anymore? Rails' implementation has changed significantly
51
- def records_by_owner
52
- @records_by_owner ||= preloaded_records.each_with_object({}) do |record, result|
53
- key = if association_key_name.is_a?(Array)
54
- Array(record[association_key_name]).map do |key|
55
- convert_key(key)
56
- end
57
- else
58
- convert_key(record[association_key_name])
59
- end
60
- owners_by_key[key].each do |owner|
61
- (result[owner] ||= []) << record
62
- end
63
- end
64
- end
65
- end
66
- end
67
- end
68
- end
1
+ module ActiveRecord
2
+ module Associations
3
+ class Preloader
4
+ class Association
5
+
6
+ class LoaderQuery
7
+ def load_records_for_keys(keys, &block)
8
+ # CPK
9
+ if association_key_name.is_a?(Array)
10
+ predicate = cpk_in_predicate(scope.klass.arel_table, association_key_name, keys)
11
+ scope.where(predicate).load(&block)
12
+ else
13
+ scope.where(association_key_name => keys).load(&block)
14
+ end
15
+ end
16
+ end
17
+
18
+ # TODO: is records_for needed anymore? Rails' implementation has changed significantly
19
+ def records_for(ids)
20
+ records = if association_key_name.is_a?(Array)
21
+ predicate = cpk_in_predicate(klass.arel_table, association_key_name, ids)
22
+ scope.where(predicate)
23
+ else
24
+ scope.where(association_key_name => ids)
25
+ end
26
+ records.load do |record|
27
+ # Processing only the first owner
28
+ # because the record is modified but not an owner
29
+ owner = owners_by_key[convert_key(record[association_key_name])].first
30
+ association = owner.association(reflection.name)
31
+ association.set_inverse_instance(record)
32
+ end
33
+ end
34
+
35
+ def owners_by_key
36
+ @owners_by_key ||= owners.each_with_object({}) do |owner, result|
37
+ # CPK
38
+ # key = convert_key(owner[owner_key_name])
39
+ key = if owner_key_name.is_a?(Array)
40
+ Array(owner_key_name).map do |key_name|
41
+ convert_key(owner[key_name])
42
+ end
43
+ else
44
+ convert_key(owner[owner_key_name])
45
+ end
46
+ (result[key] ||= []) << owner if key
47
+ end
48
+ end
49
+
50
+ # TODO: is records_by_owner needed anymore? Rails' implementation has changed significantly
51
+ def records_by_owner
52
+ @records_by_owner ||= preloaded_records.each_with_object({}) do |record, result|
53
+ key = if association_key_name.is_a?(Array)
54
+ Array(record[association_key_name]).map do |key|
55
+ convert_key(key)
56
+ end
57
+ else
58
+ convert_key(record[association_key_name])
59
+ end
60
+ owners_by_key[key].each do |owner|
61
+ (result[owner] ||= []) << record
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,71 +1,71 @@
1
- module CompositePrimaryKeys
2
- module Predicates
3
- # Similar to module_function, but does not make instance methods private.
4
- # https://idiosyncratic-ruby.com/8-self-improvement.html
5
- extend self
6
-
7
- def cpk_and_predicate(predicates)
8
- if predicates.length == 1
9
- predicates.first
10
- else
11
- Arel::Nodes::And.new(predicates)
12
- end
13
- end
14
-
15
- def cpk_or_predicate(predicates, group = true)
16
- if predicates.length <= 1
17
- predicates.first
18
- else
19
- split_point = predicates.length / 2
20
- predicates_first_half = predicates[0...split_point]
21
- predicates_second_half = predicates[split_point..-1]
22
-
23
- or_predicate = ::Arel::Nodes::Or.new(cpk_or_predicate(predicates_first_half, false),
24
- cpk_or_predicate(predicates_second_half, false))
25
-
26
- if group
27
- ::Arel::Nodes::Grouping.new(or_predicate)
28
- else
29
- or_predicate
30
- end
31
- end
32
- end
33
-
34
- def cpk_id_predicate(table, keys, values)
35
- # We zip on values then keys in case values are not provided for each key field
36
- eq_predicates = values.zip(keys).map do |value, key|
37
- table[key].eq(value)
38
- end
39
- cpk_and_predicate(eq_predicates)
40
- end
41
-
42
- def cpk_join_predicate(table1, key1, table2, key2)
43
- key1_fields = Array(key1).map {|key| table1[key]}
44
- key2_fields = Array(key2).map {|key| table2[key]}
45
-
46
- eq_predicates = key1_fields.zip(key2_fields).map do |key_field1, key_field2|
47
- key_field2 = Arel::Nodes::Quoted.new(key_field2) unless Arel::Attributes::Attribute === key_field2
48
- key_field1.eq(key_field2)
49
- end
50
- cpk_and_predicate(eq_predicates)
51
- end
52
-
53
- def cpk_in_predicate(table, primary_keys, ids)
54
- and_predicates = ids.map do |id|
55
- cpk_id_predicate(table, primary_keys, id)
56
- end
57
- cpk_or_predicate(and_predicates)
58
- end
59
- end
60
- end
61
-
62
- ActiveRecord::Associations::AssociationScope.send(:include, CompositePrimaryKeys::Predicates)
63
- ActiveRecord::Associations::JoinDependency::JoinAssociation.send(:include, CompositePrimaryKeys::Predicates)
64
- ActiveRecord::Associations::Preloader::Association.send(:include, CompositePrimaryKeys::Predicates)
65
- ActiveRecord::Associations::Preloader::Association::LoaderQuery.send(:include, CompositePrimaryKeys::Predicates)
66
- ActiveRecord::Associations::HasManyAssociation.send(:include, CompositePrimaryKeys::Predicates)
67
- ActiveRecord::Associations::HasManyThroughAssociation.send(:include, CompositePrimaryKeys::Predicates)
68
- ActiveRecord::Base.send(:extend, CompositePrimaryKeys::Predicates)
69
- ActiveRecord::Reflection::AbstractReflection.send(:include, CompositePrimaryKeys::Predicates)
70
- ActiveRecord::Relation.send(:include, CompositePrimaryKeys::Predicates)
71
- ActiveRecord::PredicateBuilder.send(:extend, CompositePrimaryKeys::Predicates)
1
+ module CompositePrimaryKeys
2
+ module Predicates
3
+ # Similar to module_function, but does not make instance methods private.
4
+ # https://idiosyncratic-ruby.com/8-self-improvement.html
5
+ extend self
6
+
7
+ def cpk_and_predicate(predicates)
8
+ if predicates.length == 1
9
+ predicates.first
10
+ else
11
+ Arel::Nodes::And.new(predicates)
12
+ end
13
+ end
14
+
15
+ def cpk_or_predicate(predicates, group = true)
16
+ if predicates.length <= 1
17
+ predicates.first
18
+ else
19
+ split_point = predicates.length / 2
20
+ predicates_first_half = predicates[0...split_point]
21
+ predicates_second_half = predicates[split_point..-1]
22
+
23
+ or_predicate = ::Arel::Nodes::Or.new(cpk_or_predicate(predicates_first_half, false),
24
+ cpk_or_predicate(predicates_second_half, false))
25
+
26
+ if group
27
+ ::Arel::Nodes::Grouping.new(or_predicate)
28
+ else
29
+ or_predicate
30
+ end
31
+ end
32
+ end
33
+
34
+ def cpk_id_predicate(table, keys, values)
35
+ # We zip on values then keys in case values are not provided for each key field
36
+ eq_predicates = values.zip(keys).map do |value, key|
37
+ table[key].eq(value)
38
+ end
39
+ cpk_and_predicate(eq_predicates)
40
+ end
41
+
42
+ def cpk_join_predicate(table1, key1, table2, key2)
43
+ key1_fields = Array(key1).map {|key| table1[key]}
44
+ key2_fields = Array(key2).map {|key| table2[key]}
45
+
46
+ eq_predicates = key1_fields.zip(key2_fields).map do |key_field1, key_field2|
47
+ key_field2 = Arel::Nodes::Quoted.new(key_field2) unless Arel::Attributes::Attribute === key_field2
48
+ key_field1.eq(key_field2)
49
+ end
50
+ cpk_and_predicate(eq_predicates)
51
+ end
52
+
53
+ def cpk_in_predicate(table, primary_keys, ids)
54
+ and_predicates = ids.map do |id|
55
+ cpk_id_predicate(table, primary_keys, id)
56
+ end
57
+ cpk_or_predicate(and_predicates)
58
+ end
59
+ end
60
+ end
61
+
62
+ ActiveRecord::Associations::AssociationScope.send(:include, CompositePrimaryKeys::Predicates)
63
+ ActiveRecord::Associations::JoinDependency::JoinAssociation.send(:include, CompositePrimaryKeys::Predicates)
64
+ ActiveRecord::Associations::Preloader::Association.send(:include, CompositePrimaryKeys::Predicates)
65
+ ActiveRecord::Associations::Preloader::Association::LoaderQuery.send(:include, CompositePrimaryKeys::Predicates)
66
+ ActiveRecord::Associations::HasManyAssociation.send(:include, CompositePrimaryKeys::Predicates)
67
+ ActiveRecord::Associations::HasManyThroughAssociation.send(:include, CompositePrimaryKeys::Predicates)
68
+ ActiveRecord::Base.send(:extend, CompositePrimaryKeys::Predicates)
69
+ ActiveRecord::Reflection::AbstractReflection.send(:include, CompositePrimaryKeys::Predicates)
70
+ ActiveRecord::Relation.send(:include, CompositePrimaryKeys::Predicates)
71
+ ActiveRecord::PredicateBuilder.send(:extend, CompositePrimaryKeys::Predicates)
@@ -1,96 +1,96 @@
1
- module ActiveRecord
2
- module Persistence
3
- module ClassMethods
4
- def delete(id_or_array)
5
- # CPK
6
- if self.composite?
7
- id_or_array = if id_or_array.is_a?(CompositePrimaryKeys::CompositeKeys)
8
- [id_or_array]
9
- else
10
- Array(id_or_array)
11
- end
12
-
13
- # Delete should return the number of deleted records
14
- id_or_array.map do |id|
15
- # Is the passed in id actually a record?
16
- id = id.kind_of?(::ActiveRecord::Base) ? id.id : id
17
- delete_by(cpk_id_predicate(self.arel_table, self.primary_key, id))
18
- end.sum
19
- else
20
- delete_by(primary_key => id_or_array)
21
- end
22
- end
23
-
24
- def _update_record(values, constraints) # :nodoc:
25
- # CPK
26
- if self.composite? && constraints[primary_key]
27
- primary_key_values = constraints.delete(primary_key)
28
- primary_key.each_with_index do |key, i|
29
- constraints[key] = primary_key_values[i]
30
- end
31
- end
32
-
33
- constraints = constraints.map { |name, value| predicate_builder[name, value] }
34
-
35
- default_constraint = build_default_constraint
36
- constraints << default_constraint if default_constraint
37
-
38
- if current_scope = self.global_current_scope
39
- constraints << current_scope.where_clause.ast
40
- end
41
-
42
- um = Arel::UpdateManager.new(arel_table)
43
- um.set(values.transform_keys { |name| arel_table[name] })
44
- um.wheres = constraints
45
-
46
- connection.update(um, "#{self} Update")
47
- end
48
-
49
- def _delete_record(constraints) # :nodoc:
50
- # CPK
51
- if self.composite? && constraints[primary_key]
52
- primary_key_values = constraints.delete(primary_key)
53
- primary_key.each_with_index do |key, i|
54
- constraints[key] = primary_key_values[i]
55
- end
56
- end
57
-
58
- constraints = constraints.map { |name, value| predicate_builder[name, value] }
59
-
60
- default_constraint = build_default_constraint
61
- constraints << default_constraint if default_constraint
62
-
63
- if current_scope = self.global_current_scope
64
- constraints << current_scope.where_clause.ast
65
- end
66
-
67
- dm = Arel::DeleteManager.new(arel_table)
68
- dm.wheres = constraints
69
-
70
- connection.delete(dm, "#{self} Destroy")
71
- end
72
- end
73
-
74
- def _create_record(attribute_names = self.attribute_names)
75
- attribute_names = attributes_for_create(attribute_names)
76
-
77
- new_id = self.class._insert_record(
78
- attributes_with_values(attribute_names)
79
- )
80
-
81
- # CPK
82
- if self.composite?
83
- self.id = self.id.zip(Array(new_id)).map {|id1, id2| id2.nil? ? id1 : id2}
84
- else
85
- self.id ||= new_id if self.class.primary_key
86
- end
87
-
88
- @new_record = false
89
- @previously_new_record = true
90
-
91
- yield(self) if block_given?
92
-
93
- id
94
- end
95
- end
96
- end
1
+ module ActiveRecord
2
+ module Persistence
3
+ module ClassMethods
4
+ def delete(id_or_array)
5
+ # CPK
6
+ if self.composite?
7
+ id_or_array = if id_or_array.is_a?(CompositePrimaryKeys::CompositeKeys)
8
+ [id_or_array]
9
+ else
10
+ Array(id_or_array)
11
+ end
12
+
13
+ # Delete should return the number of deleted records
14
+ id_or_array.map do |id|
15
+ # Is the passed in id actually a record?
16
+ id = id.kind_of?(::ActiveRecord::Base) ? id.id : id
17
+ delete_by(cpk_id_predicate(self.arel_table, self.primary_key, id))
18
+ end.sum
19
+ else
20
+ delete_by(primary_key => id_or_array)
21
+ end
22
+ end
23
+
24
+ def _update_record(values, constraints) # :nodoc:
25
+ # CPK
26
+ if self.composite? && constraints[primary_key]
27
+ primary_key_values = constraints.delete(primary_key)
28
+ primary_key.each_with_index do |key, i|
29
+ constraints[key] = primary_key_values[i]
30
+ end
31
+ end
32
+
33
+ constraints = constraints.map { |name, value| predicate_builder[name, value] }
34
+
35
+ default_constraint = build_default_constraint
36
+ constraints << default_constraint if default_constraint
37
+
38
+ if current_scope = self.global_current_scope
39
+ constraints << current_scope.where_clause.ast
40
+ end
41
+
42
+ um = Arel::UpdateManager.new(arel_table)
43
+ um.set(values.transform_keys { |name| arel_table[name] })
44
+ um.wheres = constraints
45
+
46
+ connection.update(um, "#{self} Update")
47
+ end
48
+
49
+ def _delete_record(constraints) # :nodoc:
50
+ # CPK
51
+ if self.composite? && constraints[primary_key]
52
+ primary_key_values = constraints.delete(primary_key)
53
+ primary_key.each_with_index do |key, i|
54
+ constraints[key] = primary_key_values[i]
55
+ end
56
+ end
57
+
58
+ constraints = constraints.map { |name, value| predicate_builder[name, value] }
59
+
60
+ default_constraint = build_default_constraint
61
+ constraints << default_constraint if default_constraint
62
+
63
+ if current_scope = self.global_current_scope
64
+ constraints << current_scope.where_clause.ast
65
+ end
66
+
67
+ dm = Arel::DeleteManager.new(arel_table)
68
+ dm.wheres = constraints
69
+
70
+ connection.delete(dm, "#{self} Destroy")
71
+ end
72
+ end
73
+
74
+ def _create_record(attribute_names = self.attribute_names)
75
+ attribute_names = attributes_for_create(attribute_names)
76
+
77
+ new_id = self.class._insert_record(
78
+ attributes_with_values(attribute_names)
79
+ )
80
+
81
+ # CPK
82
+ if self.composite?
83
+ self.id = self.id.zip(Array(new_id)).map {|id1, id2| id2.nil? ? id1 : id2}
84
+ else
85
+ self.id ||= new_id if self.class.primary_key
86
+ end
87
+
88
+ @new_record = false
89
+ @previously_new_record = true
90
+
91
+ yield(self) if block_given?
92
+
93
+ id
94
+ end
95
+ end
96
+ end