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

Sign up to get free protection for your applications and to get access to all the features.
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