colincasey-sequel 2.10.0 → 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. data/CHANGELOG +7 -1
  2. data/doc/advanced_associations.rdoc +614 -0
  3. data/doc/cheat_sheet.rdoc +223 -0
  4. data/doc/dataset_filtering.rdoc +158 -0
  5. data/doc/prepared_statements.rdoc +104 -0
  6. data/doc/release_notes/1.0.txt +38 -0
  7. data/doc/release_notes/1.1.txt +143 -0
  8. data/doc/release_notes/1.3.txt +101 -0
  9. data/doc/release_notes/1.4.0.txt +53 -0
  10. data/doc/release_notes/1.5.0.txt +155 -0
  11. data/doc/release_notes/2.0.0.txt +298 -0
  12. data/doc/release_notes/2.1.0.txt +271 -0
  13. data/doc/release_notes/2.10.0.txt +328 -0
  14. data/doc/release_notes/2.2.0.txt +253 -0
  15. data/doc/release_notes/2.3.0.txt +88 -0
  16. data/doc/release_notes/2.4.0.txt +106 -0
  17. data/doc/release_notes/2.5.0.txt +137 -0
  18. data/doc/release_notes/2.6.0.txt +157 -0
  19. data/doc/release_notes/2.7.0.txt +166 -0
  20. data/doc/release_notes/2.8.0.txt +171 -0
  21. data/doc/release_notes/2.9.0.txt +97 -0
  22. data/doc/schema.rdoc +29 -0
  23. data/doc/sharding.rdoc +113 -0
  24. data/lib/sequel.rb +1 -0
  25. data/lib/sequel_core/adapters/ado.rb +89 -0
  26. data/lib/sequel_core/adapters/db2.rb +143 -0
  27. data/lib/sequel_core/adapters/dbi.rb +112 -0
  28. data/lib/sequel_core/adapters/do/mysql.rb +38 -0
  29. data/lib/sequel_core/adapters/do/postgres.rb +92 -0
  30. data/lib/sequel_core/adapters/do/sqlite.rb +31 -0
  31. data/lib/sequel_core/adapters/do.rb +205 -0
  32. data/lib/sequel_core/adapters/firebird.rb +298 -0
  33. data/lib/sequel_core/adapters/informix.rb +85 -0
  34. data/lib/sequel_core/adapters/jdbc/h2.rb +69 -0
  35. data/lib/sequel_core/adapters/jdbc/mysql.rb +66 -0
  36. data/lib/sequel_core/adapters/jdbc/oracle.rb +23 -0
  37. data/lib/sequel_core/adapters/jdbc/postgresql.rb +113 -0
  38. data/lib/sequel_core/adapters/jdbc/sqlite.rb +43 -0
  39. data/lib/sequel_core/adapters/jdbc.rb +491 -0
  40. data/lib/sequel_core/adapters/mysql.rb +369 -0
  41. data/lib/sequel_core/adapters/odbc.rb +174 -0
  42. data/lib/sequel_core/adapters/openbase.rb +68 -0
  43. data/lib/sequel_core/adapters/oracle.rb +107 -0
  44. data/lib/sequel_core/adapters/postgres.rb +456 -0
  45. data/lib/sequel_core/adapters/shared/ms_access.rb +110 -0
  46. data/lib/sequel_core/adapters/shared/mssql.rb +102 -0
  47. data/lib/sequel_core/adapters/shared/mysql.rb +325 -0
  48. data/lib/sequel_core/adapters/shared/oracle.rb +61 -0
  49. data/lib/sequel_core/adapters/shared/postgres.rb +715 -0
  50. data/lib/sequel_core/adapters/shared/progress.rb +31 -0
  51. data/lib/sequel_core/adapters/shared/sqlite.rb +265 -0
  52. data/lib/sequel_core/adapters/sqlite.rb +248 -0
  53. data/lib/sequel_core/connection_pool.rb +258 -0
  54. data/lib/sequel_core/core_ext.rb +217 -0
  55. data/lib/sequel_core/core_sql.rb +202 -0
  56. data/lib/sequel_core/database/schema.rb +164 -0
  57. data/lib/sequel_core/database.rb +691 -0
  58. data/lib/sequel_core/dataset/callback.rb +13 -0
  59. data/lib/sequel_core/dataset/convenience.rb +237 -0
  60. data/lib/sequel_core/dataset/pagination.rb +96 -0
  61. data/lib/sequel_core/dataset/prepared_statements.rb +220 -0
  62. data/lib/sequel_core/dataset/query.rb +41 -0
  63. data/lib/sequel_core/dataset/schema.rb +15 -0
  64. data/lib/sequel_core/dataset/sql.rb +1010 -0
  65. data/lib/sequel_core/dataset/stored_procedures.rb +75 -0
  66. data/lib/sequel_core/dataset/unsupported.rb +43 -0
  67. data/lib/sequel_core/dataset.rb +511 -0
  68. data/lib/sequel_core/deprecated.rb +26 -0
  69. data/lib/sequel_core/exceptions.rb +44 -0
  70. data/lib/sequel_core/migration.rb +212 -0
  71. data/lib/sequel_core/object_graph.rb +230 -0
  72. data/lib/sequel_core/pretty_table.rb +71 -0
  73. data/lib/sequel_core/schema/generator.rb +320 -0
  74. data/lib/sequel_core/schema/sql.rb +325 -0
  75. data/lib/sequel_core/schema.rb +2 -0
  76. data/lib/sequel_core/sql.rb +887 -0
  77. data/lib/sequel_core/version.rb +11 -0
  78. data/lib/sequel_core.rb +172 -0
  79. data/lib/sequel_model/association_reflection.rb +267 -0
  80. data/lib/sequel_model/associations.rb +499 -0
  81. data/lib/sequel_model/base.rb +523 -0
  82. data/lib/sequel_model/caching.rb +82 -0
  83. data/lib/sequel_model/dataset_methods.rb +26 -0
  84. data/lib/sequel_model/eager_loading.rb +370 -0
  85. data/lib/sequel_model/exceptions.rb +7 -0
  86. data/lib/sequel_model/hooks.rb +101 -0
  87. data/lib/sequel_model/inflector.rb +281 -0
  88. data/lib/sequel_model/plugins.rb +62 -0
  89. data/lib/sequel_model/record.rb +568 -0
  90. data/lib/sequel_model/schema.rb +49 -0
  91. data/lib/sequel_model/validations.rb +429 -0
  92. data/lib/sequel_model.rb +91 -0
  93. data/spec/adapters/ado_spec.rb +46 -0
  94. data/spec/adapters/firebird_spec.rb +376 -0
  95. data/spec/adapters/informix_spec.rb +96 -0
  96. data/spec/adapters/mysql_spec.rb +881 -0
  97. data/spec/adapters/oracle_spec.rb +244 -0
  98. data/spec/adapters/postgres_spec.rb +687 -0
  99. data/spec/adapters/spec_helper.rb +10 -0
  100. data/spec/adapters/sqlite_spec.rb +555 -0
  101. data/spec/integration/dataset_test.rb +134 -0
  102. data/spec/integration/eager_loader_test.rb +696 -0
  103. data/spec/integration/prepared_statement_test.rb +130 -0
  104. data/spec/integration/schema_test.rb +180 -0
  105. data/spec/integration/spec_helper.rb +58 -0
  106. data/spec/integration/type_test.rb +96 -0
  107. data/spec/rcov.opts +6 -0
  108. data/spec/sequel_core/connection_pool_spec.rb +526 -0
  109. data/spec/sequel_core/core_ext_spec.rb +156 -0
  110. data/spec/sequel_core/core_sql_spec.rb +522 -0
  111. data/spec/sequel_core/database_spec.rb +1188 -0
  112. data/spec/sequel_core/dataset_spec.rb +3481 -0
  113. data/spec/sequel_core/expression_filters_spec.rb +363 -0
  114. data/spec/sequel_core/migration_spec.rb +261 -0
  115. data/spec/sequel_core/object_graph_spec.rb +272 -0
  116. data/spec/sequel_core/pretty_table_spec.rb +58 -0
  117. data/spec/sequel_core/schema_generator_spec.rb +167 -0
  118. data/spec/sequel_core/schema_spec.rb +780 -0
  119. data/spec/sequel_core/spec_helper.rb +55 -0
  120. data/spec/sequel_core/version_spec.rb +7 -0
  121. data/spec/sequel_model/association_reflection_spec.rb +93 -0
  122. data/spec/sequel_model/associations_spec.rb +1767 -0
  123. data/spec/sequel_model/base_spec.rb +419 -0
  124. data/spec/sequel_model/caching_spec.rb +215 -0
  125. data/spec/sequel_model/dataset_methods_spec.rb +78 -0
  126. data/spec/sequel_model/eager_loading_spec.rb +1165 -0
  127. data/spec/sequel_model/hooks_spec.rb +485 -0
  128. data/spec/sequel_model/inflector_spec.rb +119 -0
  129. data/spec/sequel_model/model_spec.rb +588 -0
  130. data/spec/sequel_model/plugins_spec.rb +80 -0
  131. data/spec/sequel_model/record_spec.rb +1184 -0
  132. data/spec/sequel_model/schema_spec.rb +90 -0
  133. data/spec/sequel_model/spec_helper.rb +78 -0
  134. data/spec/sequel_model/validations_spec.rb +1067 -0
  135. data/spec/spec.opts +0 -0
  136. data/spec/spec_config.rb.example +10 -0
  137. metadata +177 -3
@@ -0,0 +1,485 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "Model hooks" do
4
+ before do
5
+ MODEL_DB.reset
6
+ end
7
+
8
+ specify "should be definable using def <hook name>" do
9
+ c = Class.new(Sequel::Model) do
10
+ def before_save
11
+ "hi there"
12
+ end
13
+ end
14
+
15
+ c.new.before_save.should == 'hi there'
16
+ end
17
+
18
+ specify "should be definable using a block" do
19
+ $adds = []
20
+ c = Class.new(Sequel::Model)
21
+ c.class_eval do
22
+ before_save {$adds << 'hi'}
23
+ end
24
+
25
+ c.new.before_save
26
+ $adds.should == ['hi']
27
+ end
28
+
29
+ specify "should be definable using a method name" do
30
+ $adds = []
31
+ c = Class.new(Sequel::Model)
32
+ c.class_eval do
33
+ def bye; $adds << 'bye'; end
34
+ before_save :bye
35
+ end
36
+
37
+ c.new.before_save
38
+ $adds.should == ['bye']
39
+ end
40
+
41
+ specify "should be additive" do
42
+ $adds = []
43
+ c = Class.new(Sequel::Model)
44
+ c.class_eval do
45
+ after_save {$adds << 'hyiyie'}
46
+ after_save {$adds << 'byiyie'}
47
+ end
48
+
49
+ c.new.after_save
50
+ $adds.should == ['hyiyie', 'byiyie']
51
+ end
52
+
53
+ specify "before hooks should run in reverse order" do
54
+ $adds = []
55
+ c = Class.new(Sequel::Model)
56
+ c.class_eval do
57
+ before_save {$adds << 'hyiyie'}
58
+ before_save {$adds << 'byiyie'}
59
+ end
60
+
61
+ c.new.before_save
62
+ $adds.should == ['byiyie', 'hyiyie']
63
+ end
64
+
65
+ specify "should not be additive if the method or tag already exists" do
66
+ $adds = []
67
+ c = Class.new(Sequel::Model)
68
+ c.class_eval do
69
+ def bye; $adds << 'bye'; end
70
+ before_save :bye
71
+ before_save :bye
72
+ end
73
+
74
+ c.new.before_save
75
+ $adds.should == ['bye']
76
+
77
+ $adds = []
78
+ d = Class.new(Sequel::Model)
79
+ d.class_eval do
80
+ before_save(:bye){$adds << 'hyiyie'}
81
+ before_save(:bye){$adds << 'byiyie'}
82
+ end
83
+
84
+ d.new.before_save
85
+ $adds.should == ['byiyie']
86
+
87
+ $adds = []
88
+ e = Class.new(Sequel::Model)
89
+ e.class_eval do
90
+ def bye; $adds << 'bye'; end
91
+ before_save :bye
92
+ before_save(:bye){$adds << 'byiyie'}
93
+ end
94
+
95
+ e.new.before_save
96
+ $adds.should == ['byiyie']
97
+
98
+ $adds = []
99
+ e = Class.new(Sequel::Model)
100
+ e.class_eval do
101
+ def bye; $adds << 'bye'; end
102
+ before_save(:bye){$adds << 'byiyie'}
103
+ before_save :bye
104
+ end
105
+
106
+ e.new.before_save
107
+ $adds.should == ['bye']
108
+ end
109
+
110
+ specify "should be inheritable" do
111
+ # pending
112
+
113
+ $adds = []
114
+ a = Class.new(Sequel::Model)
115
+ a.class_eval do
116
+ after_save {$adds << '123'}
117
+ end
118
+
119
+ b = Class.new(a)
120
+ b.class_eval do
121
+ after_save {$adds << '456'}
122
+ after_save {$adds << '789'}
123
+ end
124
+
125
+ b.new.after_save
126
+ $adds.should == ['123', '456', '789']
127
+ end
128
+
129
+ specify "should be overridable in descendant classes" do
130
+ $adds = []
131
+ a = Class.new(Sequel::Model)
132
+ a.class_eval do
133
+ before_save {$adds << '123'}
134
+ end
135
+
136
+ b = Class.new(a)
137
+ b.class_eval do
138
+ def before_save; $adds << '456'; end
139
+ end
140
+
141
+ a.new.before_save
142
+ $adds.should == ['123']
143
+ $adds = []
144
+ b.new.before_save
145
+ $adds.should == ['456']
146
+ end
147
+
148
+ specify "should stop processing if a hook returns false" do
149
+ $flag = true
150
+ $adds = []
151
+
152
+ a = Class.new(Sequel::Model)
153
+ a.class_eval do
154
+ after_save {$adds << 'blah'; $flag}
155
+ after_save {$adds << 'cruel'}
156
+ end
157
+
158
+ a.new.after_save
159
+ $adds.should == ['blah', 'cruel']
160
+
161
+ # chain should not break on nil
162
+ $adds = []
163
+ $flag = nil
164
+ a.new.after_save
165
+ $adds.should == ['blah', 'cruel']
166
+
167
+ $adds = []
168
+ $flag = false
169
+ a.new.after_save
170
+ $adds.should == ['blah']
171
+
172
+ b = Class.new(a)
173
+ b.class_eval do
174
+ after_save {$adds << 'mau'}
175
+ end
176
+
177
+ $adds = []
178
+ b.new.after_save
179
+ $adds.should == ['blah']
180
+ end
181
+ end
182
+
183
+ describe "Model#after_initialize" do
184
+ specify "should be called after initialization" do
185
+ $values1 = nil
186
+ $reached_after_initialized = false
187
+
188
+ a = Class.new(Sequel::Model)
189
+ a.class_eval do
190
+ columns :x, :y
191
+ after_initialize do
192
+ $values1 = @values.clone
193
+ $reached_after_initialized = true
194
+ end
195
+ end
196
+
197
+ a.new(:x => 1, :y => 2)
198
+ $values1.should == {:x => 1, :y => 2}
199
+ $reached_after_initialized.should == true
200
+ end
201
+ end
202
+
203
+ describe "Model#before_create && Model#after_create" do
204
+ setup do
205
+ MODEL_DB.reset
206
+
207
+ @c = Class.new(Sequel::Model(:items))
208
+ @c.class_eval do
209
+ columns :x
210
+ no_primary_key
211
+
212
+ after_create {MODEL_DB << "BLAH after"}
213
+ end
214
+ end
215
+
216
+ specify "should be called around new record creation" do
217
+ @c.before_create {MODEL_DB << "BLAH before"}
218
+ @c.create(:x => 2)
219
+ MODEL_DB.sqls.should == [
220
+ 'BLAH before',
221
+ 'INSERT INTO items (x) VALUES (2)',
222
+ 'BLAH after'
223
+ ]
224
+ end
225
+
226
+ specify ".create should cancel the save and raise an error if before_create returns false and raise_on_save_failure is true" do
227
+ @c.before_create{false}
228
+ proc{@c.load(:id => 2233).save}.should_not raise_error(Sequel::ValidationFailed)
229
+ proc{@c.create(:x => 2)}.should raise_error(Sequel::BeforeHookFailed)
230
+ MODEL_DB.sqls.should == []
231
+ end
232
+
233
+ specify ".create should cancel the save and return nil if before_create returns false and raise_on_save_failure is false" do
234
+ @c.before_create{false}
235
+ @c.raise_on_save_failure = false
236
+ @c.create(:x => 2).should == nil
237
+ MODEL_DB.sqls.should == []
238
+ end
239
+ end
240
+
241
+ describe "Model#before_update && Model#after_update" do
242
+ setup do
243
+ MODEL_DB.reset
244
+
245
+ @c = Class.new(Sequel::Model(:items))
246
+ @c.class_eval do
247
+ after_update {MODEL_DB << "BLAH after"}
248
+ end
249
+ end
250
+
251
+ specify "should be called around record update" do
252
+ @c.before_update {MODEL_DB << "BLAH before"}
253
+ m = @c.load(:id => 2233)
254
+ m.save
255
+ MODEL_DB.sqls.should == [
256
+ 'BLAH before',
257
+ 'UPDATE items SET id = 2233 WHERE (id = 2233)',
258
+ 'BLAH after'
259
+ ]
260
+ end
261
+
262
+ specify "#save should cancel the save and raise an error if before_update returns false and raise_on_save_failure is true" do
263
+ @c.before_update{false}
264
+ proc{@c.load(:id => 2233).save}.should_not raise_error(Sequel::ValidationFailed)
265
+ proc{@c.load(:id => 2233).save}.should raise_error(Sequel::BeforeHookFailed)
266
+ MODEL_DB.sqls.should == []
267
+ end
268
+
269
+ specify "#save should cancel the save and return nil if before_update returns false and raise_on_save_failure is false" do
270
+ @c.before_update{false}
271
+ @c.raise_on_save_failure = false
272
+ @c.load(:id => 2233).save.should == nil
273
+ MODEL_DB.sqls.should == []
274
+ end
275
+ end
276
+
277
+ describe "Model#before_save && Model#after_save" do
278
+ setup do
279
+ MODEL_DB.reset
280
+
281
+ @c = Class.new(Sequel::Model(:items))
282
+ @c.class_eval do
283
+ columns :x
284
+ after_save {MODEL_DB << "BLAH after"}
285
+ end
286
+ end
287
+
288
+ specify "should be called around record update" do
289
+ @c.before_save {MODEL_DB << "BLAH before"}
290
+ m = @c.load(:id => 2233)
291
+ m.save
292
+ MODEL_DB.sqls.should == [
293
+ 'BLAH before',
294
+ 'UPDATE items SET id = 2233 WHERE (id = 2233)',
295
+ 'BLAH after'
296
+ ]
297
+ end
298
+
299
+ specify "should be called around record creation" do
300
+ @c.before_save {MODEL_DB << "BLAH before"}
301
+ @c.no_primary_key
302
+ @c.create(:x => 2)
303
+ MODEL_DB.sqls.should == [
304
+ 'BLAH before',
305
+ 'INSERT INTO items (x) VALUES (2)',
306
+ 'BLAH after'
307
+ ]
308
+ end
309
+
310
+ specify "#save should cancel the save and raise an error if before_save returns false and raise_on_save_failure is true" do
311
+ @c.before_save{false}
312
+ proc{@c.load(:id => 2233).save}.should_not raise_error(Sequel::ValidationFailed)
313
+ proc{@c.load(:id => 2233).save}.should raise_error(Sequel::BeforeHookFailed)
314
+ MODEL_DB.sqls.should == []
315
+ end
316
+
317
+ specify "#save should cancel the save and return nil if before_save returns false and raise_on_save_failure is false" do
318
+ @c.before_save{false}
319
+ @c.raise_on_save_failure = false
320
+ @c.load(:id => 2233).save.should == nil
321
+ MODEL_DB.sqls.should == []
322
+ end
323
+ end
324
+
325
+ describe "Model#before_destroy && Model#after_destroy" do
326
+ setup do
327
+ MODEL_DB.reset
328
+
329
+ @c = Class.new(Sequel::Model(:items))
330
+ @c.class_eval do
331
+ after_destroy {MODEL_DB << "BLAH after"}
332
+
333
+ def delete
334
+ MODEL_DB << "DELETE BLAH"
335
+ end
336
+ end
337
+ end
338
+
339
+ specify "should be called around record destruction" do
340
+ @c.before_destroy {MODEL_DB << "BLAH before"}
341
+ m = @c.load(:id => 2233)
342
+ m.destroy
343
+ MODEL_DB.sqls.should == [
344
+ 'BLAH before',
345
+ 'DELETE BLAH',
346
+ 'BLAH after'
347
+ ]
348
+ end
349
+
350
+ specify "#destroy should cancel the destroy and raise an error if before_destroy returns false and raise_on_save_failure is true" do
351
+ @c.before_destroy{false}
352
+ proc{@c.load(:id => 2233).destroy}.should raise_error(Sequel::BeforeHookFailed)
353
+ MODEL_DB.sqls.should == []
354
+ end
355
+
356
+ specify "#destroy should cancel the destroy and return nil if before_destroy returns false and raise_on_save_failure is false" do
357
+ @c.before_destroy{false}
358
+ @c.raise_on_save_failure = false
359
+ @c.load(:id => 2233).destroy.should == nil
360
+ MODEL_DB.sqls.should == []
361
+ end
362
+ end
363
+
364
+ describe "Model#before_validation && Model#after_validation" do
365
+ setup do
366
+ MODEL_DB.reset
367
+
368
+ @c = Class.new(Sequel::Model(:items))
369
+ @c.class_eval do
370
+ after_validation{MODEL_DB << "BLAH after"}
371
+
372
+ def self.validate(o)
373
+ o.errors[:id] << 'not valid' unless o[:id] == 2233
374
+ end
375
+
376
+ def save!(*columns)
377
+ MODEL_DB << "CREATE BLAH"
378
+ self
379
+ end
380
+ columns :id
381
+ end
382
+ end
383
+
384
+ specify "should be called around validation" do
385
+ @c.before_validation{MODEL_DB << "BLAH before"}
386
+ m = @c.load(:id => 2233)
387
+ m.should be_valid
388
+ MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
389
+
390
+ MODEL_DB.sqls.clear
391
+ m = @c.load(:id => 22)
392
+ m.should_not be_valid
393
+ MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
394
+ end
395
+
396
+ specify "should be called when calling save" do
397
+ @c.before_validation{MODEL_DB << "BLAH before"}
398
+ m = @c.load(:id => 2233)
399
+ m.save.should == m
400
+ MODEL_DB.sqls.should == ['BLAH before', 'BLAH after', 'CREATE BLAH']
401
+
402
+ MODEL_DB.sqls.clear
403
+ m = @c.load(:id => 22)
404
+ m.raise_on_save_failure = false
405
+ m.save.should == nil
406
+ MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
407
+ end
408
+
409
+ specify "#save should cancel the save and raise an error if before_validation returns false and raise_on_save_failure is true" do
410
+ @c.before_validation{false}
411
+ proc{@c.load(:id => 2233).save}.should_not raise_error(Sequel::ValidationFailed)
412
+ proc{@c.load(:id => 2233).save}.should raise_error(Sequel::BeforeHookFailed)
413
+ MODEL_DB.sqls.should == []
414
+ end
415
+
416
+ specify "#save should cancel the save and return nil if before_validation returns false and raise_on_save_failure is false" do
417
+ @c.before_validation{false}
418
+ @c.raise_on_save_failure = false
419
+ @c.load(:id => 2233).save.should == nil
420
+ MODEL_DB.sqls.should == []
421
+ end
422
+ end
423
+
424
+ describe "Model.has_hooks?" do
425
+ setup do
426
+ @c = Class.new(Sequel::Model(:items))
427
+ end
428
+
429
+ specify "should return false if no hooks are defined" do
430
+ @c.has_hooks?(:before_save).should be_false
431
+ end
432
+
433
+ specify "should return true if hooks are defined" do
434
+ @c.before_save {'blah'}
435
+ @c.has_hooks?(:before_save).should be_true
436
+ end
437
+
438
+ specify "should return true if hooks are inherited" do
439
+ @d = Class.new(@c)
440
+ @d.has_hooks?(:before_save).should be_false
441
+ end
442
+ end
443
+
444
+ describe "Model#add_hook_type" do
445
+ setup do
446
+ class Foo < Sequel::Model(:items)
447
+ add_hook_type :before_bar, :after_bar
448
+
449
+ def bar
450
+ return :b if before_bar == false
451
+ return :a if after_bar == false
452
+ true
453
+ end
454
+ end
455
+ @f = Class.new(Foo)
456
+ end
457
+
458
+ specify "should have before_bar and after_bar class methods" do
459
+ @f.should respond_to(:before_bar)
460
+ @f.should respond_to(:before_bar)
461
+ end
462
+
463
+ specify "should have before_bar and after_bar instance methods" do
464
+ @f.new.should respond_to(:before_bar)
465
+ @f.new.should respond_to(:before_bar)
466
+ end
467
+
468
+ specify "it should return true for bar when before_bar and after_bar hooks are returing true" do
469
+ a = 1
470
+ @f.before_bar { a += 1}
471
+ @f.new.bar.should be_true
472
+ a.should == 2
473
+ @f.after_bar { a *= 2}
474
+ @f.new.bar.should be_true
475
+ a.should == 6
476
+ end
477
+
478
+ specify "it should return nil for bar when before_bar and after_bar hooks are returing false" do
479
+ @f.new.bar.should be_true
480
+ @f.after_bar { false }
481
+ @f.new.bar.should == :a
482
+ @f.before_bar { false }
483
+ @f.new.bar.should == :b
484
+ end
485
+ end
@@ -0,0 +1,119 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe String do
4
+ it "#camelize and #camelcase should transform the word to CamelCase" do
5
+ "egg_and_hams".camelize.should == "EggAndHams"
6
+ "egg_and_hams".camelize(false).should == "eggAndHams"
7
+ "post".camelize.should == "Post"
8
+ "post".camelcase.should == "Post"
9
+ end
10
+
11
+ it "#constantize should eval the string to get a constant" do
12
+ "String".constantize.should == String
13
+ "String::Inflections".constantize.should == String::Inflections
14
+ proc{"BKSDDF".constantize}.should raise_error
15
+ proc{"++A++".constantize}.should raise_error
16
+ end
17
+
18
+ it "#dasherize should transform underscores to dashes" do
19
+ "egg_and_hams".dasherize.should == "egg-and-hams"
20
+ "post".dasherize.should == "post"
21
+ end
22
+
23
+ it "#demodulize should remove any preceding modules" do
24
+ "String::Inflections::Blah".demodulize.should == "Blah"
25
+ "String::Inflections".demodulize.should == "Inflections"
26
+ "String".demodulize.should == "String"
27
+ end
28
+
29
+ it "#humanize should remove _i, transform underscore to spaces, and capitalize" do
30
+ "egg_and_hams".humanize.should == "Egg and hams"
31
+ "post".humanize.should == "Post"
32
+ "post_id".humanize.should == "Post"
33
+ end
34
+
35
+ it "#titleize and #titlecase should underscore, humanize, and capitalize all words" do
36
+ "egg-and: hams".titleize.should == "Egg And: Hams"
37
+ "post".titleize.should == "Post"
38
+ "post".titlecase.should == "Post"
39
+ end
40
+
41
+ it "#underscore should add underscores between CamelCased words, change :: to / and - to _, and downcase" do
42
+ "EggAndHams".underscore.should == "egg_and_hams"
43
+ "EGGAndHams".underscore.should == "egg_and_hams"
44
+ "Egg::And::Hams".underscore.should == "egg/and/hams"
45
+ "post".underscore.should == "post"
46
+ "post-id".underscore.should == "post_id"
47
+ end
48
+
49
+ it "#pluralize should transform words from singular to plural" do
50
+ "post".pluralize.should == "posts"
51
+ "octopus".pluralize.should =="octopi"
52
+ "the blue mailman".pluralize.should == "the blue mailmen"
53
+ "CamelOctopus".pluralize.should == "CamelOctopi"
54
+ end
55
+
56
+ it "#singularize should transform words from plural to singular" do
57
+ "posts".singularize.should == "post"
58
+ "octopi".singularize.should == "octopus"
59
+ "the blue mailmen".singularize.should == "the blue mailman"
60
+ "CamelOctopi".singularize.should == "CamelOctopus"
61
+ end
62
+
63
+ it "#tableize should transform class names to table names" do
64
+ "RawScaledScorer".tableize.should == "raw_scaled_scorers"
65
+ "egg_and_ham".tableize.should == "egg_and_hams"
66
+ "fancyCategory".tableize.should == "fancy_categories"
67
+ end
68
+
69
+ it "#classify should tranform table names to class names" do
70
+ "egg_and_hams".classify.should == "EggAndHam"
71
+ "post".classify.should == "Post"
72
+ end
73
+
74
+ it "#foreign_key should create a foreign key name from a class name" do
75
+ "Message".foreign_key.should == "message_id"
76
+ "Message".foreign_key(false).should == "messageid"
77
+ "Admin::Post".foreign_key.should == "post_id"
78
+ end
79
+ end
80
+
81
+ describe String::Inflections do
82
+ before do
83
+ @plurals, @singulars, @uncountables = String.inflections.plurals.dup, String.inflections.singulars.dup, String.inflections.uncountables.dup
84
+ end
85
+ after do
86
+ String.inflections.plurals.replace(@plurals)
87
+ String.inflections.singulars.replace(@singulars)
88
+ String.inflections.uncountables.replace(@uncountables)
89
+ end
90
+
91
+ it "should be possible to clear the list of singulars, plurals, and uncountables" do
92
+ String.inflections.clear(:plurals)
93
+ String.inflections.plurals.should == []
94
+ String.inflections.plural('blah', 'blahs')
95
+ String.inflections.clear
96
+ String.inflections.plurals.should == []
97
+ String.inflections.singulars.should == []
98
+ String.inflections.uncountables.should == []
99
+ end
100
+
101
+ it "should be able to specify new inflection rules" do
102
+ String.inflections do |i|
103
+ i.plural(/xx$/i, 'xxx')
104
+ i.singular(/ttt$/i, 'tt')
105
+ i.irregular('yy', 'yyy')
106
+ i.uncountable(%w'zz')
107
+ end
108
+ 'roxx'.pluralize.should == 'roxxx'
109
+ 'rottt'.singularize.should == 'rott'
110
+ 'yy'.pluralize.should == 'yyy'
111
+ 'yyy'.singularize.should == 'yy'
112
+ 'zz'.pluralize.should == 'zz'
113
+ 'zz'.singularize.should == 'zz'
114
+ end
115
+
116
+ it "should be yielded and returned by String.inflections" do
117
+ String.inflections{|i| i.should == String::Inflections}.should == String::Inflections
118
+ end
119
+ end