activerecord 1.0.0

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

Potentially problematic release.


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

Files changed (106) hide show
  1. data/CHANGELOG +581 -0
  2. data/README +361 -0
  3. data/RUNNING_UNIT_TESTS +36 -0
  4. data/dev-utils/eval_debugger.rb +9 -0
  5. data/examples/associations.png +0 -0
  6. data/examples/associations.rb +87 -0
  7. data/examples/shared_setup.rb +15 -0
  8. data/examples/validation.rb +88 -0
  9. data/install.rb +60 -0
  10. data/lib/active_record.rb +48 -0
  11. data/lib/active_record/aggregations.rb +165 -0
  12. data/lib/active_record/associations.rb +536 -0
  13. data/lib/active_record/associations/association_collection.rb +70 -0
  14. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +46 -0
  15. data/lib/active_record/associations/has_many_association.rb +104 -0
  16. data/lib/active_record/base.rb +985 -0
  17. data/lib/active_record/callbacks.rb +337 -0
  18. data/lib/active_record/connection_adapters/abstract_adapter.rb +326 -0
  19. data/lib/active_record/connection_adapters/mysql_adapter.rb +131 -0
  20. data/lib/active_record/connection_adapters/postgresql_adapter.rb +177 -0
  21. data/lib/active_record/connection_adapters/sqlite_adapter.rb +107 -0
  22. data/lib/active_record/deprecated_associations.rb +70 -0
  23. data/lib/active_record/fixtures.rb +172 -0
  24. data/lib/active_record/observer.rb +71 -0
  25. data/lib/active_record/reflection.rb +126 -0
  26. data/lib/active_record/support/class_attribute_accessors.rb +43 -0
  27. data/lib/active_record/support/class_inheritable_attributes.rb +37 -0
  28. data/lib/active_record/support/clean_logger.rb +10 -0
  29. data/lib/active_record/support/inflector.rb +70 -0
  30. data/lib/active_record/transactions.rb +102 -0
  31. data/lib/active_record/validations.rb +205 -0
  32. data/lib/active_record/vendor/mysql.rb +1117 -0
  33. data/lib/active_record/vendor/simple.rb +702 -0
  34. data/lib/active_record/wrappers/yaml_wrapper.rb +15 -0
  35. data/lib/active_record/wrappings.rb +59 -0
  36. data/rakefile +122 -0
  37. data/test/abstract_unit.rb +16 -0
  38. data/test/aggregations_test.rb +34 -0
  39. data/test/all.sh +8 -0
  40. data/test/associations_test.rb +477 -0
  41. data/test/base_test.rb +513 -0
  42. data/test/class_inheritable_attributes_test.rb +33 -0
  43. data/test/connections/native_mysql/connection.rb +24 -0
  44. data/test/connections/native_postgresql/connection.rb +24 -0
  45. data/test/connections/native_sqlite/connection.rb +24 -0
  46. data/test/deprecated_associations_test.rb +336 -0
  47. data/test/finder_test.rb +67 -0
  48. data/test/fixtures/accounts/signals37 +3 -0
  49. data/test/fixtures/accounts/unknown +2 -0
  50. data/test/fixtures/auto_id.rb +4 -0
  51. data/test/fixtures/column_name.rb +3 -0
  52. data/test/fixtures/companies/first_client +6 -0
  53. data/test/fixtures/companies/first_firm +4 -0
  54. data/test/fixtures/companies/second_client +6 -0
  55. data/test/fixtures/company.rb +37 -0
  56. data/test/fixtures/company_in_module.rb +33 -0
  57. data/test/fixtures/course.rb +3 -0
  58. data/test/fixtures/courses/java +2 -0
  59. data/test/fixtures/courses/ruby +2 -0
  60. data/test/fixtures/customer.rb +30 -0
  61. data/test/fixtures/customers/david +6 -0
  62. data/test/fixtures/db_definitions/mysql.sql +96 -0
  63. data/test/fixtures/db_definitions/mysql2.sql +4 -0
  64. data/test/fixtures/db_definitions/postgresql.sql +113 -0
  65. data/test/fixtures/db_definitions/postgresql2.sql +4 -0
  66. data/test/fixtures/db_definitions/sqlite.sql +85 -0
  67. data/test/fixtures/db_definitions/sqlite2.sql +4 -0
  68. data/test/fixtures/default.rb +2 -0
  69. data/test/fixtures/developer.rb +8 -0
  70. data/test/fixtures/developers/david +2 -0
  71. data/test/fixtures/developers/jamis +2 -0
  72. data/test/fixtures/developers_projects/david_action_controller +2 -0
  73. data/test/fixtures/developers_projects/david_active_record +2 -0
  74. data/test/fixtures/developers_projects/jamis_active_record +2 -0
  75. data/test/fixtures/entrant.rb +3 -0
  76. data/test/fixtures/entrants/first +3 -0
  77. data/test/fixtures/entrants/second +3 -0
  78. data/test/fixtures/entrants/third +3 -0
  79. data/test/fixtures/fixture_database.sqlite +0 -0
  80. data/test/fixtures/fixture_database_2.sqlite +0 -0
  81. data/test/fixtures/movie.rb +5 -0
  82. data/test/fixtures/movies/first +2 -0
  83. data/test/fixtures/movies/second +2 -0
  84. data/test/fixtures/project.rb +3 -0
  85. data/test/fixtures/projects/action_controller +2 -0
  86. data/test/fixtures/projects/active_record +2 -0
  87. data/test/fixtures/reply.rb +21 -0
  88. data/test/fixtures/subscriber.rb +5 -0
  89. data/test/fixtures/subscribers/first +2 -0
  90. data/test/fixtures/subscribers/second +2 -0
  91. data/test/fixtures/topic.rb +20 -0
  92. data/test/fixtures/topics/first +9 -0
  93. data/test/fixtures/topics/second +8 -0
  94. data/test/fixtures_test.rb +20 -0
  95. data/test/inflector_test.rb +104 -0
  96. data/test/inheritance_test.rb +125 -0
  97. data/test/lifecycle_test.rb +110 -0
  98. data/test/modules_test.rb +21 -0
  99. data/test/multiple_db_test.rb +46 -0
  100. data/test/pk_test.rb +57 -0
  101. data/test/reflection_test.rb +78 -0
  102. data/test/thread_safety_test.rb +33 -0
  103. data/test/transactions_test.rb +83 -0
  104. data/test/unconnected_test.rb +24 -0
  105. data/test/validations_test.rb +126 -0
  106. metadata +166 -0
@@ -0,0 +1,33 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'test/unit'
4
+ require 'active_record/support/class_inheritable_attributes'
5
+
6
+ class A
7
+ include ClassInheritableAttributes
8
+ end
9
+
10
+ class B < A
11
+ write_inheritable_array "first", [ :one, :two ]
12
+ end
13
+
14
+ class C < A
15
+ write_inheritable_array "first", [ :three ]
16
+ end
17
+
18
+ class D < B
19
+ write_inheritable_array "first", [ :four ]
20
+ end
21
+
22
+
23
+ class ClassInheritableAttributesTest < Test::Unit::TestCase
24
+ def test_first_level
25
+ assert_equal [ :one, :two ], B.read_inheritable_attribute("first")
26
+ assert_equal [ :three ], C.read_inheritable_attribute("first")
27
+ end
28
+
29
+ def test_second_level
30
+ assert_equal [ :one, :two, :four ], D.read_inheritable_attribute("first")
31
+ assert_equal [ :one, :two ], B.read_inheritable_attribute("first")
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ print "Using native MySQL\n"
2
+ require 'fixtures/course'
3
+ require 'logger'
4
+
5
+ ActiveRecord::Base.logger = Logger.new("debug.log")
6
+
7
+ db1 = 'activerecord_unittest'
8
+ db2 = 'activerecord_unittest2'
9
+
10
+ ActiveRecord::Base.establish_connection(
11
+ :adapter => "mysql",
12
+ :host => "localhost",
13
+ :username => "root",
14
+ :password => "",
15
+ :database => db1
16
+ )
17
+
18
+ Course.establish_connection(
19
+ :adapter => "mysql",
20
+ :host => "localhost",
21
+ :username => "root",
22
+ :password => "",
23
+ :database => db2
24
+ )
@@ -0,0 +1,24 @@
1
+ print "Using native PostgreSQL\n"
2
+ require 'fixtures/course'
3
+ require 'logger'
4
+
5
+ ActiveRecord::Base.logger = Logger.new("debug.log")
6
+
7
+ db1 = 'activerecord_unittest'
8
+ db2 = 'activerecord_unittest2'
9
+
10
+ ActiveRecord::Base.establish_connection(
11
+ :adapter => "postgresql",
12
+ :host => nil,
13
+ :username => "postgres",
14
+ :password => "postgres",
15
+ :database => db1
16
+ )
17
+
18
+ Course.establish_connection(
19
+ :adapter => "postgresql",
20
+ :host => nil,
21
+ :username => "postgres",
22
+ :password => "postgres",
23
+ :database => db2
24
+ )
@@ -0,0 +1,24 @@
1
+ print "Using native SQlite\n"
2
+ require 'fixtures/course'
3
+ require 'logger'
4
+ ActiveRecord::Base.logger = Logger.new("debug.log")
5
+
6
+ base = "#{File.dirname(__FILE__)}/../../fixtures"
7
+ sqlite_test_db = "#{base}/fixture_database.sqlite"
8
+ sqlite_test_db2 = "#{base}/fixture_database_2.sqlite"
9
+
10
+ [sqlite_test_db, sqlite_test_db2].each do |db|
11
+ unless File.exist?(db) and File.size(db) > 0
12
+ puts "*** You must create the SQLite test database in: #{db} ***"
13
+ exit!
14
+ else
15
+ puts "OK: #{db}"
16
+ end
17
+ end
18
+
19
+ ActiveRecord::Base.establish_connection(
20
+ :adapter => "sqlite",
21
+ :dbfile => sqlite_test_db)
22
+ Course.establish_connection(
23
+ :adapter => "sqlite",
24
+ :dbfile => sqlite_test_db2)
@@ -0,0 +1,336 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/developer'
3
+ require 'fixtures/project'
4
+ require 'fixtures/company'
5
+ require 'fixtures/topic'
6
+ # require File.dirname(__FILE__) + '/../dev-utils/eval_debugger'
7
+ require 'fixtures/reply'
8
+
9
+ # Can't declare new classes in test case methods, so tests before that
10
+ bad_collection_keys = false
11
+ begin
12
+ class Car < ActiveRecord::Base; has_many :wheels, :name => "wheels"; end
13
+ rescue ActiveRecord::ActiveRecordError
14
+ bad_collection_keys = true
15
+ end
16
+ raise "ActiveRecord should have barked on bad collection keys" unless bad_collection_keys
17
+
18
+
19
+ class DeprecatedAssociationsTest < Test::Unit::TestCase
20
+ def setup
21
+ create_fixtures "accounts", "companies", "accounts", "developers", "projects", "developers_projects", "topics"
22
+ @signals37 = Firm.find(1)
23
+ end
24
+
25
+ def test_has_many_find
26
+ assert_equal 2, Firm.find_first.clients.length
27
+ end
28
+
29
+ def test_has_many_orders
30
+ assert_equal "Summit", Firm.find_first.clients.first.name
31
+ end
32
+
33
+ def test_has_many_class_name
34
+ assert_equal "Microsoft", Firm.find_first.clients_sorted_desc.first.name
35
+ end
36
+
37
+ def test_has_many_foreign_key
38
+ assert_equal "Microsoft", Firm.find_first.clients_of_firm.first.name
39
+ end
40
+
41
+ def test_has_many_conditions
42
+ assert_equal "Microsoft", Firm.find_first.clients_like_ms.first.name
43
+ end
44
+
45
+ def test_has_many_sql
46
+ firm = Firm.find_first
47
+ assert_equal "Microsoft", firm.clients_using_sql.first.name
48
+ assert_equal 1, firm.clients_using_sql_count
49
+ assert_equal 1, Firm.find_first.clients_using_sql_count
50
+ end
51
+
52
+ def test_has_many_queries
53
+ assert Firm.find_first.has_clients?
54
+ firm = Firm.find_first
55
+ assert_equal 2, firm.clients_count # tests using class count
56
+ firm.clients
57
+ assert firm.has_clients?
58
+ assert_equal 2, firm.clients_count # tests using collection length
59
+ end
60
+
61
+ def test_has_many_dependence
62
+ assert_equal 2, Client.find_all.length
63
+ Firm.find_first.destroy
64
+ assert_equal 0, Client.find_all.length
65
+ end
66
+
67
+ def test_has_many_dependence_with_transaction_support_on_failure
68
+ assert_equal 2, Client.find_all.length
69
+
70
+ firm = Firm.find_first
71
+ clients = firm.clients
72
+ clients.last.instance_eval { def before_destroy() raise "Trigger rollback" end }
73
+
74
+ firm.destroy rescue "do nothing"
75
+
76
+ assert_equal 2, Client.find_all.length
77
+ end
78
+
79
+ def test_has_one_dependence
80
+ firm = Firm.find(1)
81
+ assert firm.has_account?
82
+ firm.destroy
83
+ assert_equal 1, Account.find_all.length
84
+ end
85
+
86
+ def test_has_one_dependence_with_missing_association
87
+ Account.destroy_all
88
+ firm = Firm.find(1)
89
+ assert !firm.has_account?
90
+ firm.destroy
91
+ end
92
+
93
+ def test_belongs_to
94
+ assert_equal @signals37.name, Client.find(3).firm.name
95
+ assert Client.find(3).has_firm?, "Microsoft should have a firm"
96
+ # assert !Company.find(1).has_firm?, "37signals shouldn't have a firm"
97
+ end
98
+
99
+ def test_belongs_to_with_different_class_name
100
+ assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
101
+ assert Company.find(3).has_firm_with_other_name?, "Microsoft should have a firm"
102
+ assert !Company.find(1).has_firm_with_other_name?, "37signals shouldn't have a firm"
103
+ end
104
+
105
+ def test_belongs_to_with_condition
106
+ assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
107
+ assert Company.find(3).has_firm_with_condition?, "Microsoft should have a firm"
108
+ assert !Company.find(1).has_firm_with_condition?, "37signals shouldn't have a firm"
109
+ end
110
+
111
+
112
+ def test_belongs_to_equality
113
+ assert Company.find(3).firm?(Company.find(1)), "Microsoft should have 37signals as firm"
114
+ assert_raises(RuntimeError) { !Company.find(3).firm?(Company.find(3)) } # "Summit shouldn't have itself as firm"
115
+ end
116
+
117
+ def test_has_one
118
+ assert @signals37.account?(Account.find(1))
119
+ assert_equal Account.find(1).credit_limit, @signals37.account.credit_limit
120
+ assert @signals37.has_account?, "37signals should have an account"
121
+ assert Account.find(1).firm?(@signals37), "37signals account should be able to backtrack"
122
+ assert Account.find(1).has_firm?, "37signals account should be able to backtrack"
123
+
124
+ assert !Account.find(2).has_firm?, "Unknown isn't linked"
125
+ assert !Account.find(2).firm?(@signals37), "Unknown isn't linked"
126
+ end
127
+
128
+ def test_has_many_dependence_on_account
129
+ assert_equal 2, Account.find_all.length
130
+ @signals37.destroy
131
+ assert_equal 1, Account.find_all.length
132
+ end
133
+
134
+ def test_find_in
135
+ assert_equal Client.find(2).name, @signals37.find_in_clients(2).name
136
+ assert_raises(ActiveRecord::RecordNotFound) { @signals37.find_in_clients(6) }
137
+ end
138
+
139
+ def test_force_reload
140
+ firm = Firm.new
141
+ firm.save
142
+ firm.clients.each {|c|} # forcing to load all clients
143
+ assert firm.clients.empty?, "New firm shouldn't have client objects"
144
+ assert !firm.has_clients?, "New firm shouldn't have clients"
145
+ assert_equal 0, firm.clients_count, "New firm should have 0 clients"
146
+
147
+ client = Client.new("firm_id" => firm.id)
148
+ client.save
149
+
150
+ assert firm.clients.empty?, "New firm should have cached no client objects"
151
+ assert !firm.has_clients?, "New firm should have cached a no-clients response"
152
+ assert_equal 0, firm.clients_count, "New firm should have cached 0 clients count"
153
+
154
+ assert !firm.clients(true).empty?, "New firm should have reloaded client objects"
155
+ assert firm.has_clients?(true), "New firm should have reloaded with a have-clients response"
156
+ assert_equal 1, firm.clients_count(true), "New firm should have reloaded clients count"
157
+ end
158
+
159
+ def test_included_in_collection
160
+ assert @signals37.clients.include?(Client.find(2))
161
+ end
162
+
163
+ def test_build_to_collection
164
+ assert_equal 1, @signals37.clients_of_firm_count
165
+ new_client = @signals37.build_to_clients_of_firm("name" => "Another Client")
166
+ assert_equal "Another Client", new_client.name
167
+ assert new_client.save
168
+
169
+ assert new_client.firm?(@signals37)
170
+ assert_equal 2, @signals37.clients_of_firm_count(true)
171
+ end
172
+
173
+ def test_create_in_collection
174
+ assert_equal @signals37.create_in_clients_of_firm("name" => "Another Client"), @signals37.clients_of_firm(true).last
175
+ end
176
+
177
+ def test_succesful_build_association
178
+ firm = Firm.new("name" => "GlobalMegaCorp")
179
+ firm.save
180
+
181
+ account = firm.build_account("credit_limit" => 1000)
182
+ assert account.save
183
+ assert_equal account, firm.account
184
+ end
185
+
186
+ def test_failing_build_association
187
+ firm = Firm.new("name" => "GlobalMegaCorp")
188
+ firm.save
189
+
190
+ account = firm.build_account
191
+ assert !account.save
192
+ assert_equal "can't be empty", account.errors.on("credit_limit")
193
+ end
194
+
195
+ def test_create_association
196
+ firm = Firm.new("name" => "GlobalMegaCorp")
197
+ firm.save
198
+ assert_equal firm.create_account("credit_limit" => 1000), firm.account
199
+ end
200
+
201
+ def test_has_and_belongs_to_many
202
+ david = Developer.find(1)
203
+ assert david.has_projects?
204
+ assert_equal 2, david.projects_count
205
+
206
+ active_record = Project.find(1)
207
+ assert active_record.has_developers?
208
+ assert_equal 2, active_record.developers_count
209
+ assert_equal david.name, active_record.developers.first.name
210
+ end
211
+
212
+ def test_has_and_belongs_to_many_removing
213
+ david = Developer.find(1)
214
+ active_record = Project.find(1)
215
+
216
+ david.remove_projects(active_record)
217
+
218
+ assert_equal 1, david.projects_count
219
+ assert_equal 1, active_record.developers_count
220
+ end
221
+
222
+ def test_has_and_belongs_to_many_zero
223
+ david = Developer.find(1)
224
+ david.remove_projects(Project.find_all)
225
+
226
+ assert_equal 0, david.projects_count
227
+ assert !david.has_projects?
228
+ end
229
+
230
+ def test_has_and_belongs_to_many_adding
231
+ jamis = Developer.find(2)
232
+ action_controller = Project.find(2)
233
+
234
+ jamis.add_projects(action_controller)
235
+
236
+ assert_equal 2, jamis.projects_count
237
+ assert_equal 2, action_controller.developers_count
238
+ end
239
+
240
+ def test_has_and_belongs_to_many_adding_from_the_project
241
+ jamis = Developer.find(2)
242
+ action_controller = Project.find(2)
243
+
244
+ action_controller.add_developers(jamis)
245
+
246
+ assert_equal 2, jamis.projects_count
247
+ assert_equal 2, action_controller.developers_count
248
+ end
249
+
250
+ def test_has_and_belongs_to_many_adding_a_collection
251
+ aridridel = Developer.new("name" => "Aridridel")
252
+ aridridel.save
253
+
254
+ aridridel.add_projects([ Project.find(1), Project.find(2) ])
255
+ assert_equal 2, aridridel.projects_count
256
+ end
257
+
258
+ def test_belongs_to_counter
259
+ topic = Topic.create("title" => "Apple", "content" => "hello world")
260
+ assert_equal 0, topic.send(:read_attribute, "replies_count"), "No replies yet"
261
+
262
+ reply = topic.create_in_replies("title" => "I'm saying no!", "content" => "over here")
263
+ assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count"), "First reply created"
264
+
265
+ reply.destroy
266
+ assert_equal 0, Topic.find(topic.id).send(:read_attribute, "replies_count"), "First reply deleted"
267
+ end
268
+
269
+ def test_natural_assignment_of_has_one
270
+ apple = Firm.create("name" => "Apple")
271
+ citibank = Account.create("credit_limit" => 10)
272
+ apple.account = citibank
273
+ assert_equal apple.id, citibank.firm_id
274
+ end
275
+
276
+ def test_natural_assignment_of_belongs_to
277
+ apple = Firm.create("name" => "Apple")
278
+ citibank = Account.create("credit_limit" => 10)
279
+ citibank.firm = apple
280
+ assert_equal apple.id, citibank.firm_id
281
+ end
282
+
283
+ def test_natural_assignment_of_has_many
284
+ apple = Firm.create("name" => "Apple")
285
+ natural = Client.new("name" => "Natural Company")
286
+ apple.clients << natural
287
+ assert_equal apple.id, natural.firm_id
288
+ assert_equal Client.find(natural.id), Firm.find(apple.id).clients.find { |c| c.id == natural.id }
289
+ apple.clients.delete natural
290
+ assert_nil Firm.find(apple.id).clients.find { |c| c.id == natural.id }
291
+ end
292
+
293
+
294
+ def test_natural_adding_of_has_and_belongs_to_many
295
+ rails = Project.create("name" => "Rails")
296
+ ap = Project.create("name" => "Action Pack")
297
+ john = Developer.create("name" => "John")
298
+ mike = Developer.create("name" => "Mike")
299
+ rails.developers << john
300
+ rails.developers << mike
301
+
302
+ assert_equal Developer.find(john.id), Project.find(rails.id).developers.find { |d| d.id == john.id }
303
+ assert_equal Developer.find(mike.id), Project.find(rails.id).developers.find { |d| d.id == mike.id }
304
+ assert_equal Project.find(rails.id), Developer.find(mike.id).projects.find { |p| p.id == rails.id }
305
+ assert_equal Project.find(rails.id), Developer.find(john.id).projects.find { |p| p.id == rails.id }
306
+ ap.developers << john
307
+ assert_equal Developer.find(john.id), Project.find(ap.id).developers.find { |d| d.id == john.id }
308
+ assert_equal Project.find(ap.id), Developer.find(john.id).projects.find { |p| p.id == ap.id }
309
+
310
+ ap.developers.delete john
311
+ assert_nil Project.find(ap.id).developers.find { |d| d.id == john.id }
312
+ assert_nil Developer.find(john.id).projects.find { |p| p.id == ap.id }
313
+ end
314
+
315
+ def test_storing_in_pstore
316
+ require "pstore"
317
+ apple = Firm.create("name" => "Apple")
318
+ natural = Client.new("name" => "Natural Company")
319
+ apple.clients << natural
320
+
321
+ db = PStore.new("/tmp/ar-pstore-association-test")
322
+ db.transaction do
323
+ db["apple"] = apple
324
+ end
325
+
326
+ db = PStore.new("/tmp/ar-pstore-association-test")
327
+ db.transaction do
328
+ assert_equal "Natural Company", db["apple"].clients.first.name
329
+ end
330
+ end
331
+
332
+ def test_has_many_find_all
333
+ assert_equal 2, Firm.find_first.find_all_in_clients("type = 'Client'").length
334
+ assert_equal 1, Firm.find_first.find_all_in_clients("name = 'Summit'").length
335
+ end
336
+ end
@@ -0,0 +1,67 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/company'
3
+ require 'fixtures/topic'
4
+
5
+ class FinderTest < Test::Unit::TestCase
6
+ def setup
7
+ @company_fixtures = create_fixtures("companies")
8
+ @topic_fixtures = create_fixtures("topics")
9
+ end
10
+
11
+ def test_find
12
+ assert_equal(@topic_fixtures["first"]["title"], Topic.find(1).title)
13
+ end
14
+
15
+ def test_find_by_ids
16
+ assert_equal(2, Topic.find(1, 2).length)
17
+ assert_equal(@topic_fixtures["second"]["title"], Topic.find([ 2 ]).title)
18
+ end
19
+
20
+ def test_find_by_ids_missing_one
21
+ assert_raises(ActiveRecord::RecordNotFound) {
22
+ Topic.find(1, 2, 45)
23
+ }
24
+ end
25
+
26
+ def test_find_with_entire_select_statement
27
+ topics = Topic.find_by_sql "SELECT * FROM topics WHERE author_name = 'Mary'"
28
+
29
+ assert_equal(1, topics.size)
30
+ assert_equal(@topic_fixtures["second"]["title"], topics.first.title)
31
+ end
32
+
33
+ def test_find_first
34
+ first = Topic.find_first "title = 'The First Topic'"
35
+ assert_equal(@topic_fixtures["first"]["title"], first.title)
36
+ end
37
+
38
+ def test_find_first_failing
39
+ first = Topic.find_first "title = 'The First Topic!'"
40
+ assert_nil(first)
41
+ end
42
+
43
+ def test_unexisting_record_exception_handling
44
+ assert_raises(ActiveRecord::RecordNotFound) {
45
+ Topic.find(1).parent
46
+ }
47
+
48
+ Topic.find(2).parent
49
+ end
50
+
51
+ def test_find_on_conditions
52
+ assert Topic.find_on_conditions(1, "approved = 0")
53
+ assert_raises(ActiveRecord::RecordNotFound) { Topic.find_on_conditions(1, "approved = 1") }
54
+ end
55
+
56
+ def test_condition_interpolation
57
+ assert_kind_of Firm, Company.find_first(["name = '%s'", "37signals"])
58
+ assert_nil Company.find_first(["name = '%s'", "37signals!"])
59
+ assert_nil Company.find_first(["name = '%s'", "37signals!' OR 1=1"])
60
+ assert_kind_of Time, Topic.find_first(["id = %d", 1]).written_on
61
+ end
62
+
63
+ def test_string_sanitation
64
+ assert_equal "something '' 1=1", ActiveRecord::Base.sanitize("something ' 1=1")
65
+ assert_equal "something select table", ActiveRecord::Base.sanitize("something; select table")
66
+ end
67
+ end