railties 3.0.0.beta4 → 3.0.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/CHANGELOG +24 -6
  2. data/README.rdoc +25 -0
  3. data/guides/assets/javascripts/code_highlighter.js +0 -0
  4. data/guides/assets/javascripts/guides.js +0 -0
  5. data/guides/assets/stylesheets/print.css +0 -0
  6. data/guides/assets/stylesheets/reset.css +0 -0
  7. data/guides/assets/stylesheets/style.css +0 -0
  8. data/guides/source/3_0_release_notes.textile +5 -3
  9. data/guides/source/action_controller_overview.textile +19 -0
  10. data/guides/source/active_record_basics.textile +27 -21
  11. data/guides/source/active_record_querying.textile +39 -37
  12. data/guides/source/{activerecord_validations_callbacks.textile → active_record_validations_callbacks.textile} +30 -29
  13. data/guides/source/active_support_core_extensions.textile +232 -107
  14. data/guides/source/api_documentation_guidelines.textile +187 -0
  15. data/guides/source/association_basics.textile +45 -1
  16. data/guides/source/configuring.textile +7 -7
  17. data/guides/source/contributing_to_rails.textile +42 -15
  18. data/guides/source/form_helpers.textile +1 -1
  19. data/guides/source/generators.textile +37 -37
  20. data/guides/source/getting_started.textile +11 -11
  21. data/guides/source/i18n.textile +1 -1
  22. data/guides/source/index.html.erb +14 -6
  23. data/guides/source/initialization.textile +130 -124
  24. data/guides/source/layout.html.erb +5 -2
  25. data/guides/source/layouts_and_rendering.textile +2 -2
  26. data/guides/source/migrations.textile +4 -3
  27. data/guides/source/plugins.textile +15 -15
  28. data/guides/source/rails_application_templates.textile +2 -2
  29. data/guides/source/routing.textile +83 -62
  30. data/guides/source/security.textile +2 -2
  31. data/guides/w3c_validator.rb +30 -6
  32. data/lib/rails.rb +3 -3
  33. data/lib/rails/application.rb +43 -19
  34. data/lib/rails/application/bootstrap.rb +2 -0
  35. data/lib/rails/application/configuration.rb +3 -3
  36. data/lib/rails/application/finisher.rb +6 -6
  37. data/lib/rails/cli.rb +1 -19
  38. data/lib/rails/commands.rb +5 -5
  39. data/lib/rails/commands/application.rb +1 -1
  40. data/lib/rails/commands/console.rb +1 -4
  41. data/lib/rails/commands/generate.rb +0 -0
  42. data/lib/rails/commands/plugin.rb +57 -52
  43. data/lib/rails/commands/runner.rb +2 -1
  44. data/lib/rails/commands/server.rb +6 -2
  45. data/lib/rails/configuration.rb +2 -3
  46. data/lib/rails/console/app.rb +0 -2
  47. data/lib/rails/engine.rb +14 -15
  48. data/lib/rails/engine/configuration.rb +5 -5
  49. data/lib/rails/generators.rb +2 -3
  50. data/lib/rails/generators/actions.rb +4 -4
  51. data/lib/rails/generators/base.rb +1 -1
  52. data/lib/rails/generators/erb/scaffold/scaffold_generator.rb +1 -6
  53. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb +4 -4
  54. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb +3 -3
  55. data/lib/rails/generators/erb/scaffold/templates/index.html.erb +7 -7
  56. data/lib/rails/generators/erb/scaffold/templates/new.html.erb +2 -2
  57. data/lib/rails/generators/erb/scaffold/templates/show.html.erb +3 -3
  58. data/lib/rails/generators/generated_attribute.rb +2 -1
  59. data/lib/rails/generators/named_base.rb +24 -0
  60. data/lib/rails/generators/rails/app/app_generator.rb +10 -9
  61. data/lib/rails/generators/rails/app/templates/Gemfile +4 -3
  62. data/lib/rails/generators/rails/app/templates/README +6 -31
  63. data/lib/rails/generators/rails/app/templates/Rakefile +1 -1
  64. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb +0 -1
  65. data/lib/rails/generators/rails/app/templates/app/mailers/.empty_directory +0 -0
  66. data/lib/rails/generators/rails/app/templates/config/application.rb +11 -11
  67. data/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml +36 -24
  68. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml +1 -1
  69. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml +1 -1
  70. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +3 -0
  71. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +3 -0
  72. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +3 -0
  73. data/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb +1 -1
  74. data/lib/rails/generators/rails/app/templates/config/initializers/secret_token.rb.tt +2 -2
  75. data/lib/rails/generators/rails/app/templates/config/initializers/session_store.rb.tt +2 -2
  76. data/lib/rails/generators/rails/app/templates/config/routes.rb +1 -1
  77. data/lib/rails/generators/rails/app/templates/public/index.html +0 -17
  78. data/lib/rails/generators/rails/app/templates/public/javascripts/prototype.js +2027 -900
  79. data/lib/rails/generators/rails/app/templates/public/javascripts/rails.js +114 -57
  80. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +1 -1
  81. data/lib/rails/generators/rails/model/USAGE +1 -1
  82. data/lib/rails/generators/rails/resource/resource_generator.rb +4 -14
  83. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +0 -2
  84. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +28 -30
  85. data/lib/rails/generators/resource_helpers.rb +1 -1
  86. data/lib/rails/generators/test_case.rb +25 -11
  87. data/lib/rails/generators/test_unit/model/model_generator.rb +1 -1
  88. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +0 -1
  89. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb +13 -15
  90. data/lib/rails/info.rb +1 -2
  91. data/lib/rails/info_routes.rb +1 -1
  92. data/lib/rails/initializable.rb +3 -16
  93. data/lib/rails/paths.rb +31 -36
  94. data/lib/rails/plugin.rb +10 -6
  95. data/lib/rails/rack/logger.rb +11 -13
  96. data/lib/rails/railtie.rb +14 -42
  97. data/lib/rails/ruby_version_check.rb +19 -5
  98. data/lib/rails/script_rails_loader.rb +29 -0
  99. data/lib/rails/tasks/annotations.rake +2 -2
  100. data/lib/rails/tasks/documentation.rake +47 -16
  101. data/lib/rails/tasks/framework.rake +9 -9
  102. data/lib/rails/tasks/middleware.rake +1 -1
  103. data/lib/rails/tasks/misc.rake +5 -5
  104. data/lib/rails/tasks/routes.rake +1 -1
  105. data/lib/rails/tasks/tmp.rake +5 -5
  106. data/lib/rails/test_unit/testing.rake +38 -14
  107. data/lib/rails/version.rb +1 -1
  108. metadata +29 -17
  109. data/README +0 -281
  110. data/lib/rails/application/routes_reloader.rb +0 -46
  111. data/lib/rails/log_subscriber.rb +0 -115
  112. data/lib/rails/log_subscriber/test_helper.rb +0 -97
  113. data/lib/rails/webrick_server.rb +0 -156
data/CHANGELOG CHANGED
@@ -1,25 +1,43 @@
1
+ *Rails 3.0.0 [release candidate] (July 26th, 2010)*
2
+
3
+ * Application generation: --skip-testunit and --skip-activerecord become --skip-test-unit
4
+ and --skip-active-record respectively. [fxn]
5
+
6
+ * Added console to Rails::Railtie as a hook called just after console starts. [José Valim]
7
+
8
+ * Rails no longer autoload code in lib for application. You need to explicitly require it. [José Valim]
9
+
10
+ * Rails::LogSubscriber was renamed to ActiveSupport::LogSubscriber [José Valim]
11
+
12
+ * config.load_(once_)paths in config/application.rb got renamed to config.autoload_(once_)paths. [fxn]
13
+
14
+ * Abort generation/booting on Ruby 1.9.1. [fxn]
15
+
16
+ * Made the rails command work even when you're in a subdirectory [Chad Fowler]
17
+
18
+
1
19
  *Rails 3.0.0 [beta 4] (June 8th, 2010)*
2
20
 
3
- * Version bump
4
- * Removed Rails Metal [YK & JV].
21
+ * Removed Rails Metal [Yehuda Katz, José Valim].
22
+
5
23
 
6
24
  *Rails 3.0.0 [beta 3] (April 13th, 2010)*
7
25
 
8
- * Renamed config.cookie_secret to config.secret_token and pass it as env key. [JV]
26
+ * Renamed config.cookie_secret to config.secret_token and pass it as env key. [José Valim]
9
27
 
10
28
 
11
29
  *Rails 3.0.0 [beta 2] (April 1st, 2010)*
12
30
 
13
- * Session store configuration has changed [YK & CL]
31
+ * Session store configuration has changed [Yehuda Katz, Carl Lerche]
14
32
 
15
33
  config.session_store :cookie_store, {:key => "..."}
16
34
  config.cookie_secret = "fdsfhisdghfidugnfdlg"
17
35
 
18
36
  * railtie_name and engine_name are deprecated. You can now add any object to
19
- the configuration object: config.your_plugin = {} [JV]
37
+ the configuration object: config.your_plugin = {} [José Valim]
20
38
 
21
39
  * Added config.generators.templates to provide alternative paths for the generators
22
- to look for templates [JV]
40
+ to look for templates [José Valim]
23
41
 
24
42
  *Rails 3.0.0 [beta 1] (February 4, 2010)*
25
43
 
@@ -0,0 +1,25 @@
1
+ = Railties -- Gluing the Engine to the Rails
2
+
3
+ Railties is responsible to glue all frameworks together. Overall, it:
4
+
5
+ * handles all the bootstrapping process for a Rails application;
6
+
7
+ * manager rails command line interface;
8
+
9
+ * provides Rails generators core;
10
+
11
+
12
+ == Download
13
+
14
+ The latest version of Railties can be installed with Rubygems:
15
+
16
+ * gem install railties
17
+
18
+ Documentation can be found at
19
+
20
+ * http://api.rubyonrails.org
21
+
22
+
23
+ == License
24
+
25
+ Railties is released under the MIT license.
File without changes
File without changes
File without changes
File without changes
@@ -32,11 +32,11 @@ h3. Upgrading to Rails 3
32
32
 
33
33
  If you're upgrading an existing application, it's a great idea to have good test coverage before going in. You should also first upgrade to Rails 2.3.5 and make sure your application still runs as expected before attempting to update to Rails 3. Then take heed of the following changes:
34
34
 
35
- h4. Rails 3 requires Ruby 1.8.7+
35
+ h4. Rails 3 requires at least Ruby 1.8.7
36
36
 
37
37
  Rails 3.0 requires Ruby 1.8.7 or higher. Support for all of the previous Ruby versions has been dropped officially and you should upgrade as early as possible. Rails 3.0 is also compatible with Ruby 1.9.2.
38
38
 
39
- TIP: Note that Ruby 1.8.7 p248 and p249 has marshaling bugs that crash Rails 3.0.0. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02 though. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults on Rails 3.0.0, so if you want to use Rails 3 with 1.9.x jump on 1.9.2 for smooth sailing.
39
+ TIP: Note that Ruby 1.8.7 p248 and p249 have marshaling bugs that crash Rails 3.0. Ruby Enterprise Edition have these fixed since release 1.8.7-2010.02 though. On the 1.9 front, Ruby 1.9.1 is not usable because it outright segfaults on Rails 3.0, so if you want to use Rails 3 with 1.9.x jump on 1.9.2 for smooth sailing.
40
40
 
41
41
  h4. Rails Application object
42
42
 
@@ -339,7 +339,9 @@ h5. Other Changes
339
339
  * You no longer need to place a minus sign at the end of a ruby interpolation inside an ERb template to remove the trailing carriage return in the HTML output.
340
340
  * Added +grouped_collection_select+ helper to Action View.
341
341
  * +content_for?+ has been added allowing you to check for the existence of content in a view before rendering.
342
-
342
+ * passing +:value => nil+ to form helpers will set the field's +value+ attribute to nil as opposed to using the default value
343
+ * passing +:id => nil+ to form helpers will cause those fields to be rendered with no +id+ attribute
344
+ * passing +:alt => nil+ to +image_tag+ will cause the +img+ tag to render with no +alt+ attribute
343
345
 
344
346
  h3. Active Model
345
347
 
@@ -338,6 +338,25 @@ end
338
338
 
339
339
  Note that while for session values you set the key to +nil+, to delete a cookie value you should use +cookies.delete(:key)+.
340
340
 
341
+ h3. Rendering xml and json data
342
+
343
+ ActionController makes it extremely easy to render +xml+ or +json+ data. If you generate a controller using scaffold then your controller would look something like this.
344
+
345
+ <ruby>
346
+ class UsersController < ApplicationController
347
+ def index
348
+ @users = User.all
349
+ respond_to do |format|
350
+ format.html # index.html.erb
351
+ format.xml { render :xml => @users}
352
+ end
353
+ end
354
+ end
355
+ </ruby>
356
+
357
+ Notice that in the above case code is <tt>render :xml => @users</tt> and not <tt>render :xml => @users.to_xml</tt>. That is because if the input is not string then rails automatically invokes +to_xml+ .
358
+
359
+
341
360
  h3. Filters
342
361
 
343
362
  Filters are methods that are run before, after or "around" a controller action.
@@ -32,16 +32,16 @@ Active Record gives us several mechanisms, the most important being the ability
32
32
  * Validate models before they get persisted to the database
33
33
  * Perform database operations in an object-oriented fashion.
34
34
 
35
- h3. Convention over Configuration in ActiveRecord
35
+ h3. Convention over Configuration in Active Record
36
36
 
37
- When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particularly true for ORM frameworks in general. However, if you follow the conventions adopted by Rails, you'll need to write very little configuration (in some case no configuration at all) when creating ActiveRecord models. The idea is that if you configure your applications in the very same way most of the times then this should be the default way. In this cases, explicit configuration would be needed only in those cases where you can't follow the conventions for any reason.
37
+ When writing applications using other programming languages or frameworks, it may be necessary to write a lot of configuration code. This is particularly true for ORM frameworks in general. However, if you follow the conventions adopted by Rails, you'll need to write very little configuration (in some case no configuration at all) when creating Active Record models. The idea is that if you configure your applications in the very same way most of the times then this should be the default way. In this cases, explicit configuration would be needed only in those cases where you can't follow the conventions for any reason.
38
38
 
39
39
  h4. Naming Conventions
40
40
 
41
- By default, ActiveRecord uses some naming conventions to find out how the mapping between models and database tables should be created. Rails will pluralize your class names to find the respective database table. So, for a class +Book+, you should have a database table called *books*. The Rails pluralization mechanisms are very powerful, being capable to pluralize (and singularize) both regular and irregular words. When using class names composed of two or more words, the model class name should follow the Ruby conventions, using the camelCase form, while the table name must contain the words separated by underscores. Examples:
41
+ By default, Active Record uses some naming conventions to find out how the mapping between models and database tables should be created. Rails will pluralize your class names to find the respective database table. So, for a class +Book+, you should have a database table called *books*. The Rails pluralization mechanisms are very powerful, being capable to pluralize (and singularize) both regular and irregular words. When using class names composed of two or more words, the model class name should follow the Ruby conventions, using the camelCase form, while the table name must contain the words separated by underscores. Examples:
42
42
 
43
- * Database Table - Plural with underscores separating words i.e. (book_clubs)
44
- * Model Class - Singular with the first letter of each word capitalized i.e. (BookClub)
43
+ * Database Table - Plural with underscores separating words (e.g., book_clubs)
44
+ * Model Class - Singular with the first letter of each word capitalized (e.g., BookClub)
45
45
 
46
46
  |_.Model / Class |_.Table / Schema |
47
47
  |Post |posts|
@@ -53,30 +53,32 @@ By default, ActiveRecord uses some naming conventions to find out how the mappin
53
53
 
54
54
  h4. Schema Conventions
55
55
 
56
- ActiveRecord uses naming conventions for the columns in database tables, depending on the purpose of these columns.
56
+ Active Record uses naming conventions for the columns in database tables, depending on the purpose of these columns.
57
57
 
58
- * *Foreign keys* - These fields should be named following the pattern table_id i.e. (item_id, order_id). These are the fields that ActiveRecord will look for when you create associations between your models.
59
- * *Primary keys* - By default, ActiveRecord will use an integer column named "id" as the table's primary key. When using "Rails Migrations":migrations.html to create your tables, this column will be automatically created.
58
+ * *Foreign keys* - These fields should be named following the pattern table_id (e.g., item_id, order_id). These are the fields that Active Record will look for when you create associations between your models.
59
+ * *Primary keys* - By default, Active Record will use an integer column named "id" as the table's primary key. When using "Rails Migrations":migrations.html to create your tables, this column will be automatically created.
60
60
 
61
- There are also some optional column names that will create additional features to ActiveRecord instances:
61
+ There are also some optional column names that will create additional features to Active Record instances:
62
62
 
63
- * *created_at / created_on* - ActiveRecord will store the current date and time to this field when creating the record.
64
- * *updated_at / updated_on* - ActiveRecord will store the current date and times to this field when updating the record.
63
+ * *created_at* - Automatically gets set to the current date and time when the record is first created.
64
+ * *created_on* - Automatically gets set to the current date when the record is first created.
65
+ * *updated_at* - Automatically gets set to the current date and time whenever the record is updated.
66
+ * *updated_on* - Automatically gets set to the current date whenever the record is updated.
65
67
  * *lock_version* - Adds "optimistic locking":http://api.rubyonrails.com/classes/ActiveRecord/Locking.html to a model.
66
68
  * *type* - Specifies that the model uses "Single Table Inheritance":http://api.rubyonrails.com/classes/ActiveRecord/Base.html
67
69
  * *(table_name)_count* - Used to cache the number of belonging objects on associations. For example, a +comments_count+ column in a +Post+ class that has many instances of +Comment+ will cache the number of existent comments for each post.
68
70
 
69
- NOTE: While these column names are optional they are in fact reserved by ActiveRecord. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling.
71
+ NOTE: While these column names are optional they are in fact reserved by Active Record. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling.
70
72
 
71
- h3. Creating ActiveRecord Models
73
+ h3. Creating Active Record Models
72
74
 
73
- It's very easy to create ActiveRecord models. All you have to do is to subclass the ActiveRecord::Base class and you're good to go:
75
+ It's very easy to create Active Record models. All you have to do is to subclass the +ActiveRecord::Base+ class and you're good to go:
74
76
 
75
77
  <ruby>
76
78
  class Product < ActiveRecord::Base; end
77
79
  </ruby>
78
80
 
79
- This will create a +Product+ model, mapped to a *products* table at the database. By doing this you'll also have the ability to map the columns of each row in that table with the attributes of the instances of your model. So, suppose that the *products* table was created using a SQL sentence like:
81
+ This will create a +Product+ model, mapped to a *products* table at the database. By doing this you'll also have the ability to map the columns of each row in that table with the attributes of the instances of your model. So, suppose that the *products* table was created using an SQL sentence like:
80
82
 
81
83
  <sql>
82
84
  CREATE TABLE products (
@@ -99,12 +101,15 @@ h3. Overriding the Naming Conventions
99
101
  What if you need to follow a different naming convention or need to use your Rails application with a legacy database? No problem, you can easily override the default conventions.
100
102
 
101
103
  You can use the +ActiveRecord::Base.set_table_name+ method to specify the table name that should be used:
104
+
102
105
  <ruby>
103
106
  class Product < ActiveRecord::Base
104
107
  set_table_name "PRODUCT"
105
108
  end
106
109
  </ruby>
110
+
107
111
  If you do so, you will have to define manually the class name that is hosting the fixtures (class_name.yml) using the +set_fixture_class+ method in your test definition:
112
+
108
113
  <ruby>
109
114
  class FunnyJoke < ActiveSupport::TestCase
110
115
  set_fixture_class :funny_jokes => 'Joke'
@@ -113,7 +118,8 @@ class FunnyJoke < ActiveSupport::TestCase
113
118
  end
114
119
  </ruby>
115
120
 
116
- It's also possible to override the column that should be used as the table's primary key. Use the +ActiveRecord::Base.set_primary_key+ method for that:
121
+ It's also possible to override the column that should be used as the table's primary key using the +ActiveRecord::Base.set_primary_key+ method:
122
+
117
123
  <ruby>
118
124
  class Product < ActiveRecord::Base
119
125
  set_primary_key "product_id"
@@ -122,7 +128,7 @@ end
122
128
 
123
129
  h3. Reading and Writing Data
124
130
 
125
- CRUD is an acronym for the four verbs we use to operate on data: Create, Read, Update, Delete. Active Record automatically creates methods to allow an application to read and manipulate data stored within its tables.
131
+ CRUD is an acronym for the four verbs we use to operate on data: *C*reate, *R*ead, *U*pdate and *D*elete. Active Record automatically creates methods to allow an application to read and manipulate data stored within its tables.
126
132
 
127
133
  h4. Create
128
134
 
@@ -155,7 +161,7 @@ Finally, passing a block to either create or new will return a new User object:
155
161
 
156
162
  h4. Read
157
163
 
158
- ActiveRecord provides a rich API for accessing data within a database. Below are a few examples of different data access methods provided by ActiveRecord.
164
+ Active Record provides a rich API for accessing data within a database. Below are a few examples of different data access methods provided by Active Record.
159
165
 
160
166
  <ruby>
161
167
  # return all records
@@ -163,7 +169,7 @@ ActiveRecord provides a rich API for accessing data within a database. Below are
163
169
  </ruby>
164
170
 
165
171
  <ruby>
166
- # return first record
172
+ # return the first record
167
173
  user = User.first
168
174
  </ruby>
169
175
 
@@ -201,11 +207,11 @@ Likewise, once retrieved an Active Record object can be destroyed which removes
201
207
 
202
208
  h3. Validations
203
209
 
204
- Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format and many more. You can learn more about validations in the "Active Record Validations and Callbacks guide":activerecord_validations_callbacks.html#validations-overview.
210
+ Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format and many more. You can learn more about validations in the "Active Record Validations and Callbacks guide":active_record_validations_callbacks.html#validations-overview.
205
211
 
206
212
  h3. Callbacks
207
213
 
208
- Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the "Active Record Validations and Callbacks guide":activerecord_validations_callbacks.html#callbacks-overview.
214
+ Active Record callbacks allow you to attach code to certain events in the life-cycle of your models. This enables you to add behavior to your models by transparently executing code when those events occur, like when you create a new record, update it, destroy it and so on. You can learn more about callbacks in the "Active Record Validations and Callbacks guide":active_record_validations_callbacks.html#callbacks-overview.
209
215
 
210
216
  h3. Migrations
211
217
 
@@ -51,7 +51,7 @@ Active Record will perform queries on the database for you and is compatible wit
51
51
 
52
52
  h3. Retrieving Objects from the Database
53
53
 
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.
54
+ To retrieve objects from the database, Active Record provides several finder methods. Each finder method allows you to pass arguments into it to perform certain queries on your database without writing raw SQL.
55
55
 
56
56
  The methods are:
57
57
  * +where+
@@ -66,7 +66,7 @@ The methods are:
66
66
  * +readonly+
67
67
  * +from+
68
68
 
69
- All of these methods return a Relation
69
+ All of the above methods return an instance of <tt>ActiveRecord::Relation</tt>.
70
70
 
71
71
  Primary operation of <tt>Model.find(options)</tt> can be summarized as:
72
72
 
@@ -86,7 +86,7 @@ Using <tt>Model.find(primary_key)</tt>, you can retrieve the object correspondin
86
86
  <ruby>
87
87
  # Find the client with primary key (id) 10.
88
88
  client = Client.find(10)
89
- => #<Client id: 10, name: => "Ryan">
89
+ => #<Client id: 10, first_name: => "Ryan">
90
90
  </ruby>
91
91
 
92
92
  SQL equivalent of the above is:
@@ -103,7 +103,7 @@ h5. +first+
103
103
 
104
104
  <ruby>
105
105
  client = Client.first
106
- => #<Client id: 1, name: => "Lifo">
106
+ => #<Client id: 1, first_name: => "Lifo">
107
107
  </ruby>
108
108
 
109
109
  SQL equivalent of the above is:
@@ -120,7 +120,7 @@ h5. +last+
120
120
 
121
121
  <ruby>
122
122
  client = Client.last
123
- => #<Client id: 221, name: => "Russel">
123
+ => #<Client id: 221, first_name: => "Russel">
124
124
  </ruby>
125
125
 
126
126
  SQL equivalent of the above is:
@@ -140,7 +140,7 @@ h5. Using Multiple Primary Keys
140
140
  <ruby>
141
141
  # Find the clients with primary keys 1 and 10.
142
142
  client = Client.find(1, 10) # Or even Client.find([1, 10])
143
- => [#<Client id: 1, name: => "Lifo">, #<Client id: 10, name: => "Ryan">]
143
+ => [#<Client id: 1, first_name: => "Lifo">, #<Client id: 10, first_name: => "Ryan">]
144
144
  </ruby>
145
145
 
146
146
  SQL equivalent of the above is:
@@ -227,7 +227,7 @@ h4. Pure String Conditions
227
227
 
228
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.
229
229
 
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.
230
+ WARNING: Building your own conditions as pure strings can leave you vulnerable to SQL injection exploits. For example, +Client.where("first_name LIKE '%#{params[:first_name]}%'")+ is not safe. See the next section for the preferred way to handle conditions using an array.
231
231
 
232
232
  h4. Array Conditions
233
233
 
@@ -337,7 +337,7 @@ Just like in Ruby. If you want a shorter syntax be sure to check out the "Hash C
337
337
 
338
338
  h4. Hash Conditions
339
339
 
340
- Active Record also allows you to pass in a hash conditions which can increase the readability of your conditions syntax. With hash conditions, you pass in a hash with keys of the fields you want conditionalised and the values of how you want to conditionalise them:
340
+ Active Record also allows you to pass in hash conditions which can increase the readability of your conditions syntax. With hash conditions, you pass in a hash with keys of the fields you want conditionalised and the values of how you want to conditionalise them:
341
341
 
342
342
  NOTE: Only equality, range and subset checking are possible with Hash conditions.
343
343
 
@@ -347,7 +347,7 @@ h5. Equality Conditions
347
347
  Client.where({ :locked => true })
348
348
  </ruby>
349
349
 
350
- The field name does not have to be a symbol it can also be a string:
350
+ The field name can also be a string:
351
351
 
352
352
  <ruby>
353
353
  Client.where({ 'locked' => true })
@@ -447,33 +447,33 @@ h4. Limit and Offset
447
447
 
448
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.
449
449
 
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:
450
+ You can use +limit+ to specify the number of records to be retrieved, and use +offset+ to specify the number of records to skip before starting to return the records. For example
451
451
 
452
452
  <ruby>
453
453
  Client.limit(5)
454
454
  </ruby>
455
455
 
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:
456
+ will return a maximum of 5 clients and because it specifies no offset it will return the first 5 in the table. The SQL it executes looks like this:
457
457
 
458
458
  <sql>
459
459
  SELECT * FROM clients LIMIT 5
460
460
  </sql>
461
461
 
462
- Or chaining both +limit+ and +offset+:
462
+ Adding +offset+ to that
463
463
 
464
464
  <ruby>
465
- Client.limit(5).offset(5)
465
+ Client.limit(5).offset(30)
466
466
  </ruby>
467
467
 
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:
468
+ will return instead a maximum of 5 clients beginning with the 31st. The SQL looks like:
469
469
 
470
470
  <sql>
471
- SELECT * FROM clients LIMIT 5, 5
471
+ SELECT * FROM clients LIMIT 5, 30
472
472
  </sql>
473
473
 
474
474
  h4. Group
475
475
 
476
- To apply +GROUP BY+ clause to the SQL fired by the finder, you can specify the +group+ method on the find.
476
+ To apply a +GROUP BY+ clause to the SQL fired by the finder, you can specify the +group+ method on the find.
477
477
 
478
478
  For example, if you want to find a collection of the dates orders were created on:
479
479
 
@@ -491,7 +491,7 @@ SELECT * FROM orders GROUP BY date(created_at)
491
491
 
492
492
  h4. Having
493
493
 
494
- SQL uses +HAVING+ clause to specify conditions on the +GROUP BY+ fields. You can specify the +HAVING+ clause to the SQL fired by the +Model.find+ using +:having+ option on the find.
494
+ SQL uses the +HAVING+ clause to specify conditions on the +GROUP BY+ fields. You can add the +HAVING+ clause to the SQL fired by the +Model.find+ by adding the +:having+ option to the find.
495
495
 
496
496
  For example:
497
497
 
@@ -517,7 +517,7 @@ Any attempt to alter or destroy the readonly records will not succeed, raising a
517
517
  Client.first.readonly(true)
518
518
  </ruby>
519
519
 
520
- If you assign this record to a variable client, calling the following code will raise an +ActiveRecord::ReadOnlyRecord+ exception:
520
+ For example, calling the following code will raise an +ActiveRecord::ReadOnlyRecord+ exception:
521
521
 
522
522
  <ruby>
523
523
  client = Client.first.readonly(true)
@@ -527,7 +527,9 @@ client.save
527
527
 
528
528
  h4. Locking Records for Update
529
529
 
530
- Locking is helpful for preventing the race conditions when updating records in the database and ensuring atomic updated. Active Record provides two locking mechanism:
530
+ Locking is helpful for preventing race conditions when updating records in the database and ensuring atomic updates.
531
+
532
+ Active Record provides two locking mechanisms:
531
533
 
532
534
  * Optimistic Locking
533
535
  * Pessimistic Locking
@@ -538,13 +540,13 @@ Optimistic locking allows multiple users to access the same record for edits, an
538
540
 
539
541
  <strong>Optimistic locking column</strong>
540
542
 
541
- In order to use optimistic locking, the table needs to have a column called +lock_version+. Each time the record is updated, Active Record increments the +lock_version+ column and the locking facilities ensure that records instantiated twice will let the last one saved raise an +ActiveRecord::StaleObjectError+ exception if the first was also updated. Example:
543
+ In order to use optimistic locking, the table needs to have a column called +lock_version+. Each time the record is updated, Active Record increments the +lock_version+ column. If an update request is made with a lower value in the +lock_version+ field than is currently in the +lock_version+ column in the database, the update request will fail with an +ActiveRecord::StaleObjectError+. Example:
542
544
 
543
545
  <ruby>
544
546
  c1 = Client.find(1)
545
547
  c2 = Client.find(1)
546
548
 
547
- c1.name = "Michael"
549
+ c1.first_name = "Michael"
548
550
  c1.save
549
551
 
550
552
  c2.name = "should fail"
@@ -569,7 +571,7 @@ end
569
571
 
570
572
  h5. Pessimistic Locking
571
573
 
572
- Pessimistic locking uses locking mechanism provided by the underlying database. Passing +:lock => true+ to +Model.find+ obtains an exclusive lock on the selected rows. +Model.find+ using +:lock+ are usually wrapped inside a transaction for preventing deadlock conditions.
574
+ Pessimistic locking uses a locking mechanism provided by the underlying database. Passing +:lock => true+ to +Model.find+ obtains an exclusive lock on the selected rows. +Model.find+ using +:lock+ are usually wrapped inside a transaction for preventing deadlock conditions.
573
575
 
574
576
  For example:
575
577
 
@@ -601,7 +603,7 @@ end
601
603
 
602
604
  h3. Joining Tables
603
605
 
604
- <tt>Model.find</tt> provides a +:joins+ option for specifying +JOIN+ clauses on the resulting SQL. There multiple different ways to specify the +:joins+ option:
606
+ <tt>Model.find</tt> provides a +:joins+ option for specifying +JOIN+ clauses on the resulting SQL. There are multiple ways to specify the +:joins+ option:
605
607
 
606
608
  h4. Using a String SQL Fragment
607
609
 
@@ -698,7 +700,7 @@ time_range = (Time.now.midnight - 1.day)..Time.now.midnight
698
700
  Client.joins(:orders).where('orders.created_at' => time_range)
699
701
  </ruby>
700
702
 
701
- An alternative and cleaner syntax to this is to nest the hash conditions:
703
+ An alternative and cleaner syntax is to nest the hash conditions:
702
704
 
703
705
  <ruby>
704
706
  time_range = (Time.now.midnight - 1.day)..Time.now.midnight
@@ -727,7 +729,7 @@ This code looks fine at the first sight. But the problem lies within the total n
727
729
 
728
730
  <strong>Solution to N <plus> 1 queries problem</strong>
729
731
 
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.
732
+ Active Record lets you specify in advance all the associations 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 of the specified associations are loaded using the minimum possible number of queries.
731
733
 
732
734
  Revisiting the above case, we could rewrite +Client.all+ to use eager load addresses:
733
735
 
@@ -749,7 +751,7 @@ SELECT addresses.* FROM addresses
749
751
 
750
752
  h4. Eager Loading Multiple Associations
751
753
 
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.
754
+ Active Record lets you eager load any 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.
753
755
 
754
756
  h5. Array of Multiple Associations
755
757
 
@@ -765,7 +767,7 @@ h5. Nested Associations Hash
765
767
  Category.find(1).includes(:posts => [{:comments => :guest}, :tags])
766
768
  </ruby>
767
769
 
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.
770
+ This will find the category with id 1 and eager load all of the associated posts, the associated posts' tags and comments, and every comment's guest association.
769
771
 
770
772
  h4. Specifying Conditions on Eager Loaded Associations
771
773
 
@@ -773,32 +775,32 @@ Even though Active Record lets you specify conditions on the eager loaded associ
773
775
 
774
776
  h3. Dynamic Finders
775
777
 
776
- For every field (also known as an attribute) you define in your table, Active Record provides a finder method. If you have a field called +name+ on your +Client+ model for example, you get +find_by_name+ and +find_all_by_name+ for free from Active Record. If you have also have a +locked+ field on the +Client+ model, you also get +find_by_locked+ and +find_all_by_locked+.
778
+ For every field (also known as an attribute) you define in your table, Active Record provides a finder method. If you have a field called +first_name+ on your +Client+ model for example, you get +find_by_first_name+ and +find_all_by_first_name+ for free from Active Record. If you have also have a +locked+ field on the +Client+ model, you also get +find_by_locked+ and +find_all_by_locked+.
777
779
 
778
780
  You can do +find_last_by_*+ methods too which will find the last record matching your argument.
779
781
 
780
782
  You can specify an exclamation point (<tt>!</tt>) on the end of the dynamic finders to get them to raise an +ActiveRecord::RecordNotFound+ error if they do not return any records, like +Client.find_by_name!("Ryan")+
781
783
 
782
- If you want to find both by name and locked, you can chain these finders together by simply typing +and+ between the fields for example +Client.find_by_name_and_locked("Ryan", true)+.
784
+ If you want to find both by name and locked, you can chain these finders together by simply typing +and+ between the fields for example +Client.find_by_first_name_and_locked("Ryan", true)+.
783
785
 
784
786
 
785
- There's another set of dynamic finders that let you find or create/initialize objects if they aren't found. These work in a similar fashion to the other finders and can be used like +find_or_create_by_name(params[:name])+. Using this will firstly perform a find and then create if the find returns +nil+. The SQL looks like this for +Client.find_or_create_by_name("Ryan")+:
787
+ There's another set of dynamic finders that let you find or create/initialize objects if they aren't found. These work in a similar fashion to the other finders and can be used like +find_or_create_by_first_name(params[:first_name])+. Using this will first perform a find and then create if the find returns +nil+. The SQL looks like this for +Client.find_or_create_by_first_name("Ryan")+:
786
788
 
787
789
  <sql>
788
- SELECT * FROM clients WHERE (clients.name = 'Ryan') LIMIT 1
790
+ SELECT * FROM clients WHERE (clients.first_name = 'Ryan') LIMIT 1
789
791
  BEGIN
790
- INSERT INTO clients (name, updated_at, created_at, orders_count, locked)
792
+ INSERT INTO clients (first_name, updated_at, created_at, orders_count, locked)
791
793
  VALUES('Ryan', '2008-09-28 15:39:12', '2008-09-28 15:39:12', 0, '0')
792
794
  COMMIT
793
795
  </sql>
794
796
 
795
- +find_or_create+'s sibling, +find_or_initialize+, will find an object and if it does not exist will act similar to calling +new+ with the arguments you passed in. For example:
797
+ +find_or_create+'s sibling, +find_or_initialize+, will find an object and if it does not exist will act similarly to calling +new+ with the arguments you passed in. For example:
796
798
 
797
799
  <ruby>
798
- client = Client.find_or_initialize_by_name('Ryan')
800
+ client = Client.find_or_initialize_by_first_name('Ryan')
799
801
  </ruby>
800
802
 
801
- will either assign an existing client object with the name "Ryan" to the client local variable, or initialize a new object similar to calling +Client.new(:name => 'Ryan')+. From here, you can modify other fields in client by calling the attribute setters on it: +client.locked = true+ and when you want to write it to the database just call +save+ on it.
803
+ will either assign an existing client object with the name "Ryan" to the client local variable, or initialize a new object similar to calling +Client.new(:first_name => 'Ryan')+. From here, you can modify other fields in client by calling the attribute setters on it: +client.locked = true+ and when you want to write it to the database just call +save+ on it.
802
804
 
803
805
  h3. Finding by SQL
804
806
 
@@ -836,7 +838,7 @@ Client.exists?(1,2,3)
836
838
  Client.exists?([1,2,3])
837
839
  </ruby>
838
840
 
839
- Further more, +exists+ takes a +conditions+ option much like find:
841
+ The +exists+ method may also take a +conditions+ option much like find:
840
842
 
841
843
  <ruby>
842
844
  Client.exists?(:conditions => "first_name = 'Ryan'")
@@ -869,7 +871,7 @@ SELECT count(*) AS count_all FROM clients WHERE (first_name = 'Ryan')
869
871
  You can also use the +includes+ or +joins+ methods for this to do something a little more complex:
870
872
 
871
873
  <ruby>
872
- Client.count.where("clients.first_name = 'Ryan' AND orders.status = 'received'").includes("orders")
874
+ Client.where("clients.first_name = 'Ryan' AND orders.status = 'received'").includes("orders").count
873
875
  </ruby>
874
876
 
875
877
  Which will execute: