activerecord 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (86) hide show
  1. data/CHANGELOG +34 -0
  2. data/README +0 -0
  3. data/Rakefile +6 -5
  4. data/lib/active_record.rb +8 -10
  5. data/lib/active_record/association_preload.rb +17 -12
  6. data/lib/active_record/associations.rb +45 -27
  7. data/lib/active_record/associations/association_collection.rb +8 -5
  8. data/lib/active_record/associations/association_proxy.rb +2 -6
  9. data/lib/active_record/associations/belongs_to_association.rb +0 -0
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -0
  11. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +2 -3
  12. data/lib/active_record/associations/has_many_association.rb +16 -4
  13. data/lib/active_record/associations/has_many_through_association.rb +1 -1
  14. data/lib/active_record/associations/has_one_association.rb +2 -2
  15. data/lib/active_record/associations/has_one_through_association.rb +4 -0
  16. data/lib/active_record/base.rb +33 -15
  17. data/lib/active_record/calculations.rb +20 -7
  18. data/lib/active_record/callbacks.rb +0 -0
  19. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +9 -6
  20. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +17 -10
  21. data/lib/active_record/connection_adapters/abstract_adapter.rb +0 -0
  22. data/lib/active_record/connection_adapters/mysql_adapter.rb +53 -24
  23. data/lib/active_record/connection_adapters/postgresql_adapter.rb +66 -20
  24. data/lib/active_record/connection_adapters/sqlite_adapter.rb +12 -0
  25. data/lib/active_record/dirty.rb +10 -3
  26. data/lib/active_record/fixtures.rb +0 -0
  27. data/lib/active_record/locking/optimistic.rb +1 -0
  28. data/lib/active_record/migration.rb +35 -8
  29. data/lib/active_record/named_scope.rb +6 -1
  30. data/lib/active_record/observer.rb +7 -5
  31. data/lib/active_record/test_case.rb +13 -2
  32. data/lib/active_record/validations.rb +19 -9
  33. data/lib/active_record/version.rb +1 -1
  34. data/test/cases/active_schema_test_postgresql.rb +2 -2
  35. data/test/cases/adapter_test.rb +1 -1
  36. data/test/cases/associations/belongs_to_associations_test.rb +19 -0
  37. data/test/cases/associations/cascaded_eager_loading_test.rb +13 -1
  38. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
  39. data/test/cases/associations/eager_test.rb +25 -1
  40. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +27 -5
  41. data/test/cases/associations/has_many_associations_test.rb +106 -4
  42. data/test/cases/associations/has_many_through_associations_test.rb +10 -0
  43. data/test/cases/associations/has_one_associations_test.rb +22 -0
  44. data/test/cases/associations/has_one_through_associations_test.rb +44 -5
  45. data/test/cases/associations/join_model_test.rb +7 -0
  46. data/test/cases/associations_test.rb +2 -2
  47. data/test/cases/attribute_methods_test.rb +10 -10
  48. data/test/cases/base_test.rb +39 -16
  49. data/test/cases/calculations_test.rb +53 -1
  50. data/test/cases/column_definition_test.rb +36 -0
  51. data/test/cases/database_statements_test.rb +12 -0
  52. data/test/cases/defaults_test.rb +1 -1
  53. data/test/cases/deprecated_finder_test.rb +0 -0
  54. data/test/cases/dirty_test.rb +94 -0
  55. data/test/cases/finder_test.rb +7 -0
  56. data/test/cases/fixtures_test.rb +0 -0
  57. data/test/cases/helper.rb +5 -5
  58. data/test/cases/inheritance_test.rb +9 -2
  59. data/test/cases/lifecycle_test.rb +54 -1
  60. data/test/cases/locking_test.rb +20 -0
  61. data/test/cases/method_scoping_test.rb +11 -1
  62. data/test/cases/migration_test.rb +147 -22
  63. data/test/cases/multiple_db_test.rb +1 -1
  64. data/test/cases/named_scope_test.rb +50 -1
  65. data/test/cases/query_cache_test.rb +4 -3
  66. data/test/cases/readonly_test.rb +0 -0
  67. data/test/cases/reflection_test.rb +3 -3
  68. data/test/cases/schema_dumper_test.rb +46 -0
  69. data/test/cases/unconnected_test.rb +0 -0
  70. data/test/cases/validations_test.rb +30 -5
  71. data/test/debug.log +358 -0
  72. data/test/fixtures/fixture_database.sqlite3 +0 -0
  73. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  74. data/test/models/author.rb +4 -0
  75. data/test/models/category.rb +1 -0
  76. data/test/models/company.rb +10 -1
  77. data/test/models/developer.rb +4 -1
  78. data/test/models/person.rb +1 -1
  79. data/test/models/post.rb +6 -1
  80. data/test/models/project.rb +1 -1
  81. data/test/models/reply.rb +0 -0
  82. data/test/models/topic.rb +1 -0
  83. data/test/schema/mysql_specific_schema.rb +2 -2
  84. data/test/schema/schema.rb +8 -0
  85. metadata +11 -5
  86. data/lib/active_record/vendor/db2.rb +0 -362
@@ -2,7 +2,7 @@ module ActiveRecord
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 2
4
4
  MINOR = 1
5
- TINY = 0
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -13,8 +13,8 @@ class PostgresqlActiveSchemaTest < Test::Unit::TestCase
13
13
  end
14
14
 
15
15
  def test_create_database_with_encoding
16
- assert_equal "CREATE DATABASE matt ENCODING = 'utf8'", create_database(:matt)
17
- assert_equal "CREATE DATABASE aimonetti ENCODING = 'latin1'", create_database(:aimonetti, :encoding => :latin1)
16
+ assert_equal %(CREATE DATABASE "matt" ENCODING = 'utf8'), create_database(:matt)
17
+ assert_equal %(CREATE DATABASE "aimonetti" ENCODING = 'latin1'), create_database(:aimonetti, :encoding => :latin1)
18
18
  end
19
19
 
20
20
  private
@@ -118,7 +118,7 @@ class AdapterTest < ActiveRecord::TestCase
118
118
  sql_inject = "1, 7 procedure help()"
119
119
  if current_adapter?(:MysqlAdapter)
120
120
  assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject)
121
- assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
121
+ assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=> '1 ; DROP TABLE USERS', :offset=>7)
122
122
  else
123
123
  assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject)
124
124
  assert_equal " LIMIT 1,7 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
@@ -409,4 +409,23 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
409
409
  sponsor.sponsorable = new_member
410
410
  assert_equal nil, sponsor.sponsorable_id
411
411
  end
412
+
413
+ def test_save_fails_for_invalid_belongs_to
414
+ assert log = AuditLog.create(:developer_id=>0,:message=>"")
415
+
416
+ log.developer = Developer.new
417
+ assert !log.developer.valid?
418
+ assert !log.valid?
419
+ assert !log.save
420
+ assert_equal "is invalid", log.errors.on("developer")
421
+ end
422
+
423
+ def test_save_succeeds_for_invalid_belongs_to_with_validate_false
424
+ assert log = AuditLog.create(:developer_id=>0,:message=>"")
425
+
426
+ log.unvalidated_developer = Developer.new
427
+ assert !log.unvalidated_developer.valid?
428
+ assert log.valid?
429
+ assert log.save
430
+ end
412
431
  end
@@ -9,7 +9,7 @@ require 'models/topic'
9
9
  require 'models/reply'
10
10
 
11
11
  class CascadedEagerLoadingTest < ActiveRecord::TestCase
12
- fixtures :authors, :mixins, :companies, :posts, :topics
12
+ fixtures :authors, :mixins, :companies, :posts, :topics, :accounts, :comments, :categorizations
13
13
 
14
14
  def test_eager_association_loading_with_cascaded_two_levels
15
15
  authors = Author.find(:all, :include=>{:posts=>:comments}, :order=>"authors.id")
@@ -68,6 +68,18 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase
68
68
  end
69
69
  end
70
70
 
71
+ def test_eager_association_loading_with_has_many_sti_and_subclasses
72
+ silly = SillyReply.new(:title => "gaga", :content => "boo-boo", :parent_id => 1)
73
+ silly.parent_id = 1
74
+ assert silly.save
75
+
76
+ topics = Topic.find(:all, :include => :replies, :order => 'topics.id, replies_topics.id')
77
+ assert_no_queries do
78
+ assert_equal 2, topics[0].replies.size
79
+ assert_equal 0, topics[1].replies.size
80
+ end
81
+ end
82
+
71
83
  def test_eager_association_loading_with_belongs_to_sti
72
84
  replies = Reply.find(:all, :include => :topic, :order => 'topics.id')
73
85
  assert replies.include?(topics(:second))
@@ -0,0 +1,36 @@
1
+ require 'cases/helper'
2
+ require 'models/post'
3
+ require 'models/tagging'
4
+
5
+ module Namespaced
6
+ class Post < ActiveRecord::Base
7
+ set_table_name 'posts'
8
+ has_one :tagging, :as => :taggable, :class_name => 'Tagging'
9
+ end
10
+ end
11
+
12
+ class EagerLoadIncludeFullStiClassNamesTest < ActiveRecord::TestCase
13
+
14
+ def setup
15
+ generate_test_objects
16
+ end
17
+
18
+ def generate_test_objects
19
+ post = Namespaced::Post.create( :title => 'Great stuff', :body => 'This is not', :author_id => 1 )
20
+ tagging = Tagging.create( :taggable => post )
21
+ end
22
+
23
+ def test_class_names
24
+ old = ActiveRecord::Base.store_full_sti_class
25
+
26
+ ActiveRecord::Base.store_full_sti_class = false
27
+ post = Namespaced::Post.find_by_title( 'Great stuff', :include => :tagging )
28
+ assert_nil post.tagging
29
+
30
+ ActiveRecord::Base.store_full_sti_class = true
31
+ post = Namespaced::Post.find_by_title( 'Great stuff', :include => :tagging )
32
+ assert_equal 'Tagging', post.tagging.class.name
33
+ ensure
34
+ ActiveRecord::Base.store_full_sti_class = old
35
+ end
36
+ end
@@ -14,11 +14,14 @@ require 'models/job'
14
14
  require 'models/subscriber'
15
15
  require 'models/subscription'
16
16
  require 'models/book'
17
+ require 'models/developer'
18
+ require 'models/project'
17
19
 
18
20
  class EagerAssociationTest < ActiveRecord::TestCase
19
21
  fixtures :posts, :comments, :authors, :categories, :categories_posts,
20
22
  :companies, :accounts, :tags, :taggings, :people, :readers,
21
- :owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books
23
+ :owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books,
24
+ :developers, :projects, :developers_projects
22
25
 
23
26
  def test_loading_with_one_association
24
27
  posts = Post.find(:all, :include => :comments)
@@ -35,6 +38,12 @@ class EagerAssociationTest < ActiveRecord::TestCase
35
38
  assert_equal Post.find(1).last_comment, post.last_comment
36
39
  end
37
40
 
41
+ def test_loading_with_one_association_with_non_preload
42
+ posts = Post.find(:all, :include => :last_comment, :order => 'comments.id DESC')
43
+ post = posts.find { |p| p.id == 1 }
44
+ assert_equal Post.find(1).last_comment, post.last_comment
45
+ end
46
+
38
47
  def test_loading_conditions_with_or
39
48
  posts = authors(:david).posts.find(:all, :include => :comments, :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'")
40
49
  assert_nil posts.detect { |p| p.author_id != authors(:david).id },
@@ -556,6 +565,13 @@ class EagerAssociationTest < ActiveRecord::TestCase
556
565
  assert_nothing_raised { Post.find(:all, :include => 'comments') }
557
566
  end
558
567
 
568
+ def test_eager_with_floating_point_numbers
569
+ assert_queries(2) do
570
+ # Before changes, the floating point numbers will be interpreted as table names and will cause this to run in one query
571
+ Comment.find :all, :conditions => "123.456 = 123.456", :include => :post
572
+ end
573
+ end
574
+
559
575
  def test_preconfigured_includes_with_belongs_to
560
576
  author = posts(:welcome).author_with_posts
561
577
  assert_no_queries {assert_equal 5, author.posts.size}
@@ -609,4 +625,12 @@ class EagerAssociationTest < ActiveRecord::TestCase
609
625
  Comment.find :all, :include => :post
610
626
  end
611
627
  end
628
+
629
+ def test_conditions_on_join_table_with_include_and_limit
630
+ assert_equal 3, Developer.find(:all, :include => 'projects', :conditions => 'developers_projects.access_level = 1', :limit => 5).size
631
+ end
632
+
633
+ def test_order_on_join_table_with_include_and_limit
634
+ assert_equal 5, Developer.find(:all, :include => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).size
635
+ end
612
636
  end
@@ -70,7 +70,7 @@ end
70
70
 
71
71
  class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
72
72
  fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
73
- :parrots, :pirates, :treasures, :price_estimates
73
+ :parrots, :pirates, :treasures, :price_estimates, :tags, :taggings
74
74
 
75
75
  def test_has_and_belongs_to_many
76
76
  david = Developer.find(1)
@@ -299,6 +299,17 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
299
299
  assert_equal 3, projects(:active_record, :reload).developers.size
300
300
  end
301
301
 
302
+ def test_uniq_option_prevents_duplicate_push
303
+ project = projects(:active_record)
304
+ project.developers << developers(:jamis)
305
+ project.developers << developers(:david)
306
+ assert_equal 3, project.developers.size
307
+
308
+ project.developers << developers(:david)
309
+ project.developers << developers(:jamis)
310
+ assert_equal 3, project.developers.size
311
+ end
312
+
302
313
  def test_deleting
303
314
  david = Developer.find(1)
304
315
  active_record = Project.find(1)
@@ -439,6 +450,13 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
439
450
  assert_equal developers(:david), active_record.developers_with_finder_sql.find(developers(:david).id), "Ruby find"
440
451
  end
441
452
 
453
+ def test_find_in_association_with_custom_finder_sql_and_multiple_interpolations
454
+ # interpolate once:
455
+ assert_equal [developers(:david), developers(:jamis), developers(:poor_jamis)], projects(:active_record).developers_with_finder_sql, "first interpolation"
456
+ # interpolate again, for a different project id
457
+ assert_equal [developers(:david)], projects(:action_controller).developers_with_finder_sql, "second interpolation"
458
+ end
459
+
442
460
  def test_find_in_association_with_custom_finder_sql_and_string_id
443
461
  assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id.to_s), "SQL find"
444
462
  end
@@ -629,8 +647,7 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
629
647
  developer.save
630
648
  developer.reload
631
649
  assert_equal 2, developer.projects.length
632
- assert_equal projects(:active_record), developer.projects[0]
633
- assert_equal projects(:action_controller), developer.projects[1]
650
+ assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
634
651
  end
635
652
 
636
653
  def test_assign_ids_ignoring_blanks
@@ -639,8 +656,7 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
639
656
  developer.save
640
657
  developer.reload
641
658
  assert_equal 2, developer.projects.length
642
- assert_equal projects(:active_record), developer.projects[0]
643
- assert_equal projects(:action_controller), developer.projects[1]
659
+ assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
644
660
  end
645
661
 
646
662
  def test_select_limited_ids_list
@@ -681,4 +697,10 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
681
697
  assert_equal developer, project.developers.find(:first)
682
698
  assert_equal project, developer.projects.find(:first)
683
699
  end
700
+
701
+ def test_dynamic_find_should_respect_association_include
702
+ # SQL error in sort clause if :include is not included
703
+ # due to Unknown column 'authors.id'
704
+ assert Category.find(1).posts_with_authors_sorted_by_author_id.find_by_title('Welcome to the weblog')
705
+ end
684
706
  end
@@ -14,7 +14,7 @@ require 'models/reader'
14
14
  class HasManyAssociationsTest < ActiveRecord::TestCase
15
15
  fixtures :accounts, :categories, :companies, :developers, :projects,
16
16
  :developers_projects, :topics, :authors, :comments, :author_addresses,
17
- :people, :posts
17
+ :people, :posts, :readers
18
18
 
19
19
  def setup
20
20
  Client.destroyed_client_ids.clear
@@ -37,15 +37,21 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
37
37
  end
38
38
 
39
39
  def test_counting_with_single_conditions
40
- assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1')
40
+ assert_equal 1, Firm.find(:first).plain_clients.count(:conditions => ['name=?', "Microsoft"])
41
41
  end
42
42
 
43
43
  def test_counting_with_single_hash
44
- assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1')
44
+ assert_equal 1, Firm.find(:first).plain_clients.count(:conditions => {:name => "Microsoft"})
45
45
  end
46
46
 
47
47
  def test_counting_with_column_name_and_hash
48
- assert_equal 2, Firm.find(:first).plain_clients.count(:all, :conditions => '1=1')
48
+ assert_equal 2, Firm.find(:first).plain_clients.count(:name)
49
+ end
50
+
51
+ def test_counting_with_association_limit
52
+ firm = companies(:first_firm)
53
+ assert_equal firm.limited_clients.length, firm.limited_clients.size
54
+ assert_equal firm.limited_clients.length, firm.limited_clients.count
49
55
  end
50
56
 
51
57
  def test_finding
@@ -342,6 +348,34 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
342
348
  assert new_firm.new_record?
343
349
  end
344
350
 
351
+ def test_invalid_adding_with_validate_false
352
+ firm = Firm.find(:first)
353
+ client = Client.new
354
+ firm.unvalidated_clients_of_firm << client
355
+
356
+ assert firm.valid?
357
+ assert !client.valid?
358
+ assert firm.save
359
+ assert client.new_record?
360
+ end
361
+
362
+ def test_valid_adding_with_validate_false
363
+ no_of_clients = Client.count
364
+
365
+ firm = Firm.find(:first)
366
+ client = Client.new("name" => "Apple")
367
+
368
+ assert firm.valid?
369
+ assert client.valid?
370
+ assert client.new_record?
371
+
372
+ firm.unvalidated_clients_of_firm << client
373
+
374
+ assert firm.save
375
+ assert !client.new_record?
376
+ assert_equal no_of_clients+1, Client.count
377
+ end
378
+
345
379
  def test_build
346
380
  company = companies(:first_firm)
347
381
  new_client = assert_no_queries { company.clients_of_firm.build("name" => "Another Client") }
@@ -356,6 +390,25 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
356
390
  assert_equal 2, company.clients_of_firm(true).size
357
391
  end
358
392
 
393
+ def test_collection_size_after_building
394
+ company = companies(:first_firm) # company already has one client
395
+ company.clients_of_firm.build("name" => "Another Client")
396
+ company.clients_of_firm.build("name" => "Yet Another Client")
397
+ assert_equal 3, company.clients_of_firm.size
398
+ end
399
+
400
+ def test_collection_size_twice_for_regressions
401
+ post = posts(:thinking)
402
+ assert_equal 0, post.readers.size
403
+ # This test needs a post that has no readers, we assert it to ensure it holds,
404
+ # but need to reload the post because the very call to #size hides the bug.
405
+ post.reload
406
+ post.readers.build
407
+ size1 = post.readers.size
408
+ size2 = post.readers.size
409
+ assert_equal size1, size2
410
+ end
411
+
359
412
  def test_build_many
360
413
  company = companies(:first_firm)
361
414
  new_clients = assert_no_queries { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
@@ -386,6 +439,37 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
386
439
  assert_equal 2, first_topic.replies.to_ary.size
387
440
  end
388
441
 
442
+ def test_build_via_block
443
+ company = companies(:first_firm)
444
+ new_client = assert_no_queries { company.clients_of_firm.build {|client| client.name = "Another Client" } }
445
+ assert !company.clients_of_firm.loaded?
446
+
447
+ assert_equal "Another Client", new_client.name
448
+ assert new_client.new_record?
449
+ assert_equal new_client, company.clients_of_firm.last
450
+ company.name += '-changed'
451
+ assert_queries(2) { assert company.save }
452
+ assert !new_client.new_record?
453
+ assert_equal 2, company.clients_of_firm(true).size
454
+ end
455
+
456
+ def test_build_many_via_block
457
+ company = companies(:first_firm)
458
+ new_clients = assert_no_queries do
459
+ company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) do |client|
460
+ client.name = "changed"
461
+ end
462
+ end
463
+
464
+ assert_equal 2, new_clients.size
465
+ assert_equal "changed", new_clients.first.name
466
+ assert_equal "changed", new_clients.last.name
467
+
468
+ company.name += '-changed'
469
+ assert_queries(3) { assert company.save }
470
+ assert_equal 3, company.clients_of_firm(true).size
471
+ end
472
+
389
473
  def test_create_without_loading_association
390
474
  first_firm = companies(:first_firm)
391
475
  Firm.column_names
@@ -929,4 +1013,22 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
929
1013
  assert firm.clients.loaded?
930
1014
  end
931
1015
 
1016
+ def test_joins_with_namespaced_model_should_use_correct_type
1017
+ old = ActiveRecord::Base.store_full_sti_class
1018
+ ActiveRecord::Base.store_full_sti_class = true
1019
+
1020
+ firm = Namespaced::Firm.create({ :name => 'Some Company' })
1021
+ firm.clients.create({ :name => 'Some Client' })
1022
+
1023
+ stats = Namespaced::Firm.find(firm.id, {
1024
+ :select => "#{Namespaced::Firm.table_name}.id, COUNT(#{Namespaced::Client.table_name}.id) AS num_clients",
1025
+ :joins => :clients,
1026
+ :group => "#{Namespaced::Firm.table_name}.id"
1027
+ })
1028
+ assert_equal 1, stats.num_clients.to_i
1029
+
1030
+ ensure
1031
+ ActiveRecord::Base.store_full_sti_class = old
1032
+ end
1033
+
932
1034
  end
@@ -187,4 +187,14 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
187
187
  post.people_with_callbacks.clear
188
188
  assert_equal (%w(Michael David Julian Roger) * 2).sort, log.last(8).collect(&:last).sort
189
189
  end
190
+
191
+ def test_dynamic_find_should_respect_association_include
192
+ # SQL error in sort clause if :include is not included
193
+ # due to Unknown column 'comments.id'
194
+ assert Person.find(1).posts_with_comments_sorted_by_comment_id.find_by_title('Welcome to the weblog')
195
+ end
196
+
197
+ def test_count_with_include_should_alias_join_table
198
+ assert_equal 2, people(:michael).posts.count(:include => :readers)
199
+ end
190
200
  end
@@ -72,6 +72,16 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
72
72
  assert_raises(ActiveRecord::RecordNotFound) { Account.find(old_account_id) }
73
73
  end
74
74
 
75
+ def test_natural_assignment_to_already_associated_record
76
+ company = companies(:first_firm)
77
+ account = accounts(:signals37)
78
+ assert_equal company.account, account
79
+ company.account = account
80
+ company.reload
81
+ account.reload
82
+ assert_equal company.account, account
83
+ end
84
+
75
85
  def test_assignment_without_replacement
76
86
  apple = Firm.create("name" => "Apple")
77
87
  citibank = Account.create("credit_limit" => 10)
@@ -275,6 +285,18 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
275
285
  assert_equal "is invalid", firm.errors.on("account")
276
286
  end
277
287
 
288
+
289
+ def test_save_succeeds_for_invalid_has_one_with_validate_false
290
+ firm = Firm.find(:first)
291
+ assert firm.valid?
292
+
293
+ firm.unvalidated_account = Account.new
294
+
295
+ assert !firm.unvalidated_account.valid?
296
+ assert firm.valid?
297
+ assert firm.save
298
+ end
299
+
278
300
  def test_assignment_before_either_saved
279
301
  firm = Firm.new("name" => "GlobalMegaCorp")
280
302
  firm.account = a = Account.new("credit_limit" => 1000)