composite_primary_keys 7.0.13 → 7.0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +615 -608
  3. data/lib/composite_primary_keys.rb +110 -110
  4. data/lib/composite_primary_keys/associations/association.rb +23 -23
  5. data/lib/composite_primary_keys/associations/association_scope.rb +77 -77
  6. data/lib/composite_primary_keys/associations/has_and_belongs_to_many_association.rb +59 -59
  7. data/lib/composite_primary_keys/associations/has_many_association.rb +56 -56
  8. data/lib/composite_primary_keys/associations/join_dependency.rb +89 -89
  9. data/lib/composite_primary_keys/associations/join_dependency/join_part.rb +38 -38
  10. data/lib/composite_primary_keys/associations/preloader/association.rb +78 -78
  11. data/lib/composite_primary_keys/associations/preloader/has_and_belongs_to_many.rb +46 -46
  12. data/lib/composite_primary_keys/attribute_methods/dirty.rb +26 -26
  13. data/lib/composite_primary_keys/attribute_methods/read.rb +34 -34
  14. data/lib/composite_primary_keys/attribute_methods/write.rb +36 -36
  15. data/lib/composite_primary_keys/base.rb +0 -6
  16. data/lib/composite_primary_keys/composite_arrays.rb +30 -30
  17. data/lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb +4 -2
  18. data/lib/composite_primary_keys/connection_adapters/sqlserver_adapter.rb +17 -0
  19. data/lib/composite_primary_keys/core.rb +47 -47
  20. data/lib/composite_primary_keys/persistence.rb +60 -60
  21. data/lib/composite_primary_keys/relation.rb +56 -56
  22. data/lib/composite_primary_keys/relation/calculations.rb +75 -65
  23. data/lib/composite_primary_keys/relation/finder_methods.rb +196 -196
  24. data/lib/composite_primary_keys/sanitization.rb +52 -52
  25. data/lib/composite_primary_keys/validations/uniqueness.rb +37 -39
  26. data/lib/composite_primary_keys/version.rb +8 -8
  27. data/tasks/databases/sqlserver.rake +40 -27
  28. data/test/connections/databases.example.yml +18 -18
  29. data/test/connections/native_sqlserver/connection.rb +14 -11
  30. data/test/fixtures/db_definitions/mysql.sql +208 -208
  31. data/test/fixtures/db_definitions/postgresql.sql +210 -210
  32. data/test/fixtures/db_definitions/sqlite.sql +197 -197
  33. data/test/fixtures/db_definitions/sqlserver.drop.sql +94 -91
  34. data/test/fixtures/db_definitions/sqlserver.sql +232 -226
  35. data/test/fixtures/employee.rb +5 -5
  36. data/test/test_associations.rb +275 -275
  37. data/test/test_attributes.rb +60 -60
  38. data/test/test_create.rb +112 -112
  39. data/test/test_delete.rb +152 -148
  40. data/test/test_delete_all.rb +21 -21
  41. data/test/test_enum.rb +20 -20
  42. data/test/test_equal.rb +1 -1
  43. data/test/test_tutorial_example.rb +21 -21
  44. metadata +3 -2
@@ -1,110 +1,110 @@
1
- #--
2
- # Copyright (c) 2006-2012 Nic Williams and Charlie Savage
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining
5
- # a copy of this software and associated documentation files (the
6
- # "Software"), to deal in the Software without restriction, including
7
- # without limitation the rights to use, copy, modify, merge, publish,
8
- # distribute, sublicense, and/or sell copies of the Software, and to
9
- # permit persons to whom the Software is furnished to do so, subject to
10
- # the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be
13
- # included in all copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
- #++
23
-
24
- $:.unshift(File.dirname(__FILE__)) unless
25
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
26
-
27
- unless defined?(ActiveRecord)
28
- require 'rubygems'
29
- gem 'activerecord', '~>4.1.7'
30
- require 'active_record'
31
- end
32
-
33
- # AR files we override
34
- require 'active_record/counter_cache'
35
- require 'active_record/fixtures'
36
- require 'active_record/model_schema'
37
- require 'active_record/persistence'
38
- require 'active_record/relation'
39
- require 'active_record/sanitization'
40
-
41
- require 'active_record/associations/association'
42
- require 'active_record/associations/association_scope'
43
- require 'active_record/associations/has_many_association'
44
- require 'active_record/associations/has_many_through_association'
45
- require 'active_record/associations/join_dependency'
46
- require 'active_record/associations/join_dependency/join_part'
47
- require 'active_record/associations/join_dependency/join_association'
48
- require 'active_record/associations/preloader/association'
49
- require 'active_record/associations/preloader/belongs_to'
50
-
51
- require 'active_record/attribute_methods/primary_key'
52
- require 'active_record/attribute_methods/dirty'
53
- require 'active_record/attribute_methods/read'
54
- require 'active_record/attribute_methods/write'
55
- require 'active_record/locking/optimistic'
56
- require 'active_record/nested_attributes'
57
-
58
- require 'active_record/connection_adapters/abstract_adapter'
59
-
60
- require 'active_record/relation/batches'
61
- require 'active_record/relation/calculations'
62
- require 'active_record/relation/finder_methods'
63
- require 'active_record/relation/predicate_builder'
64
- require 'active_record/relation/query_methods'
65
-
66
- require 'active_record/validations/uniqueness'
67
-
68
- # CPK files
69
- require 'composite_primary_keys/persistence'
70
- require 'composite_primary_keys/base'
71
- require 'composite_primary_keys/core'
72
- require 'composite_primary_keys/composite_arrays'
73
- require 'composite_primary_keys/composite_predicates'
74
- require 'composite_primary_keys/fixtures'
75
- require 'composite_primary_keys/model_schema'
76
- require 'composite_primary_keys/relation'
77
- require 'composite_primary_keys/sanitization'
78
- require 'composite_primary_keys/version'
79
-
80
- require 'composite_primary_keys/associations/association'
81
- require 'composite_primary_keys/associations/association_scope'
82
- require 'composite_primary_keys/associations/has_many_association'
83
- require 'composite_primary_keys/associations/has_many_through_association'
84
- require 'composite_primary_keys/associations/join_dependency'
85
- require 'composite_primary_keys/associations/join_dependency/join_part'
86
- require 'composite_primary_keys/associations/join_dependency/join_association'
87
- require 'composite_primary_keys/associations/preloader/association'
88
- require 'composite_primary_keys/associations/preloader/belongs_to'
89
-
90
- require 'composite_primary_keys/dirty'
91
-
92
- require 'composite_primary_keys/attribute_methods/primary_key'
93
- require 'composite_primary_keys/attribute_methods/dirty'
94
- require 'composite_primary_keys/attribute_methods/read'
95
- require 'composite_primary_keys/attribute_methods/write'
96
- require 'composite_primary_keys/locking/optimistic'
97
- require 'composite_primary_keys/nested_attributes'
98
-
99
- require 'composite_primary_keys/connection_adapters/abstract_adapter'
100
- require 'composite_primary_keys/connection_adapters/abstract/connection_specification_changes'
101
-
102
- require 'composite_primary_keys/relation/batches'
103
- require 'composite_primary_keys/relation/calculations'
104
- require 'composite_primary_keys/relation/finder_methods'
105
- require 'composite_primary_keys/relation/predicate_builder'
106
- require 'composite_primary_keys/relation/query_methods'
107
-
108
- require 'composite_primary_keys/validations/uniqueness'
109
-
110
- require 'composite_primary_keys/composite_relation'
1
+ #--
2
+ # Copyright (c) 2006-2012 Nic Williams and Charlie Savage
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ $:.unshift(File.dirname(__FILE__)) unless
25
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
26
+
27
+ unless defined?(ActiveRecord)
28
+ require 'rubygems'
29
+ gem 'activerecord', '~>4.1.7'
30
+ require 'active_record'
31
+ end
32
+
33
+ # AR files we override
34
+ require 'active_record/counter_cache'
35
+ require 'active_record/fixtures'
36
+ require 'active_record/model_schema'
37
+ require 'active_record/persistence'
38
+ require 'active_record/relation'
39
+ require 'active_record/sanitization'
40
+
41
+ require 'active_record/associations/association'
42
+ require 'active_record/associations/association_scope'
43
+ require 'active_record/associations/has_many_association'
44
+ require 'active_record/associations/has_many_through_association'
45
+ require 'active_record/associations/join_dependency'
46
+ require 'active_record/associations/join_dependency/join_part'
47
+ require 'active_record/associations/join_dependency/join_association'
48
+ require 'active_record/associations/preloader/association'
49
+ require 'active_record/associations/preloader/belongs_to'
50
+
51
+ require 'active_record/attribute_methods/primary_key'
52
+ require 'active_record/attribute_methods/dirty'
53
+ require 'active_record/attribute_methods/read'
54
+ require 'active_record/attribute_methods/write'
55
+ require 'active_record/locking/optimistic'
56
+ require 'active_record/nested_attributes'
57
+
58
+ require 'active_record/connection_adapters/abstract_adapter'
59
+
60
+ require 'active_record/relation/batches'
61
+ require 'active_record/relation/calculations'
62
+ require 'active_record/relation/finder_methods'
63
+ require 'active_record/relation/predicate_builder'
64
+ require 'active_record/relation/query_methods'
65
+
66
+ require 'active_record/validations/uniqueness'
67
+
68
+ # CPK files
69
+ require 'composite_primary_keys/persistence'
70
+ require 'composite_primary_keys/base'
71
+ require 'composite_primary_keys/core'
72
+ require 'composite_primary_keys/composite_arrays'
73
+ require 'composite_primary_keys/composite_predicates'
74
+ require 'composite_primary_keys/fixtures'
75
+ require 'composite_primary_keys/model_schema'
76
+ require 'composite_primary_keys/relation'
77
+ require 'composite_primary_keys/sanitization'
78
+ require 'composite_primary_keys/version'
79
+
80
+ require 'composite_primary_keys/associations/association'
81
+ require 'composite_primary_keys/associations/association_scope'
82
+ require 'composite_primary_keys/associations/has_many_association'
83
+ require 'composite_primary_keys/associations/has_many_through_association'
84
+ require 'composite_primary_keys/associations/join_dependency'
85
+ require 'composite_primary_keys/associations/join_dependency/join_part'
86
+ require 'composite_primary_keys/associations/join_dependency/join_association'
87
+ require 'composite_primary_keys/associations/preloader/association'
88
+ require 'composite_primary_keys/associations/preloader/belongs_to'
89
+
90
+ require 'composite_primary_keys/dirty'
91
+
92
+ require 'composite_primary_keys/attribute_methods/primary_key'
93
+ require 'composite_primary_keys/attribute_methods/dirty'
94
+ require 'composite_primary_keys/attribute_methods/read'
95
+ require 'composite_primary_keys/attribute_methods/write'
96
+ require 'composite_primary_keys/locking/optimistic'
97
+ require 'composite_primary_keys/nested_attributes'
98
+
99
+ require 'composite_primary_keys/connection_adapters/abstract_adapter'
100
+ require 'composite_primary_keys/connection_adapters/abstract/connection_specification_changes'
101
+
102
+ require 'composite_primary_keys/relation/batches'
103
+ require 'composite_primary_keys/relation/calculations'
104
+ require 'composite_primary_keys/relation/finder_methods'
105
+ require 'composite_primary_keys/relation/predicate_builder'
106
+ require 'composite_primary_keys/relation/query_methods'
107
+
108
+ require 'composite_primary_keys/validations/uniqueness'
109
+
110
+ require 'composite_primary_keys/composite_relation'
@@ -1,23 +1,23 @@
1
- module ActiveRecord
2
- module Associations
3
- class Association
4
- def creation_attributes
5
- attributes = {}
6
-
7
- if (reflection.macro == :has_one || reflection.macro == :has_many) && !options[:through]
8
- # CPK
9
- # attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
10
- Array(reflection.foreign_key).zip(Array(reflection.active_record_primary_key)).each do |key1, key2|
11
- attributes[key1] = owner[key2]
12
- end
13
-
14
- if reflection.options[:as]
15
- attributes[reflection.type] = owner.class.base_class.name
16
- end
17
- end
18
-
19
- attributes
20
- end
21
- end
22
- end
23
- end
1
+ module ActiveRecord
2
+ module Associations
3
+ class Association
4
+ def creation_attributes
5
+ attributes = {}
6
+
7
+ if (reflection.macro == :has_one || reflection.macro == :has_many) && !options[:through]
8
+ # CPK
9
+ # attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
10
+ Array(reflection.foreign_key).zip(Array(reflection.active_record_primary_key)).each do |key1, key2|
11
+ attributes[key1] = owner[key2]
12
+ end
13
+
14
+ if reflection.options[:as]
15
+ attributes[reflection.type] = owner.class.base_class.name
16
+ end
17
+ end
18
+
19
+ attributes
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,77 +1,77 @@
1
- module ActiveRecord
2
- module Associations
3
- class AssociationScope
4
- def add_constraints(scope, owner, assoc_klass, refl, tracker)
5
- chain = refl.chain
6
- scope_chain = refl.scope_chain
7
-
8
- tables = construct_tables(chain, assoc_klass, refl, tracker)
9
-
10
- chain.each_with_index do |reflection, i|
11
- table, foreign_table = tables.shift, tables.first
12
-
13
- if reflection.source_macro == :belongs_to
14
- if reflection.options[:polymorphic]
15
- key = reflection.association_primary_key(assoc_klass)
16
- else
17
- key = reflection.association_primary_key
18
- end
19
-
20
- foreign_key = reflection.foreign_key
21
- else
22
- key = reflection.foreign_key
23
- foreign_key = reflection.active_record_primary_key
24
- end
25
-
26
- if reflection == chain.last
27
- # CPK - TODO add back in tracker support
28
- #bind_val = bind scope, table.table_name, key.to_s, owner[foreign_key], tracker
29
- #scope = scope.where(table[key].eq(bind_val))
30
- predicate = cpk_join_predicate(table, key, owner, foreign_key)
31
- scope = scope.where(predicate)
32
-
33
- if reflection.type
34
- value = owner.class.base_class.name
35
- bind_val = bind scope, table.table_name, reflection.type.to_s, value, tracker
36
- scope = scope.where(table[reflection.type].eq(bind_val))
37
- end
38
- else
39
- # CPK
40
- #constraint = table[key].eq(foreign_table[foreign_key])
41
- constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
42
-
43
- if reflection.type
44
- value = chain[i + 1].klass.base_class.name
45
- bind_val = bind scope, table.table_name, reflection.type.to_s, value, tracker
46
- scope = scope.where(table[reflection.type].eq(bind_val))
47
- end
48
-
49
- scope = scope.joins(join(foreign_table, constraint))
50
- end
51
-
52
- is_first_chain = i == 0
53
- klass = is_first_chain ? assoc_klass : reflection.klass
54
-
55
- # Exclude the scope of the association itself, because that
56
- # was already merged in the #scope method.
57
- scope_chain[i].each do |scope_chain_item|
58
- item = eval_scope(klass, scope_chain_item, owner)
59
-
60
- if scope_chain_item == refl.scope
61
- scope.merge! item.except(:where, :includes, :bind)
62
- end
63
-
64
- if is_first_chain
65
- scope.includes! item.includes_values
66
- end
67
-
68
- scope.where_values += item.where_values
69
- scope.order_values |= item.order_values
70
- end
71
- end
72
-
73
- scope
74
- end
75
- end
76
- end
77
- end
1
+ module ActiveRecord
2
+ module Associations
3
+ class AssociationScope
4
+ def add_constraints(scope, owner, assoc_klass, refl, tracker)
5
+ chain = refl.chain
6
+ scope_chain = refl.scope_chain
7
+
8
+ tables = construct_tables(chain, assoc_klass, refl, tracker)
9
+
10
+ chain.each_with_index do |reflection, i|
11
+ table, foreign_table = tables.shift, tables.first
12
+
13
+ if reflection.source_macro == :belongs_to
14
+ if reflection.options[:polymorphic]
15
+ key = reflection.association_primary_key(assoc_klass)
16
+ else
17
+ key = reflection.association_primary_key
18
+ end
19
+
20
+ foreign_key = reflection.foreign_key
21
+ else
22
+ key = reflection.foreign_key
23
+ foreign_key = reflection.active_record_primary_key
24
+ end
25
+
26
+ if reflection == chain.last
27
+ # CPK - TODO add back in tracker support
28
+ #bind_val = bind scope, table.table_name, key.to_s, owner[foreign_key], tracker
29
+ #scope = scope.where(table[key].eq(bind_val))
30
+ predicate = cpk_join_predicate(table, key, owner, foreign_key)
31
+ scope = scope.where(predicate)
32
+
33
+ if reflection.type
34
+ value = owner.class.base_class.name
35
+ bind_val = bind scope, table.table_name, reflection.type.to_s, value, tracker
36
+ scope = scope.where(table[reflection.type].eq(bind_val))
37
+ end
38
+ else
39
+ # CPK
40
+ #constraint = table[key].eq(foreign_table[foreign_key])
41
+ constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
42
+
43
+ if reflection.type
44
+ value = chain[i + 1].klass.base_class.name
45
+ bind_val = bind scope, table.table_name, reflection.type.to_s, value, tracker
46
+ scope = scope.where(table[reflection.type].eq(bind_val))
47
+ end
48
+
49
+ scope = scope.joins(join(foreign_table, constraint))
50
+ end
51
+
52
+ is_first_chain = i == 0
53
+ klass = is_first_chain ? assoc_klass : reflection.klass
54
+
55
+ # Exclude the scope of the association itself, because that
56
+ # was already merged in the #scope method.
57
+ scope_chain[i].each do |scope_chain_item|
58
+ item = eval_scope(klass, scope_chain_item, owner)
59
+
60
+ if scope_chain_item == refl.scope
61
+ scope.merge! item.except(:where, :includes, :bind)
62
+ end
63
+
64
+ if is_first_chain
65
+ scope.includes! item.includes_values
66
+ end
67
+
68
+ scope.where_values += item.where_values
69
+ scope.order_values |= item.order_values
70
+ end
71
+ end
72
+
73
+ scope
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,59 +1,59 @@
1
- module ActiveRecord
2
- module Associations
3
- class HasAndBelongsToManyAssociation
4
- def insert_record(record, validate = true, raise = false)
5
- if record.new_record?
6
- if raise
7
- record.save!(:validate => validate)
8
- else
9
- return unless record.save(:validate => validate)
10
- end
11
- end
12
-
13
- if options[:insert_sql]
14
- owner.class.connection.insert(interpolate(options[:insert_sql], record))
15
- else
16
- # CPK
17
- #stmt = join_table.compile_insert(
18
- # join_table[reflection.foreign_key] => owner.id,
19
- # join_table[reflection.association_foreign_key] => record.id
20
- #)
21
- join_values = Hash.new
22
- Array(reflection.foreign_key).zip(Array(owner.id)) do |name, value|
23
- attribute = join_table[name]
24
- join_values[attribute] = value
25
- end
26
-
27
- Array(reflection.association_foreign_key).zip(Array(record.id)) do |name, value|
28
- attribute = join_table[name]
29
- join_values[attribute] = value
30
- end
31
-
32
- stmt = join_table.compile_insert(join_values)
33
-
34
- owner.class.connection.insert stmt.to_sql
35
- end
36
-
37
- record
38
- end
39
-
40
- def delete_records(records, method)
41
- if sql = options[:delete_sql]
42
- records.each { |record| owner.class.connection.delete(interpolate(sql, record)) }
43
- else
44
- relation = join_table
45
- # CPK
46
- # stmt = relation.where(relation[reflection.foreign_key].eq(owner.id).
47
- # and(relation[reflection.association_foreign_key].in(records.map { |x| x.id }.compact))
48
- #).compile_delete
49
-
50
- predicate1 = cpk_id_predicate(relation, Array(reflection.foreign_key), Array(owner.id))
51
- predicate2 = cpk_in_predicate(relation, Array(reflection.association_foreign_key), records.map { |x| x.id }) unless records == :all
52
- stmt = relation.where(predicate1.and(predicate2)).compile_delete
53
-
54
- owner.class.connection.delete stmt.to_sql
55
- end
56
- end
57
- end
58
- end
59
- end
1
+ module ActiveRecord
2
+ module Associations
3
+ class HasAndBelongsToManyAssociation
4
+ def insert_record(record, validate = true, raise = false)
5
+ if record.new_record?
6
+ if raise
7
+ record.save!(:validate => validate)
8
+ else
9
+ return unless record.save(:validate => validate)
10
+ end
11
+ end
12
+
13
+ if options[:insert_sql]
14
+ owner.class.connection.insert(interpolate(options[:insert_sql], record))
15
+ else
16
+ # CPK
17
+ #stmt = join_table.compile_insert(
18
+ # join_table[reflection.foreign_key] => owner.id,
19
+ # join_table[reflection.association_foreign_key] => record.id
20
+ #)
21
+ join_values = Hash.new
22
+ Array(reflection.foreign_key).zip(Array(owner.id)) do |name, value|
23
+ attribute = join_table[name]
24
+ join_values[attribute] = value
25
+ end
26
+
27
+ Array(reflection.association_foreign_key).zip(Array(record.id)) do |name, value|
28
+ attribute = join_table[name]
29
+ join_values[attribute] = value
30
+ end
31
+
32
+ stmt = join_table.compile_insert(join_values)
33
+
34
+ owner.class.connection.insert stmt.to_sql
35
+ end
36
+
37
+ record
38
+ end
39
+
40
+ def delete_records(records, method)
41
+ if sql = options[:delete_sql]
42
+ records.each { |record| owner.class.connection.delete(interpolate(sql, record)) }
43
+ else
44
+ relation = join_table
45
+ # CPK
46
+ # stmt = relation.where(relation[reflection.foreign_key].eq(owner.id).
47
+ # and(relation[reflection.association_foreign_key].in(records.map { |x| x.id }.compact))
48
+ #).compile_delete
49
+
50
+ predicate1 = cpk_id_predicate(relation, Array(reflection.foreign_key), Array(owner.id))
51
+ predicate2 = cpk_in_predicate(relation, Array(reflection.association_foreign_key), records.map { |x| x.id }) unless records == :all
52
+ stmt = relation.where(predicate1.and(predicate2)).compile_delete
53
+
54
+ owner.class.connection.delete stmt.to_sql
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end