composite_primary_keys 8.1.8 → 9.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +5 -5
  2. data/History.rdoc +3 -25
  3. data/README.rdoc +1 -0
  4. data/README_DB2.rdoc +33 -33
  5. data/Rakefile +34 -34
  6. data/lib/composite_primary_keys.rb +4 -11
  7. data/lib/composite_primary_keys/associations/association.rb +14 -12
  8. data/lib/composite_primary_keys/associations/association_scope.rb +27 -54
  9. data/lib/composite_primary_keys/associations/collection_association.rb +22 -8
  10. data/lib/composite_primary_keys/associations/has_many_association.rb +16 -54
  11. data/lib/composite_primary_keys/associations/has_many_through_association.rb +58 -58
  12. data/lib/composite_primary_keys/associations/join_dependency.rb +74 -56
  13. data/lib/composite_primary_keys/associations/join_dependency/join_association.rb +13 -11
  14. data/lib/composite_primary_keys/associations/preloader/association.rb +75 -72
  15. data/lib/composite_primary_keys/associations/singular_association.rb +8 -12
  16. data/lib/composite_primary_keys/attribute_methods.rb +6 -4
  17. data/lib/composite_primary_keys/attribute_methods/primary_key.rb +13 -11
  18. data/lib/composite_primary_keys/attribute_methods/read.rb +16 -15
  19. data/lib/composite_primary_keys/attribute_methods/write.rb +21 -19
  20. data/lib/composite_primary_keys/attribute_set/builder.rb +13 -11
  21. data/lib/composite_primary_keys/base.rb +5 -69
  22. data/lib/composite_primary_keys/composite_arrays.rb +8 -51
  23. data/lib/composite_primary_keys/composite_predicates.rb +7 -16
  24. data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +10 -10
  25. data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +42 -11
  26. data/lib/composite_primary_keys/core.rb +46 -45
  27. data/lib/composite_primary_keys/dirty.rb +19 -19
  28. data/lib/composite_primary_keys/fixtures.rb +19 -17
  29. data/lib/composite_primary_keys/locking/optimistic.rb +48 -44
  30. data/lib/composite_primary_keys/nested_attributes.rb +64 -53
  31. data/lib/composite_primary_keys/persistence.rb +49 -41
  32. data/lib/composite_primary_keys/relation.rb +22 -47
  33. data/lib/composite_primary_keys/relation/batches.rb +33 -30
  34. data/lib/composite_primary_keys/relation/calculations.rb +3 -7
  35. data/lib/composite_primary_keys/relation/finder_methods.rb +123 -56
  36. data/lib/composite_primary_keys/relation/predicate_builder.rb +18 -29
  37. data/lib/composite_primary_keys/relation/where_clause.rb +33 -0
  38. data/lib/composite_primary_keys/sanitization.rb +45 -38
  39. data/lib/composite_primary_keys/validations/uniqueness.rb +37 -37
  40. data/lib/composite_primary_keys/version.rb +4 -4
  41. data/scripts/console.rb +48 -48
  42. data/scripts/txt2html +76 -76
  43. data/scripts/txt2js +65 -65
  44. data/tasks/databases/mysql.rake +42 -42
  45. data/tasks/databases/postgresql.rake +47 -47
  46. data/tasks/databases/sqlite3.rake +27 -27
  47. data/tasks/website.rake +18 -18
  48. data/test/README_tests.rdoc +56 -56
  49. data/test/abstract_unit.rb +10 -9
  50. data/test/connections/connection_spec.rb +18 -18
  51. data/test/connections/databases.yml +9 -39
  52. data/test/connections/native_ibm_db/connection.rb +18 -18
  53. data/test/connections/native_mysql/connection.rb +17 -17
  54. data/test/connections/native_postgresql/connection.rb +12 -12
  55. data/test/connections/native_sqlite3/connection.rb +9 -9
  56. data/test/db_test.rb +52 -52
  57. data/test/fixtures/article.rb +5 -5
  58. data/test/fixtures/articles.yml +6 -6
  59. data/test/fixtures/capitol.rb +3 -3
  60. data/test/fixtures/capitols.yml +16 -16
  61. data/test/fixtures/comments.yml +15 -15
  62. data/test/fixtures/db_definitions/mysql.sql +2 -12
  63. data/test/fixtures/db_definitions/oracle.sql +1 -2
  64. data/test/fixtures/db_definitions/postgresql.sql +0 -10
  65. data/test/fixtures/db_definitions/sqlite.sql +0 -9
  66. data/test/fixtures/db_definitions/sqlserver.sql +1 -2
  67. data/test/fixtures/department.rb +5 -5
  68. data/test/fixtures/departments.yml +15 -15
  69. data/test/fixtures/dorms.yml +4 -4
  70. data/test/fixtures/employee.rb +1 -2
  71. data/test/fixtures/employees.yml +19 -23
  72. data/test/fixtures/group.rb +2 -2
  73. data/test/fixtures/groups.yml +6 -6
  74. data/test/fixtures/hack.rb +4 -4
  75. data/test/fixtures/hacks.yml +2 -2
  76. data/test/fixtures/membership_status.rb +2 -2
  77. data/test/fixtures/product.rb +9 -9
  78. data/test/fixtures/product_tariff.rb +5 -5
  79. data/test/fixtures/products.yml +11 -11
  80. data/test/fixtures/reading.rb +4 -4
  81. data/test/fixtures/readings.yml +10 -10
  82. data/test/fixtures/reference_code_using_composite_key_alias.rb +8 -8
  83. data/test/fixtures/reference_code_using_simple_key_alias.rb +8 -8
  84. data/test/fixtures/reference_codes.yml +28 -28
  85. data/test/fixtures/reference_type.rb +1 -1
  86. data/test/fixtures/reference_types.yml +9 -9
  87. data/test/fixtures/restaurant.rb +9 -9
  88. data/test/fixtures/restaurants.yml +14 -14
  89. data/test/fixtures/restaurants_suburbs.yml +10 -10
  90. data/test/fixtures/room.rb +11 -11
  91. data/test/fixtures/room_assignment.rb +13 -13
  92. data/test/fixtures/room_assignments.yml +24 -24
  93. data/test/fixtures/room_attribute.rb +2 -2
  94. data/test/fixtures/room_attribute_assignment.rb +4 -4
  95. data/test/fixtures/room_attribute_assignments.yml +4 -4
  96. data/test/fixtures/room_attributes.yml +2 -2
  97. data/test/fixtures/rooms.yml +12 -12
  98. data/test/fixtures/seat.rb +5 -5
  99. data/test/fixtures/seats.yml +8 -8
  100. data/test/fixtures/street.rb +2 -2
  101. data/test/fixtures/streets.yml +16 -16
  102. data/test/fixtures/student.rb +3 -3
  103. data/test/fixtures/students.yml +15 -15
  104. data/test/fixtures/suburbs.yml +14 -14
  105. data/test/fixtures/tariff.rb +5 -5
  106. data/test/fixtures/tariffs.yml +14 -14
  107. data/test/fixtures/user.rb +0 -1
  108. data/test/plugins/pagination.rb +405 -405
  109. data/test/plugins/pagination_helper.rb +135 -135
  110. data/test/setup.rb +50 -50
  111. data/test/test_aliases.rb +18 -18
  112. data/test/test_associations.rb +7 -18
  113. data/test/test_composite_arrays.rb +24 -38
  114. data/test/test_counter_cache.rb +30 -30
  115. data/test/test_create.rb +5 -5
  116. data/test/test_delete_all.rb +7 -13
  117. data/test/test_dup.rb +37 -37
  118. data/test/test_exists.rb +39 -39
  119. data/test/test_find.rb +16 -12
  120. data/test/test_habtm.rb +26 -2
  121. data/test/test_ids.rb +109 -116
  122. data/test/test_miscellaneous.rb +32 -32
  123. data/test/test_pagination.rb +35 -35
  124. data/test/test_polymorphic.rb +0 -7
  125. data/test/test_predicates.rb +9 -28
  126. data/test/test_update.rb +3 -5
  127. data/test/test_validations.rb +13 -13
  128. metadata +24 -32
  129. data/lib/composite_primary_keys/arel/visitors/to_sql.rb +0 -36
  130. data/lib/composite_primary_keys/attribute_methods/dirty.rb +0 -29
  131. data/lib/composite_primary_keys/autosave_association.rb +0 -67
  132. data/lib/composite_primary_keys/connection_adapters/abstract_mysql_adapter.rb +0 -23
  133. data/test/fixtures/pk_called_id.rb +0 -5
  134. data/test/fixtures/pk_called_ids.yml +0 -11
  135. data/test/test_find_in_batches.rb +0 -30
  136. data/test/test_update_all.rb +0 -17
@@ -1,18 +1,14 @@
1
1
  module CompositePrimaryKeys
2
2
  module SingularAssociation
3
- extend ActiveSupport::Concern
4
- included do
5
- def get_records_with_cpk_support
6
- cpk_applies = (target && target.composite?) ||
7
- (owner && owner.composite?) ||
8
- (options[:primary_key] && options[:primary_key].kind_of?(Array)) ||
9
- (options[:foreign_key] && options[:foreign_key].kind_of?(Array))
10
- return scope.limit(1).to_a if cpk_applies
11
- get_records_without_cpk_support
12
- end
13
- alias_method_chain :get_records, :cpk_support
3
+ def get_records
4
+ cpk_applies = (target && target.composite?) ||
5
+ (owner && owner.composite?) ||
6
+ (options[:primary_key] && options[:primary_key].kind_of?(Array)) ||
7
+ (options[:foreign_key] && options[:foreign_key].kind_of?(Array))
8
+ return scope.limit(1).to_a if cpk_applies
9
+ super
14
10
  end
15
11
  end
16
12
  end
17
13
 
18
- ActiveRecord::Associations::SingularAssociation.send(:include, CompositePrimaryKeys::SingularAssociation)
14
+ ActiveRecord::Associations::SingularAssociation.prepend CompositePrimaryKeys::SingularAssociation
@@ -1,9 +1,11 @@
1
1
  module ActiveRecord
2
2
  module AttributeMethods
3
- def has_attribute?(attr_name)
4
- # CPK
5
- # @attributes.key?(attr_name.to_s)
6
- Array(attr_name).all?{|single_attr| @attributes.key?(single_attr.to_s) }
3
+ silence_warnings do
4
+ def has_attribute?(attr_name)
5
+ # CPK
6
+ # @attributes.key?(attr_name.to_s)
7
+ Array(attr_name).all?{|single_attr| @attributes.key?(single_attr.to_s) }
8
+ end
7
9
  end
8
10
  end
9
11
  end
@@ -1,19 +1,21 @@
1
1
  module ActiveRecord
2
2
  module AttributeMethods
3
3
  module PrimaryKey
4
- # Returns the primary key previous value.
5
- def id_was
6
- sync_with_transaction_state
7
- # CPK
8
- # attribute_was(self.class.primary_key)
9
- if self.composite?
10
- self.class.primary_keys.map do |key_attr|
11
- attribute_changed?(key_attr) ? changed_attributes[key_attr] : self.ids_hash[key_attr]
4
+ silence_warnings do
5
+ # Returns the primary key previous value.
6
+ def id_was
7
+ sync_with_transaction_state
8
+ # CPK
9
+ # attribute_was(self.class.primary_key)
10
+ if self.composite?
11
+ self.class.primary_keys.map do |key_attr|
12
+ attribute_changed?(key_attr) ? changed_attributes[key_attr] : self.ids_hash[key_attr]
13
+ end
14
+ else
15
+ attribute_was(self.class.primary_key)
12
16
  end
13
- else
14
- attribute_was(self.class.primary_key)
15
- end
16
17
 
18
+ end
17
19
  end
18
20
  end
19
21
  end
@@ -1,24 +1,25 @@
1
1
  module ActiveRecord
2
2
  module AttributeMethods
3
3
  module Read
4
- def read_attribute(attr_name, &block)
5
- # CPK
6
- if attr_name.kind_of?(Array)
7
- _read_attribute(attr_name, &block)
8
- else
9
- name = attr_name.to_s
4
+ silence_warnings do
5
+ def read_attribute(attr_name, &block)
10
6
  # CPK
11
- name = self.class.primary_key if name == 'id'.freeze && !composite?
12
- _read_attribute(name, &block)
7
+ if attr_name.kind_of?(Array) || attr_name.to_s == 'id'.freeze && @attributes.key?('id')
8
+ _read_attribute(attr_name, &block)
9
+ else
10
+ name = attr_name.to_s
11
+ name = self.class.primary_key if name == 'id'.freeze
12
+ _read_attribute(name, &block)
13
+ end
13
14
  end
14
- end
15
15
 
16
- def _read_attribute(attr_name)
17
- # CPK
18
- if attr_name.kind_of?(Array)
19
- attr_name.map {|name| @attributes.fetch_value(name.to_s)}
20
- else
21
- @attributes.fetch_value(attr_name.to_s) { |n| yield n if block_given? }
16
+ def _read_attribute(attr_name)
17
+ # CPK
18
+ if attr_name.kind_of?(Array)
19
+ attr_name.map {|name| @attributes.fetch_value(name.to_s)}
20
+ else
21
+ @attributes.fetch_value(attr_name.to_s) { |n| yield n if block_given? }
22
+ end
22
23
  end
23
24
  end
24
25
  end
@@ -1,28 +1,30 @@
1
1
  module ActiveRecord
2
2
  module AttributeMethods
3
3
  module Write
4
- def write_attribute_with_type_cast(attr_name, value, should_type_cast)
5
- # CPK
6
- if attr_name.kind_of?(Array)
7
- value = [nil]*attr_name.length if value.nil?
8
- unless value.length == attr_name.length
9
- raise "Number of attr_names #{attr_name.inspect} and values #{value.inspect} do not match"
10
- end
11
- [attr_name, value].transpose.map {|name,val| write_attribute(name, val)}
12
- value
13
- else
14
- attr_name = attr_name.to_s
4
+ silence_warnings do
5
+ def write_attribute_with_type_cast(attr_name, value, should_type_cast)
15
6
  # CPK
16
- # attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
17
- attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key && !self.composite?
18
-
19
- if should_type_cast
20
- @attributes.write_from_user(attr_name, value)
7
+ if attr_name.kind_of?(Array)
8
+ value = [nil]*attr_name.length if value.nil?
9
+ unless value.length == attr_name.length
10
+ raise "Number of attr_names #{attr_name.inspect} and values #{value.inspect} do not match"
11
+ end
12
+ [attr_name, value].transpose.map {|name,val| write_attribute(name, val)}
13
+ value
21
14
  else
22
- @attributes.write_cast_value(attr_name, value)
23
- end
15
+ attr_name = attr_name.to_s
16
+ # CPK
17
+ # attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key
18
+ attr_name = self.class.primary_key if attr_name == 'id' && self.class.primary_key && !self.composite?
24
19
 
25
- value
20
+ if should_type_cast
21
+ @attributes.write_from_user(attr_name, value)
22
+ else
23
+ @attributes.write_cast_value(attr_name, value)
24
+ end
25
+
26
+ value
27
+ end
26
28
  end
27
29
  end
28
30
  end
@@ -1,19 +1,21 @@
1
1
  module ActiveRecord
2
2
  class AttributeSet # :nodoc:
3
3
  class Builder # :nodoc:
4
- def build_from_database(values = {}, additional_types = {})
5
- # CPK
6
- # if always_initialized && !values.key?(always_initialized)
7
- # values[always_initialized] = nil
8
- # end
9
- Array(always_initialized).each do |always_initialized_attribute|
10
- if always_initialized_attribute && !values.key?(always_initialized_attribute)
11
- values[always_initialized_attribute] = nil
4
+ silence_warnings do
5
+ def build_from_database(values = {}, additional_types = {})
6
+ # CPK
7
+ # if always_initialized && !values.key?(always_initialized)
8
+ # values[always_initialized] = nil
9
+ # end
10
+ Array(always_initialized).each do |always_initialized_attribute|
11
+ if always_initialized_attribute && !values.key?(always_initialized_attribute)
12
+ values[always_initialized_attribute] = nil
13
+ end
12
14
  end
15
+
16
+ attributes = LazyAttributeHash.new(types, values, additional_types)
17
+ AttributeSet.new(attributes)
13
18
  end
14
-
15
- attributes = LazyAttributeHash.new(types, values, additional_types)
16
- AttributeSet.new(attributes)
17
19
  end
18
20
  end
19
21
  end
@@ -21,7 +21,8 @@ module ActiveRecord
21
21
  end
22
22
  end
23
23
 
24
- def primary_key_with_composite_key_support=(keys)
24
+ alias_method :primary_key_without_composite_key_support=, :primary_key=
25
+ def primary_key=(keys)
25
26
  unless keys.kind_of?(Array)
26
27
  self.primary_key_without_composite_key_support = keys
27
28
  return
@@ -34,7 +35,6 @@ module ActiveRecord
34
35
  include CompositeInstanceMethods
35
36
  EOV
36
37
  end
37
- alias_method_chain :primary_key=, :composite_key_support
38
38
  alias_method :primary_keys=, :primary_key=
39
39
 
40
40
  def set_primary_keys(*keys)
@@ -48,75 +48,11 @@ module ActiveRecord
48
48
  else
49
49
  self.primary_keys = keys
50
50
  end
51
- end
51
+ end
52
52
 
53
53
  def composite?
54
54
  false
55
55
  end
56
-
57
- def find_in_batches(options = {})
58
- return super unless primary_key.is_a?(Array)
59
-
60
- # Unfortunately .count uses a subquery temp table, which is a big problem when your table is large
61
- number_of_rows = count(primary_key.first)
62
- batch_size = options[:batch_size] || 100000
63
- row_number = 0
64
-
65
- while row_number < number_of_rows
66
- end_row_number = row_number + batch_size - 1
67
- end_row_number = number_of_rows - 1 if end_row_number > number_of_rows - 1
68
-
69
- # Force the necessary sorting; AR as is will sort a PK table incorrectly
70
- start_key = order(*primary_key).
71
- offset(row_number).
72
- first.
73
- attributes.
74
- slice(*primary_key)
75
-
76
- end_key = order(*(primary_key.map { |k| "#{k} ASC" })).
77
- offset(end_row_number).
78
- first.
79
- attributes.
80
- slice(*primary_key)
81
-
82
- relation = self
83
- lower_bounds = []
84
- upper_bounds = []
85
-
86
- # Iterate through the PKs positionally; when we have found a discrepancy between start and end
87
- # then we know that's where the boundaries are
88
- primary_key.each do |col|
89
- if start_key[col] == end_key[col]
90
- relation = relation.where("#{col} = '#{start_key[col]}'")
91
- else
92
- lower_bounds << [col, start_key[col]]
93
- upper_bounds << [col, end_key[col]]
94
- end
95
- end
96
-
97
- relation = relation.where(build_batch_case(lower_bounds, '>')) unless lower_bounds.empty?
98
- relation = relation.where(build_batch_case(upper_bounds, '<')) unless upper_bounds.empty?
99
-
100
- yield(relation.order(*primary_key))
101
-
102
- row_number = end_row_number + 1
103
- end
104
- end
105
-
106
- private
107
-
108
- def build_batch_case(bounds, operator)
109
- bounds = bounds.dup
110
- bound = bounds.shift
111
- if bounds.empty?
112
- "#{bound[0]} #{operator}= '#{bound[1]}' "
113
- else
114
- sql_case = "CASE WHEN #{bound[0]} = '#{bound[1]}' THEN "
115
- sql_case += build_batch_case(bounds, operator)
116
- sql_case += "ELSE #{bound[0]} #{operator} '#{bound[1]}' END "
117
- sql_case
118
- end
119
- end
120
56
  end
121
57
 
122
58
  def composite?
@@ -129,7 +65,7 @@ module ActiveRecord
129
65
  end
130
66
 
131
67
  def primary_key=(keys)
132
- primary_keys = keys
68
+ self.primary_keys = keys
133
69
  end
134
70
 
135
71
  def composite?
@@ -186,7 +122,7 @@ module ActiveRecord
186
122
  end
187
123
 
188
124
  def to_param
189
- persisted? ? to_key.to_composite_keys.to_s : nil
125
+ persisted? ? to_key.join(CompositePrimaryKeys::ID_SEP) : nil
190
126
  end
191
127
  end
192
128
  end
@@ -1,7 +1,6 @@
1
1
  module CompositePrimaryKeys
2
2
  ID_SEP = ','
3
3
  ID_SET_SEP = ';'
4
- ESCAPE_CHAR = '^'
5
4
 
6
5
  module ArrayExtension
7
6
  def to_composite_keys
@@ -9,27 +8,12 @@ module CompositePrimaryKeys
9
8
  end
10
9
  end
11
10
 
12
- # Convert mixed representation of CPKs (by strings or arrays) to normalized
13
- # representation (just by arrays).
14
- #
15
- # `ids` is Array that may contain:
16
- # 1. A CPK represented by an array or a string.
17
- # 2. An array of CPKs represented by arrays or strings.
18
- #
19
- # There is an issue. Let `ids` contain an array with serveral strings. We can't distinguish case 1
20
- # from case 2 there in general. E.g. the item can be an array containing appropriate number of strings,
21
- # and each string can contain appropriate number of commas. We consider case 2 to win there.
22
- def self.normalize(ids, cpk_size)
11
+ def self.normalize(ids)
23
12
  ids.map do |id|
24
- if Utils.cpk_as_array?(id, cpk_size) && id.any? { |item| !Utils.cpk_as_string?(item, cpk_size) }
25
- # CPK as an array - case 1
26
- id
27
- elsif id.is_a?(Array)
28
- # An array of CPKs - case 2
29
- normalize(id, cpk_size)
30
- elsif id.is_a?(String)
31
- # CPK as a string - case 1
32
- CompositeKeys.parse(id)
13
+ if id.is_a?(Array)
14
+ normalize(id)
15
+ elsif id.is_a?(String) && id.index(ID_SEP)
16
+ id.split(ID_SEP)
33
17
  else
34
18
  id
35
19
  end
@@ -38,12 +22,12 @@ module CompositePrimaryKeys
38
22
 
39
23
  class CompositeKeys < Array
40
24
 
41
- def self.parse(value)
25
+ def self.parse(value)
42
26
  case value
43
27
  when Array
44
28
  value.to_composite_keys
45
29
  when String
46
- value.split(ID_SEP).map { |key| Utils.unescape_string_key(key) }.to_composite_keys
30
+ self.new(value.split(ID_SEP))
47
31
  else
48
32
  raise(ArgumentError, "Unsupported type: #{value}")
49
33
  end
@@ -51,36 +35,9 @@ module CompositePrimaryKeys
51
35
 
52
36
  def to_s
53
37
  # Doing this makes it easier to parse Base#[](attr_name)
54
- map { |key| Utils.escape_string_key(key.to_s) }.join(ID_SEP)
55
- end
56
- end
57
-
58
- module Utils
59
- class << self
60
- def escape_string_key(key)
61
- key.gsub(Regexp.union(ESCAPE_CHAR, ID_SEP)) do |unsafe|
62
- "#{ESCAPE_CHAR}#{unsafe.ord.to_s(16).upcase}"
63
- end
64
- end
65
-
66
- def unescape_string_key(key)
67
- key.gsub(/#{Regexp.escape(ESCAPE_CHAR)}[0-9a-fA-F]{2}/) do |escaped|
68
- char = escaped.slice(1, 2).hex.chr
69
- (char == ESCAPE_CHAR || char == ID_SEP) ? char : escaped
70
- end
71
- end
72
-
73
- def cpk_as_array?(value, pk_size)
74
- # We don't permit Array to be an element of CPK.
75
- value.is_a?(Array) && value.size == pk_size && value.none? { |item| item.is_a?(Array) }
76
- end
77
-
78
- def cpk_as_string?(value, pk_size)
79
- value.is_a?(String) && value.count(ID_SEP) == pk_size - 1
80
- end
38
+ join(ID_SEP)
81
39
  end
82
40
  end
83
- private_constant :Utils
84
41
  end
85
42
 
86
43
  Array.send(:include, CompositePrimaryKeys::ArrayExtension)
@@ -8,23 +8,13 @@ module CompositePrimaryKeys
8
8
  end
9
9
  end
10
10
 
11
- def cpk_or_predicate(predicates, group = true)
12
- if predicates.length <= 1
13
- predicates.first
14
- else
15
- split_point = predicates.length / 2
16
- predicates_first_half = predicates[0...split_point]
17
- predicates_second_half = predicates[split_point..-1]
18
-
19
- or_predicate = ::Arel::Nodes::Or.new(cpk_or_predicate(predicates_first_half, false),
20
- cpk_or_predicate(predicates_second_half, false))
21
-
22
- if group
23
- ::Arel::Nodes::Grouping.new(or_predicate)
24
- else
25
- or_predicate
26
- end
11
+ def cpk_or_predicate(predicates)
12
+ or_predicate = predicates.map do |predicate|
13
+ ::Arel::Nodes::Grouping.new(predicate)
14
+ end.inject do |memo, node|
15
+ ::Arel::Nodes::Or.new(memo, node)
27
16
  end
17
+ ::Arel::Nodes::Grouping.new(or_predicate)
28
18
  end
29
19
 
30
20
  def cpk_id_predicate(table, keys, values)
@@ -39,6 +29,7 @@ module CompositePrimaryKeys
39
29
  key2_fields = Array(key2).map {|key| table2[key]}
40
30
 
41
31
  eq_predicates = key1_fields.zip(key2_fields).map do |key_field1, key_field2|
32
+ key_field2 = Arel::Nodes::Quoted.new(key_field2) unless Arel::Attributes::Attribute === key_field2
42
33
  key_field1.eq(key_field2)
43
34
  end
44
35
  cpk_and_predicate(eq_predicates)
@@ -1,11 +1,11 @@
1
- module ActiveRecord
2
- module ConnectionAdapters
3
- class AbstractAdapter
4
- def quote_column_names(name)
5
- Array(name).map do |col|
6
- quote_column_name(col.to_s)
7
- end.to_composite_keys.to_s
8
- end
9
- end
10
- end
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class AbstractAdapter
4
+ def quote_column_names(name)
5
+ Array(name).map do |col|
6
+ quote_column_name(col.to_s)
7
+ end.join(CompositePrimaryKeys::ID_SEP)
8
+ end
9
+ end
10
+ end
11
11
  end