composite_primary_keys 6.0.8 → 7.0.0
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/History.rdoc +2 -8
- data/lib/composite_primary_keys.rb +9 -11
- data/lib/composite_primary_keys/active_model/dirty.rb +14 -0
- data/lib/composite_primary_keys/associations/association_scope.rb +30 -32
- data/lib/composite_primary_keys/associations/has_and_belongs_to_many_association.rb +1 -2
- data/lib/composite_primary_keys/associations/has_many_association.rb +13 -14
- data/lib/composite_primary_keys/associations/has_many_through_association.rb +88 -0
- data/lib/composite_primary_keys/associations/join_dependency.rb +23 -15
- data/lib/composite_primary_keys/associations/join_dependency/join_association.rb +3 -3
- data/lib/composite_primary_keys/associations/preloader/association.rb +37 -21
- data/lib/composite_primary_keys/associations/preloader/belongs_to.rb +9 -3
- data/lib/composite_primary_keys/base.rb +0 -1
- data/lib/composite_primary_keys/composite_predicates.rb +11 -34
- data/lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb +6 -5
- data/lib/composite_primary_keys/core.rb +28 -16
- data/lib/composite_primary_keys/model_schema.rb +15 -0
- data/lib/composite_primary_keys/nested_attributes.rb +8 -10
- data/lib/composite_primary_keys/persistence.rb +28 -29
- data/lib/composite_primary_keys/relation.rb +86 -16
- data/lib/composite_primary_keys/relation/finder_methods.rb +113 -59
- data/lib/composite_primary_keys/version.rb +2 -2
- data/test/abstract_unit.rb +7 -8
- data/test/fixtures/db_definitions/db2-create-tables.sql +13 -20
- data/test/fixtures/db_definitions/db2-drop-tables.sql +13 -14
- data/test/fixtures/db_definitions/mysql.sql +0 -7
- data/test/fixtures/db_definitions/oracle.drop.sql +0 -1
- data/test/fixtures/db_definitions/oracle.sql +0 -6
- data/test/fixtures/db_definitions/postgresql.sql +0 -7
- data/test/fixtures/db_definitions/sqlite.sql +24 -30
- data/test/fixtures/db_definitions/sqlserver.drop.sql +1 -4
- data/test/fixtures/db_definitions/sqlserver.sql +7 -16
- data/test/fixtures/dorm.rb +2 -2
- data/test/fixtures/suburb.rb +2 -2
- data/test/test_associations.rb +1 -2
- data/test/test_attribute_methods.rb +3 -3
- data/test/test_delete.rb +3 -5
- data/test/test_equal.rb +5 -5
- data/test/test_find.rb +2 -14
- data/test/test_predicates.rb +2 -2
- data/test/test_santiago.rb +1 -1
- data/test/test_serialize.rb +1 -1
- data/test/test_suite.rb +0 -1
- data/test/test_tutorial_example.rb +3 -3
- metadata +9 -32
- data/lib/composite_primary_keys/attribute_methods/primary_key.rb +0 -17
- data/lib/composite_primary_keys/composite_relation.rb +0 -44
- data/lib/composite_primary_keys/locking/optimistic.rb +0 -51
- data/test/fixtures/model_with_callback.rb +0 -39
- data/test/fixtures/model_with_callbacks.yml +0 -3
- data/test/test_callbacks.rb +0 -36
- data/test/test_dumpable.rb +0 -15
- data/test/test_optimistic.rb +0 -18
@@ -2,14 +2,19 @@ module ActiveRecord
|
|
2
2
|
module Associations
|
3
3
|
class Preloader
|
4
4
|
class Association
|
5
|
-
def
|
5
|
+
def query_scope(ids)
|
6
6
|
# CPK
|
7
7
|
# scope.where(association_key.in(ids))
|
8
|
-
|
9
|
-
|
8
|
+
|
9
|
+
if reflection.foreign_key.is_a?(Array)
|
10
|
+
predicate = cpk_in_predicate(table, reflection.foreign_key, ids)
|
11
|
+
scope.where(predicate)
|
12
|
+
else
|
13
|
+
scope.where(association_key.in(ids))
|
14
|
+
end
|
10
15
|
end
|
11
|
-
|
12
|
-
def associated_records_by_owner
|
16
|
+
|
17
|
+
def associated_records_by_owner(preloader)
|
13
18
|
# CPK
|
14
19
|
owners_map = owners_by_key
|
15
20
|
#owner_keys = owners_map.keys.compact
|
@@ -19,29 +24,40 @@ module ActiveRecord
|
|
19
24
|
end
|
20
25
|
end.compact.uniq
|
21
26
|
|
22
|
-
|
23
|
-
|
24
|
-
|
27
|
+
# Each record may have multiple owners, and vice-versa
|
28
|
+
records_by_owner = owners.each_with_object({}) do |owner,h|
|
29
|
+
h[owner] = []
|
30
|
+
end
|
31
|
+
|
32
|
+
if owner_keys.any?
|
25
33
|
# Some databases impose a limit on the number of ids in a list (in Oracle it's 1000)
|
26
34
|
# Make several smaller queries if necessary or make one query if the adapter supports it
|
27
|
-
sliced = owner_keys.each_slice(
|
28
|
-
|
35
|
+
sliced = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size)
|
36
|
+
|
37
|
+
records = load_slices sliced
|
38
|
+
records.each do |record, owner_key|
|
39
|
+
owners_map[owner_key].each do |owner|
|
40
|
+
records_by_owner[owner] << record
|
41
|
+
end
|
42
|
+
end
|
29
43
|
end
|
30
44
|
|
31
|
-
|
32
|
-
|
33
|
-
|
45
|
+
records_by_owner
|
46
|
+
end
|
47
|
+
|
48
|
+
def load_slices(slices)
|
49
|
+
@preloaded_records = slices.flat_map { |slice|
|
50
|
+
records_for(slice)
|
51
|
+
}
|
52
|
+
|
53
|
+
@preloaded_records.map { |record|
|
34
54
|
# CPK
|
35
|
-
#
|
55
|
+
#[record, record[association_key_name]]
|
36
56
|
owner_key = Array(association_key_name).map do |key_name|
|
37
57
|
record[key_name]
|
38
58
|
end.join(CompositePrimaryKeys::ID_SEP)
|
39
|
-
|
40
|
-
|
41
|
-
records_by_owner[owner] << record
|
42
|
-
end
|
43
|
-
end
|
44
|
-
records_by_owner
|
59
|
+
[record, owner_key]
|
60
|
+
}
|
45
61
|
end
|
46
62
|
|
47
63
|
def owners_by_key
|
@@ -59,4 +75,4 @@ module ActiveRecord
|
|
59
75
|
end
|
60
76
|
end
|
61
77
|
end
|
62
|
-
end
|
78
|
+
end
|
@@ -2,10 +2,16 @@ module ActiveRecord
|
|
2
2
|
module Associations
|
3
3
|
class Preloader
|
4
4
|
class BelongsTo
|
5
|
-
def
|
5
|
+
def query_scope(ids)
|
6
6
|
# CPK
|
7
|
-
|
8
|
-
|
7
|
+
# scope.where(association_key.in(ids))
|
8
|
+
|
9
|
+
if association_key_name.is_a?(Array)
|
10
|
+
predicate = cpk_in_predicate(table, association_key_name, ids)
|
11
|
+
scope.where(predicate)
|
12
|
+
else
|
13
|
+
scope.where(association_key.in(ids))
|
14
|
+
end
|
9
15
|
end
|
10
16
|
end
|
11
17
|
end
|
@@ -4,7 +4,6 @@ module ActiveRecord
|
|
4
4
|
|
5
5
|
class Base
|
6
6
|
include CompositePrimaryKeys::ActiveRecord::Persistence
|
7
|
-
include CompositePrimaryKeys::ActiveRecord::Locking::Optimistic
|
8
7
|
|
9
8
|
INVALID_FOR_COMPOSITE_KEYS = 'Not appropriate for composite primary keys'
|
10
9
|
NOT_IMPLEMENTED_YET = 'Not implemented for composite primary keys yet'
|
@@ -8,27 +8,10 @@ module CompositePrimaryKeys
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
when Arel::Table
|
16
|
-
table.engine
|
17
|
-
when ::ActiveRecord::Base
|
18
|
-
table
|
19
|
-
else
|
20
|
-
nil
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def cpk_or_predicate(predicates, table = nil)
|
25
|
-
engine = figure_engine(table)
|
26
|
-
predicates = predicates.map do |predicate|
|
27
|
-
predicate_sql = engine ? predicate.to_sql(engine) : predicate.to_sql
|
28
|
-
"(#{predicate_sql})"
|
29
|
-
end
|
30
|
-
predicates = "(#{predicates.join(" OR ")})"
|
31
|
-
Arel::Nodes::SqlLiteral.new(predicates)
|
11
|
+
def cpk_or_predicate(predicates)
|
12
|
+
::Arel::Nodes::Grouping.new(predicates.inject { |memo,node|
|
13
|
+
::Arel::Nodes::Or.new(memo, node)
|
14
|
+
})
|
32
15
|
end
|
33
16
|
|
34
17
|
def cpk_id_predicate(table, keys, values)
|
@@ -49,25 +32,19 @@ module CompositePrimaryKeys
|
|
49
32
|
end
|
50
33
|
|
51
34
|
def cpk_in_predicate(table, primary_keys, ids)
|
52
|
-
|
53
|
-
|
54
|
-
and_predicates = ids.map do |id_set|
|
55
|
-
eq_predicates = Array(primary_keys).zip(Array(id_set)).map do |primary_key, value|
|
56
|
-
table[primary_key].eq(value)
|
57
|
-
end
|
58
|
-
cpk_and_predicate(eq_predicates)
|
59
|
-
end
|
60
|
-
|
61
|
-
cpk_or_predicate(and_predicates, table)
|
62
|
-
else
|
63
|
-
table[primary_keys.first].in(ids.flatten)
|
35
|
+
and_predicates = ids.map do |id|
|
36
|
+
cpk_id_predicate(table, primary_keys, id)
|
64
37
|
end
|
38
|
+
cpk_or_predicate(and_predicates)
|
65
39
|
end
|
66
40
|
end
|
67
41
|
end
|
68
42
|
|
69
43
|
ActiveRecord::Associations::AssociationScope.send(:include, CompositePrimaryKeys::Predicates)
|
70
|
-
ActiveRecord::Associations::HasAndBelongsToManyAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
71
44
|
ActiveRecord::Associations::JoinDependency::JoinAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
72
45
|
ActiveRecord::Associations::Preloader::Association.send(:include, CompositePrimaryKeys::Predicates)
|
46
|
+
ActiveRecord::Associations::HasManyThroughAssociation.send(:include, CompositePrimaryKeys::Predicates)
|
73
47
|
ActiveRecord::Relation.send(:include, CompositePrimaryKeys::Predicates)
|
48
|
+
|
49
|
+
|
50
|
+
|
data/lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb
CHANGED
@@ -5,14 +5,15 @@ module ActiveRecord
|
|
5
5
|
require "composite_primary_keys/connection_adapters/postgresql_adapter.rb"
|
6
6
|
end
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
def self.establish_connection(spec = ENV["DATABASE_URL"])
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
spec ||= ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_sym
|
11
|
+
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
|
12
|
+
spec = resolver.spec(spec)
|
13
|
+
|
13
14
|
# CPK
|
14
15
|
load_cpk_adapter(spec.config[:adapter])
|
15
|
-
|
16
|
+
|
16
17
|
unless respond_to?(spec.adapter_method)
|
17
18
|
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
|
18
19
|
end
|
@@ -1,26 +1,39 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module Core
|
3
|
-
def
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
def init_internals
|
4
|
+
pk = self.class.primary_key
|
5
|
+
|
6
|
+
# CPK
|
7
|
+
#@attributes[pk] = nil unless @attributes.key?(pk)
|
8
|
+
unless self.composite?
|
9
|
+
@attributes[pk] = nil unless @attributes.key?(pk)
|
10
|
+
end
|
11
|
+
|
12
|
+
@aggregation_cache = {}
|
13
|
+
@association_cache = {}
|
14
|
+
@attributes_cache = {}
|
15
|
+
@readonly = false
|
16
|
+
@destroyed = false
|
17
|
+
@marked_for_destruction = false
|
18
|
+
@destroyed_by_association = nil
|
19
|
+
@new_record = true
|
20
|
+
@txn = nil
|
21
|
+
@_start_transaction_state = {}
|
22
|
+
@transaction_state = nil
|
23
|
+
@reflects_state = [false]
|
7
24
|
end
|
8
|
-
alias_method_chain :init_internals, :cpk
|
9
25
|
|
10
|
-
def initialize_dup(other)
|
26
|
+
def initialize_dup(other) # :nodoc:
|
11
27
|
cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
|
12
28
|
self.class.initialize_attributes(cloned_attributes, :serialized => false)
|
13
|
-
|
14
|
-
# cloned_attributes.delete(self.class.primary_key)
|
15
|
-
Array(self.class.primary_key).each {|key| cloned_attributes.delete(key.to_s)}
|
29
|
+
|
16
30
|
@attributes = cloned_attributes
|
17
|
-
|
18
|
-
run_callbacks(:initialize) unless _initialize_callbacks.empty?
|
19
31
|
|
20
|
-
|
21
|
-
self.class.
|
22
|
-
|
23
|
-
|
32
|
+
# CPK
|
33
|
+
#@attributes[self.class.primary_key] = nil
|
34
|
+
Array(self.class.primary_key).each {|key| @attributes[key] = nil}
|
35
|
+
|
36
|
+
run_callbacks(:initialize) unless _initialize_callbacks.empty?
|
24
37
|
|
25
38
|
@aggregation_cache = {}
|
26
39
|
@association_cache = {}
|
@@ -28,7 +41,6 @@ module ActiveRecord
|
|
28
41
|
|
29
42
|
@new_record = true
|
30
43
|
|
31
|
-
ensure_proper_type
|
32
44
|
super
|
33
45
|
end
|
34
46
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ModelSchema
|
3
|
+
module ClassMethods
|
4
|
+
def columns
|
5
|
+
@columns ||= connection.schema_cache.columns(table_name).map do |col|
|
6
|
+
col = col.dup
|
7
|
+
# CPK
|
8
|
+
#col.primary = (col.name == primary_key)
|
9
|
+
col.primary = Array(primary_key).include?(col.name)
|
10
|
+
col
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -12,10 +12,10 @@ module ActiveRecord
|
|
12
12
|
if attributes_collection.is_a? Hash
|
13
13
|
keys = attributes_collection.keys
|
14
14
|
attributes_collection = if keys.include?('id') || keys.include?(:id)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
[attributes_collection]
|
16
|
+
else
|
17
|
+
attributes_collection.values
|
18
|
+
end
|
19
19
|
end
|
20
20
|
|
21
21
|
association = association(association_name)
|
@@ -50,18 +50,16 @@ module ActiveRecord
|
|
50
50
|
end
|
51
51
|
elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s }
|
52
52
|
unless call_reject_if(association_name, attributes)
|
53
|
-
# Make sure we are
|
53
|
+
# Make sure we are operating on the actual object which is in the association's
|
54
54
|
# proxy_target array (either by finding it, or adding it if not found)
|
55
|
-
|
56
|
-
|
55
|
+
# Take into account that the proxy_target may have changed due to callbacks
|
56
|
+
target_record = association.target.detect { |record| record.id.to_s == attributes['id'].to_s }
|
57
57
|
if target_record
|
58
58
|
existing_record = target_record
|
59
59
|
else
|
60
|
-
association.add_to_target(existing_record)
|
60
|
+
association.add_to_target(existing_record, :skip_callbacks)
|
61
61
|
end
|
62
|
-
end
|
63
62
|
|
64
|
-
if !call_reject_if(association_name, attributes)
|
65
63
|
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
|
66
64
|
end
|
67
65
|
else
|
@@ -2,24 +2,29 @@ module CompositePrimaryKeys
|
|
2
2
|
module ActiveRecord
|
3
3
|
module Persistence
|
4
4
|
def relation_for_destroy
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
# CPK
|
6
|
+
#pk = self.class.primary_key
|
7
|
+
#column = self.class.columns_hash[pk]
|
8
|
+
#substitute = self.class.connection.substitute_at(column, 0)
|
9
|
+
#relation = self.class.unscoped.where(
|
10
|
+
# self.class.arel_table[pk].eq(substitute))
|
11
|
+
#relation.bind_values = [[column, id]]
|
9
12
|
|
10
|
-
|
11
|
-
raise ActiveRecord::CompositeKeyError, "No primary key(s) defined for #{self.class.name}"
|
12
|
-
end
|
13
|
+
relation = self.class.unscoped
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
Array(self.class.primary_key).each_with_index do |key, index|
|
16
|
+
column = self.class.columns_hash[key]
|
17
|
+
substitute = self.class.connection.substitute_at(column, index)
|
18
|
+
relation = relation.where(self.class.arel_table[key].eq(substitute))
|
19
|
+
relation.bind_values += [[column, self[key]]]
|
16
20
|
end
|
17
21
|
|
18
|
-
relation
|
22
|
+
relation
|
19
23
|
end
|
20
|
-
|
21
24
|
|
22
25
|
def touch(name = nil)
|
26
|
+
raise ActiveRecordError, "cannot touch on a new record object" unless persisted?
|
27
|
+
|
23
28
|
attributes = timestamp_attributes_for_update_in_model
|
24
29
|
attributes << name if name
|
25
30
|
|
@@ -34,35 +39,29 @@ module CompositePrimaryKeys
|
|
34
39
|
|
35
40
|
changes[self.class.locking_column] = increment_lock if locking_enabled?
|
36
41
|
|
37
|
-
|
42
|
+
changed_attributes.except!(*changes.keys)
|
38
43
|
|
39
44
|
relation = self.class.send(:relation)
|
40
45
|
arel_table = self.class.arel_table
|
41
46
|
primary_key = self.class.primary_key
|
42
47
|
|
48
|
+
# CPK
|
49
|
+
#self.class.unscoped.where(primary_key => self[primary_key]).update_all(changes) == 1
|
43
50
|
primary_key_predicate = relation.cpk_id_predicate(arel_table, Array(primary_key), Array(id))
|
44
|
-
|
45
51
|
self.class.unscoped.where(primary_key_predicate).update_all(changes) == 1
|
52
|
+
else
|
53
|
+
true
|
46
54
|
end
|
47
55
|
end
|
48
56
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
52
|
-
klass = self.class
|
53
|
-
|
54
|
-
attributes_with_values = arel_attributes_with_values_for_update(attribute_names)
|
55
|
-
return 0 if attributes_with_values.empty?
|
57
|
+
def create_record(attribute_names = @attributes.keys)
|
58
|
+
attributes_values = arel_attributes_with_values_for_create(attribute_names)
|
56
59
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
stmt = klass.unscoped.where(ids_hash).arel.compile_update(attributes_with_values)
|
63
|
-
end
|
64
|
-
|
65
|
-
klass.connection.update stmt.to_sql
|
60
|
+
new_id = self.class.unscoped.insert attributes_values
|
61
|
+
self.id ||= new_id if self.class.primary_key
|
62
|
+
|
63
|
+
@new_record = false
|
64
|
+
id
|
66
65
|
end
|
67
66
|
end
|
68
67
|
end
|
@@ -1,25 +1,10 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class Relation
|
3
|
-
def add_cpk_support
|
4
|
-
extend CompositePrimaryKeys::CompositeRelation
|
5
|
-
end
|
6
|
-
|
7
|
-
alias :where_values_hash_without_cpk :where_values_hash
|
8
|
-
def where_values_hash(relation_table_name = table_name)
|
9
|
-
# CPK adds this so that it finds the Equality nodes beneath the And node:
|
10
|
-
nodes_from_and = with_default_scope.where_values.grep(Arel::Nodes::And).map {|and_node| and_node.children.grep(Arel::Nodes::Equality) }.flatten
|
11
|
-
|
12
|
-
equalities = (nodes_from_and + with_default_scope.where_values.grep(Arel::Nodes::Equality)).find_all { |node|
|
13
|
-
node.left.relation.name == relation_table_name
|
14
|
-
}
|
15
|
-
|
16
|
-
Hash[equalities.map { |where| [where.left.name, where.right] }]
|
17
|
-
end
|
18
|
-
|
19
3
|
alias :initialize_without_cpk :initialize
|
20
4
|
def initialize(klass, table, values = {})
|
21
5
|
initialize_without_cpk(klass, table, values)
|
22
6
|
add_cpk_support if klass && klass.composite?
|
7
|
+
add_cpk_where_values_hash
|
23
8
|
end
|
24
9
|
|
25
10
|
alias :initialize_copy_without_cpk :initialize_copy
|
@@ -27,5 +12,90 @@ module ActiveRecord
|
|
27
12
|
initialize_copy_without_cpk(other)
|
28
13
|
add_cpk_support if klass.composite?
|
29
14
|
end
|
15
|
+
|
16
|
+
def add_cpk_support
|
17
|
+
class << self
|
18
|
+
include CompositePrimaryKeys::ActiveRecord::Batches
|
19
|
+
include CompositePrimaryKeys::ActiveRecord::Calculations
|
20
|
+
include CompositePrimaryKeys::ActiveRecord::FinderMethods
|
21
|
+
include CompositePrimaryKeys::ActiveRecord::QueryMethods
|
22
|
+
|
23
|
+
def delete(id_or_array)
|
24
|
+
# Without CPK:
|
25
|
+
# where(primary_key => id_or_array).delete_all
|
26
|
+
|
27
|
+
id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
|
28
|
+
[id_or_array]
|
29
|
+
else
|
30
|
+
Array(id_or_array)
|
31
|
+
end
|
32
|
+
|
33
|
+
id_or_array.each do |id|
|
34
|
+
where(cpk_id_predicate(table, self.primary_key, id)).delete_all
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def destroy(id_or_array)
|
39
|
+
# Without CPK:
|
40
|
+
#if id.is_a?(Array)
|
41
|
+
# id.map { |one_id| destroy(one_id) }
|
42
|
+
#else
|
43
|
+
# find(id).destroy
|
44
|
+
#end
|
45
|
+
|
46
|
+
id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
|
47
|
+
[id_or_array]
|
48
|
+
else
|
49
|
+
Array(id_or_array)
|
50
|
+
end
|
51
|
+
|
52
|
+
id_or_array.each do |id|
|
53
|
+
where(cpk_id_predicate(table, self.primary_key, id)).each do |record|
|
54
|
+
record.destroy
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def add_cpk_where_values_hash
|
62
|
+
class << self
|
63
|
+
def where_values_hash
|
64
|
+
# CPK adds this so that it finds the Equality nodes beneath the And node:
|
65
|
+
#equalities = where_values.grep(Arel::Nodes::Equality).find_all { |node|
|
66
|
+
# node.left.relation.name == table_name
|
67
|
+
# }
|
68
|
+
nodes_from_and = where_values.grep(Arel::Nodes::And).map {|and_node| and_node.children.grep(Arel::Nodes::Equality) }.flatten
|
69
|
+
|
70
|
+
equalities = (nodes_from_and + where_values.grep(Arel::Nodes::Equality)).find_all { |node|
|
71
|
+
node.left.relation.name == table_name
|
72
|
+
}
|
73
|
+
|
74
|
+
binds = Hash[bind_values.find_all(&:first).map { |column, v| [column.name, v] }]
|
75
|
+
|
76
|
+
Hash[equalities.map { |where|
|
77
|
+
name = where.left.name
|
78
|
+
[name, binds.fetch(name.to_s) { where.right }]
|
79
|
+
}]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def update_record(values, id, id_was) # :nodoc:
|
85
|
+
substitutes, binds = substitute_values values
|
86
|
+
|
87
|
+
# CPK
|
88
|
+
um = if self.composite?
|
89
|
+
relation = @klass.unscoped.where(cpk_id_predicate(@klass.arel_table, @klass.primary_key, id_was || id))
|
90
|
+
relation.arel.compile_update(substitutes, @klass.primary_key)
|
91
|
+
else
|
92
|
+
@klass.unscoped.where(@klass.arel_table[@klass.primary_key].eq(id_was || id)).arel.compile_update(substitutes, @klass.primary_key)
|
93
|
+
end
|
94
|
+
|
95
|
+
@klass.connection.update(
|
96
|
+
um,
|
97
|
+
'SQL',
|
98
|
+
binds)
|
99
|
+
end
|
30
100
|
end
|
31
101
|
end
|