ibm_db 2.5.26-universal-darwin-14 → 2.6.1-universal-darwin-14

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +11 -0
  3. data/MANIFEST +14 -14
  4. data/README +225 -225
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/extconf.rb +264 -261
  8. data/ext/extconf_MacOS.rb +269 -0
  9. data/ext/ibm_db.c +11879 -11793
  10. data/ext/ruby_ibm_db.h +241 -240
  11. data/ext/ruby_ibm_db_cli.c +851 -845
  12. data/ext/ruby_ibm_db_cli.h +500 -489
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -19
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3339 -3289
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/test/cases/adapter_test.rb +207 -207
  19. data/test/cases/associations/belongs_to_associations_test.rb +711 -711
  20. data/test/cases/associations/cascaded_eager_loading_test.rb +181 -181
  21. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +851 -851
  22. data/test/cases/associations/join_model_test.rb +743 -743
  23. data/test/cases/attribute_methods_test.rb +822 -822
  24. data/test/cases/base_test.rb +2133 -2133
  25. data/test/cases/calculations_test.rb +482 -482
  26. data/test/cases/migration_test.rb +2408 -2408
  27. data/test/cases/persistence_test.rb +642 -642
  28. data/test/cases/query_cache_test.rb +257 -257
  29. data/test/cases/relations_test.rb +1182 -1182
  30. data/test/cases/schema_dumper_test.rb +256 -256
  31. data/test/cases/transaction_callbacks_test.rb +300 -300
  32. data/test/cases/validations/uniqueness_validation_test.rb +299 -299
  33. data/test/cases/xml_serialization_test.rb +408 -408
  34. data/test/config.yml +154 -154
  35. data/test/connections/native_ibm_db/connection.rb +43 -43
  36. data/test/ibm_db_test.rb +24 -24
  37. data/test/models/warehouse_thing.rb +4 -4
  38. data/test/schema/schema.rb +751 -751
  39. metadata +6 -8
  40. data/lib/linux/rb18x/ibm_db.bundle +0 -0
  41. data/lib/linux/rb19x/ibm_db.bundle +0 -0
  42. data/lib/linux/rb20x/ibm_db.bundle +0 -0
  43. data/lib/linux/rb21x/ibm_db.bundle +0 -0
@@ -1,181 +1,181 @@
1
- require "cases/helper"
2
- require 'models/post'
3
- require 'models/comment'
4
- require 'models/author'
5
- require 'models/categorization'
6
- require 'models/category'
7
- require 'models/company'
8
- require 'models/topic'
9
- require 'models/reply'
10
- require 'models/person'
11
- require 'models/vertex'
12
- require 'models/edge'
13
-
14
- class CascadedEagerLoadingTest < ActiveRecord::TestCase
15
- fixtures :authors, :mixins, :companies, :posts, :topics, :accounts, :comments,
16
- :categorizations, :people, :categories, :edges, :vertices
17
-
18
- def test_eager_association_loading_with_cascaded_two_levels
19
- authors = Author.find(:all, :include=>{:posts=>:comments}, :order=>"authors.id")
20
- assert_equal 3, authors.size
21
- assert_equal 5, authors[0].posts.size
22
- assert_equal 3, authors[1].posts.size
23
- assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i}
24
- end
25
-
26
- def test_eager_association_loading_with_cascaded_two_levels_and_one_level
27
- authors = Author.find(:all, :include=>[{:posts=>:comments}, :categorizations], :order=>"authors.id")
28
- assert_equal 3, authors.size
29
- assert_equal 5, authors[0].posts.size
30
- assert_equal 3, authors[1].posts.size
31
- assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i}
32
- assert_equal 1, authors[0].categorizations.size
33
- assert_equal 2, authors[1].categorizations.size
34
- end
35
-
36
- def test_eager_association_loading_with_hmt_does_not_table_name_collide_when_joining_associations
37
- assert_nothing_raised do
38
- Author.joins(:posts).eager_load(:comments).where(:posts => {:taggings_count => 1}).all
39
- end
40
- authors = Author.joins(:posts).eager_load(:comments).where(:posts => {:taggings_count => 1}).all
41
- assert_equal 1, assert_no_queries { authors.size }
42
- assert_equal 10, assert_no_queries { authors[0].comments.size }
43
- end
44
-
45
- def test_eager_association_loading_grafts_stashed_associations_to_correct_parent
46
- assert_nothing_raised do
47
- Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').order('people.id').all
48
- end
49
- assert_equal people(:michael), Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').order('people.id').first
50
- end
51
-
52
- def test_cascaded_eager_association_loading_with_join_for_count
53
- categories = Category.joins(:categorizations).includes([{:posts=>:comments}, :authors])
54
-
55
- assert_nothing_raised do
56
- assert_equal 4, categories.count
57
- assert_equal 4, categories.all.count
58
- assert_equal 3, categories.count(:distinct => true)
59
- assert_equal 3, categories.all.uniq.size # Must uniq since instantiating with inner joins will get dupes
60
- end
61
- end
62
-
63
- def test_cascaded_eager_association_loading_with_duplicated_includes
64
- categories = Category.includes(:categorizations).includes(:categorizations => :author).where("categorizations.id is not null")
65
- assert_nothing_raised do
66
- assert_equal 3, categories.count
67
- assert_equal 3, categories.all.size
68
- end
69
- end
70
-
71
- def test_cascaded_eager_association_loading_with_twice_includes_edge_cases
72
- categories = Category.includes(:categorizations => :author).includes(:categorizations => :post).where("posts.id is not null")
73
- assert_nothing_raised do
74
- assert_equal 3, categories.count
75
- assert_equal 3, categories.all.size
76
- end
77
- end
78
-
79
- def test_eager_association_loading_with_join_for_count
80
- authors = Author.joins(:special_posts).includes([:posts, :categorizations])
81
-
82
- assert_nothing_raised { authors.count }
83
- assert_queries(3) { authors.all }
84
- end
85
-
86
- def test_eager_association_loading_with_cascaded_two_levels_with_two_has_many_associations
87
- authors = Author.find(:all, :include=>{:posts=>[:comments, :categorizations]}, :order=>"authors.id")
88
- assert_equal 3, authors.size
89
- assert_equal 5, authors[0].posts.size
90
- assert_equal 3, authors[1].posts.size
91
- assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i}
92
- end
93
-
94
- def test_eager_association_loading_with_cascaded_two_levels_and_self_table_reference
95
- authors = Author.find(:all, :include=>{:posts=>[:comments, :author]}, :order=>"authors.id")
96
- assert_equal 3, authors.size
97
- assert_equal 5, authors[0].posts.size
98
- assert_equal authors(:david).name, authors[0].name
99
- assert_equal [authors(:david).name], authors[0].posts.collect{|post| post.author.name}.uniq
100
- end
101
-
102
- def test_eager_association_loading_with_cascaded_two_levels_with_condition
103
- authors = Author.find(:all, :include=>{:posts=>:comments}, :conditions=>"authors.id=1", :order=>"authors.id")
104
- assert_equal 1, authors.size
105
- assert_equal 5, authors[0].posts.size
106
- end
107
-
108
- def test_eager_association_loading_with_cascaded_three_levels_by_ping_pong
109
- firms = Firm.find(:all, :include=>{:account=>{:firm=>:account}}, :order=>"companies.id")
110
- assert_equal 2, firms.size
111
- assert_equal firms.first.account, firms.first.account.firm.account
112
- assert_equal companies(:first_firm).account, assert_no_queries { firms.first.account.firm.account }
113
- assert_equal companies(:first_firm).account.firm.account, assert_no_queries { firms.first.account.firm.account }
114
- end
115
-
116
- def test_eager_association_loading_with_has_many_sti
117
- topics = Topic.find(:all, :include => :replies, :order => 'topics.id')
118
- first, second, = topics(:first).replies.size, topics(:second).replies.size
119
- assert_no_queries do
120
- assert_equal first, topics[0].replies.size
121
- assert_equal second, topics[1].replies.size
122
- end
123
- end
124
-
125
- def test_eager_association_loading_with_has_many_sti_and_subclasses
126
- silly = SillyReply.new(:title => "gaga", :content => "boo-boo", :parent_id => 1)
127
- silly.parent_id = 1
128
- assert silly.save
129
-
130
- topics = Topic.find(:all, :include => :replies, :order => 'topics.id, replies_topics.id')
131
- assert_no_queries do
132
- assert_equal 2, topics[0].replies.size
133
- assert_equal 0, topics[1].replies.size
134
- end
135
- end
136
-
137
- def test_eager_association_loading_with_belongs_to_sti
138
- replies = Reply.find(:all, :include => :topic, :order => 'topics.id')
139
- assert replies.include?(topics(:second))
140
- assert !replies.include?(topics(:first))
141
- assert_equal topics(:first), assert_no_queries { replies.first.topic }
142
- end
143
-
144
- unless current_adapter?(:IBM_DBAdapter)
145
- def test_eager_association_loading_with_multiple_stis_and_order
146
- author = Author.find(:first, :include => { :posts => [ :special_comments , :very_special_comment ] }, :order => ['authors.name', 'comments.body', 'very_special_comments_posts.body'], :conditions => 'posts.id = 4')
147
- assert_equal authors(:david), author
148
- assert_no_queries do
149
- author.posts.first.special_comments
150
- author.posts.first.very_special_comment
151
- end
152
- end
153
- end
154
-
155
- def test_eager_association_loading_of_stis_with_multiple_references
156
- authors = Author.find(:all, :include => { :posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } } }, :order => 'comments.body, very_special_comments_posts.body', :conditions => 'posts.id = 4')
157
- assert_equal [authors(:david)], authors
158
- assert_no_queries do
159
- authors.first.posts.first.special_comments.first.post.special_comments
160
- authors.first.posts.first.special_comments.first.post.very_special_comment
161
- end
162
- end
163
-
164
- def test_eager_association_loading_where_first_level_returns_nil
165
- authors = Author.find(:all, :include => {:post_about_thinking => :comments}, :order => 'authors.id DESC')
166
- assert_equal [authors(:bob), authors(:mary), authors(:david)], authors
167
- assert_no_queries do
168
- authors[2].post_about_thinking.comments.first
169
- end
170
- end
171
-
172
- def test_eager_association_loading_with_recursive_cascading_four_levels_has_many_through
173
- source = Vertex.find(:first, :include=>{:sinks=>{:sinks=>{:sinks=>:sinks}}}, :order => 'vertices.id')
174
- assert_equal vertices(:vertex_4), assert_no_queries { source.sinks.first.sinks.first.sinks.first }
175
- end
176
-
177
- def test_eager_association_loading_with_recursive_cascading_four_levels_has_and_belongs_to_many
178
- sink = Vertex.find(:first, :include=>{:sources=>{:sources=>{:sources=>:sources}}}, :order => 'vertices.id DESC')
179
- assert_equal vertices(:vertex_1), assert_no_queries { sink.sources.first.sources.first.sources.first.sources.first }
180
- end
181
- end
1
+ require "cases/helper"
2
+ require 'models/post'
3
+ require 'models/comment'
4
+ require 'models/author'
5
+ require 'models/categorization'
6
+ require 'models/category'
7
+ require 'models/company'
8
+ require 'models/topic'
9
+ require 'models/reply'
10
+ require 'models/person'
11
+ require 'models/vertex'
12
+ require 'models/edge'
13
+
14
+ class CascadedEagerLoadingTest < ActiveRecord::TestCase
15
+ fixtures :authors, :mixins, :companies, :posts, :topics, :accounts, :comments,
16
+ :categorizations, :people, :categories, :edges, :vertices
17
+
18
+ def test_eager_association_loading_with_cascaded_two_levels
19
+ authors = Author.find(:all, :include=>{:posts=>:comments}, :order=>"authors.id")
20
+ assert_equal 3, authors.size
21
+ assert_equal 5, authors[0].posts.size
22
+ assert_equal 3, authors[1].posts.size
23
+ assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i}
24
+ end
25
+
26
+ def test_eager_association_loading_with_cascaded_two_levels_and_one_level
27
+ authors = Author.find(:all, :include=>[{:posts=>:comments}, :categorizations], :order=>"authors.id")
28
+ assert_equal 3, authors.size
29
+ assert_equal 5, authors[0].posts.size
30
+ assert_equal 3, authors[1].posts.size
31
+ assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i}
32
+ assert_equal 1, authors[0].categorizations.size
33
+ assert_equal 2, authors[1].categorizations.size
34
+ end
35
+
36
+ def test_eager_association_loading_with_hmt_does_not_table_name_collide_when_joining_associations
37
+ assert_nothing_raised do
38
+ Author.joins(:posts).eager_load(:comments).where(:posts => {:taggings_count => 1}).all
39
+ end
40
+ authors = Author.joins(:posts).eager_load(:comments).where(:posts => {:taggings_count => 1}).all
41
+ assert_equal 1, assert_no_queries { authors.size }
42
+ assert_equal 10, assert_no_queries { authors[0].comments.size }
43
+ end
44
+
45
+ def test_eager_association_loading_grafts_stashed_associations_to_correct_parent
46
+ assert_nothing_raised do
47
+ Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').order('people.id').all
48
+ end
49
+ assert_equal people(:michael), Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').order('people.id').first
50
+ end
51
+
52
+ def test_cascaded_eager_association_loading_with_join_for_count
53
+ categories = Category.joins(:categorizations).includes([{:posts=>:comments}, :authors])
54
+
55
+ assert_nothing_raised do
56
+ assert_equal 4, categories.count
57
+ assert_equal 4, categories.all.count
58
+ assert_equal 3, categories.count(:distinct => true)
59
+ assert_equal 3, categories.all.uniq.size # Must uniq since instantiating with inner joins will get dupes
60
+ end
61
+ end
62
+
63
+ def test_cascaded_eager_association_loading_with_duplicated_includes
64
+ categories = Category.includes(:categorizations).includes(:categorizations => :author).where("categorizations.id is not null")
65
+ assert_nothing_raised do
66
+ assert_equal 3, categories.count
67
+ assert_equal 3, categories.all.size
68
+ end
69
+ end
70
+
71
+ def test_cascaded_eager_association_loading_with_twice_includes_edge_cases
72
+ categories = Category.includes(:categorizations => :author).includes(:categorizations => :post).where("posts.id is not null")
73
+ assert_nothing_raised do
74
+ assert_equal 3, categories.count
75
+ assert_equal 3, categories.all.size
76
+ end
77
+ end
78
+
79
+ def test_eager_association_loading_with_join_for_count
80
+ authors = Author.joins(:special_posts).includes([:posts, :categorizations])
81
+
82
+ assert_nothing_raised { authors.count }
83
+ assert_queries(3) { authors.all }
84
+ end
85
+
86
+ def test_eager_association_loading_with_cascaded_two_levels_with_two_has_many_associations
87
+ authors = Author.find(:all, :include=>{:posts=>[:comments, :categorizations]}, :order=>"authors.id")
88
+ assert_equal 3, authors.size
89
+ assert_equal 5, authors[0].posts.size
90
+ assert_equal 3, authors[1].posts.size
91
+ assert_equal 10, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i}
92
+ end
93
+
94
+ def test_eager_association_loading_with_cascaded_two_levels_and_self_table_reference
95
+ authors = Author.find(:all, :include=>{:posts=>[:comments, :author]}, :order=>"authors.id")
96
+ assert_equal 3, authors.size
97
+ assert_equal 5, authors[0].posts.size
98
+ assert_equal authors(:david).name, authors[0].name
99
+ assert_equal [authors(:david).name], authors[0].posts.collect{|post| post.author.name}.uniq
100
+ end
101
+
102
+ def test_eager_association_loading_with_cascaded_two_levels_with_condition
103
+ authors = Author.find(:all, :include=>{:posts=>:comments}, :conditions=>"authors.id=1", :order=>"authors.id")
104
+ assert_equal 1, authors.size
105
+ assert_equal 5, authors[0].posts.size
106
+ end
107
+
108
+ def test_eager_association_loading_with_cascaded_three_levels_by_ping_pong
109
+ firms = Firm.find(:all, :include=>{:account=>{:firm=>:account}}, :order=>"companies.id")
110
+ assert_equal 2, firms.size
111
+ assert_equal firms.first.account, firms.first.account.firm.account
112
+ assert_equal companies(:first_firm).account, assert_no_queries { firms.first.account.firm.account }
113
+ assert_equal companies(:first_firm).account.firm.account, assert_no_queries { firms.first.account.firm.account }
114
+ end
115
+
116
+ def test_eager_association_loading_with_has_many_sti
117
+ topics = Topic.find(:all, :include => :replies, :order => 'topics.id')
118
+ first, second, = topics(:first).replies.size, topics(:second).replies.size
119
+ assert_no_queries do
120
+ assert_equal first, topics[0].replies.size
121
+ assert_equal second, topics[1].replies.size
122
+ end
123
+ end
124
+
125
+ def test_eager_association_loading_with_has_many_sti_and_subclasses
126
+ silly = SillyReply.new(:title => "gaga", :content => "boo-boo", :parent_id => 1)
127
+ silly.parent_id = 1
128
+ assert silly.save
129
+
130
+ topics = Topic.find(:all, :include => :replies, :order => 'topics.id, replies_topics.id')
131
+ assert_no_queries do
132
+ assert_equal 2, topics[0].replies.size
133
+ assert_equal 0, topics[1].replies.size
134
+ end
135
+ end
136
+
137
+ def test_eager_association_loading_with_belongs_to_sti
138
+ replies = Reply.find(:all, :include => :topic, :order => 'topics.id')
139
+ assert replies.include?(topics(:second))
140
+ assert !replies.include?(topics(:first))
141
+ assert_equal topics(:first), assert_no_queries { replies.first.topic }
142
+ end
143
+
144
+ unless current_adapter?(:IBM_DBAdapter)
145
+ def test_eager_association_loading_with_multiple_stis_and_order
146
+ author = Author.find(:first, :include => { :posts => [ :special_comments , :very_special_comment ] }, :order => ['authors.name', 'comments.body', 'very_special_comments_posts.body'], :conditions => 'posts.id = 4')
147
+ assert_equal authors(:david), author
148
+ assert_no_queries do
149
+ author.posts.first.special_comments
150
+ author.posts.first.very_special_comment
151
+ end
152
+ end
153
+ end
154
+
155
+ def test_eager_association_loading_of_stis_with_multiple_references
156
+ authors = Author.find(:all, :include => { :posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } } }, :order => 'comments.body, very_special_comments_posts.body', :conditions => 'posts.id = 4')
157
+ assert_equal [authors(:david)], authors
158
+ assert_no_queries do
159
+ authors.first.posts.first.special_comments.first.post.special_comments
160
+ authors.first.posts.first.special_comments.first.post.very_special_comment
161
+ end
162
+ end
163
+
164
+ def test_eager_association_loading_where_first_level_returns_nil
165
+ authors = Author.find(:all, :include => {:post_about_thinking => :comments}, :order => 'authors.id DESC')
166
+ assert_equal [authors(:bob), authors(:mary), authors(:david)], authors
167
+ assert_no_queries do
168
+ authors[2].post_about_thinking.comments.first
169
+ end
170
+ end
171
+
172
+ def test_eager_association_loading_with_recursive_cascading_four_levels_has_many_through
173
+ source = Vertex.find(:first, :include=>{:sinks=>{:sinks=>{:sinks=>:sinks}}}, :order => 'vertices.id')
174
+ assert_equal vertices(:vertex_4), assert_no_queries { source.sinks.first.sinks.first.sinks.first }
175
+ end
176
+
177
+ def test_eager_association_loading_with_recursive_cascading_four_levels_has_and_belongs_to_many
178
+ sink = Vertex.find(:first, :include=>{:sources=>{:sources=>{:sources=>:sources}}}, :order => 'vertices.id DESC')
179
+ assert_equal vertices(:vertex_1), assert_no_queries { sink.sources.first.sources.first.sources.first.sources.first }
180
+ end
181
+ end
@@ -1,851 +1,851 @@
1
- require "cases/helper"
2
- require 'models/developer'
3
- require 'models/project'
4
- require 'models/company'
5
- require 'models/customer'
6
- require 'models/order'
7
- require 'models/categorization'
8
- require 'models/category'
9
- require 'models/post'
10
- require 'models/author'
11
- require 'models/tag'
12
- require 'models/tagging'
13
- require 'models/parrot'
14
- require 'models/pirate'
15
- require 'models/treasure'
16
- require 'models/price_estimate'
17
- require 'models/club'
18
- require 'models/member'
19
- require 'models/membership'
20
- require 'models/sponsor'
21
- require 'models/country'
22
- require 'models/treaty'
23
- require 'active_support/core_ext/string/conversions'
24
-
25
- class ProjectWithAfterCreateHook < ActiveRecord::Base
26
- self.table_name = 'projects'
27
- has_and_belongs_to_many :developers,
28
- :class_name => "DeveloperForProjectWithAfterCreateHook",
29
- :join_table => "developers_projects",
30
- :foreign_key => "project_id",
31
- :association_foreign_key => "developer_id"
32
-
33
- after_create :add_david
34
-
35
- def add_david
36
- david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
37
- david.projects << self
38
- end
39
- end
40
-
41
- class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
42
- self.table_name = 'developers'
43
- has_and_belongs_to_many :projects,
44
- :class_name => "ProjectWithAfterCreateHook",
45
- :join_table => "developers_projects",
46
- :association_foreign_key => "project_id",
47
- :foreign_key => "developer_id"
48
- end
49
-
50
- class ProjectWithSymbolsForKeys < ActiveRecord::Base
51
- self.table_name = 'projects'
52
- has_and_belongs_to_many :developers,
53
- :class_name => "DeveloperWithSymbolsForKeys",
54
- :join_table => :developers_projects,
55
- :foreign_key => :project_id,
56
- :association_foreign_key => "developer_id"
57
- end
58
-
59
- class DeveloperWithSymbolsForKeys < ActiveRecord::Base
60
- self.table_name = 'developers'
61
- has_and_belongs_to_many :projects,
62
- :class_name => "ProjectWithSymbolsForKeys",
63
- :join_table => :developers_projects,
64
- :association_foreign_key => :project_id,
65
- :foreign_key => "developer_id"
66
- end
67
-
68
- class DeveloperWithCounterSQL < ActiveRecord::Base
69
- self.table_name = 'developers'
70
- has_and_belongs_to_many :projects,
71
- :class_name => "DeveloperWithCounterSQL",
72
- :join_table => "developers_projects",
73
- :association_foreign_key => "project_id",
74
- :foreign_key => "developer_id",
75
- :counter_sql => proc { "SELECT COUNT(*) AS count_all FROM projects INNER JOIN developers_projects ON projects.id = developers_projects.project_id WHERE developers_projects.developer_id =#{id}" }
76
- end
77
-
78
- class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
79
- fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
80
- :parrots, :pirates, :parrots_pirates, :treasures, :price_estimates, :tags, :taggings
81
-
82
- def setup_data_for_habtm_case
83
- ActiveRecord::Base.connection.execute('delete from countries_treaties')
84
-
85
- country = Country.new(:name => 'India')
86
- country.country_id = 'c1'
87
- country.save!
88
-
89
- treaty = Treaty.new(:name => 'peace')
90
- treaty.treaty_id = 't1'
91
- country.treaties << treaty
92
- end
93
-
94
- def test_should_property_quote_string_primary_keys
95
- setup_data_for_habtm_case
96
-
97
- con = ActiveRecord::Base.connection
98
- sql = 'select * from countries_treaties'
99
- record = con.select_rows(sql).last
100
- assert_equal 'c1', record[0]
101
- assert_equal 't1', record[1]
102
- end
103
-
104
- def test_proper_usage_of_primary_keys_and_join_table
105
- setup_data_for_habtm_case
106
-
107
- assert_equal 'country_id', Country.primary_key
108
- assert_equal 'treaty_id', Treaty.primary_key
109
-
110
- country = Country.first
111
- assert_equal 1, country.treaties.count
112
- end
113
-
114
- def test_has_and_belongs_to_many
115
- david = Developer.find(1)
116
-
117
- assert !david.projects.empty?
118
- assert_equal 2, david.projects.size
119
-
120
- active_record = Project.find(1)
121
- assert !active_record.developers.empty?
122
- assert_equal 3, active_record.developers.size
123
- assert active_record.developers.include?(david)
124
- end
125
-
126
- def test_triple_equality
127
- assert !(Array === Developer.find(1).projects)
128
- assert Developer.find(1).projects === Array
129
- end
130
-
131
- def test_adding_single
132
- jamis = Developer.find(2)
133
- jamis.projects.reload # causing the collection to load
134
- action_controller = Project.find(2)
135
- assert_equal 1, jamis.projects.size
136
- assert_equal 1, action_controller.developers.size
137
-
138
- jamis.projects << action_controller
139
-
140
- assert_equal 2, jamis.projects.size
141
- assert_equal 2, jamis.projects(true).size
142
- assert_equal 2, action_controller.developers(true).size
143
- end
144
-
145
- def test_adding_type_mismatch
146
- jamis = Developer.find(2)
147
- assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil }
148
- assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 }
149
- end
150
-
151
- def test_adding_from_the_project
152
- jamis = Developer.find(2)
153
- action_controller = Project.find(2)
154
- action_controller.developers.reload
155
- assert_equal 1, jamis.projects.size
156
- assert_equal 1, action_controller.developers.size
157
-
158
- action_controller.developers << jamis
159
-
160
- assert_equal 2, jamis.projects(true).size
161
- assert_equal 2, action_controller.developers.size
162
- assert_equal 2, action_controller.developers(true).size
163
- end
164
-
165
- def test_adding_from_the_project_fixed_timestamp
166
- jamis = Developer.find(2)
167
- action_controller = Project.find(2)
168
- action_controller.developers.reload
169
- assert_equal 1, jamis.projects.size
170
- assert_equal 1, action_controller.developers.size
171
- updated_at = jamis.updated_at
172
-
173
- action_controller.developers << jamis
174
-
175
- assert_equal updated_at, jamis.updated_at
176
- assert_equal 2, jamis.projects(true).size
177
- assert_equal 2, action_controller.developers.size
178
- assert_equal 2, action_controller.developers(true).size
179
- end
180
-
181
- def test_adding_multiple
182
- aredridel = Developer.new("name" => "Aredridel")
183
- aredridel.save
184
- aredridel.projects.reload
185
- aredridel.projects.push(Project.find(1), Project.find(2))
186
- assert_equal 2, aredridel.projects.size
187
- assert_equal 2, aredridel.projects(true).size
188
- end
189
-
190
- def test_adding_a_collection
191
- aredridel = Developer.new("name" => "Aredridel")
192
- aredridel.save
193
- aredridel.projects.reload
194
- aredridel.projects.concat([Project.find(1), Project.find(2)])
195
- assert_equal 2, aredridel.projects.size
196
- assert_equal 2, aredridel.projects(true).size
197
- end
198
-
199
- def test_habtm_adding_before_save
200
- no_of_devels = Developer.count
201
- no_of_projects = Project.count
202
- aredridel = Developer.new("name" => "Aredridel")
203
- aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
204
- assert !aredridel.persisted?
205
- assert !p.persisted?
206
- assert aredridel.save
207
- assert aredridel.persisted?
208
- assert_equal no_of_devels+1, Developer.count
209
- assert_equal no_of_projects+1, Project.count
210
- assert_equal 2, aredridel.projects.size
211
- assert_equal 2, aredridel.projects(true).size
212
- end
213
-
214
- def test_habtm_saving_multiple_relationships
215
- new_project = Project.new("name" => "Grimetime")
216
- amount_of_developers = 4
217
- developers = (0...amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }.reverse
218
-
219
- new_project.developer_ids = [developers[0].id, developers[1].id]
220
- new_project.developers_with_callback_ids = [developers[2].id, developers[3].id]
221
- assert new_project.save
222
-
223
- new_project.reload
224
- assert_equal amount_of_developers, new_project.developers.size
225
- assert_equal developers, new_project.developers
226
- end
227
-
228
- def test_habtm_unique_order_preserved
229
- assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
230
- assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
231
- end
232
-
233
- def test_build
234
- devel = Developer.find(1)
235
- proj = assert_no_queries { devel.projects.build("name" => "Projekt") }
236
- assert !devel.projects.loaded?
237
-
238
- assert_equal devel.projects.last, proj
239
- assert devel.projects.loaded?
240
-
241
- assert !proj.persisted?
242
- devel.save
243
- assert proj.persisted?
244
- assert_equal devel.projects.last, proj
245
- assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
246
- end
247
-
248
- def test_new_aliased_to_build
249
- devel = Developer.find(1)
250
- proj = assert_no_queries { devel.projects.new("name" => "Projekt") }
251
- assert !devel.projects.loaded?
252
-
253
- assert_equal devel.projects.last, proj
254
- assert devel.projects.loaded?
255
-
256
- assert !proj.persisted?
257
- devel.save
258
- assert proj.persisted?
259
- assert_equal devel.projects.last, proj
260
- assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
261
- end
262
-
263
- def test_build_by_new_record
264
- devel = Developer.new(:name => "Marcel", :salary => 75000)
265
- devel.projects.build(:name => "Make bed")
266
- proj2 = devel.projects.build(:name => "Lie in it")
267
- assert_equal devel.projects.last, proj2
268
- assert !proj2.persisted?
269
- devel.save
270
- assert devel.persisted?
271
- assert proj2.persisted?
272
- assert_equal devel.projects.last, proj2
273
- assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
274
- end
275
-
276
- def test_create
277
- devel = Developer.find(1)
278
- proj = devel.projects.create("name" => "Projekt")
279
- assert !devel.projects.loaded?
280
-
281
- assert_equal devel.projects.last, proj
282
- assert !devel.projects.loaded?
283
-
284
- assert proj.persisted?
285
- assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
286
- end
287
-
288
- def test_create_by_new_record
289
- devel = Developer.new(:name => "Marcel", :salary => 75000)
290
- devel.projects.build(:name => "Make bed")
291
- proj2 = devel.projects.build(:name => "Lie in it")
292
- assert_equal devel.projects.last, proj2
293
- assert !proj2.persisted?
294
- devel.save
295
- assert devel.persisted?
296
- assert proj2.persisted?
297
- assert_equal devel.projects.last, proj2
298
- assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
299
- end
300
-
301
- def test_creation_respects_hash_condition
302
- # in Oracle '' is saved as null therefore need to save ' ' in not null column
303
- post = categories(:general).post_with_conditions.build(:body => ' ')
304
-
305
- assert post.save
306
- assert_equal 'Yet Another Testing Title', post.title
307
-
308
- # in Oracle '' is saved as null therefore need to save ' ' in not null column
309
- another_post = categories(:general).post_with_conditions.create(:body => ' ')
310
-
311
- assert another_post.persisted?
312
- assert_equal 'Yet Another Testing Title', another_post.title
313
- end
314
-
315
- def test_uniq_after_the_fact
316
- dev = developers(:jamis)
317
- dev.projects << projects(:active_record)
318
- dev.projects << projects(:active_record)
319
-
320
- assert_equal 3, dev.projects.size
321
- assert_equal 1, dev.projects.uniq.size
322
- end
323
-
324
- def test_uniq_before_the_fact
325
- projects(:active_record).developers << developers(:jamis)
326
- projects(:active_record).developers << developers(:david)
327
- assert_equal 3, projects(:active_record, :reload).developers.size
328
- end
329
-
330
- def test_uniq_option_prevents_duplicate_push
331
- project = projects(:active_record)
332
- project.developers << developers(:jamis)
333
- project.developers << developers(:david)
334
- assert_equal 3, project.developers.size
335
-
336
- project.developers << developers(:david)
337
- project.developers << developers(:jamis)
338
- assert_equal 3, project.developers.size
339
- end
340
-
341
- def test_deleting
342
- david = Developer.find(1)
343
- active_record = Project.find(1)
344
- david.projects.reload
345
- assert_equal 2, david.projects.size
346
- assert_equal 3, active_record.developers.size
347
-
348
- david.projects.delete(active_record)
349
-
350
- assert_equal 1, david.projects.size
351
- assert_equal 1, david.projects(true).size
352
- assert_equal 2, active_record.developers(true).size
353
- end
354
-
355
- def test_deleting_array
356
- david = Developer.find(1)
357
- david.projects.reload
358
- david.projects.delete(Project.find(:all))
359
- assert_equal 0, david.projects.size
360
- assert_equal 0, david.projects(true).size
361
- end
362
-
363
- def test_deleting_with_sql
364
- david = Developer.find(1)
365
- active_record = Project.find(1)
366
- active_record.developers.reload
367
- assert_equal 3, active_record.developers_by_sql.size
368
-
369
- active_record.developers_by_sql.delete(david)
370
- assert_equal 2, active_record.developers_by_sql(true).size
371
- end
372
-
373
- def test_deleting_array_with_sql
374
- active_record = Project.find(1)
375
- active_record.developers.reload
376
- assert_equal 3, active_record.developers_by_sql.size
377
-
378
- active_record.developers_by_sql.delete(Developer.find(:all))
379
- assert_equal 0, active_record.developers_by_sql(true).size
380
- end
381
-
382
- def test_deleting_all
383
- david = Developer.find(1)
384
- david.projects.reload
385
- david.projects.clear
386
- assert_equal 0, david.projects.size
387
- assert_equal 0, david.projects(true).size
388
- end
389
-
390
- def test_removing_associations_on_destroy
391
- david = DeveloperWithBeforeDestroyRaise.find(1)
392
- assert !david.projects.empty?
393
- david.destroy
394
- assert david.projects.empty?
395
- assert DeveloperWithBeforeDestroyRaise.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = 1").empty?
396
- end
397
-
398
- def test_destroying
399
- david = Developer.find(1)
400
- project = Project.find(1)
401
- david.projects.reload
402
- assert_equal 2, david.projects.size
403
- assert_equal 3, project.developers.size
404
-
405
- assert_no_difference "Project.count" do
406
- david.projects.destroy(project)
407
- end
408
-
409
- join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id} AND project_id = #{project.id}")
410
- assert join_records.empty?
411
-
412
- assert_equal 1, david.reload.projects.size
413
- assert_equal 1, david.projects(true).size
414
- end
415
-
416
- def test_destroying_many
417
- david = Developer.find(1)
418
- david.projects.reload
419
- projects = Project.all
420
-
421
- assert_no_difference "Project.count" do
422
- david.projects.destroy(*projects)
423
- end
424
-
425
- join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
426
- assert join_records.empty?
427
-
428
- assert_equal 0, david.reload.projects.size
429
- assert_equal 0, david.projects(true).size
430
- end
431
-
432
- def test_destroy_all
433
- david = Developer.find(1)
434
- david.projects.reload
435
- assert !david.projects.empty?
436
-
437
- assert_no_difference "Project.count" do
438
- david.projects.destroy_all
439
- end
440
-
441
- join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
442
- assert join_records.empty?
443
-
444
- assert david.projects.empty?
445
- assert david.projects(true).empty?
446
- end
447
-
448
- def test_destroy_associations_destroys_multiple_associations
449
- george = parrots(:george)
450
- assert !george.pirates.empty?
451
- assert !george.treasures.empty?
452
-
453
- assert_no_difference "Pirate.count" do
454
- assert_no_difference "Treasure.count" do
455
- george.destroy_associations
456
- end
457
- end
458
-
459
- join_records = Parrot.connection.select_all("SELECT * FROM parrots_pirates WHERE parrot_id = #{george.id}")
460
- assert join_records.empty?
461
- assert george.pirates(true).empty?
462
-
463
- join_records = Parrot.connection.select_all("SELECT * FROM parrots_treasures WHERE parrot_id = #{george.id}")
464
- assert join_records.empty?
465
- assert george.treasures(true).empty?
466
- end
467
-
468
- def test_deprecated_push_with_attributes_was_removed
469
- jamis = developers(:jamis)
470
- assert_raise(NoMethodError) do
471
- jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today)
472
- end
473
- end
474
-
475
- def test_associations_with_conditions
476
- assert_equal 3, projects(:active_record).developers.size
477
- assert_equal 1, projects(:active_record).developers_named_david.size
478
- assert_equal 1, projects(:active_record).developers_named_david_with_hash_conditions.size
479
-
480
- assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id)
481
- assert_equal developers(:david), projects(:active_record).developers_named_david_with_hash_conditions.find(developers(:david).id)
482
- assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id)
483
-
484
- projects(:active_record).developers_named_david.clear
485
- assert_equal 2, projects(:active_record, :reload).developers.size
486
- end
487
-
488
- def test_find_in_association
489
- # Using sql
490
- assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
491
-
492
- # Using ruby
493
- active_record = projects(:active_record)
494
- active_record.developers.reload
495
- assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find"
496
- end
497
-
498
- def test_include_uses_array_include_after_loaded
499
- project = projects(:active_record)
500
- project.developers.class # force load target
501
-
502
- developer = project.developers.first
503
-
504
- assert_no_queries do
505
- assert project.developers.loaded?
506
- assert project.developers.include?(developer)
507
- end
508
- end
509
-
510
- def test_include_checks_if_record_exists_if_target_not_loaded
511
- project = projects(:active_record)
512
- developer = project.developers.first
513
-
514
- project.reload
515
- assert ! project.developers.loaded?
516
- assert_queries(1) do
517
- assert project.developers.include?(developer)
518
- end
519
- assert ! project.developers.loaded?
520
- end
521
-
522
- def test_include_returns_false_for_non_matching_record_to_verify_scoping
523
- project = projects(:active_record)
524
- developer = Developer.create :name => "Bryan", :salary => 50_000
525
-
526
- assert ! project.developers.loaded?
527
- assert ! project.developers.include?(developer)
528
- end
529
-
530
- def test_find_in_association_with_custom_finder_sql
531
- assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id), "SQL find"
532
-
533
- active_record = projects(:active_record)
534
- active_record.developers_with_finder_sql.reload
535
- assert_equal developers(:david), active_record.developers_with_finder_sql.find(developers(:david).id), "Ruby find"
536
- end
537
-
538
- def test_find_in_association_with_custom_finder_sql_and_multiple_interpolations
539
- # interpolate once:
540
- assert_equal [developers(:david), developers(:jamis), developers(:poor_jamis)], projects(:active_record).developers_with_finder_sql, "first interpolation"
541
- # interpolate again, for a different project id
542
- assert_equal [developers(:david)], projects(:action_controller).developers_with_finder_sql, "second interpolation"
543
- end
544
-
545
- def test_find_in_association_with_custom_finder_sql_and_string_id
546
- assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id.to_s), "SQL find"
547
- end
548
-
549
- def test_find_with_merged_options
550
- assert_equal 1, projects(:active_record).limited_developers.size
551
- assert_equal 1, projects(:active_record).limited_developers.find(:all).size
552
- assert_equal 3, projects(:active_record).limited_developers.find(:all, :limit => nil).size
553
- end
554
-
555
- def test_dynamic_find_should_respect_association_order
556
- # Developers are ordered 'name DESC, id DESC'
557
- high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
558
-
559
- assert_equal high_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'")
560
- assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
561
- end
562
-
563
- def test_dynamic_find_all_should_respect_association_order
564
- # Developers are ordered 'name DESC, id DESC'
565
- low_id_jamis = developers(:jamis)
566
- middle_id_jamis = developers(:poor_jamis)
567
- high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
568
-
569
- assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'")
570
- assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis')
571
- end
572
-
573
- def test_find_should_append_to_association_order
574
- ordered_developers = projects(:active_record).developers.order('projects.id')
575
- assert_equal ['developers.name desc, developers.id desc', 'projects.id'], ordered_developers.order_values
576
- end
577
-
578
- def test_dynamic_find_all_should_respect_association_limit
579
- assert_equal 1, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'").length
580
- assert_equal 1, projects(:active_record).limited_developers.find_all_by_name('Jamis').length
581
- end
582
-
583
- def test_dynamic_find_all_order_should_override_association_limit
584
- assert_equal 2, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'", :limit => 9_000).length
585
- assert_equal 2, projects(:active_record).limited_developers.find_all_by_name('Jamis', :limit => 9_000).length
586
- end
587
-
588
- def test_dynamic_find_all_should_respect_readonly_access
589
- projects(:active_record).readonly_developers.each { |d| assert_raise(ActiveRecord::ReadOnlyRecord) { d.save! } if d.valid?}
590
- projects(:active_record).readonly_developers.each { |d| d.readonly? }
591
- end
592
-
593
- def test_new_with_values_in_collection
594
- jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
595
- david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
596
- project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie")
597
- project.developers << jamis
598
- project.save!
599
- project.reload
600
-
601
- assert project.developers.include?(jamis)
602
- assert project.developers.include?(david)
603
- end
604
-
605
- def test_find_in_association_with_options
606
- developers = projects(:active_record).developers.all
607
- assert_equal 3, developers.size
608
-
609
- assert_equal developers(:poor_jamis), projects(:active_record).developers.where("salary < 10000").first
610
- end
611
-
612
- def test_replace_with_less
613
- david = developers(:david)
614
- david.projects = [projects(:action_controller)]
615
- assert david.save
616
- assert_equal 1, david.projects.length
617
- end
618
-
619
- def test_replace_with_new
620
- david = developers(:david)
621
- david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
622
- david.save
623
- assert_equal 2, david.projects.length
624
- assert !david.projects.include?(projects(:active_record))
625
- end
626
-
627
- def test_replace_on_new_object
628
- new_developer = Developer.new("name" => "Matz")
629
- new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
630
- new_developer.save
631
- assert_equal 2, new_developer.projects.length
632
- end
633
-
634
- def test_consider_type
635
- developer = Developer.find(:first)
636
- special_project = SpecialProject.create("name" => "Special Project")
637
-
638
- other_project = developer.projects.first
639
- developer.special_projects << special_project
640
- developer.reload
641
-
642
- assert developer.projects.include?(special_project)
643
- assert developer.special_projects.include?(special_project)
644
- assert !developer.special_projects.include?(other_project)
645
- end
646
-
647
- def test_update_attributes_after_push_without_duplicate_join_table_rows
648
- developer = Developer.new("name" => "Kano")
649
- project = SpecialProject.create("name" => "Special Project")
650
- assert developer.save
651
- developer.projects << project
652
- developer.update_column("name", "Bruza")
653
- assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i
654
- SELECT count(*) FROM developers_projects
655
- WHERE project_id = #{project.id}
656
- AND developer_id = #{developer.id}
657
- end_sql
658
- end
659
-
660
- def test_updating_attributes_on_non_rich_associations
661
- welcome = categories(:technology).posts.first
662
- welcome.title = "Something else"
663
- assert welcome.save!
664
- end
665
-
666
- def test_habtm_respects_select
667
- categories(:technology).select_testing_posts(true).each do |o|
668
- assert_respond_to o, :correctness_marker
669
- end
670
- assert_respond_to categories(:technology).select_testing_posts.find(:first), :correctness_marker
671
- end
672
-
673
- def test_habtm_selects_all_columns_by_default
674
- assert_equal Project.column_names.sort, developers(:david).projects.first.attributes.keys.sort
675
- end
676
-
677
- def test_habtm_respects_select_query_method
678
- assert_equal ['id'], developers(:david).projects.select(:id).first.attributes.keys
679
- end
680
-
681
- def test_join_table_alias
682
- assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size
683
- end
684
-
685
- def test_join_with_group
686
- group = Developer.columns.inject([]) do |g, c|
687
- g << "developers.#{c.name}"
688
- g << "developers_projects_2.#{c.name}"
689
- end
690
- Project.columns.each { |c| group << "projects.#{c.name}" }
691
-
692
- assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => group.join(",")).size
693
- end
694
-
695
- def test_find_grouped
696
- all_posts_from_category1 = Post.find(:all, :conditions => "category_id = 1", :joins => :categories)
697
- grouped_posts_of_category1 = Post.find(:all, :conditions => "category_id = 1", :group => "author_id", :select => 'count(posts.id) as posts_count', :joins => :categories)
698
- assert_equal 5, all_posts_from_category1.size
699
- assert_equal 2, grouped_posts_of_category1.size
700
- end
701
-
702
- def test_find_scoped_grouped
703
- assert_equal 5, categories(:general).posts_grouped_by_title.size
704
- assert_equal 1, categories(:technology).posts_grouped_by_title.size
705
- end
706
-
707
- def test_find_scoped_grouped_having
708
- assert_equal 2, projects(:active_record).well_payed_salary_groups.size
709
- assert projects(:active_record).well_payed_salary_groups.all? { |g| g.salary > 10000 }
710
- end
711
-
712
- def test_get_ids
713
- assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
714
- assert_equal [projects(:active_record).id], developers(:jamis).project_ids
715
- end
716
-
717
- def test_get_ids_for_loaded_associations
718
- developer = developers(:david)
719
- developer.projects(true)
720
- assert_queries(0) do
721
- developer.project_ids
722
- developer.project_ids
723
- end
724
- end
725
-
726
- def test_get_ids_for_unloaded_associations_does_not_load_them
727
- developer = developers(:david)
728
- assert !developer.projects.loaded?
729
- assert_equal projects(:active_record, :action_controller).map(&:id).sort, developer.project_ids.sort
730
- assert !developer.projects.loaded?
731
- end
732
-
733
- def test_assign_ids
734
- developer = Developer.new("name" => "Joe")
735
- developer.project_ids = projects(:active_record, :action_controller).map(&:id)
736
- developer.save
737
- developer.reload
738
- assert_equal 2, developer.projects.length
739
- assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
740
- end
741
-
742
- def test_assign_ids_ignoring_blanks
743
- developer = Developer.new("name" => "Joe")
744
- developer.project_ids = [projects(:active_record).id, nil, projects(:action_controller).id, '']
745
- developer.save
746
- developer.reload
747
- assert_equal 2, developer.projects.length
748
- assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
749
- end
750
-
751
- def test_scoped_find_on_through_association_doesnt_return_read_only_records
752
- tag = Post.find(1).tags.find_by_name("General")
753
-
754
- assert_nothing_raised do
755
- tag.save!
756
- end
757
- end
758
-
759
- def test_has_many_through_polymorphic_has_manys_works
760
- assert_equal [10, 20].to_set, pirates(:redbeard).treasure_estimates.map(&:price).to_set
761
- end
762
-
763
- def test_symbols_as_keys
764
- developer = DeveloperWithSymbolsForKeys.new(:name => 'David')
765
- project = ProjectWithSymbolsForKeys.new(:name => 'Rails Testing')
766
- project.developers << developer
767
- project.save!
768
-
769
- assert_equal 1, project.developers.size
770
- assert_equal 1, developer.projects.size
771
- assert_equal developer, project.developers.find(:first)
772
- assert_equal project, developer.projects.find(:first)
773
- end
774
-
775
- def test_self_referential_habtm_without_foreign_key_set_should_raise_exception
776
- assert_raise(ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded) {
777
- Member.class_eval do
778
- has_and_belongs_to_many :friends, :class_name => "Member", :join_table => "member_friends"
779
- end
780
- }
781
- end
782
-
783
- def test_dynamic_find_should_respect_association_include
784
- # SQL error in sort clause if :include is not included
785
- # due to Unknown column 'authors.id'
786
- assert Category.find(1).posts_with_authors_sorted_by_author_id.find_by_title('Welcome to the weblog')
787
- end
788
-
789
- def test_counting_on_habtm_association_and_not_array
790
- david = Developer.find(1)
791
- # Extra parameter just to make sure we aren't falling back to
792
- # Array#count in Ruby >=1.8.7, which would raise an ArgumentError
793
- assert_nothing_raised { david.projects.count(:all, :conditions => '1=1') }
794
- end
795
-
796
- def test_count
797
- david = Developer.find(1)
798
- assert_equal 2, david.projects.count
799
- end
800
-
801
- def test_count_with_counter_sql
802
- developer = DeveloperWithCounterSQL.create(:name => 'tekin')
803
- developer.project_ids = [projects(:active_record).id]
804
- developer.save
805
- developer.reload
806
- assert_equal 1, developer.projects.count
807
- end
808
-
809
- unless current_adapter?(:PostgreSQLAdapter, :IBM_DBAdapter)
810
- def test_count_with_finder_sql
811
- assert_equal 3, projects(:active_record).developers_with_finder_sql.count
812
- assert_equal 3, projects(:active_record).developers_with_multiline_finder_sql.count
813
- end
814
- end
815
-
816
- def test_association_proxy_transaction_method_starts_transaction_in_association_class
817
- Post.expects(:transaction)
818
- Category.find(:first).posts.transaction do
819
- # nothing
820
- end
821
- end
822
-
823
- def test_caching_of_columns
824
- david = Developer.find(1)
825
- # clear cache possibly created by other tests
826
- david.projects.reset_column_information
827
-
828
- assert_queries(1) { david.projects.columns; david.projects.columns }
829
-
830
- ## and again to verify that reset_column_information clears the cache correctly
831
- david.projects.reset_column_information
832
- assert_queries(1) { david.projects.columns; david.projects.columns }
833
- end
834
-
835
- def test_attributes_are_being_set_when_initialized_from_habm_association_with_where_clause
836
- new_developer = projects(:action_controller).developers.where(:name => "Marcelo").build
837
- assert_equal new_developer.name, "Marcelo"
838
- end
839
-
840
- def test_attributes_are_being_set_when_initialized_from_habm_association_with_multiple_where_clauses
841
- new_developer = projects(:action_controller).developers.where(:name => "Marcelo").where(:salary => 90_000).build
842
- assert_equal new_developer.name, "Marcelo"
843
- assert_equal new_developer.salary, 90_000
844
- end
845
-
846
- def test_include_method_in_has_and_belongs_to_many_association_should_return_true_for_instance_added_with_build
847
- project = Project.new
848
- developer = project.developers.build
849
- assert project.developers.include?(developer)
850
- end
851
- end
1
+ require "cases/helper"
2
+ require 'models/developer'
3
+ require 'models/project'
4
+ require 'models/company'
5
+ require 'models/customer'
6
+ require 'models/order'
7
+ require 'models/categorization'
8
+ require 'models/category'
9
+ require 'models/post'
10
+ require 'models/author'
11
+ require 'models/tag'
12
+ require 'models/tagging'
13
+ require 'models/parrot'
14
+ require 'models/pirate'
15
+ require 'models/treasure'
16
+ require 'models/price_estimate'
17
+ require 'models/club'
18
+ require 'models/member'
19
+ require 'models/membership'
20
+ require 'models/sponsor'
21
+ require 'models/country'
22
+ require 'models/treaty'
23
+ require 'active_support/core_ext/string/conversions'
24
+
25
+ class ProjectWithAfterCreateHook < ActiveRecord::Base
26
+ self.table_name = 'projects'
27
+ has_and_belongs_to_many :developers,
28
+ :class_name => "DeveloperForProjectWithAfterCreateHook",
29
+ :join_table => "developers_projects",
30
+ :foreign_key => "project_id",
31
+ :association_foreign_key => "developer_id"
32
+
33
+ after_create :add_david
34
+
35
+ def add_david
36
+ david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
37
+ david.projects << self
38
+ end
39
+ end
40
+
41
+ class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
42
+ self.table_name = 'developers'
43
+ has_and_belongs_to_many :projects,
44
+ :class_name => "ProjectWithAfterCreateHook",
45
+ :join_table => "developers_projects",
46
+ :association_foreign_key => "project_id",
47
+ :foreign_key => "developer_id"
48
+ end
49
+
50
+ class ProjectWithSymbolsForKeys < ActiveRecord::Base
51
+ self.table_name = 'projects'
52
+ has_and_belongs_to_many :developers,
53
+ :class_name => "DeveloperWithSymbolsForKeys",
54
+ :join_table => :developers_projects,
55
+ :foreign_key => :project_id,
56
+ :association_foreign_key => "developer_id"
57
+ end
58
+
59
+ class DeveloperWithSymbolsForKeys < ActiveRecord::Base
60
+ self.table_name = 'developers'
61
+ has_and_belongs_to_many :projects,
62
+ :class_name => "ProjectWithSymbolsForKeys",
63
+ :join_table => :developers_projects,
64
+ :association_foreign_key => :project_id,
65
+ :foreign_key => "developer_id"
66
+ end
67
+
68
+ class DeveloperWithCounterSQL < ActiveRecord::Base
69
+ self.table_name = 'developers'
70
+ has_and_belongs_to_many :projects,
71
+ :class_name => "DeveloperWithCounterSQL",
72
+ :join_table => "developers_projects",
73
+ :association_foreign_key => "project_id",
74
+ :foreign_key => "developer_id",
75
+ :counter_sql => proc { "SELECT COUNT(*) AS count_all FROM projects INNER JOIN developers_projects ON projects.id = developers_projects.project_id WHERE developers_projects.developer_id =#{id}" }
76
+ end
77
+
78
+ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
79
+ fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
80
+ :parrots, :pirates, :parrots_pirates, :treasures, :price_estimates, :tags, :taggings
81
+
82
+ def setup_data_for_habtm_case
83
+ ActiveRecord::Base.connection.execute('delete from countries_treaties')
84
+
85
+ country = Country.new(:name => 'India')
86
+ country.country_id = 'c1'
87
+ country.save!
88
+
89
+ treaty = Treaty.new(:name => 'peace')
90
+ treaty.treaty_id = 't1'
91
+ country.treaties << treaty
92
+ end
93
+
94
+ def test_should_property_quote_string_primary_keys
95
+ setup_data_for_habtm_case
96
+
97
+ con = ActiveRecord::Base.connection
98
+ sql = 'select * from countries_treaties'
99
+ record = con.select_rows(sql).last
100
+ assert_equal 'c1', record[0]
101
+ assert_equal 't1', record[1]
102
+ end
103
+
104
+ def test_proper_usage_of_primary_keys_and_join_table
105
+ setup_data_for_habtm_case
106
+
107
+ assert_equal 'country_id', Country.primary_key
108
+ assert_equal 'treaty_id', Treaty.primary_key
109
+
110
+ country = Country.first
111
+ assert_equal 1, country.treaties.count
112
+ end
113
+
114
+ def test_has_and_belongs_to_many
115
+ david = Developer.find(1)
116
+
117
+ assert !david.projects.empty?
118
+ assert_equal 2, david.projects.size
119
+
120
+ active_record = Project.find(1)
121
+ assert !active_record.developers.empty?
122
+ assert_equal 3, active_record.developers.size
123
+ assert active_record.developers.include?(david)
124
+ end
125
+
126
+ def test_triple_equality
127
+ assert !(Array === Developer.find(1).projects)
128
+ assert Developer.find(1).projects === Array
129
+ end
130
+
131
+ def test_adding_single
132
+ jamis = Developer.find(2)
133
+ jamis.projects.reload # causing the collection to load
134
+ action_controller = Project.find(2)
135
+ assert_equal 1, jamis.projects.size
136
+ assert_equal 1, action_controller.developers.size
137
+
138
+ jamis.projects << action_controller
139
+
140
+ assert_equal 2, jamis.projects.size
141
+ assert_equal 2, jamis.projects(true).size
142
+ assert_equal 2, action_controller.developers(true).size
143
+ end
144
+
145
+ def test_adding_type_mismatch
146
+ jamis = Developer.find(2)
147
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil }
148
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 }
149
+ end
150
+
151
+ def test_adding_from_the_project
152
+ jamis = Developer.find(2)
153
+ action_controller = Project.find(2)
154
+ action_controller.developers.reload
155
+ assert_equal 1, jamis.projects.size
156
+ assert_equal 1, action_controller.developers.size
157
+
158
+ action_controller.developers << jamis
159
+
160
+ assert_equal 2, jamis.projects(true).size
161
+ assert_equal 2, action_controller.developers.size
162
+ assert_equal 2, action_controller.developers(true).size
163
+ end
164
+
165
+ def test_adding_from_the_project_fixed_timestamp
166
+ jamis = Developer.find(2)
167
+ action_controller = Project.find(2)
168
+ action_controller.developers.reload
169
+ assert_equal 1, jamis.projects.size
170
+ assert_equal 1, action_controller.developers.size
171
+ updated_at = jamis.updated_at
172
+
173
+ action_controller.developers << jamis
174
+
175
+ assert_equal updated_at, jamis.updated_at
176
+ assert_equal 2, jamis.projects(true).size
177
+ assert_equal 2, action_controller.developers.size
178
+ assert_equal 2, action_controller.developers(true).size
179
+ end
180
+
181
+ def test_adding_multiple
182
+ aredridel = Developer.new("name" => "Aredridel")
183
+ aredridel.save
184
+ aredridel.projects.reload
185
+ aredridel.projects.push(Project.find(1), Project.find(2))
186
+ assert_equal 2, aredridel.projects.size
187
+ assert_equal 2, aredridel.projects(true).size
188
+ end
189
+
190
+ def test_adding_a_collection
191
+ aredridel = Developer.new("name" => "Aredridel")
192
+ aredridel.save
193
+ aredridel.projects.reload
194
+ aredridel.projects.concat([Project.find(1), Project.find(2)])
195
+ assert_equal 2, aredridel.projects.size
196
+ assert_equal 2, aredridel.projects(true).size
197
+ end
198
+
199
+ def test_habtm_adding_before_save
200
+ no_of_devels = Developer.count
201
+ no_of_projects = Project.count
202
+ aredridel = Developer.new("name" => "Aredridel")
203
+ aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
204
+ assert !aredridel.persisted?
205
+ assert !p.persisted?
206
+ assert aredridel.save
207
+ assert aredridel.persisted?
208
+ assert_equal no_of_devels+1, Developer.count
209
+ assert_equal no_of_projects+1, Project.count
210
+ assert_equal 2, aredridel.projects.size
211
+ assert_equal 2, aredridel.projects(true).size
212
+ end
213
+
214
+ def test_habtm_saving_multiple_relationships
215
+ new_project = Project.new("name" => "Grimetime")
216
+ amount_of_developers = 4
217
+ developers = (0...amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }.reverse
218
+
219
+ new_project.developer_ids = [developers[0].id, developers[1].id]
220
+ new_project.developers_with_callback_ids = [developers[2].id, developers[3].id]
221
+ assert new_project.save
222
+
223
+ new_project.reload
224
+ assert_equal amount_of_developers, new_project.developers.size
225
+ assert_equal developers, new_project.developers
226
+ end
227
+
228
+ def test_habtm_unique_order_preserved
229
+ assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
230
+ assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
231
+ end
232
+
233
+ def test_build
234
+ devel = Developer.find(1)
235
+ proj = assert_no_queries { devel.projects.build("name" => "Projekt") }
236
+ assert !devel.projects.loaded?
237
+
238
+ assert_equal devel.projects.last, proj
239
+ assert devel.projects.loaded?
240
+
241
+ assert !proj.persisted?
242
+ devel.save
243
+ assert proj.persisted?
244
+ assert_equal devel.projects.last, proj
245
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
246
+ end
247
+
248
+ def test_new_aliased_to_build
249
+ devel = Developer.find(1)
250
+ proj = assert_no_queries { devel.projects.new("name" => "Projekt") }
251
+ assert !devel.projects.loaded?
252
+
253
+ assert_equal devel.projects.last, proj
254
+ assert devel.projects.loaded?
255
+
256
+ assert !proj.persisted?
257
+ devel.save
258
+ assert proj.persisted?
259
+ assert_equal devel.projects.last, proj
260
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
261
+ end
262
+
263
+ def test_build_by_new_record
264
+ devel = Developer.new(:name => "Marcel", :salary => 75000)
265
+ devel.projects.build(:name => "Make bed")
266
+ proj2 = devel.projects.build(:name => "Lie in it")
267
+ assert_equal devel.projects.last, proj2
268
+ assert !proj2.persisted?
269
+ devel.save
270
+ assert devel.persisted?
271
+ assert proj2.persisted?
272
+ assert_equal devel.projects.last, proj2
273
+ assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
274
+ end
275
+
276
+ def test_create
277
+ devel = Developer.find(1)
278
+ proj = devel.projects.create("name" => "Projekt")
279
+ assert !devel.projects.loaded?
280
+
281
+ assert_equal devel.projects.last, proj
282
+ assert !devel.projects.loaded?
283
+
284
+ assert proj.persisted?
285
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
286
+ end
287
+
288
+ def test_create_by_new_record
289
+ devel = Developer.new(:name => "Marcel", :salary => 75000)
290
+ devel.projects.build(:name => "Make bed")
291
+ proj2 = devel.projects.build(:name => "Lie in it")
292
+ assert_equal devel.projects.last, proj2
293
+ assert !proj2.persisted?
294
+ devel.save
295
+ assert devel.persisted?
296
+ assert proj2.persisted?
297
+ assert_equal devel.projects.last, proj2
298
+ assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
299
+ end
300
+
301
+ def test_creation_respects_hash_condition
302
+ # in Oracle '' is saved as null therefore need to save ' ' in not null column
303
+ post = categories(:general).post_with_conditions.build(:body => ' ')
304
+
305
+ assert post.save
306
+ assert_equal 'Yet Another Testing Title', post.title
307
+
308
+ # in Oracle '' is saved as null therefore need to save ' ' in not null column
309
+ another_post = categories(:general).post_with_conditions.create(:body => ' ')
310
+
311
+ assert another_post.persisted?
312
+ assert_equal 'Yet Another Testing Title', another_post.title
313
+ end
314
+
315
+ def test_uniq_after_the_fact
316
+ dev = developers(:jamis)
317
+ dev.projects << projects(:active_record)
318
+ dev.projects << projects(:active_record)
319
+
320
+ assert_equal 3, dev.projects.size
321
+ assert_equal 1, dev.projects.uniq.size
322
+ end
323
+
324
+ def test_uniq_before_the_fact
325
+ projects(:active_record).developers << developers(:jamis)
326
+ projects(:active_record).developers << developers(:david)
327
+ assert_equal 3, projects(:active_record, :reload).developers.size
328
+ end
329
+
330
+ def test_uniq_option_prevents_duplicate_push
331
+ project = projects(:active_record)
332
+ project.developers << developers(:jamis)
333
+ project.developers << developers(:david)
334
+ assert_equal 3, project.developers.size
335
+
336
+ project.developers << developers(:david)
337
+ project.developers << developers(:jamis)
338
+ assert_equal 3, project.developers.size
339
+ end
340
+
341
+ def test_deleting
342
+ david = Developer.find(1)
343
+ active_record = Project.find(1)
344
+ david.projects.reload
345
+ assert_equal 2, david.projects.size
346
+ assert_equal 3, active_record.developers.size
347
+
348
+ david.projects.delete(active_record)
349
+
350
+ assert_equal 1, david.projects.size
351
+ assert_equal 1, david.projects(true).size
352
+ assert_equal 2, active_record.developers(true).size
353
+ end
354
+
355
+ def test_deleting_array
356
+ david = Developer.find(1)
357
+ david.projects.reload
358
+ david.projects.delete(Project.find(:all))
359
+ assert_equal 0, david.projects.size
360
+ assert_equal 0, david.projects(true).size
361
+ end
362
+
363
+ def test_deleting_with_sql
364
+ david = Developer.find(1)
365
+ active_record = Project.find(1)
366
+ active_record.developers.reload
367
+ assert_equal 3, active_record.developers_by_sql.size
368
+
369
+ active_record.developers_by_sql.delete(david)
370
+ assert_equal 2, active_record.developers_by_sql(true).size
371
+ end
372
+
373
+ def test_deleting_array_with_sql
374
+ active_record = Project.find(1)
375
+ active_record.developers.reload
376
+ assert_equal 3, active_record.developers_by_sql.size
377
+
378
+ active_record.developers_by_sql.delete(Developer.find(:all))
379
+ assert_equal 0, active_record.developers_by_sql(true).size
380
+ end
381
+
382
+ def test_deleting_all
383
+ david = Developer.find(1)
384
+ david.projects.reload
385
+ david.projects.clear
386
+ assert_equal 0, david.projects.size
387
+ assert_equal 0, david.projects(true).size
388
+ end
389
+
390
+ def test_removing_associations_on_destroy
391
+ david = DeveloperWithBeforeDestroyRaise.find(1)
392
+ assert !david.projects.empty?
393
+ david.destroy
394
+ assert david.projects.empty?
395
+ assert DeveloperWithBeforeDestroyRaise.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = 1").empty?
396
+ end
397
+
398
+ def test_destroying
399
+ david = Developer.find(1)
400
+ project = Project.find(1)
401
+ david.projects.reload
402
+ assert_equal 2, david.projects.size
403
+ assert_equal 3, project.developers.size
404
+
405
+ assert_no_difference "Project.count" do
406
+ david.projects.destroy(project)
407
+ end
408
+
409
+ join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id} AND project_id = #{project.id}")
410
+ assert join_records.empty?
411
+
412
+ assert_equal 1, david.reload.projects.size
413
+ assert_equal 1, david.projects(true).size
414
+ end
415
+
416
+ def test_destroying_many
417
+ david = Developer.find(1)
418
+ david.projects.reload
419
+ projects = Project.all
420
+
421
+ assert_no_difference "Project.count" do
422
+ david.projects.destroy(*projects)
423
+ end
424
+
425
+ join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
426
+ assert join_records.empty?
427
+
428
+ assert_equal 0, david.reload.projects.size
429
+ assert_equal 0, david.projects(true).size
430
+ end
431
+
432
+ def test_destroy_all
433
+ david = Developer.find(1)
434
+ david.projects.reload
435
+ assert !david.projects.empty?
436
+
437
+ assert_no_difference "Project.count" do
438
+ david.projects.destroy_all
439
+ end
440
+
441
+ join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
442
+ assert join_records.empty?
443
+
444
+ assert david.projects.empty?
445
+ assert david.projects(true).empty?
446
+ end
447
+
448
+ def test_destroy_associations_destroys_multiple_associations
449
+ george = parrots(:george)
450
+ assert !george.pirates.empty?
451
+ assert !george.treasures.empty?
452
+
453
+ assert_no_difference "Pirate.count" do
454
+ assert_no_difference "Treasure.count" do
455
+ george.destroy_associations
456
+ end
457
+ end
458
+
459
+ join_records = Parrot.connection.select_all("SELECT * FROM parrots_pirates WHERE parrot_id = #{george.id}")
460
+ assert join_records.empty?
461
+ assert george.pirates(true).empty?
462
+
463
+ join_records = Parrot.connection.select_all("SELECT * FROM parrots_treasures WHERE parrot_id = #{george.id}")
464
+ assert join_records.empty?
465
+ assert george.treasures(true).empty?
466
+ end
467
+
468
+ def test_deprecated_push_with_attributes_was_removed
469
+ jamis = developers(:jamis)
470
+ assert_raise(NoMethodError) do
471
+ jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today)
472
+ end
473
+ end
474
+
475
+ def test_associations_with_conditions
476
+ assert_equal 3, projects(:active_record).developers.size
477
+ assert_equal 1, projects(:active_record).developers_named_david.size
478
+ assert_equal 1, projects(:active_record).developers_named_david_with_hash_conditions.size
479
+
480
+ assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id)
481
+ assert_equal developers(:david), projects(:active_record).developers_named_david_with_hash_conditions.find(developers(:david).id)
482
+ assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id)
483
+
484
+ projects(:active_record).developers_named_david.clear
485
+ assert_equal 2, projects(:active_record, :reload).developers.size
486
+ end
487
+
488
+ def test_find_in_association
489
+ # Using sql
490
+ assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
491
+
492
+ # Using ruby
493
+ active_record = projects(:active_record)
494
+ active_record.developers.reload
495
+ assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find"
496
+ end
497
+
498
+ def test_include_uses_array_include_after_loaded
499
+ project = projects(:active_record)
500
+ project.developers.class # force load target
501
+
502
+ developer = project.developers.first
503
+
504
+ assert_no_queries do
505
+ assert project.developers.loaded?
506
+ assert project.developers.include?(developer)
507
+ end
508
+ end
509
+
510
+ def test_include_checks_if_record_exists_if_target_not_loaded
511
+ project = projects(:active_record)
512
+ developer = project.developers.first
513
+
514
+ project.reload
515
+ assert ! project.developers.loaded?
516
+ assert_queries(1) do
517
+ assert project.developers.include?(developer)
518
+ end
519
+ assert ! project.developers.loaded?
520
+ end
521
+
522
+ def test_include_returns_false_for_non_matching_record_to_verify_scoping
523
+ project = projects(:active_record)
524
+ developer = Developer.create :name => "Bryan", :salary => 50_000
525
+
526
+ assert ! project.developers.loaded?
527
+ assert ! project.developers.include?(developer)
528
+ end
529
+
530
+ def test_find_in_association_with_custom_finder_sql
531
+ assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id), "SQL find"
532
+
533
+ active_record = projects(:active_record)
534
+ active_record.developers_with_finder_sql.reload
535
+ assert_equal developers(:david), active_record.developers_with_finder_sql.find(developers(:david).id), "Ruby find"
536
+ end
537
+
538
+ def test_find_in_association_with_custom_finder_sql_and_multiple_interpolations
539
+ # interpolate once:
540
+ assert_equal [developers(:david), developers(:jamis), developers(:poor_jamis)], projects(:active_record).developers_with_finder_sql, "first interpolation"
541
+ # interpolate again, for a different project id
542
+ assert_equal [developers(:david)], projects(:action_controller).developers_with_finder_sql, "second interpolation"
543
+ end
544
+
545
+ def test_find_in_association_with_custom_finder_sql_and_string_id
546
+ assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id.to_s), "SQL find"
547
+ end
548
+
549
+ def test_find_with_merged_options
550
+ assert_equal 1, projects(:active_record).limited_developers.size
551
+ assert_equal 1, projects(:active_record).limited_developers.find(:all).size
552
+ assert_equal 3, projects(:active_record).limited_developers.find(:all, :limit => nil).size
553
+ end
554
+
555
+ def test_dynamic_find_should_respect_association_order
556
+ # Developers are ordered 'name DESC, id DESC'
557
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
558
+
559
+ assert_equal high_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'")
560
+ assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
561
+ end
562
+
563
+ def test_dynamic_find_all_should_respect_association_order
564
+ # Developers are ordered 'name DESC, id DESC'
565
+ low_id_jamis = developers(:jamis)
566
+ middle_id_jamis = developers(:poor_jamis)
567
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
568
+
569
+ assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'")
570
+ assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis')
571
+ end
572
+
573
+ def test_find_should_append_to_association_order
574
+ ordered_developers = projects(:active_record).developers.order('projects.id')
575
+ assert_equal ['developers.name desc, developers.id desc', 'projects.id'], ordered_developers.order_values
576
+ end
577
+
578
+ def test_dynamic_find_all_should_respect_association_limit
579
+ assert_equal 1, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'").length
580
+ assert_equal 1, projects(:active_record).limited_developers.find_all_by_name('Jamis').length
581
+ end
582
+
583
+ def test_dynamic_find_all_order_should_override_association_limit
584
+ assert_equal 2, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'", :limit => 9_000).length
585
+ assert_equal 2, projects(:active_record).limited_developers.find_all_by_name('Jamis', :limit => 9_000).length
586
+ end
587
+
588
+ def test_dynamic_find_all_should_respect_readonly_access
589
+ projects(:active_record).readonly_developers.each { |d| assert_raise(ActiveRecord::ReadOnlyRecord) { d.save! } if d.valid?}
590
+ projects(:active_record).readonly_developers.each { |d| d.readonly? }
591
+ end
592
+
593
+ def test_new_with_values_in_collection
594
+ jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
595
+ david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
596
+ project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie")
597
+ project.developers << jamis
598
+ project.save!
599
+ project.reload
600
+
601
+ assert project.developers.include?(jamis)
602
+ assert project.developers.include?(david)
603
+ end
604
+
605
+ def test_find_in_association_with_options
606
+ developers = projects(:active_record).developers.all
607
+ assert_equal 3, developers.size
608
+
609
+ assert_equal developers(:poor_jamis), projects(:active_record).developers.where("salary < 10000").first
610
+ end
611
+
612
+ def test_replace_with_less
613
+ david = developers(:david)
614
+ david.projects = [projects(:action_controller)]
615
+ assert david.save
616
+ assert_equal 1, david.projects.length
617
+ end
618
+
619
+ def test_replace_with_new
620
+ david = developers(:david)
621
+ david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
622
+ david.save
623
+ assert_equal 2, david.projects.length
624
+ assert !david.projects.include?(projects(:active_record))
625
+ end
626
+
627
+ def test_replace_on_new_object
628
+ new_developer = Developer.new("name" => "Matz")
629
+ new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
630
+ new_developer.save
631
+ assert_equal 2, new_developer.projects.length
632
+ end
633
+
634
+ def test_consider_type
635
+ developer = Developer.find(:first)
636
+ special_project = SpecialProject.create("name" => "Special Project")
637
+
638
+ other_project = developer.projects.first
639
+ developer.special_projects << special_project
640
+ developer.reload
641
+
642
+ assert developer.projects.include?(special_project)
643
+ assert developer.special_projects.include?(special_project)
644
+ assert !developer.special_projects.include?(other_project)
645
+ end
646
+
647
+ def test_update_attributes_after_push_without_duplicate_join_table_rows
648
+ developer = Developer.new("name" => "Kano")
649
+ project = SpecialProject.create("name" => "Special Project")
650
+ assert developer.save
651
+ developer.projects << project
652
+ developer.update_column("name", "Bruza")
653
+ assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i
654
+ SELECT count(*) FROM developers_projects
655
+ WHERE project_id = #{project.id}
656
+ AND developer_id = #{developer.id}
657
+ end_sql
658
+ end
659
+
660
+ def test_updating_attributes_on_non_rich_associations
661
+ welcome = categories(:technology).posts.first
662
+ welcome.title = "Something else"
663
+ assert welcome.save!
664
+ end
665
+
666
+ def test_habtm_respects_select
667
+ categories(:technology).select_testing_posts(true).each do |o|
668
+ assert_respond_to o, :correctness_marker
669
+ end
670
+ assert_respond_to categories(:technology).select_testing_posts.find(:first), :correctness_marker
671
+ end
672
+
673
+ def test_habtm_selects_all_columns_by_default
674
+ assert_equal Project.column_names.sort, developers(:david).projects.first.attributes.keys.sort
675
+ end
676
+
677
+ def test_habtm_respects_select_query_method
678
+ assert_equal ['id'], developers(:david).projects.select(:id).first.attributes.keys
679
+ end
680
+
681
+ def test_join_table_alias
682
+ assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size
683
+ end
684
+
685
+ def test_join_with_group
686
+ group = Developer.columns.inject([]) do |g, c|
687
+ g << "developers.#{c.name}"
688
+ g << "developers_projects_2.#{c.name}"
689
+ end
690
+ Project.columns.each { |c| group << "projects.#{c.name}" }
691
+
692
+ assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => group.join(",")).size
693
+ end
694
+
695
+ def test_find_grouped
696
+ all_posts_from_category1 = Post.find(:all, :conditions => "category_id = 1", :joins => :categories)
697
+ grouped_posts_of_category1 = Post.find(:all, :conditions => "category_id = 1", :group => "author_id", :select => 'count(posts.id) as posts_count', :joins => :categories)
698
+ assert_equal 5, all_posts_from_category1.size
699
+ assert_equal 2, grouped_posts_of_category1.size
700
+ end
701
+
702
+ def test_find_scoped_grouped
703
+ assert_equal 5, categories(:general).posts_grouped_by_title.size
704
+ assert_equal 1, categories(:technology).posts_grouped_by_title.size
705
+ end
706
+
707
+ def test_find_scoped_grouped_having
708
+ assert_equal 2, projects(:active_record).well_payed_salary_groups.size
709
+ assert projects(:active_record).well_payed_salary_groups.all? { |g| g.salary > 10000 }
710
+ end
711
+
712
+ def test_get_ids
713
+ assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
714
+ assert_equal [projects(:active_record).id], developers(:jamis).project_ids
715
+ end
716
+
717
+ def test_get_ids_for_loaded_associations
718
+ developer = developers(:david)
719
+ developer.projects(true)
720
+ assert_queries(0) do
721
+ developer.project_ids
722
+ developer.project_ids
723
+ end
724
+ end
725
+
726
+ def test_get_ids_for_unloaded_associations_does_not_load_them
727
+ developer = developers(:david)
728
+ assert !developer.projects.loaded?
729
+ assert_equal projects(:active_record, :action_controller).map(&:id).sort, developer.project_ids.sort
730
+ assert !developer.projects.loaded?
731
+ end
732
+
733
+ def test_assign_ids
734
+ developer = Developer.new("name" => "Joe")
735
+ developer.project_ids = projects(:active_record, :action_controller).map(&:id)
736
+ developer.save
737
+ developer.reload
738
+ assert_equal 2, developer.projects.length
739
+ assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
740
+ end
741
+
742
+ def test_assign_ids_ignoring_blanks
743
+ developer = Developer.new("name" => "Joe")
744
+ developer.project_ids = [projects(:active_record).id, nil, projects(:action_controller).id, '']
745
+ developer.save
746
+ developer.reload
747
+ assert_equal 2, developer.projects.length
748
+ assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
749
+ end
750
+
751
+ def test_scoped_find_on_through_association_doesnt_return_read_only_records
752
+ tag = Post.find(1).tags.find_by_name("General")
753
+
754
+ assert_nothing_raised do
755
+ tag.save!
756
+ end
757
+ end
758
+
759
+ def test_has_many_through_polymorphic_has_manys_works
760
+ assert_equal [10, 20].to_set, pirates(:redbeard).treasure_estimates.map(&:price).to_set
761
+ end
762
+
763
+ def test_symbols_as_keys
764
+ developer = DeveloperWithSymbolsForKeys.new(:name => 'David')
765
+ project = ProjectWithSymbolsForKeys.new(:name => 'Rails Testing')
766
+ project.developers << developer
767
+ project.save!
768
+
769
+ assert_equal 1, project.developers.size
770
+ assert_equal 1, developer.projects.size
771
+ assert_equal developer, project.developers.find(:first)
772
+ assert_equal project, developer.projects.find(:first)
773
+ end
774
+
775
+ def test_self_referential_habtm_without_foreign_key_set_should_raise_exception
776
+ assert_raise(ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded) {
777
+ Member.class_eval do
778
+ has_and_belongs_to_many :friends, :class_name => "Member", :join_table => "member_friends"
779
+ end
780
+ }
781
+ end
782
+
783
+ def test_dynamic_find_should_respect_association_include
784
+ # SQL error in sort clause if :include is not included
785
+ # due to Unknown column 'authors.id'
786
+ assert Category.find(1).posts_with_authors_sorted_by_author_id.find_by_title('Welcome to the weblog')
787
+ end
788
+
789
+ def test_counting_on_habtm_association_and_not_array
790
+ david = Developer.find(1)
791
+ # Extra parameter just to make sure we aren't falling back to
792
+ # Array#count in Ruby >=1.8.7, which would raise an ArgumentError
793
+ assert_nothing_raised { david.projects.count(:all, :conditions => '1=1') }
794
+ end
795
+
796
+ def test_count
797
+ david = Developer.find(1)
798
+ assert_equal 2, david.projects.count
799
+ end
800
+
801
+ def test_count_with_counter_sql
802
+ developer = DeveloperWithCounterSQL.create(:name => 'tekin')
803
+ developer.project_ids = [projects(:active_record).id]
804
+ developer.save
805
+ developer.reload
806
+ assert_equal 1, developer.projects.count
807
+ end
808
+
809
+ unless current_adapter?(:PostgreSQLAdapter, :IBM_DBAdapter)
810
+ def test_count_with_finder_sql
811
+ assert_equal 3, projects(:active_record).developers_with_finder_sql.count
812
+ assert_equal 3, projects(:active_record).developers_with_multiline_finder_sql.count
813
+ end
814
+ end
815
+
816
+ def test_association_proxy_transaction_method_starts_transaction_in_association_class
817
+ Post.expects(:transaction)
818
+ Category.find(:first).posts.transaction do
819
+ # nothing
820
+ end
821
+ end
822
+
823
+ def test_caching_of_columns
824
+ david = Developer.find(1)
825
+ # clear cache possibly created by other tests
826
+ david.projects.reset_column_information
827
+
828
+ assert_queries(1) { david.projects.columns; david.projects.columns }
829
+
830
+ ## and again to verify that reset_column_information clears the cache correctly
831
+ david.projects.reset_column_information
832
+ assert_queries(1) { david.projects.columns; david.projects.columns }
833
+ end
834
+
835
+ def test_attributes_are_being_set_when_initialized_from_habm_association_with_where_clause
836
+ new_developer = projects(:action_controller).developers.where(:name => "Marcelo").build
837
+ assert_equal new_developer.name, "Marcelo"
838
+ end
839
+
840
+ def test_attributes_are_being_set_when_initialized_from_habm_association_with_multiple_where_clauses
841
+ new_developer = projects(:action_controller).developers.where(:name => "Marcelo").where(:salary => 90_000).build
842
+ assert_equal new_developer.name, "Marcelo"
843
+ assert_equal new_developer.salary, 90_000
844
+ end
845
+
846
+ def test_include_method_in_has_and_belongs_to_many_association_should_return_true_for_instance_added_with_build
847
+ project = Project.new
848
+ developer = project.developers.build
849
+ assert project.developers.include?(developer)
850
+ end
851
+ end