composite_primary_keys 0.7.5 → 0.8.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.
Files changed (46) hide show
  1. data/Manifest.txt +75 -0
  2. data/Rakefile +83 -101
  3. data/lib/composite_primary_keys.rb +8 -0
  4. data/lib/composite_primary_keys/associations.rb +66 -18
  5. data/lib/composite_primary_keys/base.rb +169 -159
  6. data/lib/composite_primary_keys/calculations.rb +63 -0
  7. data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +11 -0
  8. data/lib/composite_primary_keys/version.rb +2 -2
  9. data/scripts/txt2html +4 -2
  10. data/scripts/txt2js +3 -2
  11. data/test/abstract_unit.rb +9 -2
  12. data/test/connections/native_mysql/connection.rb +5 -2
  13. data/test/connections/native_postgresql/connection.rb +15 -0
  14. data/test/connections/native_sqlite/connection.rb +10 -0
  15. data/test/fixtures/db_definitions/mysql.sql +20 -0
  16. data/test/fixtures/db_definitions/postgresql.sql +100 -0
  17. data/test/fixtures/db_definitions/sqlite.sql +84 -0
  18. data/test/fixtures/group.rb +3 -0
  19. data/test/fixtures/groups.yml +3 -0
  20. data/test/fixtures/membership.rb +7 -0
  21. data/test/fixtures/membership_status.rb +3 -0
  22. data/test/fixtures/membership_statuses.yml +8 -0
  23. data/test/fixtures/memberships.yml +6 -0
  24. data/test/{associations_test.rb → test_associations.rb} +22 -12
  25. data/test/{attributes_test.rb → test_attributes.rb} +4 -5
  26. data/test/{clone_test.rb → test_clone.rb} +2 -3
  27. data/test/{create_test.rb → test_create.rb} +2 -3
  28. data/test/{delete_test.rb → test_delete.rb} +2 -3
  29. data/test/{dummy_test.rb → test_dummy.rb} +4 -5
  30. data/test/{find_test.rb → test_find.rb} +3 -4
  31. data/test/{ids_test.rb → test_ids.rb} +4 -4
  32. data/test/{miscellaneous_test.rb → test_miscellaneous.rb} +2 -3
  33. data/test/{pagination_test.rb → test_pagination.rb} +4 -3
  34. data/test/{santiago_test.rb → test_santiago.rb} +5 -3
  35. data/test/test_tutorial_examle.rb +29 -0
  36. data/test/{update_test.rb → test_update.rb} +2 -3
  37. data/website/index.html +267 -201
  38. data/website/index.txt +74 -70
  39. data/website/stylesheets/screen.css +33 -3
  40. data/website/version-raw.js +1 -1
  41. data/website/version.js +1 -1
  42. metadata +80 -66
  43. data/scripts/http-access2-2.0.6.gem +0 -0
  44. data/scripts/rubyforge +0 -217
  45. data/scripts/rubyforge-orig +0 -217
  46. data/test/fixtures/db_definitions/mysql.drop.sql +0 -10
@@ -0,0 +1,75 @@
1
+ CHANGELOG
2
+ Manifest.txt
3
+ README
4
+ Rakefile
5
+ install.rb
6
+ lib/composite_primary_keys.rb
7
+ lib/composite_primary_keys/associations.rb
8
+ lib/composite_primary_keys/base.rb
9
+ lib/composite_primary_keys/calculations.rb
10
+ lib/composite_primary_keys/composite_arrays.rb
11
+ lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb
12
+ lib/composite_primary_keys/fixtures.rb
13
+ lib/composite_primary_keys/reflection.rb
14
+ lib/composite_primary_keys/version.rb
15
+ scripts/txt2html
16
+ scripts/txt2js
17
+ test/abstract_unit.rb
18
+ test/composite_arrays_test.rb
19
+ test/connections/native_mysql/connection.rb
20
+ test/connections/native_oracle/connection.rb
21
+ test/connections/native_postgresql/connection.rb
22
+ test/connections/native_sqlite/connection.rb
23
+ test/fixtures/article.rb
24
+ test/fixtures/articles.yml
25
+ test/fixtures/db_definitions/mysql.sql
26
+ test/fixtures/db_definitions/postgresql.sql
27
+ test/fixtures/db_definitions/sqlite.sql
28
+ test/fixtures/group.rb
29
+ test/fixtures/groups.yml
30
+ test/fixtures/membership.rb
31
+ test/fixtures/membership_status.rb
32
+ test/fixtures/membership_statuses.yml
33
+ test/fixtures/memberships.yml
34
+ test/fixtures/product.rb
35
+ test/fixtures/product_tariff.rb
36
+ test/fixtures/product_tariffs.yml
37
+ test/fixtures/products.yml
38
+ test/fixtures/reading.rb
39
+ test/fixtures/readings.yml
40
+ test/fixtures/reference_code.rb
41
+ test/fixtures/reference_codes.yml
42
+ test/fixtures/reference_type.rb
43
+ test/fixtures/reference_types.yml
44
+ test/fixtures/street.rb
45
+ test/fixtures/streets.yml
46
+ test/fixtures/suburb.rb
47
+ test/fixtures/suburbs.yml
48
+ test/fixtures/tariff.rb
49
+ test/fixtures/tariffs.yml
50
+ test/fixtures/user.rb
51
+ test/fixtures/users.yml
52
+ test/hash_tricks.rb
53
+ test/test_associations.rb
54
+ test/test_attributes.rb
55
+ test/test_clone.rb
56
+ test/test_create.rb
57
+ test/test_delete.rb
58
+ test/test_dummy.rb
59
+ test/test_find.rb
60
+ test/test_ids.rb
61
+ test/test_miscellaneous.rb
62
+ test/test_pagination.rb
63
+ test/test_santiago.rb
64
+ test/test_tutorial_examle.rb
65
+ test/test_update.rb
66
+ website/index.html
67
+ website/index.txt
68
+ website/javascripts/rounded_corners_lite.inc.js
69
+ website/stylesheets/screen.css
70
+ website/template.js
71
+ website/template.rhtml
72
+ website/version-raw.js
73
+ website/version-raw.txt
74
+ website/version.js
75
+ website/version.txt
data/Rakefile CHANGED
@@ -1,12 +1,56 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
+ require 'rake/clean'
3
4
  require 'rake/testtask'
4
5
  require 'rake/rdoctask'
5
6
  require 'rake/packagetask'
6
7
  require 'rake/gempackagetask'
7
8
  require 'rake/contrib/rubyforgepublisher'
9
+ require 'fileutils'
10
+ require 'hoe'
11
+ include FileUtils
8
12
  require File.join(File.dirname(__FILE__), 'lib', 'composite_primary_keys', 'version')
9
13
 
14
+ AUTHOR = "Dr Nic Williams"
15
+ EMAIL = "drnicwilliams@gmail.com"
16
+ DESCRIPTION = "Composite key support for ActiveRecords"
17
+ GEM_NAME = "composite_primary_keys" # what ppl will type to install your gem
18
+ RUBYFORGE_PROJECT = "compositekeys"
19
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
20
+
21
+ REV = nil #File.read(".svn/entries")[/committed-rev="(\d+)"/, 1] rescue nil
22
+ VERSION = ENV['VERSION'] || (CompositePrimaryKeys::VERSION::STRING + (REV ? ".#{REV}" : ""))
23
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
24
+ RDOC_OPTS = ['--quiet', '--title', "newgem documentation",
25
+ "--opname", "index.html",
26
+ "--line-numbers",
27
+ "--main", "README",
28
+ "--inline-source"]
29
+
30
+ class Hoe
31
+ def extra_deps
32
+ @extra_deps.reject { |x| Array(x).first == 'hoe' }
33
+ end
34
+ end
35
+
36
+ # Generate all the Rake tasks
37
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
38
+ hoe = Hoe.new(GEM_NAME, VERSION) do |p|
39
+ p.author = AUTHOR
40
+ p.description = DESCRIPTION
41
+ p.email = EMAIL
42
+ p.summary = DESCRIPTION
43
+ p.url = HOMEPATH
44
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
45
+ p.test_globs = ["test/**/test*.rb"]
46
+ p.clean_globs = CLEAN #An array of file patterns to delete on clean.
47
+
48
+ # == Optional
49
+ #p.changes - A description of the release's latest changes.
50
+ p.extra_deps = [['activerecord', '>= 1.14.3']] #An array of rubygem dependencies.
51
+ #p.spec_extras - A hash of extra values to set in the gemspec.
52
+ end
53
+
10
54
  PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
11
55
  PKG_NAME = 'composite_primary_keys'
12
56
  PKG_VERSION = CompositePrimaryKeys::VERSION::STRING + PKG_BUILD
@@ -18,16 +62,10 @@ RUBY_FORGE_PROJECT = "compositekeys"
18
62
  RUBY_FORGE_USER = "nicwilliams"
19
63
 
20
64
 
21
- desc "Default Task"
22
- task :default => [ :test_mysql ] # UNTESTED =, :test_sqlite, :test_postgresql ]
23
- task :test => [ :test_mysql ]
24
-
25
- # Run the unit tests
26
-
27
- for adapter in %w( mysql ) # UNTESTED - postgresql sqlite sqlite3 firebird sqlserver sqlserver_odbc db2 oracle sybase openbase )
65
+ for adapter in %w( mysql sqlite oracle postgresql ) # UNTESTED - firebird sqlserver sqlserver_odbc db2 sybase openbase )
28
66
  Rake::TestTask.new("test_#{adapter}") { |t|
29
67
  t.libs << "test" << "test/connections/native_#{adapter}"
30
- t.pattern = "test/*_test{,_#{adapter}}.rb"
68
+ t.pattern = "test/test_*.rb"
31
69
  t.verbose = true
32
70
  }
33
71
  end
@@ -37,121 +75,65 @@ SCHEMA_PATH = File.join(File.dirname(__FILE__), *%w(test fixtures db_definitions
37
75
  desc 'Build the MySQL test databases'
38
76
  task :build_mysql_databases do
39
77
  puts File.join(SCHEMA_PATH, 'mysql.sql')
40
- %x( mysqladmin -u root create "#{PKG_NAME}_unittest" )
41
- %x( mysql -u root "#{PKG_NAME}_unittest" < #{File.join(SCHEMA_PATH, 'mysql.sql')} )
78
+ sh %{ mysqladmin -u root create "#{PKG_NAME}_unittest" }
79
+ sh %{ mysql -u root "#{PKG_NAME}_unittest" < #{File.join(SCHEMA_PATH, 'mysql.sql')} }
42
80
  end
43
81
 
44
82
  desc 'Drop the MySQL test databases'
45
83
  task :drop_mysql_databases do
46
- %x( mysqladmin -u root -f drop "#{PKG_NAME}_unittest" )
84
+ sh %{ mysqladmin -u root -f drop "#{PKG_NAME}_unittest" }
47
85
  end
48
86
 
49
87
  desc 'Rebuild the MySQL test databases'
88
+
50
89
  task :rebuild_mysql_databases => [:drop_mysql_databases, :build_mysql_databases]
51
90
 
91
+ desc 'Build the sqlite test databases'
92
+ task :build_sqlite_databases do
93
+ file = File.join(SCHEMA_PATH, 'sqlite.sql')
94
+ cmd = "sqlite3 test.db < #{file}"
95
+ puts cmd
96
+ sh %{ #{cmd} }
97
+ end
98
+
99
+ desc 'Drop the sqlite test databases'
100
+ task :drop_sqlite_databases do
101
+ sh %{ rm -f test.db }
102
+ end
103
+
104
+ desc 'Rebuild the sqlite test databases'
105
+ task :rebuild_sqlite_databases => [:drop_sqlite_databases, :build_sqlite_databases]
106
+
52
107
  desc 'Build the PostgreSQL test databases'
53
108
  task :build_postgresql_databases do
54
- %x( createdb "#{PKG_NAME}_unittest" )
55
- %x( psql "#{PKG_NAME}_unittest" -f #{File.join(SCHEMA_PATH, 'postgresql.sql')} )
109
+ sh %{ createdb "#{PKG_NAME}_unittest" }
110
+ sh %{ psql "#{PKG_NAME}_unittest" -f #{File.join(SCHEMA_PATH, 'postgresql.sql')} }
56
111
  end
57
112
 
58
113
  desc 'Drop the PostgreSQL test databases'
59
114
  task :drop_postgresql_databases do
60
- %x( dropdb "#{PKG_NAME}_unittest" )
115
+ sh %{ dropdb "#{PKG_NAME}_unittest" }
61
116
  end
62
117
 
63
118
  desc 'Rebuild the PostgreSQL test databases'
64
119
  task :rebuild_postgresql_databases => [:drop_postgresql_databases, :build_postgresql_databases]
65
120
 
66
- # Generate the RDoc documentation
67
-
68
- Rake::RDocTask.new { |rdoc|
69
- rdoc.rdoc_dir = 'doc'
70
- rdoc.title = "Composite Primary Keys -- Composite keys for Active Records/Rails"
71
- rdoc.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
72
- rdoc.template = "#{ENV['template']}.rb" if ENV['template']
73
- rdoc.rdoc_files.include('README', 'CHANGELOG')
74
- rdoc.rdoc_files.include('lib/**/*.rb')
75
- rdoc.rdoc_files.exclude('lib/active_record/vendor/*')
76
- rdoc.rdoc_files.include('dev-utils/*.rb')
77
- }
78
-
79
- # Enhance rdoc task to copy referenced images also
80
- task :rdoc do
81
- FileUtils.mkdir_p "doc/files/examples/"
121
+ desc 'Generate website files'
122
+ task :website_generate do
123
+ sh %{ ruby scripts/txt2html website/index.txt > website/index.html }
124
+ sh %{ ruby scripts/txt2js website/version.txt > website/version.js }
125
+ sh %{ ruby scripts/txt2js website/version-raw.txt > website/version-raw.js }
82
126
  end
83
127
 
84
-
85
- # Create compressed packages
86
-
87
- dist_dirs = [ "lib", "test", "website", "scripts" ]
88
-
89
- spec = Gem::Specification.new do |s|
90
- s.name = PKG_NAME
91
- s.version = PKG_VERSION
92
- s.summary = "Support for composite primary keys in ActiveRecords"
93
- s.description = %q{ActiveRecords only support a single primary key, preventing their use on legacy databases where tables have primary keys over 2+ columns. This solution allows an ActiveRecord to be extended to support multiple keys using the class method set_primary_keys.}
94
-
95
- s.files = [ "Rakefile", "install.rb", "README", "CHANGELOG" ]
96
- dist_dirs.each do |dir|
97
- s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
98
- end
99
-
100
- s.add_dependency('activerecord', '>= 1.14.3' + PKG_BUILD)
101
-
102
- s.require_path = 'lib'
103
- s.autorequire = 'composite_primary_keys'
104
-
105
- s.has_rdoc = true
106
- s.extra_rdoc_files = %w( README )
107
- s.rdoc_options.concat ['--main', 'README']
108
-
109
- s.author = "Dr Nic Williams"
110
- s.email = "drnicwilliams@gmail.com"
111
- s.homepage = "http://compositekeys.rubyforge.org"
112
- s.rubyforge_project = "compositekeys"
113
- end
114
-
115
- Rake::GemPackageTask.new(spec) do |p|
116
- p.gem_spec = spec
117
- p.need_tar = false
118
- p.need_zip = false
128
+ desc 'Upload website files to rubyforge'
129
+ task :website_upload do
130
+ config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
131
+ host = "#{config["username"]}@rubyforge.org"
132
+ remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/"
133
+ local_dir = 'website'
134
+ sh %{rsync -av --delete #{local_dir}/ #{host}:#{remote_dir}}
119
135
  end
120
136
 
121
- task :lines do
122
- lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
123
-
124
- for file_name in FileList["lib/composite_primary_keys/**/*.rb"]
125
- next if file_name =~ /vendor/
126
- f = File.open(file_name)
127
-
128
- while line = f.gets
129
- lines += 1
130
- next if line =~ /^\s*$/
131
- next if line =~ /^\s*#/
132
- codelines += 1
133
- end
134
- puts "L: #{sprintf("%4d", lines)}, LOC #{sprintf("%4d", codelines)} | #{file_name}"
135
-
136
- total_lines += lines
137
- total_codelines += codelines
138
-
139
- lines, codelines = 0, 0
140
- end
141
-
142
- puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
137
+ desc 'Generate and upload website files'
138
+ task :website => [:website_generate, :website_upload] do
143
139
  end
144
-
145
-
146
- # Publishing ------------------------------------------------------
147
-
148
- desc "Publish the release files to RubyForge."
149
- task :release => [ :package ] do
150
- `ruby scripts/rubyforge login`
151
-
152
- for ext in %w( gem tgz zip )
153
- release_command = "ruby scripts/rubyforge add_release #{PKG_NAME} #{PKG_NAME} 'REL #{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.#{ext}"
154
- puts release_command
155
- system(release_command)
156
- end
157
- end
@@ -39,7 +39,15 @@ require 'composite_primary_keys/composite_arrays'
39
39
  require 'composite_primary_keys/associations'
40
40
  require 'composite_primary_keys/reflection'
41
41
  require 'composite_primary_keys/base'
42
+ require 'composite_primary_keys/calculations'
42
43
 
43
44
  ActiveRecord::Base.class_eval do
44
45
  include CompositePrimaryKeys::ActiveRecord::Base
45
46
  end
47
+
48
+ RAILS_CONNECTION_ADAPTERS.each do |adapter|
49
+ begin
50
+ require "composite_primary_keys/connection_adapters/" + adapter + "_adapter"
51
+ rescue MissingSourceFile
52
+ end
53
+ end
@@ -125,10 +125,12 @@ module ActiveRecord::Associations::ClassMethods
125
125
  def composite_association_join
126
126
  join = case reflection.macro
127
127
  when :has_and_belongs_to_many
128
+ # TODO replace (keys) = (ids), with key1=id1 and key2=id2
128
129
  " LEFT OUTER JOIN %s ON (%s) = (%s) " % [
129
130
  table_alias_for(options[:join_table], aliased_join_table_name),
130
131
  full_keys(aliased_join_table_name, options[:foreign_key] || reflection.active_record.to_s.classify.foreign_key),
131
132
  full_keys(reflection.active_record.table_name, reflection.active_record.primary_key)] +
133
+ # TODO replace (keys) = (ids), with key1=id1 and key2=id2
132
134
  " LEFT OUTER JOIN %s ON (%s) = (%s) " % [
133
135
  table_name_and_alias,
134
136
  full_keys(aliased_table_name, klass.primary_key),
@@ -153,10 +155,12 @@ module ActiveRecord::Associations::ClassMethods
153
155
  second_key = options[:foreign_key] || primary_key
154
156
  end
155
157
 
158
+ # TODO replace (keys) = (ids), with key1=id1 and key2=id2
156
159
  " LEFT OUTER JOIN %s ON (%s) = (%s) " % [
157
160
  table_alias_for(through_reflection.klass.table_name, aliased_join_table_name),
158
161
  full_keys(aliased_join_table_name, through_reflection.primary_key_name),
159
162
  full_keys(parent.aliased_table_name, parent.primary_key)] +
163
+ # TODO replace (keys) = (ids), with key1=id1 and key2=id2
160
164
  " LEFT OUTER JOIN %s ON (%s) = (%s) " % [
161
165
  table_name_and_alias,
162
166
  full_keys(aliased_table_name, first_key),
@@ -171,17 +175,21 @@ module ActiveRecord::Associations::ClassMethods
171
175
  raise AssociationNotSupported, "Polymorphic joins not supported for composite keys"
172
176
  else
173
177
  foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key
174
- " LEFT OUTER JOIN %s ON (%s) = (%s) " % [
178
+ # TODO replace (keys) = (ids), with key1=id1 and key2=id2
179
+ " LEFT OUTER JOIN %s ON %s " % [
175
180
  table_name_and_alias,
176
- full_keys(aliased_table_name, foreign_key),
177
- full_keys(parent.aliased_table_name, parent.primary_key)
181
+ composite_join_clause(
182
+ full_keys(aliased_table_name, foreign_key),
183
+ full_keys(parent.aliased_table_name, parent.primary_key)),
178
184
  ]
179
185
  end
180
186
  when :belongs_to
181
- " LEFT OUTER JOIN %s ON (%s) = (%s) " % [
187
+ # TODO replace (keys) = (ids), with key1=id1 and key2=id2
188
+ " LEFT OUTER JOIN %s ON %s " % [
182
189
  table_name_and_alias,
183
- full_keys(aliased_table_name, reflection.klass.primary_key),
184
- full_keys(parent.aliased_table_name, options[:foreign_key] || klass.to_s.foreign_key)
190
+ composite_join_clause(
191
+ full_keys(aliased_table_name, reflection.klass.primary_key),
192
+ full_keys(parent.aliased_table_name, options[:foreign_key] || klass.to_s.foreign_key)),
185
193
  ]
186
194
  else
187
195
  ""
@@ -197,12 +205,47 @@ module ActiveRecord::Associations::ClassMethods
197
205
  def full_keys(table_name, keys)
198
206
  keys.collect {|key| "#{table_name}.#{key}"}.join(CompositePrimaryKeys::ID_SEP)
199
207
  end
208
+
209
+ def composite_join_clause(full_keys1, full_keys2)
210
+ full_keys1 = full_keys1.split(CompositePrimaryKeys::ID_SEP) if full_keys1.is_a?(String)
211
+ full_keys2 = full_keys2.split(CompositePrimaryKeys::ID_SEP) if full_keys2.is_a?(String)
212
+ where_clause = [full_keys1, full_keys2].transpose.map do |key_pair|
213
+ "#{key_pair.first}=#{key_pair.last}"
214
+ end.join(" AND ")
215
+ "(#{where_clause})"
216
+ end
200
217
  end
201
218
  end
202
219
  end
203
220
 
204
221
  module ActiveRecord::Associations
205
222
  class AssociationProxy #:nodoc:
223
+
224
+ def composite_where_clause(full_keys, ids)
225
+ full_keys = full_keys.split(CompositePrimaryKeys::ID_SEP) if full_keys.is_a?(String)
226
+ if ids.is_a?(String)
227
+ ids = [[ids]]
228
+ elsif not ids.first.is_a?(Array) # if single comp key passed, turn into an array of 1
229
+ ids = [ids.to_composite_ids]
230
+ end
231
+ where_clause = ids.map do |id_set|
232
+ transposed = id_set.size == 1 ? [[full_keys, id_set.first]] : [full_keys, id_set].transpose
233
+ transposed.map do |full_key, id|
234
+ "#{full_key.to_s}=#{@reflection.klass.sanitize(id)}"
235
+ end.join(" AND ")
236
+ end.join(") OR (")
237
+ "(#{where_clause})"
238
+ end
239
+
240
+ def composite_join_clause(full_keys1, full_keys2)
241
+ full_keys1 = full_keys1.split(CompositePrimaryKeys::ID_SEP) if full_keys1.is_a?(String)
242
+ full_keys2 = full_keys2.split(CompositePrimaryKeys::ID_SEP) if full_keys2.is_a?(String)
243
+ where_clause = [full_keys1, full_keys2].transpose.map do |key_pair|
244
+ "#{key_pair.first}=#{key_pair.last}"
245
+ end.join(" AND ")
246
+ "(#{where_clause})"
247
+ end
248
+
206
249
  def full_keys(table_name, keys)
207
250
  keys = keys.split(CompositePrimaryKeys::ID_SEP) if keys.is_a?(String)
208
251
  keys.is_a?(Array) ?
@@ -211,7 +254,7 @@ module ActiveRecord::Associations
211
254
  end
212
255
 
213
256
  def full_columns_equals(table_name, keys, quoted_ids)
214
- if keys.is_a?(Symbol) or (keys.is_a?(String) and keys == keys.split(CompositePrimaryKeys::ID_SEP))
257
+ if keys.is_a?(Symbol) or (keys.is_a?(String) and keys == keys.to_s.split(CompositePrimaryKeys::ID_SEP))
215
258
  return "#{table_name}.#{keys} = #{quoted_ids}"
216
259
  end
217
260
  keys = keys.split(CompositePrimaryKeys::ID_SEP) if keys.is_a?(String)
@@ -259,10 +302,8 @@ module ActiveRecord::Associations
259
302
  "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_id = #{@owner.quoted_id} AND " +
260
303
  "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote @owner.class.base_class.name.to_s}"
261
304
  else
262
- @finder_sql = "(%s) = (%s)" % [
263
- full_keys(@reflection.table_name, @reflection.primary_key_name),
264
- @owner.quoted_id
265
- ]
305
+ @finder_sql = full_columns_equals(@reflection.klass.table_name,
306
+ @reflection.primary_key_name, @owner.quoted_id)
266
307
  end
267
308
  @finder_sql << " AND (#{conditions})" if conditions
268
309
  end
@@ -298,10 +339,11 @@ module ActiveRecord::Associations
298
339
  end
299
340
  end
300
341
 
301
- "INNER JOIN %s ON (%s) = (%s) %s #{@reflection.options[:joins]} #{custom_joins}" % [
342
+ "INNER JOIN %s ON %s %s #{@reflection.options[:joins]} #{custom_joins}" % [
302
343
  @reflection.through_reflection.table_name,
303
- full_keys(@reflection.table_name, reflection_primary_key),
304
- full_keys(@reflection.through_reflection.table_name, source_primary_key),
344
+ composite_join_clause(
345
+ full_keys(@reflection.table_name, reflection_primary_key),
346
+ full_keys(@reflection.through_reflection.table_name, source_primary_key)),
305
347
  polymorphic_join
306
348
  ]
307
349
  end
@@ -311,10 +353,16 @@ module ActiveRecord::Associations
311
353
  when @reflection.options[:finder_sql]
312
354
  @finder_sql = interpolate_sql(@reflection.options[:finder_sql])
313
355
 
314
- @finder_sql = "(%s) = (%s)" % [
315
- full_keys(@reflection.klass.table_name, @reflection.primary_key_name),
316
- @owner.quoted_id
317
- ]
356
+ @finder_sql << " AND (#{conditions})" if conditions
357
+ when @reflection.options[:as]
358
+ @finder_sql =
359
+ "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_id = #{@owner.quoted_id} AND " +
360
+ "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}"
361
+ @finder_sql << " AND (#{conditions})" if conditions
362
+
363
+ else
364
+ @finder_sql = composite_where_clause(
365
+ full_keys(@reflection.klass.table_name, @reflection.primary_key_name), @owner.quoted_id),
318
366
  @finder_sql << " AND (#{conditions})" if conditions
319
367
  end
320
368