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
@@ -625,9 +625,9 @@ class ClientsController < ApplicationController
625
625
  # returns it. The user will get the PDF as a file download.
626
626
  def download_pdf
627
627
  client = Client.find(params[:id])
628
- send_data(generate_pdf,
628
+ send_data generate_pdf(client),
629
629
  :filename => "#{client.name}.pdf",
630
- :type => "application/pdf")
630
+ :type => "application/pdf"
631
631
  end
632
632
 
633
633
  private
@@ -4,7 +4,7 @@ This guide should provide you with all you need to get started in sending and re
4
4
 
5
5
  endprologue.
6
6
 
7
- WARNING. This Guide is based on Rails 3.0. Some of the code shown here will not work in other versions of Rails.
7
+ WARNING. This Guide is based on Rails 3.0. Some of the code shown here will not work in earlier versions of Rails.
8
8
 
9
9
  h3. Introduction
10
10
 
@@ -19,7 +19,7 @@ h4. Walkthrough to Generating a Mailer
19
19
  h5. Create the Mailer
20
20
 
21
21
  <shell>
22
- ./script/generate mailer UserMailer
22
+ rails generate mailer UserMailer
23
23
  create app/mailers/user_mailer.rb
24
24
  invoke erb
25
25
  create app/views/user_mailer
@@ -111,7 +111,7 @@ Let's see how we would go about wiring it up using an observer.
111
111
  First off, we need to create a simple +User+ scaffold:
112
112
 
113
113
  <shell>
114
- $ script/generate scaffold user name:string email:string login:string
114
+ $ rails generate scaffold user name:string email:string login:string
115
115
  $ rake db:migrate
116
116
  </shell>
117
117
 
@@ -333,7 +333,7 @@ Receiving and parsing emails with Action Mailer can be a rather complex endeavou
333
333
 
334
334
  * Implement a +receive+ method in your mailer.
335
335
 
336
- * Configure your email server to forward emails from the address(es) you would like your app to receive to +/path/to/app/script/runner 'UserMailer.receive(STDIN.read)'+.
336
+ * Configure your email server to forward emails from the address(es) you would like your app to receive to +/path/to/app/script/rails runner 'UserMailer.receive(STDIN.read)'+.
337
337
 
338
338
  Once a method called +receive+ is defined in any mailer, Action Mailer will parse the raw incoming email into an email object, decode it, instantiate a new mailer, and pass the email object to the mailer +receive+ instance method. Here's an example:
339
339
 
@@ -33,13 +33,13 @@ gem install actionpack
33
33
  gem install rack
34
34
  </shell>
35
35
 
36
- Now we'll create a simple "Hello World" application that uses the +titleize+ method provided by Action View.
36
+ Now we'll create a simple "Hello World" application that uses the +titleize+ method provided by Active Support.
37
37
 
38
38
  *hello_world.rb:*
39
39
 
40
40
  <ruby>
41
41
  require 'rubygems'
42
- require 'action_view'
42
+ require 'active_support/core_ext/string/inflections'
43
43
  require 'rack'
44
44
 
45
45
  def hello_world(env)
@@ -11,6 +11,8 @@ This guide covers different ways to retrieve data from the database using Active
11
11
 
12
12
  endprologue.
13
13
 
14
+ WARNING. This Guide is based on Rails 3.0. Some of the code shown here will not work in other versions of Rails.
15
+
14
16
  If you're used to using raw SQL to find database records then, generally, you will find that there are better ways to carry out the same operations in Rails. Active Record insulates you from the need to use SQL in most cases.
15
17
 
16
18
  Code examples throughout this guide will refer to one or more of the following models:
@@ -49,7 +51,22 @@ Active Record will perform queries on the database for you and is compatible wit
49
51
 
50
52
  h3. Retrieving Objects from the Database
51
53
 
52
- To retrieve objects from the database, Active Record provides a class method called +Model.find+. This method allows you to pass arguments into it to perform certain queries on your database without the need of writing raw SQL.
54
+ To retrieve objects from the database, Active Record provides several finder methods. These methods allows you to pass arguments into it to perform certain queries on your database without the need of writing raw SQL.
55
+
56
+ The methods are:
57
+ * +where+
58
+ * +select+
59
+ * +group+
60
+ * +order+
61
+ * +limit+
62
+ * +offset+
63
+ * +joins+
64
+ * +includes+
65
+ * +lock+
66
+ * +readonly+
67
+ * +from+
68
+
69
+ All of these methods return a Relation
53
70
 
54
71
  Primary operation of <tt>Model.find(options)</tt> can be summarized as:
55
72
 
@@ -64,7 +81,7 @@ Active Record lets you retrieve a single object using three different ways.
64
81
 
65
82
  h5. Using a Primary Key
66
83
 
67
- Using <tt>Model.find(primary_key, options = nil)</tt>, you can retrieve the object corresponding to the supplied _primary key_ and matching the supplied options (if any). For example:
84
+ Using <tt>Model.find(primary_key)</tt>, you can retrieve the object corresponding to the supplied _primary key_ and matching the supplied options (if any). For example:
68
85
 
69
86
  <ruby>
70
87
  # Find the client with primary key (id) 10.
@@ -82,7 +99,7 @@ SELECT * FROM clients WHERE (clients.id = 10)
82
99
 
83
100
  h5. +first+
84
101
 
85
- <tt>Model.first(options = nil)</tt> finds the first record matched by the supplied options. If no +options+ are supplied, the first matching record is returned. For example:
102
+ <tt>Model.first</tt> finds the first record matched by the supplied options. For example:
86
103
 
87
104
  <ruby>
88
105
  client = Client.first
@@ -97,11 +114,9 @@ SELECT * FROM clients LIMIT 1
97
114
 
98
115
  <tt>Model.first</tt> returns +nil+ if no matching record is found. No exception will be raised.
99
116
 
100
- NOTE: +Model.find(:first, options)+ is equivalent to +Model.first(options)+
101
-
102
117
  h5. +last+
103
118
 
104
- <tt>Model.last(options = nil)</tt> finds the last record matched by the supplied options. If no +options+ are supplied, the last matching record is returned. For example:
119
+ <tt>Model.last</tt> finds the last record matched by the supplied options. For example:
105
120
 
106
121
  <ruby>
107
122
  client = Client.last
@@ -116,13 +131,11 @@ SELECT * FROM clients ORDER BY clients.id DESC LIMIT 1
116
131
 
117
132
  <tt>Model.last</tt> returns +nil+ if no matching record is found. No exception will be raised.
118
133
 
119
- NOTE: +Model.find(:last, options)+ is equivalent to +Model.last(options)+
120
-
121
134
  h4. Retrieving Multiple Objects
122
135
 
123
136
  h5. Using Multiple Primary Keys
124
137
 
125
- <tt>Model.find(array_of_primary_key, options = nil)</tt> also accepts an array of _primary keys_. An array of all the matching records for the supplied _primary keys_ is returned. For example:
138
+ <tt>Model.find(array_of_primary_key)</tt> also accepts an array of _primary keys_. An array of all the matching records for the supplied _primary keys_ is returned. For example:
126
139
 
127
140
  <ruby>
128
141
  # Find the clients with primary keys 1 and 10.
@@ -138,26 +151,6 @@ SELECT * FROM clients WHERE (clients.id IN (1,10))
138
151
 
139
152
  <tt>Model.find(array_of_primary_key)</tt> will raise an +ActiveRecord::RecordNotFound+ exception unless a matching record is found for <strong>all</strong> of the supplied primary keys.
140
153
 
141
- h5. Find all
142
-
143
- <tt>Model.all(options = nil)</tt> finds all the records matching the supplied +options+. If no +options+ are supplied, all rows from the database are returned.
144
-
145
- <ruby>
146
- # Find all the clients.
147
- clients = Client.all
148
- => [#<Client id: 1, name: => "Lifo">, #<Client id: 10, name: => "Ryan">, #<Client id: 221, name: => "Russel">]
149
- </ruby>
150
-
151
- And the equivalent SQL is:
152
-
153
- <sql>
154
- SELECT * FROM clients
155
- </sql>
156
-
157
- <tt>Model.all</tt> returns an empty array +[]+ if no matching record is found. No exception will be raised.
158
-
159
- NOTE: +Model.find(:all, options)+ is equivalent to +Model.all(options)+
160
-
161
154
  h4. Retrieving Multiple Objects in Batches
162
155
 
163
156
  Sometimes you need to iterate over a large set of records. For example to send a newsletter to all users, to export some data, etc.
@@ -166,14 +159,14 @@ The following may seem very straight forward at first:
166
159
 
167
160
  <ruby>
168
161
  # Very inefficient when users table has thousands of rows.
169
- User.all.each do |user|
162
+ User.each do |user|
170
163
  NewsLetter.weekly_deliver(user)
171
164
  end
172
165
  </ruby>
173
166
 
174
167
  But if the total number of rows in the table is very large, the above approach may vary from being under performant to just plain impossible.
175
168
 
176
- This is because +User.all+ makes Active Record fetch _the entire table_, build a model object per row, and keep the entire array in the memory. Sometimes that is just too many objects and demands too much memory.
169
+ This is because +User.each+ makes Active Record fetch _the entire table_, build a model object per row, and keep the entire array in the memory. Sometimes that is just too many objects and demands too much memory.
177
170
 
178
171
  h5. +find_each+
179
172
 
@@ -232,16 +225,16 @@ The +find+ method allows you to specify conditions to limit the records returned
232
225
 
233
226
  h4. Pure String Conditions
234
227
 
235
- If you'd like to add conditions to your find, you could just specify them in there, just like +Client.first(:conditions => "orders_count = '2'")+. This will find all clients where the +orders_count+ field's value is 2.
228
+ If you'd like to add conditions to your find, you could just specify them in there, just like +Client.where("orders_count = '2'")+. This will find all clients where the +orders_count+ field's value is 2.
236
229
 
237
- WARNING: Building your own conditions as pure strings can leave you vulnerable to SQL injection exploits. For example, +Client.first(:conditions => "name LIKE '%#{params[:name]}%'")+ is not safe. See the next section for the preferred way to handle conditions using an array.
230
+ WARNING: Building your own conditions as pure strings can leave you vulnerable to SQL injection exploits. For example, +Client.where("name LIKE '%#{params[:name]}%'")+ is not safe. See the next section for the preferred way to handle conditions using an array.
238
231
 
239
232
  h4. Array Conditions
240
233
 
241
234
  Now what if that number could vary, say as an argument from somewhere, or perhaps from the user's level status somewhere? The find then becomes something like:
242
235
 
243
236
  <ruby>
244
- Client.first(:conditions => ["orders_count = ?", params[:orders]])
237
+ Client.where(["orders_count = ?", params[:orders]])
245
238
  </ruby>
246
239
 
247
240
  Active Record will go through the first element in the conditions value and any additional elements will replace the question marks +(?)+ in the first element.
@@ -249,7 +242,7 @@ Active Record will go through the first element in the conditions value and any
249
242
  Or if you want to specify two conditions, you can do it like:
250
243
 
251
244
  <ruby>
252
- Client.first(:conditions => ["orders_count = ? AND locked = ?", params[:orders], false])
245
+ Client.where(["orders_count = ? AND locked = ?", params[:orders], false])
253
246
  </ruby>
254
247
 
255
248
  In this example, the first question mark will be replaced with the value in +params[:orders]+ and the second will be replaced with the SQL representation of +false+, which depends on the adapter.
@@ -257,13 +250,13 @@ In this example, the first question mark will be replaced with the value in +par
257
250
  The reason for doing code like:
258
251
 
259
252
  <ruby>
260
- Client.first(:conditions => ["orders_count = ?", params[:orders]])
253
+ Client.where(["orders_count = ?", params[:orders]])
261
254
  </ruby>
262
255
 
263
256
  instead of:
264
257
 
265
258
  <ruby>
266
- Client.first(:conditions => "orders_count = #{params[:orders]}")
259
+ Client.where("orders_count = #{params[:orders]}")
267
260
  </ruby>
268
261
 
269
262
  is because of argument safety. Putting the variable directly into the conditions string will pass the variable to the database *as-is*. This means that it will be an unescaped variable directly from a user who may have malicious intent. If you do this, you put your entire database at risk because once a user finds out he or she can exploit your database they can do just about anything to it. Never ever put your arguments directly inside the conditions string.
@@ -275,7 +268,7 @@ h5. Placeholder Conditions
275
268
  Similar to the +(?)+ replacement style of params, you can also specify keys/values hash in your array conditions:
276
269
 
277
270
  <ruby>
278
- Client.all(:conditions =>
271
+ Client.where(
279
272
  ["created_at >= :start_date AND created_at <= :end_date", { :start_date => params[:start_date], :end_date => params[:end_date] }])
280
273
  </ruby>
281
274
 
@@ -286,7 +279,7 @@ h5. Range Conditions
286
279
  If you're looking for a range inside of a table (for example, users created in a certain timeframe) you can use the conditions option coupled with the +IN+ SQL statement for this. If you had two dates coming in from a controller you could do something like this to look for a range:
287
280
 
288
281
  <ruby>
289
- Client.all(:conditions => ["created_at IN (?)",
282
+ Client.where(["created_at IN (?)",
290
283
  (params[:start_date].to_date)..(params[:end_date].to_date)])
291
284
  </ruby>
292
285
 
@@ -308,7 +301,7 @@ h5. Time and Date Conditions
308
301
  Things can get *really* messy if you pass in Time objects as it will attempt to compare your field to *every second* in that range:
309
302
 
310
303
  <ruby>
311
- Client.all(:conditions => ["created_at IN (?)",
304
+ Client.where(["created_at IN (?)",
312
305
  (params[:start_date].to_date.to_time)..(params[:end_date].to_date.to_time)])
313
306
  </ruby>
314
307
 
@@ -329,14 +322,14 @@ Where _query_ is the actual query used to get that error.
329
322
  In this example it would be better to use greater-than and less-than operators in SQL, like so:
330
323
 
331
324
  <ruby>
332
- Client.all(:conditions =>
325
+ Client.where(
333
326
  ["created_at > ? AND created_at < ?", params[:start_date], params[:end_date]])
334
327
  </ruby>
335
328
 
336
329
  You can also use the greater-than-or-equal-to and less-than-or-equal-to like this:
337
330
 
338
331
  <ruby>
339
- Client.all(:conditions =>
332
+ Client.where(
340
333
  ["created_at >= ? AND created_at <= ?", params[:start_date], params[:end_date]])
341
334
  </ruby>
342
335
 
@@ -351,13 +344,13 @@ NOTE: Only equality, range and subset checking are possible with Hash conditions
351
344
  h5. Equality Conditions
352
345
 
353
346
  <ruby>
354
- Client.all(:conditions => { :locked => true })
347
+ Client.where({ :locked => true })
355
348
  </ruby>
356
349
 
357
350
  The field name does not have to be a symbol it can also be a string:
358
351
 
359
352
  <ruby>
360
- Client.all(:conditions => { 'locked' => true })
353
+ Client.where({ 'locked' => true })
361
354
  </ruby>
362
355
 
363
356
  h5. Range Conditions
@@ -365,7 +358,7 @@ h5. Range Conditions
365
358
  The good thing about this is that we can pass in a range for our fields without it generating a large query as shown in the preamble of this section.
366
359
 
367
360
  <ruby>
368
- Client.all(:conditions => { :created_at => (Time.now.midnight - 1.day)..Time.now.midnight})
361
+ Client.where({ :created_at => (Time.now.midnight - 1.day)..Time.now.midnight})
369
362
  </ruby>
370
363
 
371
364
  This will find all clients created yesterday by using a +BETWEEN+ SQL statement:
@@ -381,7 +374,7 @@ h5. Subset Conditions
381
374
  If you want to find records using the +IN+ expression you can pass an array to the conditions hash:
382
375
 
383
376
  <ruby>
384
- Client.all(:conditions => { :orders_count => [1,3,5] })
377
+ Client.where({ :orders_count => [1,3,5] })
385
378
  </ruby>
386
379
 
387
380
  This code will generate SQL like this:
@@ -390,22 +383,6 @@ This code will generate SQL like this:
390
383
  SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
391
384
  </sql>
392
385
 
393
- h3. Find Options
394
-
395
- Apart from +:conditions+, +Model.find+ takes a variety of other options via the options hash for customizing the resulting record set.
396
-
397
- <ruby>
398
- Model.find(id_or_array_of_ids, options_hash)
399
- Model.find(:last, options_hash)
400
- Model.find(:first, options_hash)
401
-
402
- Model.first(options_hash)
403
- Model.last(options_hash)
404
- Model.all(options_hash)
405
- </ruby>
406
-
407
- The following sections give a top level overview of all the possible keys for the +options_hash+.
408
-
409
386
  h4. Ordering
410
387
 
411
388
  To retrieve records from the database in a specific order, you can specify the +:order+ option to the +find+ call.
@@ -413,37 +390,37 @@ To retrieve records from the database in a specific order, you can specify the +
413
390
  For example, if you're getting a set of records and want to order them in ascending order by the +created_at+ field in your table:
414
391
 
415
392
  <ruby>
416
- Client.all(:order => "created_at")
393
+ Client.order("created_at")
417
394
  </ruby>
418
395
 
419
396
  You could specify +ASC+ or +DESC+ as well:
420
397
 
421
398
  <ruby>
422
- Client.all(:order => "created_at DESC")
399
+ Client.order("created_at DESC")
423
400
  # OR
424
- Client.all(:order => "created_at ASC")
401
+ Client.order("created_at ASC")
425
402
  </ruby>
426
403
 
427
404
  Or ordering by multiple fields:
428
405
 
429
406
  <ruby>
430
- Client.all(:order => "orders_count ASC, created_at DESC")
407
+ Client.order("orders_count ASC, created_at DESC")
431
408
  </ruby>
432
409
 
433
410
  h4. Selecting Specific Fields
434
411
 
435
412
  By default, <tt>Model.find</tt> selects all the fields from the result set using +select *+.
436
413
 
437
- To select only a subset of fields from the result set, you can specify the subset via +:select+ option on the +find+.
414
+ To select only a subset of fields from the result set, you can specify the subset via the +select+ method.
438
415
 
439
- NOTE: If the +:select+ option is used, all the returning objects will be "read only":#readonly-objects.
416
+ NOTE: If the +select+ method is used, all the returning objects will be "read only":#readonly-objects.
440
417
 
441
418
  <br />
442
419
 
443
420
  For example, to select only +viewable_by+ and +locked+ columns:
444
421
 
445
422
  <ruby>
446
- Client.all(:select => "viewable_by, locked")
423
+ Client.select("viewable_by, locked")
447
424
  </ruby>
448
425
 
449
426
  The SQL query used by this find call will be somewhat like:
@@ -463,17 +440,17 @@ Where +&lt;attribute&gt;+ is the attribute you asked for. The +id+ method will n
463
440
  You can also call SQL functions within the select option. For example, if you would like to only grab a single record per unique value in a certain field by using the +DISTINCT+ function you can do it like this:
464
441
 
465
442
  <ruby>
466
- Client.all(:select => "DISTINCT(name)")
443
+ Client.select("DISTINCT(name)")
467
444
  </ruby>
468
445
 
469
446
  h4. Limit and Offset
470
447
 
471
- To apply +LIMIT+ to the SQL fired by the +Model.find+, you can specify the +LIMIT+ using +:limit+ and +:offset+ options on the find.
448
+ To apply +LIMIT+ to the SQL fired by the +Model.find+, you can specify the +LIMIT+ using +limit+ and +offset+ methods on the relation.
472
449
 
473
- If you want to limit the amount of records to a certain subset of all the records retrieved you usually use +:limit+ for this, sometimes coupled with +:offset+. Limit is the maximum number of records that will be retrieved from a query, and offset is the number of records it will start reading from from the first record of the set. For example:
450
+ If you want to limit the amount of records to a certain subset of all the records retrieved you usually use +limit+ for this, sometimes coupled with +offset+. Limit is the maximum number of records that will be retrieved from a query, and offset is the number of records it will start reading from from the first record of the set. For example:
474
451
 
475
452
  <ruby>
476
- Client.all(:limit => 5)
453
+ Client.limit(5)
477
454
  </ruby>
478
455
 
479
456
  This code will return a maximum of 5 clients and because it specifies no offset it will return the first 5 clients in the table. The SQL it executes will look like this:
@@ -482,10 +459,10 @@ This code will return a maximum of 5 clients and because it specifies no offset
482
459
  SELECT * FROM clients LIMIT 5
483
460
  </sql>
484
461
 
485
- Or specifying both +:limit+ and +:offset+:
462
+ Or chaining both +limit+ and +offset+:
486
463
 
487
464
  <ruby>
488
- Client.all(:limit => 5, :offset => 5)
465
+ Client.limit(5).offset(5)
489
466
  </ruby>
490
467
 
491
468
  This code will return a maximum of 5 clients and because it specifies an offset this time, it will return these records starting from the 5th client in the clients table. The SQL looks like:
@@ -496,12 +473,12 @@ SELECT * FROM clients LIMIT 5, 5
496
473
 
497
474
  h4. Group
498
475
 
499
- To apply +GROUP BY+ clause to the SQL fired by the +Model.find+, you can specify the +:group+ option on the find.
476
+ To apply +GROUP BY+ clause to the SQL fired by the finder, you can specify the +group+ method on the find.
500
477
 
501
478
  For example, if you want to find a collection of the dates orders were created on:
502
479
 
503
480
  <ruby>
504
- Order.all(:group => "date(created_at)", :order => "created_at")
481
+ Order.group("date(created_at)").order("created_at")
505
482
  </ruby>
506
483
 
507
484
  And this will give you a single +Order+ object for each date where there are orders in the database.
@@ -519,7 +496,7 @@ SQL uses +HAVING+ clause to specify conditions on the +GROUP BY+ fields. You can
519
496
  For example:
520
497
 
521
498
  <ruby>
522
- Order.all(:group => "date(created_at)", :having => ["created_at > ?", 1.month.ago])
499
+ Order.group("date(created_at)".having(["created_at > ?", 1.month.ago])
523
500
  </ruby>
524
501
 
525
502
  The SQL that would be executed would be something like this:
@@ -532,18 +509,18 @@ This will return single order objects for each day, but only for the last month.
532
509
 
533
510
  h4. Readonly Objects
534
511
 
535
- To explicitly disallow modification/destruction of the matching records returned by +Model.find+, you could specify the +:readonly+ option as +true+ to the find call.
512
+ To explicitly disallow modification/destruction of the matching records returned in a Relation object, you could chain the +readonly+ method as +true+ to the find call.
536
513
 
537
514
  Any attempt to alter or destroy the readonly records will not succeed, raising an +ActiveRecord::ReadOnlyRecord+ exception. To set this option, specify it like this:
538
515
 
539
516
  <ruby>
540
- Client.first(:readonly => true)
517
+ Client.first.readonly(true)
541
518
  </ruby>
542
519
 
543
520
  If you assign this record to a variable client, calling the following code will raise an +ActiveRecord::ReadOnlyRecord+ exception:
544
521
 
545
522
  <ruby>
546
- client = Client.first(:readonly => true)
523
+ client = Client.first.readonly(true)
547
524
  client.locked = false
548
525
  client.save
549
526
  </ruby>
@@ -676,7 +653,7 @@ Now all of the following will produce the expected join queries using +INNER JOI
676
653
  h5. Joining a Single Association
677
654
 
678
655
  <ruby>
679
- Category.all :joins => :posts
656
+ Category.joins(:posts)
680
657
  </ruby>
681
658
 
682
659
  This produces:
@@ -689,7 +666,7 @@ SELECT categories.* FROM categories
689
666
  h5. Joining Multiple Associations
690
667
 
691
668
  <ruby>
692
- Post.all :joins => [:category, :comments]
669
+ Post.joins(:category, :comments)
693
670
  </ruby>
694
671
 
695
672
  This produces:
@@ -703,13 +680,13 @@ SELECT posts.* FROM posts
703
680
  h5. Joining Nested Associations (Single Level)
704
681
 
705
682
  <ruby>
706
- Post.all :joins => {:comments => :guest}
683
+ Post.joins(:comments => :guest)
707
684
  </ruby>
708
685
 
709
686
  h5. Joining Nested Associations (Multiple Level)
710
687
 
711
688
  <ruby>
712
- Category.all :joins => {:posts => [{:comments => :guest}, :tags]}
689
+ Category.joins(:posts => [{:comments => :guest}, :tags])
713
690
  </ruby>
714
691
 
715
692
  h4. Specifying Conditions on the Joined Tables
@@ -718,14 +695,14 @@ You can specify conditions on the joined tables using the regular "Array":#array
718
695
 
719
696
  <ruby>
720
697
  time_range = (Time.now.midnight - 1.day)..Time.now.midnight
721
- Client.all :joins => :orders, :conditions => {'orders.created_at' => time_range}
698
+ Client.joins(:orders).where('orders.created_at' => time_range)
722
699
  </ruby>
723
700
 
724
701
  An alternative and cleaner syntax to this is to nest the hash conditions:
725
702
 
726
703
  <ruby>
727
704
  time_range = (Time.now.midnight - 1.day)..Time.now.midnight
728
- Client.all :joins => :orders, :conditions => {:orders => {:created_at => time_range}}
705
+ Client.joins(:orders).where(:orders => {:created_at => time_range})
729
706
  </ruby>
730
707
 
731
708
  This will find all clients who have orders that were created yesterday, again using a +BETWEEN+ SQL expression.
@@ -750,12 +727,12 @@ This code looks fine at the first sight. But the problem lies within the total n
750
727
 
751
728
  <strong>Solution to N <plus> 1 queries problem</strong>
752
729
 
753
- Active Record lets you specify all the associations in advanced that are going to be loaded. This is possible by specifying the +:include+ option of the +Model.find+ call. By +:include+, Active Record ensures that all the specified associations are loaded using minimum possible number of queries.
730
+ Active Record lets you specify all the associations in advanced that are going to be loaded. This is possible by specifying the +includes+ method of the +Model.find+ call. With +includes+, Active Record ensures that all the specified associations are loaded using minimum possible number of queries.
754
731
 
755
732
  Revisiting the above case, we could rewrite +Client.all+ to use eager load addresses:
756
733
 
757
734
  <ruby>
758
- clients = Client.all(:include => :address, :limit => 10)
735
+ clients = Client.includes(:address).limit(10)
759
736
 
760
737
  clients.each do |client|
761
738
  puts client.address.postcode
@@ -772,12 +749,12 @@ SELECT addresses.* FROM addresses
772
749
 
773
750
  h4. Eager Loading Multiple Associations
774
751
 
775
- Active Record lets you eager load any possible number of associations with a single +Model.find+ call by using an array, hash, or a nested hash of array/hash with the +:include+ option.
752
+ Active Record lets you eager load any possible number of associations with a single +Model.find+ call by using an array, hash, or a nested hash of array/hash with the +includes+ method.
776
753
 
777
754
  h5. Array of Multiple Associations
778
755
 
779
756
  <ruby>
780
- Post.all :include => [:category, :comments]
757
+ Post.includes(:category, :comments)
781
758
  </ruby>
782
759
 
783
760
  This loads all the posts and the associated category and comments for each post.
@@ -785,14 +762,14 @@ This loads all the posts and the associated category and comments for each post.
785
762
  h5. Nested Associations Hash
786
763
 
787
764
  <ruby>
788
- Category.find 1, :include => {:posts => [{:comments => :guest}, :tags]}
765
+ Category.find(1).includes(:posts => [{:comments => :guest}, :tags])
789
766
  </ruby>
790
767
 
791
768
  The above code finds the category with id 1 and eager loads all the posts associated with the found category. Additionally, it will also eager load every posts' tags and comments. Every comment's guest association will get eager loaded as well.
792
769
 
793
770
  h4. Specifying Conditions on Eager Loaded Associations
794
771
 
795
- Even though Active Record lets you specify conditions on the eager loaded associations just like +:joins+, the recommended way is to use ":joins":#joining-tables instead.
772
+ Even though Active Record lets you specify conditions on the eager loaded associations just like +joins+, the recommended way is to use "joins":#joining-tables instead.
796
773
 
797
774
  h3. Dynamic Finders
798
775
 
@@ -889,10 +866,10 @@ Which will execute:
889
866
  SELECT count(*) AS count_all FROM clients WHERE (first_name = 'Ryan')
890
867
  </sql>
891
868
 
892
- You can also use +:include+ or +:joins+ for this to do something a little more complex:
869
+ You can also use the +includes+ or +joins+ methods for this to do something a little more complex:
893
870
 
894
871
  <ruby>
895
- Client.count(:conditions => "clients.first_name = 'Ryan' AND orders.status = 'received'", :include => "orders")
872
+ Client.count.where("clients.first_name = 'Ryan' AND orders.status = 'received'").includes("orders")
896
873
  </ruby>
897
874
 
898
875
  Which will execute:
@@ -957,5 +934,6 @@ h3. Changelog
957
934
 
958
935
  "Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/16
959
936
 
937
+ * February 3, 2010: Update to Rails 3 by "James Miller":credits.html#bensie
960
938
  * February 7, 2009: Second version by "Pratik":credits.html#lifo
961
939
  * December 29 2008: Initial version by "Ryan Bigg":credits.html#radar