Upgraded Rails and RSpec
[monkeycharger.git] / vendor / rails / activerecord / test / finder_test.rb
blob0c7a519bbb51271bfa8c7533ff31cd5e4ad3f2ca
1 require 'abstract_unit'
2 require 'fixtures/author'
3 require 'fixtures/comment'
4 require 'fixtures/company'
5 require 'fixtures/topic'
6 require 'fixtures/reply'
7 require 'fixtures/entrant'
8 require 'fixtures/developer'
9 require 'fixtures/post'
11 class FinderTest < Test::Unit::TestCase
12   fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors
14   def test_find
15     assert_equal(topics(:first).title, Topic.find(1).title)
16   end
18   # find should handle strings that come from URLs
19   # (example: Category.find(params[:id]))
20   def test_find_with_string
21     assert_equal(Topic.find(1).title,Topic.find("1").title)
22   end
24   def test_exists
25     assert Topic.exists?(1)
26     assert Topic.exists?("1")
27     assert Topic.exists?(:author_name => "David")
28     assert Topic.exists?(:author_name => "Mary", :approved => true)
29     assert Topic.exists?(["parent_id = ?", 1])
30     assert !Topic.exists?(45)
31     assert !Topic.exists?("foo")
32     assert_raise(NoMethodError) { Topic.exists?([1,2]) }
33   end
35   def test_find_by_array_of_one_id
36     assert_kind_of(Array, Topic.find([ 1 ]))
37     assert_equal(1, Topic.find([ 1 ]).length)
38   end
40   def test_find_by_ids
41     assert_equal 2, Topic.find(1, 2).size
42     assert_equal topics(:second).title, Topic.find([2]).first.title
43   end
45   def test_find_by_ids_with_limit_and_offset
46     assert_equal 2, Entrant.find([1,3,2], :limit => 2).size
47     assert_equal 1, Entrant.find([1,3,2], :limit => 3, :offset => 2).size
49     # Also test an edge case: If you have 11 results, and you set a
50     #   limit of 3 and offset of 9, then you should find that there
51     #   will be only 2 results, regardless of the limit.
52     devs = Developer.find :all
53     last_devs = Developer.find devs.map(&:id), :limit => 3, :offset => 9
54     assert_equal 2, last_devs.size
55   end
57   def test_find_an_empty_array
58     assert_equal [], Topic.find([])
59   end
61   def test_find_by_ids_missing_one
62     assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, 2, 45) }
63   end
65   def test_find_all_with_limit
66     entrants = Entrant.find(:all, :order => "id ASC", :limit => 2)
68     assert_equal(2, entrants.size)
69     assert_equal(entrants(:first).name, entrants.first.name)
70   end
72   def test_find_all_with_prepared_limit_and_offset
73     entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 1)
75     assert_equal(2, entrants.size)
76     assert_equal(entrants(:second).name, entrants.first.name)
78     entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 2)
79     assert_equal(1, entrants.size)
80     assert_equal(entrants(:third).name, entrants.first.name)
81   end
83   def test_find_all_with_limit_and_offset_and_multiple_orderings
84     developers = Developer.find(:all, :order => "salary ASC, id DESC", :limit => 3, :offset => 1)
85     assert_equal ["David", "fixture_10", "fixture_9"], developers.collect {|d| d.name}
86   end
88   def test_find_with_limit_and_condition
89     developers = Developer.find(:all, :order => "id DESC", :conditions => "salary = 100000", :limit => 3, :offset =>7)
90     assert_equal(1, developers.size)
91     assert_equal("fixture_3", developers.first.name)
92   end
94   def test_find_with_entire_select_statement
95     topics = Topic.find_by_sql "SELECT * FROM topics WHERE author_name = 'Mary'"
97     assert_equal(1, topics.size)
98     assert_equal(topics(:second).title, topics.first.title)
99   end
101   def test_find_with_prepared_select_statement
102     topics = Topic.find_by_sql ["SELECT * FROM topics WHERE author_name = ?", "Mary"]
104     assert_equal(1, topics.size)
105     assert_equal(topics(:second).title, topics.first.title)
106   end
108   def test_find_by_sql_with_sti_on_joined_table
109     accounts = Account.find_by_sql("SELECT * FROM accounts INNER JOIN companies ON companies.id = accounts.firm_id")
110     assert_equal [Account], accounts.collect(&:class).uniq
111   end
113   def test_find_first
114     first = Topic.find(:first, :conditions => "title = 'The First Topic'")
115     assert_equal(topics(:first).title, first.title)
116   end
118   def test_find_first_failing
119     first = Topic.find(:first, :conditions => "title = 'The First Topic!'")
120     assert_nil(first)
121   end
123   def test_unexisting_record_exception_handling
124     assert_raises(ActiveRecord::RecordNotFound) {
125       Topic.find(1).parent
126     }
128     Topic.find(2).topic
129   end
131   def test_find_only_some_columns
132     topic = Topic.find(1, :select => "author_name")
133     assert_raises(ActiveRecord::MissingAttributeError) {topic.title}
134     assert_equal "David", topic.author_name
135     assert !topic.attribute_present?("title")
136     #assert !topic.respond_to?("title")
137     assert topic.attribute_present?("author_name")
138     assert topic.respond_to?("author_name")
139   end
140   
141   def test_find_on_blank_conditions
142     [nil, " ", [], {}].each do |blank|
143       assert_nothing_raised { Topic.find(:first, :conditions => blank) }
144     end
145   end
146   
147   def test_find_on_blank_bind_conditions
148     [ [""], ["",{}] ].each do |blank|
149       assert_nothing_raised { Topic.find(:first, :conditions => blank) }
150     end
151   end
153   def test_find_on_array_conditions
154     assert Topic.find(1, :conditions => ["approved = ?", false])
155     assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => ["approved = ?", true]) }
156   end
158   def test_find_on_hash_conditions
159     assert Topic.find(1, :conditions => { :approved => false })
160     assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :approved => true }) }
161   end
163   def test_find_on_hash_conditions_with_explicit_table_name
164     assert Topic.find(1, :conditions => { 'topics.approved' => false })
165     assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { 'topics.approved' => true }) }
166   end
168   def test_find_on_association_proxy_conditions
169     assert_equal [1, 2, 3, 5, 6, 7, 8, 9, 10], Comment.find_all_by_post_id(authors(:david).posts).map(&:id).sort
170   end
172   def test_find_on_hash_conditions_with_range
173     assert_equal [1,2], Topic.find(:all, :conditions => { :id => 1..2 }).map(&:id).sort
174     assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :id => 2..3 }) }
175   end
177   def test_find_on_hash_conditions_with_multiple_ranges
178     assert_equal [1,2,3], Comment.find(:all, :conditions => { :id => 1..3, :post_id => 1..2 }).map(&:id).sort
179     assert_equal [1], Comment.find(:all, :conditions => { :id => 1..1, :post_id => 1..10 }).map(&:id).sort
180   end
182   def test_find_on_multiple_hash_conditions
183     assert Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => false })
184     assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => true }) }
185     assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "HHC", :replies_count => 1, :approved => false }) }
186     assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => true }) }
187   end
190   def test_condition_interpolation
191     assert_kind_of Firm, Company.find(:first, :conditions => ["name = '%s'", "37signals"])
192     assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!"])
193     assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!' OR 1=1"])
194     assert_kind_of Time, Topic.find(:first, :conditions => ["id = %d", 1]).written_on
195   end
197   def test_condition_array_interpolation
198     assert_kind_of Firm, Company.find(:first, :conditions => ["name = '%s'", "37signals"])
199     assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!"])
200     assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!' OR 1=1"])
201     assert_kind_of Time, Topic.find(:first, :conditions => ["id = %d", 1]).written_on
202   end
204   def test_condition_hash_interpolation
205     assert_kind_of Firm, Company.find(:first, :conditions => { :name => "37signals"})
206     assert_nil Company.find(:first, :conditions => { :name => "37signals!"})
207     assert_kind_of Time, Topic.find(:first, :conditions => {:id => 1}).written_on
208   end
210   def test_hash_condition_find_malformed
211     assert_raises(ActiveRecord::StatementInvalid) {
212       Company.find(:first, :conditions => { :id => 2, :dhh => true })
213     }
214   end
216   def test_hash_condition_find_with_escaped_characters
217     Company.create("name" => "Ain't noth'n like' \#stuff")
218     assert Company.find(:first, :conditions => { :name => "Ain't noth'n like' \#stuff" })
219   end
221   def test_hash_condition_find_with_array
222     p1, p2 = Post.find(:all, :limit => 2, :order => 'id asc')
223     assert_equal [p1, p2], Post.find(:all, :conditions => { :id => [p1, p2] }, :order => 'id asc')
224     assert_equal [p1, p2], Post.find(:all, :conditions => { :id => [p1, p2.id] }, :order => 'id asc')
225   end
227   def test_hash_condition_find_with_nil
228     topic = Topic.find(:first, :conditions => { :last_read => nil } )
229     assert_not_nil topic
230     assert_nil topic.last_read
231   end
233   def test_bind_variables
234     assert_kind_of Firm, Company.find(:first, :conditions => ["name = ?", "37signals"])
235     assert_nil Company.find(:first, :conditions => ["name = ?", "37signals!"])
236     assert_nil Company.find(:first, :conditions => ["name = ?", "37signals!' OR 1=1"])
237     assert_kind_of Time, Topic.find(:first, :conditions => ["id = ?", 1]).written_on
238     assert_raises(ActiveRecord::PreparedStatementInvalid) {
239       Company.find(:first, :conditions => ["id=? AND name = ?", 2])
240     }
241     assert_raises(ActiveRecord::PreparedStatementInvalid) {
242            Company.find(:first, :conditions => ["id=?", 2, 3, 4])
243     }
244   end
246   def test_bind_variables_with_quotes
247     Company.create("name" => "37signals' go'es agains")
248     assert Company.find(:first, :conditions => ["name = ?", "37signals' go'es agains"])
249   end
251   def test_named_bind_variables_with_quotes
252     Company.create("name" => "37signals' go'es agains")
253     assert Company.find(:first, :conditions => ["name = :name", {:name => "37signals' go'es agains"}])
254   end
256   def test_bind_arity
257     assert_nothing_raised                                 { bind '' }
258     assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '', 1 }
260     assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '?' }
261     assert_nothing_raised                                 { bind '?', 1 }
262     assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '?', 1, 1  }
263   end
265   def test_named_bind_variables
266     assert_equal '1', bind(':a', :a => 1) # ' ruby-mode
267     assert_equal '1 1', bind(':a :a', :a => 1)  # ' ruby-mode
269     assert_kind_of Firm, Company.find(:first, :conditions => ["name = :name", { :name => "37signals" }])
270     assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!" }])
271     assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!' OR 1=1" }])
272     assert_kind_of Time, Topic.find(:first, :conditions => ["id = :id", { :id => 1 }]).written_on
273   end
275   def test_bind_enumerable
276     quoted_abc = %(#{ActiveRecord::Base.connection.quote('a')},#{ActiveRecord::Base.connection.quote('b')},#{ActiveRecord::Base.connection.quote('c')})
278     assert_equal '1,2,3', bind('?', [1, 2, 3])
279     assert_equal quoted_abc, bind('?', %w(a b c))
281     assert_equal '1,2,3', bind(':a', :a => [1, 2, 3])
282     assert_equal quoted_abc, bind(':a', :a => %w(a b c)) # '
284     require 'set'
285     assert_equal '1,2,3', bind('?', Set.new([1, 2, 3]))
286     assert_equal quoted_abc, bind('?', Set.new(%w(a b c)))
288     assert_equal '1,2,3', bind(':a', :a => Set.new([1, 2, 3]))
289     assert_equal quoted_abc, bind(':a', :a => Set.new(%w(a b c))) # '
290   end
292   def test_bind_empty_enumerable
293     quoted_nil = ActiveRecord::Base.connection.quote(nil)
294     assert_equal quoted_nil, bind('?', [])
295     assert_equal " in (#{quoted_nil})", bind(' in (?)', [])
296     assert_equal "foo in (#{quoted_nil})", bind('foo in (?)', [])
297   end
299   def test_bind_string
300     assert_equal ActiveRecord::Base.connection.quote(''), bind('?', '')
301   end
303   def test_bind_record
304     o = Struct.new(:quoted_id).new(1)
305     assert_equal '1', bind('?', o)
307     os = [o] * 3
308     assert_equal '1,1,1', bind('?', os)
309   end
311   def test_string_sanitation
312     assert_not_equal "#{ActiveRecord::Base.connection.quoted_string_prefix}'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1")
313     assert_equal "#{ActiveRecord::Base.connection.quoted_string_prefix}'something; select table'", ActiveRecord::Base.sanitize("something; select table")
314   end
316   def test_count
317     assert_equal(0, Entrant.count(:conditions => "id > 3"))
318     assert_equal(1, Entrant.count(:conditions => ["id > ?", 2]))
319     assert_equal(2, Entrant.count(:conditions => ["id > ?", 1]))
320   end
322   def test_count_by_sql
323     assert_equal(0, Entrant.count_by_sql("SELECT COUNT(*) FROM entrants WHERE id > 3"))
324     assert_equal(1, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 2]))
325     assert_equal(2, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 1]))
326   end
328   def test_find_by_one_attribute
329     assert_equal topics(:first), Topic.find_by_title("The First Topic")
330     assert_nil Topic.find_by_title("The First Topic!")
331   end
332   
333   def test_find_by_one_attribute_caches_dynamic_finder
334     # ensure this test can run independently of order
335     class << Topic; self; end.send(:remove_method, :find_by_title) if Topic.respond_to?(:find_by_title)
336     assert !Topic.respond_to?(:find_by_title)
337     t = Topic.find_by_title("The First Topic")
338     assert Topic.respond_to?(:find_by_title)
339   end
341   def test_dynamic_finder_returns_same_results_after_caching
342     # ensure this test can run independently of order
343     class << Topic; self; end.send(:remove_method, :find_by_title) if Topic.respond_to?(:find_by_title)
344     t = Topic.find_by_title("The First Topic")
345     assert_equal t, Topic.find_by_title("The First Topic") # find_by_title has been cached
346   end
348   def test_find_by_one_attribute_with_order_option
349     assert_equal accounts(:signals37), Account.find_by_credit_limit(50, :order => 'id')
350     assert_equal accounts(:rails_core_account), Account.find_by_credit_limit(50, :order => 'id DESC')
351   end
353   def test_find_by_one_attribute_with_conditions
354     assert_equal accounts(:rails_core_account), Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6])
355   end
357   def test_dynamic_finder_on_one_attribute_with_conditions_caches_method
358     # ensure this test can run independently of order
359     class << Account; self; end.send(:remove_method, :find_by_credit_limit) if Account.respond_to?(:find_by_credit_limit)
360     assert !Account.respond_to?(:find_by_credit_limit)
361     a = Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6])
362     assert Account.respond_to?(:find_by_credit_limit)
363   end
365   def test_dynamic_finder_on_one_attribute_with_conditions_returns_same_results_after_caching
366     # ensure this test can run independently of order
367     class << Account; self; end.send(:remove_method, :find_by_credit_limit) if Account.respond_to?(:find_by_credit_limit)
368     a = Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6])
369     assert_equal a, Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6]) # find_by_credit_limit has been cached
370   end
372   def test_find_by_one_attribute_with_several_options
373     assert_equal accounts(:unknown), Account.find_by_credit_limit(50, :order => 'id DESC', :conditions => ['id != ?', 3])
374   end
376   def test_find_by_one_missing_attribute
377     assert_raises(NoMethodError) { Topic.find_by_undertitle("The First Topic!") }
378   end
380   def test_find_by_invalid_method_syntax
381     assert_raises(NoMethodError) { Topic.fail_to_find_by_title("The First Topic") }
382     assert_raises(NoMethodError) { Topic.find_by_title?("The First Topic") }
383     assert_raises(NoMethodError) { Topic.fail_to_find_or_create_by_title("Nonexistent Title") }
384     assert_raises(NoMethodError) { Topic.find_or_create_by_title?("Nonexistent Title") }
385   end
387   def test_find_by_two_attributes
388     assert_equal topics(:first), Topic.find_by_title_and_author_name("The First Topic", "David")
389     assert_nil Topic.find_by_title_and_author_name("The First Topic", "Mary")
390   end
392   def test_find_all_by_one_attribute
393     topics = Topic.find_all_by_content("Have a nice day")
394     assert_equal 2, topics.size
395     assert topics.include?(topics(:first))
397     assert_equal [], Topic.find_all_by_title("The First Topic!!")
398   end
400   def test_find_all_by_one_attribute_with_options
401     topics = Topic.find_all_by_content("Have a nice day", :order => "id DESC")
402     assert topics(:first), topics.last
404     topics = Topic.find_all_by_content("Have a nice day", :order => "id")
405     assert topics(:first), topics.first
406   end
408   def test_find_all_by_array_attribute
409     assert_equal 2, Topic.find_all_by_title(["The First Topic", "The Second Topic's of the day"]).size
410   end
412   def test_find_all_by_boolean_attribute
413     topics = Topic.find_all_by_approved(false)
414     assert_equal 1, topics.size
415     assert topics.include?(topics(:first))
417     topics = Topic.find_all_by_approved(true)
418     assert_equal 1, topics.size
419     assert topics.include?(topics(:second))
420   end
422   def test_find_by_nil_attribute
423     topic = Topic.find_by_last_read nil
424     assert_not_nil topic
425     assert_nil topic.last_read
426   end
428   def test_find_all_by_nil_attribute
429     topics = Topic.find_all_by_last_read nil
430     assert_equal 1, topics.size
431     assert_nil topics[0].last_read
432   end
434   def test_find_by_nil_and_not_nil_attributes
435     topic = Topic.find_by_last_read_and_author_name nil, "Mary"
436     assert_equal "Mary", topic.author_name
437   end
439   def test_find_all_by_nil_and_not_nil_attributes
440     topics = Topic.find_all_by_last_read_and_author_name nil, "Mary"
441     assert_equal 1, topics.size
442     assert_equal "Mary", topics[0].author_name
443   end
445   def test_find_or_create_from_one_attribute
446     number_of_companies = Company.count
447     sig38 = Company.find_or_create_by_name("38signals")
448     assert_equal number_of_companies + 1, Company.count
449     assert_equal sig38, Company.find_or_create_by_name("38signals")
450     assert !sig38.new_record?
451   end
453   def test_find_or_create_from_two_attributes
454     number_of_topics = Topic.count
455     another = Topic.find_or_create_by_title_and_author_name("Another topic","John")
456     assert_equal number_of_topics + 1, Topic.count
457     assert_equal another, Topic.find_or_create_by_title_and_author_name("Another topic", "John")
458     assert !another.new_record?
459   end
461   def test_find_or_create_from_one_attribute_and_hash
462     number_of_companies = Company.count
463     sig38 = Company.find_or_create_by_name({:name => "38signals", :firm_id => 17, :client_of => 23})
464     assert_equal number_of_companies + 1, Company.count
465     assert_equal sig38, Company.find_or_create_by_name({:name => "38signals", :firm_id => 17, :client_of => 23})
466     assert !sig38.new_record?
467     assert_equal "38signals", sig38.name
468     assert_equal 17, sig38.firm_id
469     assert_equal 23, sig38.client_of
470   end
472   def test_find_or_initialize_from_one_attribute
473     sig38 = Company.find_or_initialize_by_name("38signals")
474     assert_equal "38signals", sig38.name
475     assert sig38.new_record?
476   end
477   
478   def test_find_or_initialize_from_one_attribute_should_set_attribute_even_when_protected
479     c = Company.find_or_initialize_by_name_and_rating("Fortune 1000", 1000)
480     assert_equal "Fortune 1000", c.name
481     assert_equal 1000, c.rating
482     assert c.valid?
483     assert c.new_record?    
484   end
486   def test_find_or_create_from_one_attribute_should_set_attribute_even_when_protected
487     c = Company.find_or_create_by_name_and_rating("Fortune 1000", 1000)
488     assert_equal "Fortune 1000", c.name
489     assert_equal 1000, c.rating
490     assert c.valid?
491     assert !c.new_record?    
492   end
494   def test_dynamic_find_or_initialize_from_one_attribute_caches_method
495     class << Company; self; end.send(:remove_method, :find_or_initialize_by_name) if Company.respond_to?(:find_or_initialize_by_name)    
496     assert !Company.respond_to?(:find_or_initialize_by_name)
497     sig38 = Company.find_or_initialize_by_name("38signals")
498     assert Company.respond_to?(:find_or_initialize_by_name)
499   end
501   def test_find_or_initialize_from_two_attributes
502     another = Topic.find_or_initialize_by_title_and_author_name("Another topic","John")
503     assert_equal "Another topic", another.title
504     assert_equal "John", another.author_name
505     assert another.new_record?
506   end
508   def test_find_or_initialize_from_one_attribute_and_hash
509     sig38 = Company.find_or_initialize_by_name({:name => "38signals", :firm_id => 17, :client_of => 23})
510     assert_equal "38signals", sig38.name
511     assert_equal 17, sig38.firm_id
512     assert_equal 23, sig38.client_of
513     assert sig38.new_record?
514   end
516   def test_find_with_bad_sql
517     assert_raises(ActiveRecord::StatementInvalid) { Topic.find_by_sql "select 1 from badtable" }
518   end
520   def test_find_with_invalid_params
521     assert_raises(ArgumentError) { Topic.find :first, :join => "It should be `joins'" }
522     assert_raises(ArgumentError) { Topic.find :first, :conditions => '1 = 1', :join => "It should be `joins'" }
523   end
525   def test_dynamic_finder_with_invalid_params
526     assert_raises(ArgumentError) { Topic.find_by_title 'No Title', :join => "It should be `joins'" }
527   end
529   def test_find_all_with_limit
530     first_five_developers = Developer.find :all, :order => 'id ASC', :limit =>  5
531     assert_equal 5, first_five_developers.length
532     assert_equal 'David', first_five_developers.first.name
533     assert_equal 'fixture_5', first_five_developers.last.name
535     no_developers = Developer.find :all, :order => 'id ASC', :limit => 0
536     assert_equal 0, no_developers.length
537   end
539   def test_find_all_with_limit_and_offset
540     first_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 0
541     second_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 3
542     last_two_developers = Developer.find :all, :order => 'id ASC', :limit => 2, :offset => 8
544     assert_equal 3, first_three_developers.length
545     assert_equal 3, second_three_developers.length
546     assert_equal 2, last_two_developers.length
548     assert_equal 'David', first_three_developers.first.name
549     assert_equal 'fixture_4', second_three_developers.first.name
550     assert_equal 'fixture_9', last_two_developers.first.name
551   end
553   def test_find_all_with_limit_and_offset_and_multiple_order_clauses
554     first_three_posts = Post.find :all, :order => 'author_id, id', :limit => 3, :offset => 0
555     second_three_posts = Post.find :all, :order => ' author_id,id ', :limit => 3, :offset => 3
556     last_posts = Post.find :all, :order => ' author_id, id  ', :limit => 3, :offset => 6
558     assert_equal [[0,3],[1,1],[1,2]], first_three_posts.map { |p| [p.author_id, p.id] }
559     assert_equal [[1,4],[1,5],[1,6]], second_three_posts.map { |p| [p.author_id, p.id] }
560     assert_equal [[2,7]], last_posts.map { |p| [p.author_id, p.id] }
561   end
563   def test_find_all_with_join
564     developers_on_project_one = Developer.find(
565       :all,
566       :joins => 'LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id',
567       :conditions => 'project_id=1'
568     )
569     assert_equal 3, developers_on_project_one.length
570     developer_names = developers_on_project_one.map { |d| d.name }
571     assert developer_names.include?('David')
572     assert developer_names.include?('Jamis')
573   end
575   def test_joins_dont_clobber_id
576     first = Firm.find(
577       :first,
578       :joins => 'INNER JOIN companies AS clients ON clients.firm_id = companies.id',
579       :conditions => 'companies.id = 1'
580     )
581     assert_equal 1, first.id
582   end
584   def test_find_by_id_with_conditions_with_or
585     assert_nothing_raised do
586       Post.find([1,2,3],
587         :conditions => "posts.id <= 3 OR posts.#{QUOTED_TYPE} = 'Post'")
588     end
589   end
591   # http://dev.rubyonrails.org/ticket/6778
592   def test_find_ignores_previously_inserted_record
593     post = Post.create!(:title => 'test', :body => 'it out')
594     assert_equal [], Post.find_all_by_id(nil)
595   end
597   def test_find_by_empty_ids
598     assert_equal [], Post.find([])
599   end
601   def test_find_by_empty_in_condition
602     assert_equal [], Post.find(:all, :conditions => ['id in (?)', []])
603   end
605   def test_find_by_records
606     p1, p2 = Post.find(:all, :limit => 2, :order => 'id asc')
607     assert_equal [p1, p2], Post.find(:all, :conditions => ['id in (?)', [p1, p2]], :order => 'id asc')
608     assert_equal [p1, p2], Post.find(:all, :conditions => ['id in (?)', [p1, p2.id]], :order => 'id asc')
609   end
611   def test_select_value
612     assert_equal "37signals", Company.connection.select_value("SELECT name FROM companies WHERE id = 1")
613     assert_nil Company.connection.select_value("SELECT name FROM companies WHERE id = -1")
614     # make sure we didn't break count...
615     assert_equal 0, Company.count_by_sql("SELECT COUNT(*) FROM companies WHERE name = 'Halliburton'")
616     assert_equal 1, Company.count_by_sql("SELECT COUNT(*) FROM companies WHERE name = '37signals'")
617   end
619   def test_select_values
620     assert_equal ["1","2","3","4","5","6","7","8","9"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map! { |i| i.to_s }
621     assert_equal ["37signals","Summit","Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel", "Odegy"], Company.connection.select_values("SELECT name FROM companies ORDER BY id")
622   end
624   def test_select_rows
625     assert_equal(
626       [["1", nil, nil, "37signals"],
627        ["2", "1", "2", "Summit"],
628        ["3", "1", "1", "Microsoft"]],
629       Company.connection.select_rows("SELECT id, firm_id, client_of, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! {|i| i.map! {|j| j.to_s unless j.nil?}})
630     assert_equal [["1", "37signals"], ["2", "Summit"], ["3", "Microsoft"]],
631       Company.connection.select_rows("SELECT id, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! {|i| i.map! {|j| j.to_s unless j.nil?}}
632   end
634   protected
635     def bind(statement, *vars)
636       if vars.first.is_a?(Hash)
637         ActiveRecord::Base.send(:replace_named_bind_variables, statement, vars.first)
638       else
639         ActiveRecord::Base.send(:replace_bind_variables, statement, vars)
640       end
641     end