composite_primary_keys 3.1.11 → 4.0.0.beta1

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.
Files changed (62) hide show
  1. data/History.txt +6 -8
  2. data/lib/composite_primary_keys.rb +53 -36
  3. data/lib/composite_primary_keys/associations/association.rb +23 -0
  4. data/lib/composite_primary_keys/associations/association_scope.rb +67 -0
  5. data/lib/composite_primary_keys/associations/has_and_belongs_to_many_association.rb +31 -121
  6. data/lib/composite_primary_keys/associations/has_many_association.rb +27 -66
  7. data/lib/composite_primary_keys/associations/join_dependency/join_association.rb +22 -0
  8. data/lib/composite_primary_keys/associations/join_dependency/join_part.rb +39 -0
  9. data/lib/composite_primary_keys/associations/preloader/association.rb +61 -0
  10. data/lib/composite_primary_keys/associations/preloader/belongs_to.rb +13 -0
  11. data/lib/composite_primary_keys/associations/preloader/has_and_belongs_to_many.rb +46 -0
  12. data/lib/composite_primary_keys/attribute_methods/dirty.rb +30 -0
  13. data/lib/composite_primary_keys/attribute_methods/read.rb +88 -0
  14. data/lib/composite_primary_keys/attribute_methods/write.rb +33 -0
  15. data/lib/composite_primary_keys/base.rb +18 -70
  16. data/lib/composite_primary_keys/composite_predicates.rb +53 -0
  17. data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +6 -4
  18. data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +19 -41
  19. data/lib/composite_primary_keys/fixtures.rb +19 -6
  20. data/lib/composite_primary_keys/persistence.rb +32 -13
  21. data/lib/composite_primary_keys/relation.rb +23 -16
  22. data/lib/composite_primary_keys/relation/calculations.rb +48 -0
  23. data/lib/composite_primary_keys/relation/finder_methods.rb +117 -0
  24. data/lib/composite_primary_keys/relation/query_methods.rb +24 -0
  25. data/lib/composite_primary_keys/validations/uniqueness.rb +19 -23
  26. data/lib/composite_primary_keys/version.rb +5 -5
  27. data/test/connections/native_mysql/connection.rb +1 -1
  28. data/test/fixtures/articles.yml +1 -0
  29. data/test/fixtures/products.yml +2 -4
  30. data/test/fixtures/readings.yml +1 -0
  31. data/test/fixtures/suburbs.yml +1 -4
  32. data/test/fixtures/users.yml +1 -0
  33. data/test/test_associations.rb +61 -63
  34. data/test/test_attributes.rb +16 -21
  35. data/test/test_create.rb +3 -3
  36. data/test/test_delete.rb +87 -84
  37. data/test/{test_clone.rb → test_dup.rb} +8 -5
  38. data/test/test_exists.rb +22 -10
  39. data/test/test_habtm.rb +0 -74
  40. data/test/test_ids.rb +2 -1
  41. data/test/test_miscellaneous.rb +2 -2
  42. data/test/test_polymorphic.rb +1 -1
  43. data/test/test_suite.rb +1 -1
  44. data/test/test_update.rb +3 -3
  45. metadata +76 -75
  46. data/lib/composite_primary_keys/association_preload.rb +0 -158
  47. data/lib/composite_primary_keys/associations.rb +0 -155
  48. data/lib/composite_primary_keys/associations/association_proxy.rb +0 -33
  49. data/lib/composite_primary_keys/associations/has_one_association.rb +0 -27
  50. data/lib/composite_primary_keys/associations/through_association_scope.rb +0 -103
  51. data/lib/composite_primary_keys/attribute_methods.rb +0 -84
  52. data/lib/composite_primary_keys/calculations.rb +0 -31
  53. data/lib/composite_primary_keys/connection_adapters/ibm_db_adapter.rb +0 -21
  54. data/lib/composite_primary_keys/connection_adapters/oracle_adapter.rb +0 -15
  55. data/lib/composite_primary_keys/connection_adapters/oracle_enhanced_adapter.rb +0 -17
  56. data/lib/composite_primary_keys/connection_adapters/sqlite3_adapter.rb +0 -15
  57. data/lib/composite_primary_keys/finder_methods.rb +0 -123
  58. data/lib/composite_primary_keys/primary_key.rb +0 -19
  59. data/lib/composite_primary_keys/query_methods.rb +0 -24
  60. data/lib/composite_primary_keys/read.rb +0 -25
  61. data/lib/composite_primary_keys/reflection.rb +0 -37
  62. data/lib/composite_primary_keys/write.rb +0 -18
@@ -1,11 +1,6 @@
1
- == 3.1.11 2012-05-20
2
- Fix AssociationReflection#derive_primary_key for belongs_to relationships (Heinrich Lee Yu).
3
-
4
- == 3.1.10 2011-07-08
5
- * Bugfix for belongs_to with includes (John Ash)
6
- * Improved tests for calling clear on a habtm association, which involved (David Rueck)
7
- * Fixed bug that resulted in unrelated records being deleted when calling (David Rueck)
8
- * Output deprecation warnings about extra columns in join table CPK-aware (David Rueck)
1
+ == 4.0.0.beta1 2011-06-09
2
+ * ActiveRecord 3.1 compatibility. This required a significant rewrite due to
3
+ all the changes in AR 3.1 versus 3.0.
9
4
 
10
5
  == 3.1.9 2011-06-04
11
6
  * Improve HABTM association tests (David Rueck)
@@ -19,6 +14,7 @@ Fix AssociationReflection#derive_primary_key for belongs_to relationships (Heinr
19
14
  * Minor test cleanup (Charlie Savage)
20
15
  * Make version requirements more explicit (Charlie Savage)
21
16
  * Remove Arel extensions used for calculations (Charlie Savage)
17
+ * Fix test that included wrong error constant
22
18
 
23
19
  == 3.1.6 2011-04-03
24
20
  * Updated belongs_to association to be a bit more flexible with non-CPK (Charlie Savage)
@@ -27,12 +23,14 @@ Fix AssociationReflection#derive_primary_key for belongs_to relationships (Heinr
27
23
  * Fix write issue when one of they keys in a composite key is
28
24
  called id (Tom Hughes)
29
25
 
26
+
30
27
  == 3.1.5 2011-03-24
31
28
  * Fix simple calculation methods (Charlie Savage)
32
29
  * Fix instantiation of cpk records via associations (Charlie Savage)
33
30
  * Fix Relation#delete (Charlie Savage)
34
31
  * Fix Relation#destroy (Charlie Savage)
35
32
 
33
+
36
34
  == 3.1.4 2011-03-06
37
35
  * Support ActiveRecord 3.0.5 - interpolate_sql was removed and
38
36
  replaced by interpolate_and_sanitize_sql (Charlie Savage)
@@ -26,50 +26,67 @@ $:.unshift(File.dirname(__FILE__)) unless
26
26
 
27
27
  unless defined?(ActiveRecord)
28
28
  require 'rubygems'
29
- gem 'activerecord', '>= 3.0.5', '~> 3.0.0'
29
+ gem 'activerecord', '=3.1.0.rc1'
30
30
  require 'active_record'
31
31
  end
32
32
 
33
- require 'active_record/associations.rb'
34
- require 'active_record/associations/association_proxy.rb'
35
- require 'active_record/associations/association_collection'
36
- require 'active_record/associations/association_proxy'
37
- require 'active_record/associations/belongs_to_association'
38
- require 'active_record/associations/belongs_to_polymorphic_association'
33
+ # AR files we override
34
+ require 'active_record/fixtures'
35
+ require 'active_record/persistence'
36
+ require 'active_record/relation'
37
+
38
+ require 'active_record/associations/association'
39
+ require 'active_record/associations/association_scope'
39
40
  require 'active_record/associations/has_and_belongs_to_many_association'
40
41
  require 'active_record/associations/has_many_association'
41
- require 'active_record/associations/has_one_association'
42
- require 'active_record/associations/has_one_through_association'
43
- require 'active_record/associations/through_association_scope'
44
- require 'active_record/persistence'
42
+ require 'active_record/associations/join_dependency/join_part'
43
+ require 'active_record/associations/join_dependency/join_association'
44
+ require 'active_record/associations/preloader/association'
45
+ require 'active_record/associations/preloader/belongs_to'
46
+ require 'active_record/associations/preloader/has_and_belongs_to_many'
47
+
48
+ require 'active_record/attribute_methods/dirty'
49
+ require 'active_record/attribute_methods/read'
50
+ require 'active_record/attribute_methods/write'
51
+
52
+ require 'active_record/connection_adapters/abstract_adapter'
53
+ require 'active_record/connection_adapters/postgresql_adapter'
54
+
55
+ require 'active_record/relation/calculations'
56
+ require 'active_record/relation/finder_methods'
45
57
  require 'active_record/relation/query_methods'
46
- require 'active_record/attribute_methods/primary_key'
47
- require 'active_record/fixtures'
48
58
 
59
+ require 'active_record/validations/uniqueness'
60
+
61
+
62
+ # CPK files
63
+ require 'composite_primary_keys/base'
49
64
  require 'composite_primary_keys/composite_arrays'
50
- require 'composite_primary_keys/associations'
51
- require 'composite_primary_keys/associations/association_proxy'
52
- require 'composite_primary_keys/associations/has_one_association'
53
- require 'composite_primary_keys/associations/has_many_association'
54
- require 'composite_primary_keys/associations/has_and_belongs_to_many_association'
55
- require 'composite_primary_keys/associations/through_association_scope'
56
- require 'composite_primary_keys/association_preload'
65
+ require 'composite_primary_keys/composite_predicates'
66
+ require 'composite_primary_keys/fixtures'
57
67
  require 'composite_primary_keys/persistence'
58
- require 'composite_primary_keys/reflection'
59
68
  require 'composite_primary_keys/relation'
60
- require 'composite_primary_keys/read'
61
- require 'composite_primary_keys/write'
62
- require 'composite_primary_keys/finder_methods'
63
- require 'composite_primary_keys/base'
64
- require 'composite_primary_keys/calculations'
65
- require 'composite_primary_keys/validations/uniqueness'
66
- require 'composite_primary_keys/query_methods'
67
- require 'composite_primary_keys/primary_key'
68
- require 'composite_primary_keys/fixtures'
69
+ require 'composite_primary_keys/version'
69
70
 
70
- Dir[File.dirname(__FILE__) + '/composite_primary_keys/connection_adapters/*.rb'].each do |adapter|
71
- begin
72
- require adapter.gsub('.rb','')
73
- rescue MissingSourceFile
74
- end
75
- end
71
+ require 'composite_primary_keys/associations/association'
72
+ require 'composite_primary_keys/associations/association_scope'
73
+ require 'composite_primary_keys/associations/has_and_belongs_to_many_association'
74
+ require 'composite_primary_keys/associations/has_many_association'
75
+ require 'composite_primary_keys/associations/join_dependency/join_part'
76
+ require 'composite_primary_keys/associations/join_dependency/join_association'
77
+ require 'composite_primary_keys/associations/preloader/association'
78
+ require 'composite_primary_keys/associations/preloader/belongs_to'
79
+ require 'composite_primary_keys/associations/preloader/has_and_belongs_to_many'
80
+
81
+ require 'composite_primary_keys/attribute_methods/dirty'
82
+ require 'composite_primary_keys/attribute_methods/read'
83
+ require 'composite_primary_keys/attribute_methods/write'
84
+
85
+ require 'composite_primary_keys/connection_adapters/abstract_adapter'
86
+ require 'composite_primary_keys/connection_adapters/postgresql_adapter'
87
+
88
+ require 'composite_primary_keys/relation/calculations'
89
+ require 'composite_primary_keys/relation/finder_methods'
90
+ require 'composite_primary_keys/relation/query_methods'
91
+
92
+ require 'composite_primary_keys/validations/uniqueness'
@@ -0,0 +1,23 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ class Association
4
+ def creation_attributes
5
+ attributes = {}
6
+
7
+ if reflection.macro.in?([:has_one, :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
@@ -0,0 +1,67 @@
1
+ module ActiveRecord
2
+ module Associations
3
+ class AssociationScope
4
+ def add_constraints(scope)
5
+ tables = construct_tables
6
+
7
+ chain.each_with_index do |reflection, i|
8
+ table, foreign_table = tables.shift, tables.first
9
+
10
+ if reflection.source_macro == :has_and_belongs_to_many
11
+ join_table = tables.shift
12
+
13
+ # CPK
14
+ # scope = scope.joins(join(
15
+ # join_table,
16
+ # table[reflection.active_record_primary_key].
17
+ # eq(join_table[reflection.association_foreign_key])
18
+ #))
19
+ predicate = cpk_join_predicate(table, reflection.association_primary_key,
20
+ join_table, reflection.association_foreign_key)
21
+ scope = scope.joins(join(join_table, predicate))
22
+
23
+ table, foreign_table = join_table, tables.first
24
+ end
25
+
26
+ if reflection.source_macro == :belongs_to
27
+ key = reflection.association_primary_key
28
+ foreign_key = reflection.foreign_key
29
+ else
30
+ key = reflection.foreign_key
31
+ foreign_key = reflection.active_record_primary_key
32
+ end
33
+
34
+ if reflection == chain.last
35
+ # CPK
36
+ # scope = scope.where(table[key].eq(owner[foreign_key]))
37
+ predicate = cpk_join_predicate(table, key, owner, foreign_key)
38
+ scope = scope.where(predicate)
39
+
40
+ conditions[i].each do |condition|
41
+ if options[:through] && condition.is_a?(Hash)
42
+ condition = { table.name => condition }
43
+ end
44
+
45
+ scope = scope.where(interpolate(condition))
46
+ end
47
+ else
48
+ # CPK
49
+ # constraint = table[key].eq(foreign_table[foreign_key])
50
+ constraint = cpk_join_predicate(table, key, foreign_table, foreign_key)
51
+ scope = scope.where(predicate)
52
+
53
+ join = join(foreign_table, constraint)
54
+
55
+ scope = scope.joins(join)
56
+
57
+ unless conditions[i].empty?
58
+ scope = scope.where(sanitize(conditions[i], table))
59
+ end
60
+ end
61
+ end
62
+
63
+ scope
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,143 +1,53 @@
1
1
  module ActiveRecord
2
2
  module Associations
3
3
  class HasAndBelongsToManyAssociation
4
- def construct_sql
5
- if @reflection.options[:finder_sql]
6
- @finder_sql = interpolate_and_sanitize_sql(@reflection.options[:finder_sql])
4
+ def insert_record(record, validate = true)
5
+ return if record.new_record? && !record.save(:validate => validate)
6
+
7
+ if options[:insert_sql]
8
+ owner.connection.insert(interpolate(options[:insert_sql], record))
7
9
  else
8
10
  # CPK
9
- # @finder_sql = "#{@owner.connection.quote_table_name @reflection.options[:join_table]}.#{@reflection.primary_key_name} = #{owner_quoted_id} "
10
- @finder_sql = full_columns_equals(@reflection.options[:join_table], @reflection.cpk_primary_key, owner_quoted_id)
11
- @finder_sql << " AND (#{conditions})" if conditions
12
- end
13
-
14
- join_condition = if composite?
15
- conditions = Array.new
16
- primary_keys.length.times do |i|
17
- conditions << "#{@reflection.quoted_table_name}.#{@reflection.klass.primary_key[i]} = #{@owner.connection.quote_table_name @reflection.options[:join_table]}.#{@reflection.association_foreign_key[i]}"
11
+ #stmt = join_table.compile_insert(
12
+ # join_table[reflection.foreign_key] => owner.id,
13
+ # join_table[reflection.association_foreign_key] => record.id
14
+ #)
15
+ join_values = Hash.new
16
+ Array(reflection.foreign_key).zip(Array(owner.id)) do |name, value|
17
+ attribute = join_table[name]
18
+ join_values[attribute] = value
18
19
  end
19
- conditions.join(' AND ')
20
- else
21
- "#{@reflection.quoted_table_name}.#{@reflection.klass.primary_key} = #{@owner.connection.quote_table_name @reflection.options[:join_table]}.#{@reflection.association_foreign_key}"
22
- end
23
- #@join_sql = "INNER JOIN #{@owner.connection.quote_table_name @reflection.options[:join_table]} ON #{@reflection.quoted_table_name}.#{@reflection.klass.primary_key} = #{@owner.connection.quote_table_name @reflection.options[:join_table]}.#{@reflection.association_foreign_key}"
24
- @join_sql = "INNER JOIN #{@owner.connection.quote_table_name @reflection.options[:join_table]} ON (#{join_condition})"
25
20
 
26
- construct_counter_sql
27
- end
28
-
29
- def insert_record(record, force = true, validate = true)
30
- unless record.persisted?
31
- if force
32
- record.save!
33
- else
34
- return false unless record.save(:validate => validate)
21
+ Array(reflection.association_foreign_key).zip(Array(record.id)) do |name, value|
22
+ attribute = join_table[name]
23
+ join_values[attribute] = value
35
24
  end
36
- end
37
-
38
- if @reflection.options[:insert_sql]
39
- @owner.connection.insert(interpolate_and_sanitize_sql(@reflection.options[:insert_sql], record))
40
- else
41
- relation = Arel::Table.new(@reflection.options[:join_table])
42
- timestamps = record_timestamp_columns(record)
43
- timezone = record.send(:current_time_from_proper_timezone) if timestamps.any?
44
25
 
45
- # CPK
46
- #attributes = Hash[columns.map do |column|
47
- # name = column.name
48
- # value = case name.to_s
49
- # when @reflection.primary_key_name.to_s
50
- # @owner.id
51
- # when @reflection.association_foreign_key.to_s
52
- # record.id
53
- # when *timestamps
54
- # timezone
55
- # else
56
- # @owner.send(:quote_value, record[name], column) if record.has_attribute?(name)
57
- # end
58
- # [relation[name], value] unless value.nil?
59
- #end]
60
-
61
- # CPK
62
- owner_foreign_keys = @reflection.cpk_primary_key.map{|key| key.to_s}
63
- association_foreign_keys = Array(@reflection.association_foreign_key).map{|key| key.to_s}
26
+ stmt = join_table.compile_insert(join_values)
64
27
 
65
- attributes = Hash[columns.map do |column|
66
- name = column.name.to_s
67
- value = case
68
- when owner_foreign_keys.include?(name)
69
- index = owner_foreign_keys.index(name)
70
- primary_keys = Array(@owner.class.primary_key)
71
- primary_key = primary_keys[index]
72
- @owner[primary_key]
73
- when association_foreign_keys.include?(name)
74
- index = association_foreign_keys.index(name)
75
- primary_keys = Array(@reflection.klass.primary_key)
76
- primary_key = primary_keys[index]
77
- record[primary_key]
78
- when timestamps.include?(name)
79
- timezone
80
- else
81
- @owner.send(:quote_value, record[name], column) if record.has_attribute?(name)
82
- end
83
- [relation[name], value] unless value.nil?
84
- end]
85
-
86
- relation.insert(attributes)
28
+ owner.connection.insert stmt.to_sql
87
29
  end
88
30
 
89
- return true
31
+ record
90
32
  end
91
33
 
92
- # CPK
93
- #def delete_records(records)
94
- # if sql = @reflection.options[:delete_sql]
95
- # records.each { |record| @owner.connection.delete(interpolate_and_sanitize_sql(sql, record)) }
96
- # else
97
- # relation = Arel::Table.new(@reflection.options[:join_table])
98
- # relation.where(relation[@reflection.primary_key_name].eq(@owner.id).
99
- # and(relation[@reflection.association_foreign_key].in(records.map { |x| x.id }.compact))
100
- # ).delete
101
- # end
102
- #end
103
-
104
- # CPK
105
- def delete_records(records)
106
- if sql = @reflection.options[:delete_sql]
107
- records.each { |record| @owner.connection.delete(interpolate_and_sanitize_sql(sql, record)) }
34
+ def delete_records(records, method)
35
+ if sql = options[:delete_sql]
36
+ records.each { |record| owner.connection.delete(interpolate(sql, record)) }
108
37
  else
109
- relation = Arel::Table.new(@reflection.options[:join_table])
38
+ relation = join_table
39
+ # CPK
40
+ # stmt = relation.where(relation[reflection.foreign_key].eq(owner.id).
41
+ # and(relation[reflection.association_foreign_key].in(records.map { |x| x.id }.compact))
42
+ #).compile_delete
110
43
 
111
- if @reflection.cpk_primary_key.size > 1
112
- owner_conditions = []
113
- @reflection.cpk_primary_key.each_with_index do |column,i|
114
- owner_conditions << relation[column.to_sym].eq(@owner.id[i])
115
- end
116
- owner_conditions_arel = owner_conditions.inject { |conds, cond| conds.and(cond) }
117
- else
118
- owner_conditions_arel = relation[@reflection.primary_key_name].eq(@owner.id)
119
- end
44
+ predicate1 = cpk_id_predicate(relation, Array(reflection.foreign_key), Array(owner.id))
45
+ predicate2 = cpk_in_predicate(relation, Array(reflection.association_foreign_key), records.map { |x| x.id })
46
+ stmt = relation.where(predicate1.and(predicate2)).compile_delete
120
47
 
121
- if @reflection.association_foreign_key.kind_of?(Array)
122
- association_conditions = []
123
- records.each do |rec|
124
- record_conditions = []
125
- @reflection.association_foreign_key.each_with_index do |column,i|
126
- record_conditions << relation[column.to_sym].eq(rec.id[i])
127
- end
128
- association_conditions << record_conditions.inject { |conds, cond| conds.and(cond) }
129
- end
130
- association_conditions_arel = association_conditions.inject { |conds, cond| conds.or(cond) }
131
- else
132
- association_conditions_arel = relation[@reflection.association_foreign_key].in(records.map { |x| x.id }.compact)
133
- end
134
-
135
- all_conditions_arel = owner_conditions_arel.and(association_conditions_arel)
136
-
137
- relation.where(all_conditions_arel).delete
48
+ owner.connection.delete stmt.to_sql
138
49
  end
139
50
  end
140
-
141
51
  end
142
52
  end
143
53
  end
@@ -1,79 +1,40 @@
1
1
  module ActiveRecord
2
2
  module Associations
3
3
  class HasManyAssociation
4
- def construct_sql
5
- case
6
- when @reflection.options[:finder_sql]
7
- @finder_sql = interpolate_and_sanitize_sql(@reflection.options[:finder_sql])
8
-
9
- when @reflection.options[:as]
10
- @finder_sql =
11
- "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND " +
12
- "#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}"
13
- @finder_sql << " AND (#{conditions})" if conditions
14
-
15
- else
16
- # CPK
17
- # @finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
18
- @finder_sql = full_columns_equals(@reflection.table_name, @reflection.cpk_primary_key, owner_quoted_id)
19
- @finder_sql << " AND (#{conditions})" if conditions
20
- end
21
-
22
- construct_counter_sql
23
- end
24
-
25
- def owner_quoted_id
26
- if (keys = @reflection.options[:primary_key])
27
- keys.is_a?(Array) ? keys.collect {|k| quote_value(@owner.send(k)) } : quote_value(@owner.send(keys))
4
+ def delete_records(records, method)
5
+ if method == :destroy
6
+ records.each { |r| r.destroy }
7
+ update_counter(-records.length) unless inverse_updates_counter_cache?
28
8
  else
29
- @owner.quoted_id
30
- end
31
- end
32
-
33
- def delete_records(records)
34
- case @reflection.options[:dependent]
35
- when :destroy
36
- records.each { |r| r.destroy }
37
- when :delete_all
38
- @reflection.klass.delete(records.map { |record| record.id })
39
- else
40
- relation = Arel::Table.new(@reflection.table_name)
41
- # CPK
42
- #relation.where(relation[@reflection.primary_key_name].eq(@owner.id).
43
- # and(relation[@reflection.klass.primary_key].in(records.map { |r| r.id }))
44
- #).update(relation[@reflection.primary_key_name] => nil)
45
-
46
- id_predicate = nil
47
- owner_key_values = @reflection.cpk_primary_key.zip([@owner.id].flatten)
48
- owner_key_values.each do |key, value|
49
- eq = relation[key].eq(value)
50
- id_predicate = id_predicate ? id_predicate.and(eq) : eq
9
+ # CPK
10
+ # keys = records.map { |r| r[reflection.association_primary_key] }
11
+ # scope = scoped.where(reflection.association_primary_key => keys)
12
+ table = Arel::Table.new(reflection.table_name)
13
+ and_conditions = records.map do |record|
14
+ eq_conditions = Array(reflection.association_primary_key).map do |name|
15
+ table[name].eq(record[name])
51
16
  end
17
+ Arel::Nodes::And.new(eq_conditions)
18
+ end
52
19
 
53
- record_predicates = nil
54
- records.each do |record|
55
- keys = [@reflection.klass.primary_key].flatten
56
- values = [record.id].flatten
57
-
58
- record_predicate = nil
59
- keys.zip(values).each do |key, value|
60
- eq = relation[key].eq(value)
61
- record_predicate = record_predicate ? record_predicate.and(eq) : eq
62
- end
63
- record_predicates = record_predicates ? record_predicates.or(record_predicate) : record_predicate
64
- end
20
+ condition = and_conditions.shift
21
+ and_conditions.each do |and_condition|
22
+ condition = condition.or(and_condition)
23
+ end
65
24
 
66
- relation = relation.where(id_predicate.and(record_predicates))
25
+ scope = scoped.where(condition)
67
26
 
68
- nullify_relation = Arel::Table.new(@reflection.table_name)
69
- nullify = @reflection.cpk_primary_key.inject(Hash.new) do |hash, key|
70
- hash[nullify_relation[key]] = nil
27
+ if method == :delete_all
28
+ update_counter(-scope.delete_all)
29
+ else
30
+ # CPK
31
+ # update_counter(-scope.update_all(reflection.foreign_key => nil))
32
+ updates = Array(reflection.foreign_key).inject(Hash.new) do |hash, name|
33
+ hash[name] = nil
71
34
  hash
72
35
  end
73
-
74
- relation.update(nullify)
75
-
76
- @owner.class.update_counters(@owner.id, cached_counter_attribute_name => -records.size) if has_cached_counter?
36
+ update_counter(-scope.update_all(updates))
37
+ end
77
38
  end
78
39
  end
79
40
  end