railties 3.0.0.beta → 3.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (232) hide show
  1. data/CHANGELOG +15 -1
  2. data/README +9 -9
  3. data/bin/rails +28 -9
  4. data/guides/images/challenge.png +0 -0
  5. data/guides/images/edge_badge.png +0 -0
  6. data/guides/images/posts_index.png +0 -0
  7. data/guides/images/rails_welcome.png +0 -0
  8. data/guides/rails_guides.rb +9 -22
  9. data/guides/rails_guides/generator.rb +79 -50
  10. data/guides/rails_guides/textile_extensions.rb +3 -3
  11. data/guides/source/2_2_release_notes.textile +1 -1
  12. data/guides/source/2_3_release_notes.textile +1 -1
  13. data/guides/source/3_0_release_notes.textile +46 -38
  14. data/guides/source/action_controller_overview.textile +2 -2
  15. data/guides/source/action_mailer_basics.textile +4 -4
  16. data/guides/source/action_view_overview.textile +2 -2
  17. data/guides/source/active_record_querying.textile +73 -95
  18. data/guides/source/active_support_core_extensions.textile +993 -85
  19. data/guides/source/activerecord_validations_callbacks.textile +3 -3
  20. data/guides/source/caching_with_rails.textile +1 -1
  21. data/guides/source/command_line.textile +90 -88
  22. data/guides/source/configuring.textile +10 -10
  23. data/guides/source/contribute.textile +2 -2
  24. data/guides/source/contributing_to_rails.textile +14 -7
  25. data/guides/source/credits.textile.erb +8 -0
  26. data/guides/source/debugging_rails_applications.textile +6 -6
  27. data/guides/source/form_helpers.textile +1 -1
  28. data/guides/source/generators.textile +14 -14
  29. data/guides/source/getting_started.textile +634 -500
  30. data/guides/source/index.textile.erb +16 -1
  31. data/guides/source/layout.html.erb +7 -1
  32. data/guides/source/layouts_and_rendering.textile +299 -71
  33. data/guides/source/migrations.textile +5 -5
  34. data/guides/source/performance_testing.textile +8 -8
  35. data/guides/source/plugins.textile +26 -24
  36. data/guides/source/rails_on_rack.textile +5 -5
  37. data/guides/source/routing.textile +119 -117
  38. data/guides/source/security.textile +1 -1
  39. data/guides/source/testing.textile +4 -4
  40. data/lib/rails.rb +4 -1
  41. data/lib/rails/application.rb +44 -7
  42. data/lib/rails/application/bootstrap.rb +2 -14
  43. data/lib/rails/application/configuration.rb +69 -5
  44. data/lib/rails/application/finisher.rb +2 -3
  45. data/lib/rails/application/metal_loader.rb +1 -1
  46. data/lib/rails/application/routes_reloader.rb +1 -1
  47. data/lib/rails/backtrace_cleaner.rb +0 -11
  48. data/lib/rails/commands.rb +7 -6
  49. data/lib/rails/commands/application.rb +1 -1
  50. data/lib/rails/commands/console.rb +1 -1
  51. data/lib/rails/commands/dbconsole.rb +12 -0
  52. data/lib/rails/commands/destroy.rb +2 -2
  53. data/lib/rails/commands/generate.rb +2 -2
  54. data/lib/rails/commands/performance/benchmarker.rb +2 -2
  55. data/lib/rails/commands/performance/profiler.rb +2 -2
  56. data/lib/rails/commands/plugin.rb +6 -6
  57. data/lib/rails/commands/runner.rb +2 -0
  58. data/lib/rails/commands/server.rb +23 -8
  59. data/lib/rails/configuration.rb +2 -84
  60. data/lib/rails/console/app.rb +4 -3
  61. data/lib/rails/console/helpers.rb +3 -1
  62. data/lib/rails/engine.rb +107 -12
  63. data/lib/rails/engine/configuration.rb +8 -2
  64. data/lib/rails/generators.rb +22 -7
  65. data/lib/rails/generators/actions.rb +16 -6
  66. data/lib/rails/generators/base.rb +15 -8
  67. data/lib/rails/generators/erb.rb +21 -0
  68. data/lib/{generators → rails/generators}/erb/controller/controller_generator.rb +4 -5
  69. data/lib/{generators → rails/generators}/erb/controller/templates/view.html.erb +0 -0
  70. data/lib/rails/generators/erb/mailer/mailer_generator.rb +13 -0
  71. data/lib/{generators → rails/generators}/erb/mailer/templates/view.text.erb +0 -0
  72. data/lib/{generators → rails/generators}/erb/scaffold/scaffold_generator.rb +14 -26
  73. data/lib/{generators → rails/generators}/erb/scaffold/templates/_form.html.erb +1 -1
  74. data/lib/{generators → rails/generators}/erb/scaffold/templates/edit.html.erb +0 -0
  75. data/lib/{generators → rails/generators}/erb/scaffold/templates/index.html.erb +1 -1
  76. data/lib/{generators → rails/generators}/erb/scaffold/templates/layout.html.erb +1 -0
  77. data/lib/{generators → rails/generators}/erb/scaffold/templates/new.html.erb +0 -0
  78. data/lib/{generators → rails/generators}/erb/scaffold/templates/show.html.erb +0 -0
  79. data/lib/rails/generators/named_base.rb +4 -0
  80. data/lib/{generators → rails/generators}/rails/app/USAGE +0 -0
  81. data/lib/{generators → rails/generators}/rails/app/app_generator.rb +21 -7
  82. data/lib/rails/generators/rails/app/templates/Gemfile +34 -0
  83. data/lib/{generators → rails/generators}/rails/app/templates/README +9 -8
  84. data/lib/{generators → rails/generators}/rails/app/templates/Rakefile +0 -0
  85. data/lib/{generators → rails/generators}/rails/app/templates/app/controllers/application_controller.rb +0 -0
  86. data/lib/{generators → rails/generators}/rails/app/templates/app/helpers/application_helper.rb +0 -0
  87. data/lib/{generators → rails/generators}/rails/app/templates/app/models/.empty_directory +0 -0
  88. data/lib/{generators → rails/generators}/rails/app/templates/app/views/layouts/.empty_directory +0 -0
  89. data/lib/{generators → rails/generators}/rails/app/templates/config.ru +0 -0
  90. data/lib/{generators → rails/generators}/rails/app/templates/config/application.rb +4 -3
  91. data/lib/rails/generators/rails/app/templates/config/boot.rb +14 -0
  92. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/frontbase.yml +0 -0
  93. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/ibm_db.yml +0 -0
  94. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/mysql.yml +0 -0
  95. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/oracle.yml +0 -0
  96. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/postgresql.yml +0 -0
  97. data/lib/{generators → rails/generators}/rails/app/templates/config/databases/sqlite3.yml +0 -0
  98. data/lib/{generators → rails/generators}/rails/app/templates/config/environment.rb +0 -0
  99. data/lib/{generators → rails/generators}/rails/app/templates/config/environments/development.rb.tt +0 -0
  100. data/lib/{generators → rails/generators}/rails/app/templates/config/environments/production.rb.tt +9 -0
  101. data/lib/{generators → rails/generators}/rails/app/templates/config/environments/test.rb.tt +0 -0
  102. data/lib/{generators → rails/generators}/rails/app/templates/config/initializers/backtrace_silencers.rb +0 -0
  103. data/lib/{generators → rails/generators}/rails/app/templates/config/initializers/cookie_verification_secret.rb.tt +1 -1
  104. data/lib/{generators → rails/generators}/rails/app/templates/config/initializers/inflections.rb +0 -0
  105. data/lib/{generators → rails/generators}/rails/app/templates/config/initializers/mime_types.rb +0 -0
  106. data/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +10 -0
  107. data/lib/{generators → rails/generators}/rails/app/templates/config/locales/en.yml +0 -0
  108. data/lib/{generators → rails/generators}/rails/app/templates/config/routes.rb +0 -0
  109. data/lib/{generators → rails/generators}/rails/app/templates/db/seeds.rb +0 -0
  110. data/lib/{generators → rails/generators}/rails/app/templates/doc/README_FOR_APP +0 -0
  111. data/lib/{generators → rails/generators}/rails/app/templates/gitignore +0 -0
  112. data/lib/{generators → rails/generators}/rails/app/templates/public/404.html +0 -0
  113. data/lib/{generators → rails/generators}/rails/app/templates/public/422.html +0 -0
  114. data/lib/{generators → rails/generators}/rails/app/templates/public/500.html +0 -0
  115. data/lib/{generators → rails/generators}/rails/app/templates/public/favicon.ico +0 -0
  116. data/lib/{generators → rails/generators}/rails/app/templates/public/images/rails.png +0 -0
  117. data/lib/{generators → rails/generators}/rails/app/templates/public/index.html +17 -17
  118. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/application.js +0 -0
  119. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/controls.js +5 -3
  120. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/dragdrop.js +7 -6
  121. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/effects.js +8 -13
  122. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/prototype.js +1573 -1019
  123. data/lib/{generators → rails/generators}/rails/app/templates/public/javascripts/rails.js +1 -2
  124. data/lib/{generators → rails/generators}/rails/app/templates/public/robots.txt +0 -0
  125. data/lib/{generators → rails/generators}/rails/app/templates/public/stylesheets/.empty_directory +0 -0
  126. data/lib/{generators → rails/generators}/rails/app/templates/script/rails +0 -1
  127. data/lib/{generators → rails/generators}/rails/app/templates/test/fixtures/.empty_directory +0 -0
  128. data/lib/{generators → rails/generators}/rails/app/templates/test/functional/.empty_directory +0 -0
  129. data/lib/{generators → rails/generators}/rails/app/templates/test/integration/.empty_directory +0 -0
  130. data/lib/{generators → rails/generators}/rails/app/templates/test/performance/browsing_test.rb +1 -1
  131. data/lib/{generators → rails/generators}/rails/app/templates/test/test_helper.rb +1 -1
  132. data/lib/{generators → rails/generators}/rails/app/templates/test/unit/.empty_directory +0 -0
  133. data/lib/{generators → rails/generators}/rails/controller/USAGE +1 -1
  134. data/lib/{generators → rails/generators}/rails/controller/controller_generator.rb +6 -0
  135. data/lib/{generators → rails/generators}/rails/controller/templates/controller.rb +0 -0
  136. data/lib/{generators → rails/generators}/rails/generator/USAGE +1 -1
  137. data/lib/{generators → rails/generators}/rails/generator/generator_generator.rb +0 -0
  138. data/lib/{generators → rails/generators}/rails/generator/templates/%file_name%_generator.rb.tt +0 -0
  139. data/lib/{generators → rails/generators}/rails/generator/templates/USAGE.tt +1 -1
  140. data/lib/{generators → rails/generators}/rails/generator/templates/templates/.empty_directory +0 -0
  141. data/lib/{generators → rails/generators}/rails/helper/USAGE +1 -1
  142. data/lib/{generators → rails/generators}/rails/helper/helper_generator.rb +0 -0
  143. data/lib/{generators → rails/generators}/rails/helper/templates/helper.rb +0 -0
  144. data/lib/{generators → rails/generators}/rails/integration_test/USAGE +1 -1
  145. data/lib/{generators → rails/generators}/rails/integration_test/integration_test_generator.rb +0 -0
  146. data/lib/{generators → rails/generators}/rails/mailer/USAGE +1 -1
  147. data/lib/{generators → rails/generators}/rails/mailer/mailer_generator.rb +0 -0
  148. data/lib/{generators → rails/generators}/rails/mailer/templates/mailer.rb +0 -0
  149. data/lib/{generators → rails/generators}/rails/metal/USAGE +1 -1
  150. data/lib/{generators → rails/generators}/rails/metal/metal_generator.rb +0 -0
  151. data/lib/{generators → rails/generators}/rails/metal/templates/metal.rb +0 -0
  152. data/lib/{generators → rails/generators}/rails/migration/USAGE +2 -2
  153. data/lib/{generators → rails/generators}/rails/migration/migration_generator.rb +0 -0
  154. data/lib/{generators → rails/generators}/rails/model/USAGE +2 -2
  155. data/lib/{generators → rails/generators}/rails/model/model_generator.rb +0 -0
  156. data/lib/{generators → rails/generators}/rails/observer/USAGE +1 -1
  157. data/lib/{generators → rails/generators}/rails/observer/observer_generator.rb +0 -0
  158. data/lib/{generators → rails/generators}/rails/performance_test/USAGE +1 -1
  159. data/lib/{generators → rails/generators}/rails/performance_test/performance_test_generator.rb +0 -0
  160. data/lib/{generators → rails/generators}/rails/plugin/USAGE +1 -1
  161. data/lib/{generators → rails/generators}/rails/plugin/plugin_generator.rb +1 -1
  162. data/lib/{generators → rails/generators}/rails/plugin/templates/MIT-LICENSE.tt +0 -0
  163. data/lib/{generators → rails/generators}/rails/plugin/templates/README.tt +0 -0
  164. data/lib/rails/generators/rails/plugin/templates/Rakefile.tt +23 -0
  165. data/lib/{generators → rails/generators}/rails/plugin/templates/init.rb +0 -0
  166. data/lib/{generators → rails/generators}/rails/plugin/templates/install.rb +0 -0
  167. data/lib/{generators → rails/generators}/rails/plugin/templates/lib/%file_name%.rb.tt +0 -0
  168. data/lib/{generators → rails/generators}/rails/plugin/templates/lib/tasks/%file_name%_tasks.rake.tt +0 -0
  169. data/lib/{generators → rails/generators}/rails/plugin/templates/uninstall.rb +0 -0
  170. data/lib/{generators → rails/generators}/rails/resource/USAGE +3 -3
  171. data/lib/{generators → rails/generators}/rails/resource/resource_generator.rb +3 -1
  172. data/lib/{generators → rails/generators}/rails/scaffold/USAGE +4 -4
  173. data/lib/{generators → rails/generators}/rails/scaffold/scaffold_generator.rb +1 -1
  174. data/lib/{generators → rails/generators}/rails/scaffold_controller/USAGE +1 -1
  175. data/lib/{generators → rails/generators}/rails/scaffold_controller/scaffold_controller_generator.rb +0 -0
  176. data/lib/{generators → rails/generators}/rails/scaffold_controller/templates/controller.rb +2 -2
  177. data/lib/{generators → rails/generators}/rails/session_migration/USAGE +1 -1
  178. data/lib/{generators → rails/generators}/rails/session_migration/session_migration_generator.rb +0 -0
  179. data/lib/{generators → rails/generators}/rails/stylesheets/USAGE +1 -1
  180. data/lib/{generators → rails/generators}/rails/stylesheets/stylesheets_generator.rb +0 -0
  181. data/lib/{generators → rails/generators}/rails/stylesheets/templates/scaffold.css +4 -0
  182. data/lib/{generators → rails/generators}/test_unit.rb +0 -0
  183. data/lib/{generators → rails/generators}/test_unit/controller/controller_generator.rb +2 -1
  184. data/lib/rails/generators/test_unit/controller/templates/functional_test.rb +18 -0
  185. data/lib/{generators → rails/generators}/test_unit/helper/helper_generator.rb +1 -1
  186. data/lib/{generators → rails/generators}/test_unit/helper/templates/helper_test.rb +0 -0
  187. data/lib/{generators → rails/generators}/test_unit/integration/integration_generator.rb +1 -1
  188. data/lib/{generators → rails/generators}/test_unit/integration/templates/integration_test.rb +0 -0
  189. data/lib/{generators → rails/generators}/test_unit/mailer/mailer_generator.rb +1 -8
  190. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb +20 -0
  191. data/lib/{generators → rails/generators}/test_unit/model/model_generator.rb +1 -1
  192. data/lib/{generators → rails/generators}/test_unit/model/templates/fixtures.yml +0 -0
  193. data/lib/{generators → rails/generators}/test_unit/model/templates/unit_test.rb +0 -0
  194. data/lib/{generators → rails/generators}/test_unit/observer/observer_generator.rb +1 -1
  195. data/lib/{generators → rails/generators}/test_unit/observer/templates/unit_test.rb +0 -0
  196. data/lib/{generators → rails/generators}/test_unit/performance/performance_generator.rb +1 -1
  197. data/lib/{generators → rails/generators}/test_unit/performance/templates/performance_test.rb +0 -0
  198. data/lib/{generators → rails/generators}/test_unit/plugin/plugin_generator.rb +1 -1
  199. data/lib/{generators → rails/generators}/test_unit/plugin/templates/%file_name%_test.rb.tt +0 -0
  200. data/lib/{generators → rails/generators}/test_unit/plugin/templates/test_helper.rb +0 -0
  201. data/lib/{generators → rails/generators}/test_unit/scaffold/scaffold_generator.rb +1 -1
  202. data/lib/{generators → rails/generators}/test_unit/scaffold/templates/functional_test.rb +9 -5
  203. data/{builtin/rails_info → lib}/rails/info.rb +0 -0
  204. data/{builtin/rails_info → lib}/rails/info_controller.rb +0 -0
  205. data/{builtin/routes.rb → lib/rails/info_routes.rb} +2 -2
  206. data/lib/rails/{subscriber.rb → log_subscriber.rb} +27 -27
  207. data/lib/rails/{subscriber → log_subscriber}/test_helper.rb +15 -16
  208. data/lib/rails/plugin.rb +31 -8
  209. data/lib/rails/rack/debugger.rb +3 -1
  210. data/lib/rails/rack/logger.rb +4 -4
  211. data/lib/rails/railtie.rb +179 -16
  212. data/lib/rails/railtie/configuration.rb +56 -1
  213. data/lib/rails/tasks/documentation.rake +38 -20
  214. data/lib/rails/tasks/framework.rake +16 -9
  215. data/lib/rails/tasks/misc.rake +3 -5
  216. data/lib/rails/tasks/routes.rake +2 -2
  217. data/lib/rails/test_help.rb +21 -1
  218. data/lib/rails/test_unit/railtie.rb +1 -3
  219. data/lib/rails/version.rb +3 -2
  220. metadata +199 -171
  221. data/builtin/rails_info/rails/info_helper.rb +0 -2
  222. data/lib/generators/erb.rb +0 -8
  223. data/lib/generators/erb/mailer/mailer_generator.rb +0 -20
  224. data/lib/generators/rails/app/templates/Gemfile +0 -34
  225. data/lib/generators/rails/app/templates/config/boot.rb +0 -17
  226. data/lib/generators/rails/app/templates/config/initializers/session_store.rb.tt +0 -15
  227. data/lib/generators/rails/model_subclass/model_subclass_generator.rb +0 -12
  228. data/lib/generators/rails/plugin/templates/Rakefile.tt +0 -10
  229. data/lib/generators/test_unit/controller/templates/functional_test.rb +0 -8
  230. data/lib/generators/test_unit/mailer/templates/fixture +0 -3
  231. data/lib/generators/test_unit/mailer/templates/functional_test.rb +0 -22
  232. data/lib/rails/railties_path.rb +0 -1
@@ -6,6 +6,68 @@ By referring to this guide you will learn the extensions to the Ruby core classe
6
6
 
7
7
  endprologue.
8
8
 
9
+ h3. How to Load Core Extensions
10
+
11
+ h4. Stand-Alone Active Support
12
+
13
+ In order to have a near zero default footprint, Active Support does not load anything by default. It is broken in small pieces so that you may load just what you need, and also has some convenience entry points to load related extensions in one shot, even everything.
14
+
15
+ Thus, after a simple require like:
16
+
17
+ <ruby>
18
+ require 'active_support'
19
+ </ruby>
20
+
21
+ objects do not even respond to +blank?+, let's see how to load its definition.
22
+
23
+ h5. Cherry-picking a Definition
24
+
25
+ The most lightweight way to get +blank?+ is to cherry-pick the file that defines it.
26
+
27
+ For every single method defined as a core extension this guide has a note that says where is such a method defined. In the case of +blank?+ the note reads:
28
+
29
+ NOTE: Defined in +active_support/core_ext/object/blank.rb+.
30
+
31
+ That means that this single call is enough:
32
+
33
+ <ruby>
34
+ require 'active_support/core_ext/object/blank'
35
+ </ruby>
36
+
37
+ Active Support has been carefully revised so that cherry-picking a file loads only strictly needed dependencies, if any.
38
+
39
+ h5. Loading Grouped Core Extensions
40
+
41
+ The next level is to simply load all extensions to +Object+. As a rule of thumb, extensions to +SomeClass+ are available in one shot by loading +active_support/core_ext/some_class+.
42
+
43
+ Thus, if that would do, to have +blank?+ available we could just load all extensions to +Object+:
44
+
45
+ <ruby>
46
+ require 'active_support/core_ext/object'
47
+ </ruby>
48
+
49
+ h5. Loading All Core Extensions
50
+
51
+ You may prefer just to load all core extensions, there is a file for that:
52
+
53
+ <ruby>
54
+ require 'active_support/core_ext'
55
+ </ruby>
56
+
57
+ h5. Loading All Active Support
58
+
59
+ And finally, if you want to have all Active Support available just issue:
60
+
61
+ <ruby>
62
+ require 'active_support/all'
63
+ </ruby>
64
+
65
+ That does not even put the entire Active Support in memory upfront indeed, some stuff is configured via +autoload+, so it is only loaded if used.
66
+
67
+ h4. Active Support Within a Ruby on Rails Application
68
+
69
+ A Ruby on Rails application loads all Active Support unless +config.active_support.bare+ is true. In that case, the application will only load what the framework itself cherry-picks for its own needs, and can still cherry-pick itself at any granularity level, as explained in the previous section.
70
+
9
71
  h3. Extensions to All Objects
10
72
 
11
73
  h4. +blank?+ and +present?+
@@ -138,16 +200,19 @@ end
138
200
 
139
201
  NOTE: Defined in +active_support/core_ext/object/try.rb+.
140
202
 
141
- h4. +metaclass+
203
+ h4. +singleton_class+
142
204
 
143
- The method +metaclass+ returns the singleton class on any object:
205
+ The method +singleton_class+ returns the singleton class of the receiver:
144
206
 
145
207
  <ruby>
146
- String.metaclass # => #<Class:String>
147
- String.new.metaclass # => #<Class:#<String:0x17a1d1c>>
208
+ String.singleton_class # => #<Class:String>
209
+ String.new.singleton_class # => #<Class:#<String:0x17a1d1c>>
148
210
  </ruby>
149
211
 
150
- NOTE: Defined in +active_support/core_ext/object/metaclass.rb+.
212
+ WARNING: Fixnums and symbols have no singleton classes, +singleton_class+
213
+ raises +TypeError+ on them.
214
+
215
+ NOTE: Defined in +active_support/core_ext/object/singleton_class.rb+.
151
216
 
152
217
  h4. +class_eval(*args, &block)+
153
218
 
@@ -168,7 +233,7 @@ class Proc
168
233
  end
169
234
  </ruby>
170
235
 
171
- NOTE: Defined in +active_support/core_ext/object/metaclass.rb+.
236
+ NOTE: Defined in +active_support/core_ext/object/singleton_class.rb+.
172
237
 
173
238
  h4. +acts_like?(duck)+
174
239
 
@@ -323,6 +388,40 @@ TIP: Since +with_options+ forwards calls to its receiver they can be nested. Eac
323
388
 
324
389
  NOTE: Defined in +active_support/core_ext/object/with_options.rb+.
325
390
 
391
+ h5. +subclasses_of+
392
+
393
+ The method +subclasses_of+ receives an arbitrary number of class objects and returns all their anonymous or reachable descendants as a single array:
394
+
395
+ <ruby>
396
+ class C; end
397
+ subclasses_of(C) # => []
398
+
399
+ subclasses_of(Integer) # => [Bignum, Fixnum]
400
+
401
+ module M
402
+ class A; end
403
+ class B1 < A; end
404
+ class B2 < A; end
405
+ end
406
+
407
+ module N
408
+ class C < M::B1; end
409
+ end
410
+
411
+ subclasses_of(M::A) # => [N::C, M::B2, M::B1]
412
+ </ruby>
413
+
414
+ The order in which these classes are returned is unspecified. The returned collection may have duplicates:
415
+
416
+ <ruby>
417
+ subclasses_of(Numeric, Integer)
418
+ # => [Bignum, Float, Fixnum, Integer, Date::Infinity, Rational, BigDecimal, Bignum, Fixnum]
419
+ </ruby>
420
+
421
+ See also +Class#subclasses+ in "Extensions to +Class+ FIX THIS LINK":FIXME.
422
+
423
+ NOTE: Defined in +active_support/core_ext/object/extending.rb+.
424
+
326
425
  h4. Instance Variables
327
426
 
328
427
  Active Support provides several methods to ease access to instance variables.
@@ -341,7 +440,7 @@ end
341
440
  C.new(0, 1).instance_variable_names # => ["@y", "@x"]
342
441
  </ruby>
343
442
 
344
- WARNING: The order in which the names are returned is unespecified, and it indeed depends on the version of the interpreter.
443
+ WARNING: The order in which the names are returned is unspecified, and it indeed depends on the version of the interpreter.
345
444
 
346
445
  NOTE: Defined in +active_support/core_ext/object/instance_variables.rb+.
347
446
 
@@ -422,11 +521,23 @@ end
422
521
 
423
522
  NOTE: Defined in +active_support/core_ext/kernel/reporting.rb+.
424
523
 
425
- h3. Extensions to +Module+
524
+ h4. +require_library_or_gem+
525
+
526
+ The convenience method +require_library_or_gem+ tries to load its argument with a regular +require+ first. If it fails loads +rubygems+ and tries again.
527
+
528
+ If the first attempt is a failure and +rubygems+ can't be loaded the method raises +LoadError+. On the other hand, if +rubygems+ is available but the argument is not loadable as a gem, the method gives up and +LoadError+ is also raised.
529
+
530
+ For example, that's the way the MySQL adapter loads the MySQL library:
531
+
532
+ <ruby>
533
+ require_library_or_gem('mysql')
534
+ </ruby>
535
+
536
+ NOTE: Defined in +active_support/core_ext/kernel/requires.rb+.
426
537
 
427
- h4. Aliasing
538
+ h3. Extensions to +Module+
428
539
 
429
- h5. +alias_method_chain+
540
+ h4. +alias_method_chain+
430
541
 
431
542
  Using plain Ruby you can wrap methods with other methods, that's called _alias chaining_.
432
543
 
@@ -450,53 +561,495 @@ That's the method +get+, +post+, etc., delegate the work to.
450
561
  That technique has a risk, it could be the case that +:original_process+ was taken. To try to avoid collisions people choose some label that characterizes what the chaining is about:
451
562
 
452
563
  <ruby>
453
- ActionController::TestCase.class_eval do
454
- def process_with_stringified_params(...)
455
- params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
456
- process_without_stringified_params(action, params, session, flash, http_method)
457
- end
458
- alias_method :process_without_stringified_params, :process
459
- alias_method :process, :process_with_stringified_params
564
+ ActionController::TestCase.class_eval do
565
+ def process_with_stringified_params(...)
566
+ params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
567
+ process_without_stringified_params(action, params, session, flash, http_method)
568
+ end
569
+ alias_method :process_without_stringified_params, :process
570
+ alias_method :process, :process_with_stringified_params
571
+ end
572
+ </ruby>
573
+
574
+ The method +alias_method_chain+ provides a shortcut for that pattern:
575
+
576
+ <ruby>
577
+ ActionController::TestCase.class_eval do
578
+ def process_with_stringified_params(...)
579
+ params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
580
+ process_without_stringified_params(action, params, session, flash, http_method)
581
+ end
582
+ alias_method_chain :process, :stringified_params
583
+ end
584
+ </ruby>
585
+
586
+ Rails uses +alias_method_chain+ all over the code base. For example validations are added to +ActiveRecord::Base#save+ by wrapping the method that way in a separate module specialised in validations.
587
+
588
+ NOTE: Defined in +active_support/core_ext/module/aliasing.rb+.
589
+
590
+ h4. Attributes
591
+
592
+ h5. +alias_attribute+
593
+
594
+ Model attributes have a reader, a writer, and a predicate. You can aliase a model attribute having the corresponding three methods defined for you in one shot. As in other aliasing methods, the new name is the first argument, and the old name is the second (my mnemonic is they go in the same order as if you did an assignment):
595
+
596
+ <ruby>
597
+ class User < ActiveRecord::Base
598
+ # let me refer to the email column as "login",
599
+ # much meaningful for authentication code
600
+ alias_attribute :login, :email
601
+ end
602
+ </ruby>
603
+
604
+ NOTE: Defined in +active_support/core_ext/module/aliasing.rb+.
605
+
606
+ h5. +attr_accessor_with_default+
607
+
608
+ The method +attr_accessor_with_default+ serves the same purpose as the Ruby macro +attr_accessor+ but allows you to set a default value for the attribute:
609
+
610
+ <ruby>
611
+ class Url
612
+ attr_accessor_with_default :port, 80
613
+ end
614
+
615
+ Url.new.port # => 80
616
+ </ruby>
617
+
618
+ The default value can be also specified with a block, which is called in the context of the corresponding object:
619
+
620
+ <ruby>
621
+ class User
622
+ attr_accessor :name, :surname
623
+ attr_accessor_with_default(:full_name) {
624
+ [name, surname].compact.join(" ")
625
+ }
626
+ end
627
+
628
+ u = User.new
629
+ u.name = 'Xavier'
630
+ u.surname = 'Noria'
631
+ u.full_name # => "Xavier Noria"
632
+ </ruby>
633
+
634
+ The result is not cached, the block is invoked in each call to the reader.
635
+
636
+ You can overwrite the default with the writer:
637
+
638
+ <ruby>
639
+ url = Url.new
640
+ url.host # => 80
641
+ url.host = 8080
642
+ url.host # => 8080
643
+ </ruby>
644
+
645
+ The default value is returned as long as the attribute is unset. The reader does not rely on the value of the attribute to know whether it has to return the default. It rather monitors the writer: if there's any assignment the value is no longer considered to be unset.
646
+
647
+ Active Resource uses this macro to set a default value for the +:primary_key+ attribute:
648
+
649
+ <ruby>
650
+ attr_accessor_with_default :primary_key, 'id'
651
+ </ruby>
652
+
653
+ NOTE: Defined in +active_support/core_ext/module/attr_accessor_with_default.rb+.
654
+
655
+ h5. Internal Attributes
656
+
657
+ When you are defining an attribute in a class that is meant to be subclassed name collisions are a risk. That's remarkably important for libraries.
658
+
659
+ Active Support defines the macros +attr_internal_reader+, +attr_internal_writer+, and +attr_internal_accessor+. They behave like their Ruby builtin +attr_*+ counterparts, except they name the unerlying instace variable in a way that makes collisions less likely.
660
+
661
+ The macro +attr_internal+ is a synonim for +attr_internal_accessor+:
662
+
663
+ <ruby>
664
+ # library
665
+ class ThirdPartyLibrary::Crawler
666
+ attr_internal :log_level
667
+ end
668
+
669
+ # client code
670
+ class MyCrawler < ThirdPartyLibrary::Crawler
671
+ attr_accessor :log_level
672
+ end
673
+ </ruby>
674
+
675
+ In the previous example it could be the case that +:log_level+ does not belong to the public interface of the library and it is only used for development. The client code, unaware of the potential conflict, subclasses and defines its own +:log_level+. Thanks to +attr_internal+ there's no collision.
676
+
677
+ By default the internal instance variable is named with a leading underscore, +@_log_level+ in the example above. That's configurable via +Module.attr_internal_naming_format+ though, you can pass any +sprintf+-like format string with a leading +@+ and a +%s+ somewhere, which is where the name will be placed. The default is +"@_%s"+.
678
+
679
+ Rails uses internal attributes in a few spots, for examples for views:
680
+
681
+ <ruby>
682
+ module ActionView
683
+ class Base
684
+ attr_internal :captures
685
+ attr_internal :request, :layout
686
+ attr_internal :controller, :template
687
+ end
688
+ end
689
+ </ruby>
690
+
691
+ NOTE: Defined in +active_support/core_ext/module/attr_internal.rb+.
692
+
693
+ h5. Module Attributes
694
+
695
+ The macros +mattr_reader+, +mattr_writer+, and +mattr_accessor+ are analogous to the +cattr_*+ macros defined for class. Check "Class Attributes":#class-attributes.
696
+
697
+ For example, the dependencies mechanism uses them:
698
+
699
+ <ruby>
700
+ module ActiveSupport
701
+ module Dependencies
702
+ mattr_accessor :warnings_on_first_load
703
+ mattr_accessor :history
704
+ mattr_accessor :loaded
705
+ mattr_accessor :mechanism
706
+ mattr_accessor :load_paths
707
+ mattr_accessor :load_once_paths
708
+ mattr_accessor :autoloaded_constants
709
+ mattr_accessor :explicitly_unloadable_constants
710
+ mattr_accessor :logger
711
+ mattr_accessor :log_activity
712
+ mattr_accessor :constant_watch_stack
713
+ mattr_accessor :constant_watch_stack_mutex
714
+ end
715
+ end
716
+ </ruby>
717
+
718
+ NOTE: Defined in +active_support/core_ext/module/attribute_accessors.rb+.
719
+
720
+ h4. Method Delegation
721
+
722
+ The class method +delegate+ offers an easy way to forward methods.
723
+
724
+ For example, if +User+ has some details like the age factored out to +Profile+, it could be handy to still be able to acces such attribute directly, <tt>user.age</tt>, instead of having to explicit the chain <tt>user.profile.age</tt>.
725
+
726
+ That can be accomplished by hand:
727
+
728
+ <ruby>
729
+ class User
730
+ has_one :profile
731
+
732
+ def age
733
+ profile.age
734
+ end
735
+ end
736
+ </ruby>
737
+
738
+ But with +delegate+ you can make that shorter and the intention even more obvious:
739
+
740
+ <ruby>
741
+ class User
742
+ has_one :profile
743
+
744
+ delegate :age, to => :profile
745
+ end
746
+ </ruby>
747
+
748
+ The macro accepts more than one method:
749
+
750
+ <ruby>
751
+ class User
752
+ has_one :profile
753
+
754
+ delegate :age, :avatar, :twitter_username, to => :profile
755
+ end
756
+ </ruby>
757
+
758
+ Methods can be delegated to objects returned by methods, as in the examples above, but also to instance variables, class variables, and constants. Just pass their names as symbols or strings, including the at signs in the last cases.
759
+
760
+ For example, +ActionView::Base+ delegates +erb_trim_mode=+:
761
+
762
+ <ruby>
763
+ module ActionView
764
+ class Base
765
+ delegate :erb_trim_mode=, :to => 'ActionView::Template::Handlers::ERB'
766
+ end
767
+ end
768
+ </ruby>
769
+
770
+ In fact, you can delegate to any expression passed as a string. It will be evaluated in the context of the receiver. Controllers for example delegate alerts and notices to the current flash:
771
+
772
+ <ruby>
773
+ delegate :alert, :notice, :to => "request.flash"
774
+ </ruby>
775
+
776
+ If the target is +nil+ calling any delegated method will raise an exception even if +nil+ responds to such method. You can override this behavior setting the option +:allow_nil+ to true, in which case the forwarded call will simply return +nil+.
777
+
778
+ If the target is a method, the name of delegated methods can also be prefixed. If the +:prefix+ option is set to (exactly) the +true+ object, the value of the +:to+ option is prefixed:
779
+
780
+ <ruby>
781
+ class Invoice
782
+ belongs_to :customer
783
+
784
+ # defines a method called customer_name
785
+ delegate :name, :to => :customer, :prefix => true
786
+ end
787
+ </ruby>
788
+
789
+ And a custom prefix can be set as well, in that case it does not matter wheter the target is a method or not:
790
+
791
+ <ruby>
792
+ class Account
793
+ belongs_to :user
794
+
795
+ # defines a method called admin_email
796
+ delegate :email, :to => :user, :prefix => 'admin'
797
+ end
798
+ </ruby>
799
+
800
+ NOTE: Defined in +active_support/core_ext/module/delegation.rb+.
801
+
802
+ h4. Method Removal
803
+
804
+ h5. +remove_possible_method+
805
+
806
+ The method +remove_possible_method+ is like the standard +remove_method+, except it silently returns on failure:
807
+
808
+ <ruby>
809
+ class A; end
810
+
811
+ A.class_eval do
812
+ remove_method(:nonexistent) # raises NameError
813
+ remove_possible_method(:nonexistent) # no problem, continue
814
+ end
815
+ </ruby>
816
+
817
+ This may come in handy if you need to define a method that may already exist, since redefining a method issues a warning "method redefined; discarding old redefined_method_name".
818
+
819
+ NOTE: Defined in +active_support/core_ext/module/remove_method.rb+.
820
+
821
+ h4. Parents
822
+
823
+ h5. +parent+
824
+
825
+ The +parent+ method on a nested named module returns the module that contains its corresponding constant:
826
+
827
+ <ruby>
828
+ module X
829
+ module Y
830
+ module Z
831
+ end
832
+ end
833
+ end
834
+ M = X::Y::Z
835
+
836
+ X::Y::Z.parent # => X::Y
837
+ M.parent # => X::Y
838
+ </ruby>
839
+
840
+ If the module is anonymous or belongs to the top-level, +parent+ returns +Object+.
841
+
842
+ WARNING: Note that in that case +parent_name+ returns +nil+.
843
+
844
+ NOTE: Defined in +active_support/core_ext/module/introspection.rb+.
845
+
846
+ h5. +parent_name+
847
+
848
+ The +parent_name+ method on a nested named module returns the fully-qualified name of the module that contains its corresponding constant:
849
+
850
+ <ruby>
851
+ module X
852
+ module Y
853
+ module Z
854
+ end
855
+ end
856
+ end
857
+ M = X::Y::Z
858
+
859
+ X::Y::Z.parent_name # => "X::Y"
860
+ M.parent_name # => "X::Y"
861
+ </ruby>
862
+
863
+ For top-level or anonymous modules +parent_name+ returns +nil+.
864
+
865
+ WARNING: Note that in that case +parent+ returns +Object+.
866
+
867
+ NOTE: Defined in +active_support/core_ext/module/introspection.rb+.
868
+
869
+ h5. +parents+
870
+
871
+ The method +parents+ calls +parent+ on the receiver and upwards until +Object+ is reached. The chain is returned in an array, from bottom to top:
872
+
873
+ <ruby>
874
+ module X
875
+ module Y
876
+ module Z
877
+ end
878
+ end
879
+ end
880
+ M = X::Y::Z
881
+
882
+ X::Y::Z.parents # => [X::Y, X, Object]
883
+ M.parents # => [X::Y, X, Object]
884
+ </ruby>
885
+
886
+ NOTE: Defined in +active_support/core_ext/module/introspection.rb+.
887
+
888
+ h4. Constants
889
+
890
+ The method +local_constants+ returns the names of the constants that have been defined in the receiver module:
891
+
892
+ <ruby>
893
+ module X
894
+ X1 = 1
895
+ X2 = 2
896
+ module Y
897
+ Y1 = :y1
898
+ X1 = :overrides_X1_above
899
+ end
900
+ end
901
+
902
+ X.local_constants # => ["X2", "X1", "Y"], assumes Ruby 1.8
903
+ X::Y.local_constants # => ["X1", "Y1"], assumes Ruby 1.8
904
+ </ruby>
905
+
906
+ The names are returned as strings in Ruby 1.8, and as symbols in Ruby 1.9. The method +local_constant_names+ returns always strings.
907
+
908
+ WARNING: This method is exact if running under Ruby 1.9. In previous versions it may miss some constants if their value in some ancestor stores the exact same object than in the receiver.
909
+
910
+ NOTE: Defined in +active_support/core_ext/module/introspection.rb+.
911
+
912
+ h4. Synchronization
913
+
914
+ The +synchronize+ macro declares a method to be synchronized:
915
+
916
+ <ruby>
917
+ class Counter
918
+ @@mutex = Mutex.new
919
+ attr_reader :value
920
+
921
+ def initialize
922
+ @value = 0
923
+ end
924
+
925
+ def incr
926
+ @value += 1 # non-atomic
927
+ end
928
+ synchronize :incr, :with => '@@mutex'
929
+ end
930
+ </ruby>
931
+
932
+ The method receives the name of an action, and a +:with+ option with code. The code is evaluated in the context of the receiver each time the method is invoked, and it should evaluate to a +Mutex+ instance or any other object that responds to +synchronize+ and accepts a block.
933
+
934
+ NOTE: Defined in +active_support/core_ext/module/synchronization.rb+.
935
+
936
+ h4. Reachable
937
+
938
+ A named module is reachable if it is stored in its correspoding constant. It means you can reach the module object via the constant.
939
+
940
+ That is what ordinarily happens, if a module is called "M", the +M+ constant exists and holds it:
941
+
942
+ <ruby>
943
+ module M
944
+ end
945
+
946
+ M.reachable? # => true
947
+ </ruby>
948
+
949
+ But since constants and modules are indeed kind of decoupled, module objects can become unreachable:
950
+
951
+ <ruby>
952
+ module M
953
+ end
954
+
955
+ orphan = Object.send(:remove_const, :M)
956
+
957
+ # The module object is orphan now but it still has a name.
958
+ orphan.name # => "M"
959
+
960
+ # You cannot reach it via the constant M because it does not even exist.
961
+ orphan.reachable? # => false
962
+
963
+ # Let's define a module called "M" again.
964
+ module M
965
+ end
966
+
967
+ # The constant M exists now again, and it stores a module
968
+ # object called "M", but it is a new instance.
969
+ orphan.reachable? # => false
970
+ </ruby>
971
+
972
+ NOTE: Defined in +active_support/core_ext/module/reachable.rb+.
973
+
974
+ h4. Anonymous
975
+
976
+ A module may or may not have a name:
977
+
978
+ <ruby>
979
+ module M
980
+ end
981
+ M.name # => "M"
982
+
983
+ N = Module.new
984
+ N.name # => "N"
985
+
986
+ Module.new.name # => "" in 1.8, nil in 1.9
987
+ </ruby>
988
+
989
+ You can check whether a module has a name with the predicate +anonymous?+:
990
+
991
+ <ruby>
992
+ module M
460
993
  end
994
+ M.anonymous? # => false
995
+
996
+ Module.new.anonymous? # => true
461
997
  </ruby>
462
998
 
463
- The method +alias_method_chain+ provides a shortcut for that pattern:
999
+ Note that being unreachable does not imply being anonymous:
464
1000
 
465
1001
  <ruby>
466
- ActionController::TestCase.class_eval do
467
- def process_with_stringified_params(...)
468
- params = Hash[*params.map {|k, v| [k, v.to_s]}.flatten]
469
- process_without_stringified_params(action, params, session, flash, http_method)
470
- end
471
- alias_method_chain :process, :stringified_params
1002
+ module M
472
1003
  end
1004
+
1005
+ m = Object.send(:remove_const, :M)
1006
+
1007
+ m.reachable? # => false
1008
+ m.anonymous? # => false
473
1009
  </ruby>
474
1010
 
475
- Rails uses +alias_method_chain+ all over the code base. For example validations are added to +ActiveRecord::Base#save+ by wrapping the method that way in a separate module specialised in validations.
1011
+ though an anonymous module is unreachable by definition.
476
1012
 
477
- NOTE: Defined in +active_support/core_ext/module/aliasing.rb+.
1013
+ NOTE: Defined in +active_support/core_ext/module/anonymous.rb+.
478
1014
 
479
- h5. +alias_attribute+
1015
+ h3. Extensions to +Class+
480
1016
 
481
- Model attributes have a reader, a writer, and a predicate. You can aliase a model attribute having the corresponding three methods defined for you in one shot. As in other aliasing methods, the new name is the first argument, and the old name is the second (my mnemonic is they go in the same order as if you did an assignment):
1017
+ h4. Class Attributes
1018
+
1019
+ The method +Class#class_attribute+ declares one or more inheritable class attributes that can be overriden at any level down the hierarchy:
482
1020
 
483
1021
  <ruby>
484
- class User < ActiveRecord::Base
485
- # let me refer to the email column as "login",
486
- # much meaningful for authentication code
487
- alias_attribute :login, :email
1022
+ class A
1023
+ class_attribute :x
488
1024
  end
489
- </ruby>
490
1025
 
491
- NOTE: Defined in +active_support/core_ext/module/aliasing.rb+.
1026
+ class B < A; end
492
1027
 
493
- h4. Delegation
1028
+ class C < B; end
494
1029
 
495
- The class method +delegate+
1030
+ A.x = :a
1031
+ B.x # => :a
1032
+ C.x # => :a
496
1033
 
497
- h3. Extensions to +Class+
1034
+ B.x = :b
1035
+ A.x # => :a
1036
+ C.x # => :b
498
1037
 
499
- h4. Class Attribute Accessors
1038
+ C.x = :c
1039
+ A.x # => :a
1040
+ B.x # => :b
1041
+ </ruby>
1042
+
1043
+ For example that's the way the +allow_forgery_protection+ flag is implemented for controllers:
1044
+
1045
+ <ruby>
1046
+ class_attribute :allow_forgery_protection
1047
+ self.allow_forgery_protection = true
1048
+ </ruby>
1049
+
1050
+ For convenience +class_attribute+ defines also a predicate, so that declaration also generates +allow_forgery_protection?+. Such predicate returns the double boolean negation of the value.
1051
+
1052
+ NOTE: Defined in +active_support/core_ext/class/attribute.rb+
500
1053
 
501
1054
  The macros +cattr_reader+, +cattr_writer+, and +cattr_accessor+ are analogous to their +attr_*+ counterparts but for classes. They initialize a class variable to +nil+ unless it already exists, and generate the corresponding class methods to access it:
502
1055
 
@@ -529,6 +1082,8 @@ module ActiveRecord
529
1082
  end
530
1083
  </ruby>
531
1084
 
1085
+ A model may find that option useful as a way to prevent mass-assignment from setting the attribute.
1086
+
532
1087
  NOTE: Defined in +active_support/core_ext/class/attribute_accessors.rb+.
533
1088
 
534
1089
  h4. Class Inheritable Attributes
@@ -587,9 +1142,11 @@ If for whatever reason an application loads the definition of a mailer class and
587
1142
 
588
1143
  NOTE: Defined in +active_support/core_ext/class/delegating_attributes.rb+.
589
1144
 
590
- h4. Subclasses
1145
+ h4. Descendants
591
1146
 
592
- The +subclasses+ method returns the names of all subclasses of a given class as an array of strings. That comprises not only direct subclasses, but all descendants down the hierarchy:
1147
+ h5. +subclasses+
1148
+
1149
+ The +subclasses+ method returns the names of all the anonymous or reachable descendants of its receiver as an array of strings:
593
1150
 
594
1151
  <ruby>
595
1152
  class C; end
@@ -614,56 +1171,76 @@ The order in which these class names are returned is unspecified.
614
1171
 
615
1172
  See also +Object#subclasses_of+ in "Extensions to All Objects FIX THIS LINK":FIXME.
616
1173
 
617
- NOTE: Defined in +active_support/core_ext/class/removal.rb+.
1174
+ WARNING: This method is redefined in some Rails core classes.
1175
+
1176
+ NOTE: Defined in +active_support/core_ext/class/subclasses.rb+.
1177
+
1178
+ h3. Extensions to +String+
1179
+
1180
+ h4. Output Safety
1181
+
1182
+ Inserting data into HTML templates needs extra care. For example you can't just interpolate +@review.title+ verbatim into an HTML page. On one hand if the review title is "Flanagan & Matz rules!" the output won't be well-formed because an ampersand has to be escaped as "&amp;amp;". On the other hand, depending on the application that may be a big security hole because users can inject malicious HTML setting a hand-crafted review title. Check out the "section about cross-site scripting in the Security guide":security.html#cross-site-scripting-xss for further information about the risks.
618
1183
 
619
- h4. Class Removal
1184
+ Active Support has the concept of <i>(html) safe</i> strings since Rails 3. A safe string is one that is marked as being insertable into HTML as is. It is trusted, no matter whether it has been escaped or not.
620
1185
 
621
- Roughly speaking, the +remove_class+ method removes the class objects passed as arguments:
1186
+ Strings are considered to be <i>unsafe</i> by default:
622
1187
 
623
1188
  <ruby>
624
- Class.remove_class(Hash, Dir) # => [Hash, Dir]
625
- Hash # => NameError: uninitialized constant Hash
626
- Dir # => NameError: uninitialized constant Dir
1189
+ "".html_safe? # => false
627
1190
  </ruby>
628
1191
 
629
- More specifically, +remove_class+ attempts to remove constants with the same name as the passed class objects from their parent modules. So technically this method does not guarantee the class objects themselves are not still valid and alive somewhere after the method call:
1192
+ You can obtain a safe string from a given one with the +html_safe+ method:
630
1193
 
631
1194
  <ruby>
632
- module M
633
- class A; end
634
- class B < A; end
635
- end
636
-
637
- A2 = M::A
1195
+ s = "".html_safe
1196
+ s.html_safe? # => true
1197
+ </ruby>
638
1198
 
639
- M::A.object_id # => 13053950
640
- Class.remove_class(M::A)
1199
+ It is important to understand that +html_safe+ performs no escaping whatsoever, it is just an assertion:
641
1200
 
642
- M::B.superclass.object_id # => 13053950 (same object as before)
643
- A2.name # => "M::A" (name is hard-coded in object)
1201
+ <ruby>
1202
+ s = "<script>...</script>".html_safe
1203
+ s.html_safe? # => true
1204
+ s # => "<script>...</script>"
644
1205
  </ruby>
645
1206
 
646
- WARNING: Removing fundamental classes like +String+ can result in really funky behaviour.
1207
+ It is your responsability to ensure calling +html_safe+ on a particular string is fine.
647
1208
 
648
- The method +remove_subclasses+ provides a shortcut for removing all descendants of a given class, where "removing" has the meaning explained above:
1209
+ NOTE: For performance reasons safe strings are implemented in a way that cannot offer an in-place +html_safe!+ variant.
1210
+
1211
+ If you append onto a safe string, either in-place with +concat+/<tt><<</tt>, or with <tt>+</tt>, the result is a safe string. Unsafe arguments are escaped:
649
1212
 
650
1213
  <ruby>
651
- class A; end
652
- class B1 < A; end
653
- class B2 < A; end
654
- class C < A; end
1214
+ "".html_safe + "<" # => "&lt;"
1215
+ </ruby>
1216
+
1217
+ Safe arguments are directly appended:
655
1218
 
656
- A.subclasses # => ["C", "B2", "B1"]
657
- A.remove_subclasses
658
- A.subclasses # => []
659
- C # => NameError: uninitialized constant C
1219
+ <ruby>
1220
+ "".html_safe + "<".html_safe # => "<"
660
1221
  </ruby>
661
1222
 
662
- See also +Object#remove_subclasses_of+ in "Extensions to All Objects FIX THIS LINK":FIXME.
1223
+ These methods should not be used in ordinary views. In Rails 3 unsafe values are automatically escaped:
663
1224
 
664
- NOTE: Defined in +active_support/core_ext/class/removal.rb+.
1225
+ <erb>
1226
+ <%= @review.title %> <%# fine in Rails 3, escaped if needed %>
1227
+ </erb>
665
1228
 
666
- h3. Extensions to +String+
1229
+ To insert something verbatim use the +raw+ helper rather than calling +html_safe+:
1230
+
1231
+ <erb>
1232
+ <%= raw @cms.current_template %> <%# inserts @cms.current_template as is %>
1233
+ </erb>
1234
+
1235
+ The +raw+ helper calls +html_safe+ for you:
1236
+
1237
+ <ruby>
1238
+ def raw(stringish)
1239
+ stringish.to_s.html_safe
1240
+ end
1241
+ </ruby>
1242
+
1243
+ NOTE: Defined in +active_support/core_ext/string/output_safety.rb+.
667
1244
 
668
1245
  h4. +squish+
669
1246
 
@@ -755,6 +1332,338 @@ The call +str.last(n)+ is equivalent to +str.from(-n)+ if +n+ > 0, and returns a
755
1332
 
756
1333
  NOTE: Defined in +active_support/core_ext/string/access.rb+.
757
1334
 
1335
+ h4. Inflections
1336
+
1337
+ h5. +pluralize+
1338
+
1339
+ The method +pluralize+ returns the plural of its receiver:
1340
+
1341
+ <ruby>
1342
+ "table".pluralize # => "tables"
1343
+ "ruby".pluralize # => "rubies"
1344
+ "equipment".pluralize # => "equipment"
1345
+ </ruby>
1346
+
1347
+ As the previous example shows, Active Support knows some irregular plurals and uncountable nouns. Builtin rules can be extended in +config/initializers/inflections.rb+. That file is generated by the +rails+ command and has instructions in comments.
1348
+
1349
+ Active Record uses this method to compute the default table name that corresponds to a model:
1350
+
1351
+ <ruby>
1352
+ # active_record/base.rb
1353
+ def undecorated_table_name(class_name = base_class.name)
1354
+ table_name = class_name.to_s.demodulize.underscore
1355
+ table_name = table_name.pluralize if pluralize_table_names
1356
+ table_name
1357
+ end
1358
+ </ruby>
1359
+
1360
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1361
+
1362
+ h5. +singularize+
1363
+
1364
+ The inverse of +pluralize+:
1365
+
1366
+ <ruby>
1367
+ "tables".singularize # => "table"
1368
+ "rubies".singularize # => "ruby"
1369
+ "equipment".singularize # => "equipment"
1370
+ </ruby>
1371
+
1372
+ Associations compute the name of the corresponding default associated class using this method:
1373
+
1374
+ <ruby>
1375
+ # active_record/reflection.rb
1376
+ def derive_class_name
1377
+ class_name = name.to_s.camelize
1378
+ class_name = class_name.singularize if collection?
1379
+ class_name
1380
+ end
1381
+ </ruby>
1382
+
1383
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1384
+
1385
+ h5. +camelize+
1386
+
1387
+ The method +camelize+ returns its receiver in camel case:
1388
+
1389
+ <ruby>
1390
+ "product".camelize # => "Product"
1391
+ "admin_user".camelize # => "AdminUser"
1392
+ </ruby>
1393
+
1394
+ As a rule of thumb you can think of this method as the one that transforms paths into Ruby class or module names, where slashes separate namespaces:
1395
+
1396
+ <ruby>
1397
+ "backoffice/session".camelize # => "Backoffice::Session"
1398
+ </ruby>
1399
+
1400
+ For example, Action Pack uses this method to load the class that provides a certain session store:
1401
+
1402
+ <ruby>
1403
+ # action_controller/metal/session_management.rb
1404
+ def session_store=(store)
1405
+ if store == :active_record_store
1406
+ self.session_store = ActiveRecord::SessionStore
1407
+ else
1408
+ @@session_store = store.is_a?(Symbol) ?
1409
+ ActionDispatch::Session.const_get(store.to_s.camelize) :
1410
+ store
1411
+ end
1412
+ end
1413
+ </ruby>
1414
+
1415
+ +camelize+ accepts an optional argument, it can be +:upper+ (default), or +:lower+. With the latter the first letter becomes lowercase:
1416
+
1417
+ <ruby>
1418
+ "visual_effect".camelize(:lower) # => "visualEffect"
1419
+ </ruby>
1420
+
1421
+ That may be handy to compute method names in a language that follows that convention, for example JavaScript.
1422
+
1423
+ +camelize+ is aliased to +camelcase+.
1424
+
1425
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1426
+
1427
+ h5. +underscore+
1428
+
1429
+ The method +underscore+ is the inverse of +camelize+, explained above:
1430
+
1431
+ <ruby>
1432
+ "Product".underscore # => "product"
1433
+ "AdminUser".underscore # => "admin_user"
1434
+ </ruby>
1435
+
1436
+ Also converts "::" back to "/":
1437
+
1438
+ <ruby>
1439
+ "Backoffice::Session".underscore # => "backoffice/session"
1440
+ </ruby>
1441
+
1442
+ and understands strings that start with lowercase:
1443
+
1444
+ <ruby>
1445
+ "visualEffect".underscore # => "visual_effect"
1446
+ </ruby>
1447
+
1448
+ +underscore+ accepts no argument though.
1449
+
1450
+ Rails class and module autoloading uses +underscore+ to infer the relative path without extension of a file that would define a given missing constant:
1451
+
1452
+ <ruby>
1453
+ # active_support/dependencies.rb
1454
+ def load_missing_constant(from_mod, const_name)
1455
+ ...
1456
+ qualified_name = qualified_name_for from_mod, const_name
1457
+ path_suffix = qualified_name.underscore
1458
+ ...
1459
+ end
1460
+ </ruby>
1461
+
1462
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1463
+
1464
+ h5. +titleize+
1465
+
1466
+ The method +titleize+ capitalizes the words in the receiver:
1467
+
1468
+ <ruby>
1469
+ "alice in wonderland".titleize # => "Alice In Wonderland"
1470
+ "fermat's enigma".titleize # => "Fermat's Enigma"
1471
+ </ruby>
1472
+
1473
+ +titleize+ is aliased to +titlecase+.
1474
+
1475
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1476
+
1477
+ h5. +dasherize+
1478
+
1479
+ The method +dasherize+ replaces the underscores in the receiver with dashes:
1480
+
1481
+ <ruby>
1482
+ "name".dasherize # => "name"
1483
+ "contact_data".dasherize # => "contact-data"
1484
+ </ruby>
1485
+
1486
+ The XML serializer of models uses this method to dasherize node names:
1487
+
1488
+ <ruby>
1489
+ # active_model/serializers/xml.rb
1490
+ def reformat_name(name)
1491
+ name = name.camelize if camelize?
1492
+ dasherize? ? name.dasherize : name
1493
+ end
1494
+ </ruby>
1495
+
1496
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1497
+
1498
+ h5. +demodulize+
1499
+
1500
+ Given a string with a qualified constant reference expression, +demodulize+ returns the very constant name, that is, the rightmost part of it:
1501
+
1502
+ <ruby>
1503
+ "Product".demodulize # => "Product"
1504
+ "Backoffice::UsersController".demodulize # => "UsersController"
1505
+ "Admin::Hotel::ReservationUtils".demodulize # => "ReservationUtils"
1506
+ </ruby>
1507
+
1508
+ Active Record for example uses this method to compute the name of a counter cache column:
1509
+
1510
+ <ruby>
1511
+ # active_record/reflection.rb
1512
+ def counter_cache_column
1513
+ if options[:counter_cache] == true
1514
+ "#{active_record.name.demodulize.underscore.pluralize}_count"
1515
+ elsif options[:counter_cache]
1516
+ options[:counter_cache]
1517
+ end
1518
+ end
1519
+ </ruby>
1520
+
1521
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1522
+
1523
+ h5. +parameterize+
1524
+
1525
+ The method +parameterize+ normalizes its receiver in a way that can be used in pretty URLs.
1526
+
1527
+ <ruby>
1528
+ "John Smith".parameterize # => "john-smith"
1529
+ "Kurt Gödel".parameterize # => "kurt-godel"
1530
+ </ruby>
1531
+
1532
+ In fact, the result string is wrapped in an instance of +ActiveSupport::Multibyte::Chars+.
1533
+
1534
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1535
+
1536
+ h5. +tableize+
1537
+
1538
+ The method +tableize+ is +underscore+ followed by +pluralize+.
1539
+
1540
+ <ruby>
1541
+ "Person".tableize # => "people"
1542
+ "Invoice".tableize # => "invoices"
1543
+ "InvoiceLine".tableize # => "invoice_lines"
1544
+ </ruby>
1545
+
1546
+ As a rule of thumb, +tableize+ returns the table name that corresponds to a given model for simple cases. The actual implementation in Active Record is not straight +tableize+ indeed, because it also demodulizes de class name and checks a few options that may affect the returned string.
1547
+
1548
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1549
+
1550
+ h5. +classify+
1551
+
1552
+ The method +classify+ is the inverse of +tableize+. It gives you the class name corresponding to a table name:
1553
+
1554
+ <ruby>
1555
+ "people".classify # => "Person"
1556
+ "invoices".classify # => "Invoice"
1557
+ "invoice_lines".classify # => "InvoiceLine"
1558
+ </ruby>
1559
+
1560
+ The method understands qualified table names:
1561
+
1562
+ <ruby>
1563
+ "highrise_production.companies".classify # => "Company"
1564
+ </ruby>
1565
+
1566
+ Note that +classify+ returns a class name as a string. You can get the actual class object invoking +constantize+ on it, explained next.
1567
+
1568
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1569
+
1570
+ h5. +constantize+
1571
+
1572
+ The method +constantize+ resolves the constant reference expression in its receiver:
1573
+
1574
+ <ruby>
1575
+ "Fixnum".constantize # => Fixnum
1576
+
1577
+ module M
1578
+ X = 1
1579
+ end
1580
+ "M::X".constantize # => 1
1581
+ </ruby>
1582
+
1583
+ If the string evaluates to no known constant, or its content is not even a valid constant name, +constantize+ raises +NameError+.
1584
+
1585
+ Constant name resolution by +constantize+ starts always at the top-level +Object+ even if there is no leading "::".
1586
+
1587
+ <ruby>
1588
+ X = :in_Object
1589
+ module M
1590
+ X = :in_M
1591
+
1592
+ X # => :in_M
1593
+ "::X".constantize # => :in_Object
1594
+ "X".constantize # => :in_Object (!)
1595
+ end
1596
+ </ruby>
1597
+
1598
+ So, it is in general not equivalent to what Ruby would do in the same spot, had a real constant be evaluated.
1599
+
1600
+ Mailer test cases obtain the mailer being tested from the name of the test class using +constantize+:
1601
+
1602
+ <ruby>
1603
+ # action_mailer/test_case.rb
1604
+ def determine_default_mailer(name)
1605
+ name.sub(/Test$/, '').constantize
1606
+ rescue NameError => e
1607
+ raise NonInferrableMailerError.new(name)
1608
+ end
1609
+ </ruby>
1610
+
1611
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1612
+
1613
+ h5. +humanize+
1614
+
1615
+ The method +humanize+ gives you a sensible name for display out of an attribute name. To do so it replaces underscores with spaces, removes any "_id" suffix, and capitalizes the first word:
1616
+
1617
+ <ruby>
1618
+ "name".humanize # => "Name"
1619
+ "author_id".humanize # => "Author"
1620
+ "comments_count".humanize # => "Comments count"
1621
+ </ruby>
1622
+
1623
+ The helper method +full_messages+ uses +humanize+ as a fallback to include attribute names:
1624
+
1625
+ <ruby>
1626
+ def full_messages
1627
+ full_messages = []
1628
+
1629
+ each do |attribute, messages|
1630
+ ...
1631
+ attr_name = attribute.to_s.gsub('.', '_').humanize
1632
+ attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
1633
+ ...
1634
+ end
1635
+
1636
+ full_messages
1637
+ end
1638
+ </ruby>
1639
+
1640
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1641
+
1642
+ h5. +foreign_key+
1643
+
1644
+ The method +foreign_key+ gives a foreign key column name from a class name. To do so it demodulizes, underscores, and adds "_id":
1645
+
1646
+ <ruby>
1647
+ "User".foreign_key # => "user_id"
1648
+ "InvoiceLine".foreign_key # => "invoice_line_id"
1649
+ "Admin::Session".foreign_key # => "session_id"
1650
+ </ruby>
1651
+
1652
+ Pass a false argument if you do not want the underscore in "_id":
1653
+
1654
+ <ruby>
1655
+ "User".foreign_key(false) # => "userid"
1656
+ </ruby>
1657
+
1658
+ Associations use this method to infer foreign keys, for example +has_one+ and +has_many+ do this:
1659
+
1660
+ <ruby>
1661
+ # active_record/associations.rb
1662
+ foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key
1663
+ </ruby>
1664
+
1665
+ NOTE: Defined in +active_support/core_ext/string/inflections.rb+.
1666
+
758
1667
  h3. Extensions to +Numeric+
759
1668
 
760
1669
  h4. Bytes
@@ -816,7 +1725,15 @@ NOTE: Defined in +active_support/core_ext/integer/inflections.rb+.
816
1725
 
817
1726
  h3. Extensions to +Float+
818
1727
 
819
- ...
1728
+ h4. +round+
1729
+
1730
+ The builtin method +Float#round+ rounds a float to the nearest integer. Active Support adds an optional parameter to let you specify a precision:
1731
+
1732
+ <ruby>
1733
+ Math::E.round(4) # => 2.7183
1734
+ </ruby>
1735
+
1736
+ NOTE: Defined in +active_support/core_ext/float/rounding.rb+.
820
1737
 
821
1738
  h3. Extensions to +BigDecimal+
822
1739
 
@@ -1765,7 +2682,7 @@ File.atomic_write(joined_asset_path) do |cache|
1765
2682
  end
1766
2683
  </ruby>
1767
2684
 
1768
- To accomplish this +atomic_write+ creates a temporary file. That's the file the code in the block actually writes to. On completion, the temporary file is renamed. If the target file exists +atomic_write+ overwrites it and keeps owners and permissions.
2685
+ To accomplish this +atomic_write+ creates a temporary file. That's the file the code in the block actually writes to. On completion, the temporary file is renamed, which is an atomic operation on POSIX systems. If the target file exists +atomic_write+ overwrites it and keeps owners and permissions.
1769
2686
 
1770
2687
  WARNING. Note you can't append with +atomic_write+.
1771
2688
 
@@ -1799,20 +2716,11 @@ NOTE: Defined in +active_support/core_ext/name_error.rb+.
1799
2716
 
1800
2717
  h3. Extensions to +LoadError+
1801
2718
 
1802
- Rails hijacks +LoadError.new+ to return a +MissingSourceFile+ exception:
2719
+ Active Support adds +is_missing?+ to +LoadError+, and also assigns that class to the constant +MissingSourceFile+ for backwards compatibility.
1803
2720
 
1804
- <shell>
1805
- $ ruby -e 'require "nonexistent"'
1806
- ...: no such file to load -- nonexistent (LoadError)
1807
- ...
1808
- $ script/runner 'require "nonexistent"'
1809
- ...: no such file to load -- nonexistent (MissingSourceFile)
1810
- ...
1811
- </shell>
2721
+ Given a path name +is_missing?+ tests whether the exception was raised due to that particular file (except perhaps for the ".rb" extension).
1812
2722
 
1813
- The class +MissingSourceFile+ is a subclass of +LoadError+, so any code that rescues +LoadError+ as usual still works as expected. Point is these exception objects respond to +is_missing?+, which given a path name tests whether the exception was raised due to that particular file (except perhaps for the ".rb" extension).
1814
-
1815
- For example, when an action of +PostsController+ is called Rails tries to load +posts_helper.rb+, but that file may not exist. That's fine, the helper module is not mandatory so Rails silences a load error. But it could be the case that the helper module does exist, but it in turn requires another library that is missing. In that case Rails must reraise the exception. The method +is_missing?+ provides a way to distinguish both cases:
2723
+ For example, when an action of +PostsController+ is called Rails tries to load +posts_helper.rb+, but that file may not exist. That's fine, the helper module is not mandatory so Rails silences a load error. But it could be the case that the helper module does exist and in turn requires another library that is missing. In that case Rails must reraise the exception. The method +is_missing?+ provides a way to distinguish both cases:
1816
2724
 
1817
2725
  <ruby>
1818
2726
  def default_helper_module!
@@ -1820,7 +2728,7 @@ def default_helper_module!
1820
2728
  module_path = module_name.underscore
1821
2729
  helper module_path
1822
2730
  rescue MissingSourceFile => e
1823
- raise e unless e.is_missing? "#{module_path}_helper"
2731
+ raise e unless e.is_missing? "helpers/#{module_path}_helper"
1824
2732
  rescue NameError => e
1825
2733
  raise e unless e.missing_name? "#{module_name}Helper"
1826
2734
  end