aboutsummaryrefslogtreecommitdiffstats
path: root/guides/source
diff options
context:
space:
mode:
Diffstat (limited to 'guides/source')
-rw-r--r--guides/source/2_2_release_notes.md30
-rw-r--r--guides/source/4_0_release_notes.md6
-rw-r--r--guides/source/action_controller_overview.md65
-rw-r--r--guides/source/action_mailer_basics.md42
-rw-r--r--guides/source/action_view_overview.md2
-rw-r--r--guides/source/active_record_querying.md82
-rw-r--r--guides/source/active_record_validations.md41
-rw-r--r--guides/source/active_support_core_extensions.md4
-rw-r--r--guides/source/active_support_instrumentation.md12
-rw-r--r--guides/source/asset_pipeline.md32
-rw-r--r--guides/source/association_basics.md44
-rw-r--r--guides/source/command_line.md10
-rw-r--r--guides/source/configuring.md4
-rw-r--r--guides/source/contributing_to_ruby_on_rails.md43
-rw-r--r--guides/source/debugging_rails_applications.md28
-rw-r--r--guides/source/engines.md9
-rw-r--r--guides/source/form_helpers.md28
-rw-r--r--guides/source/generators.md4
-rw-r--r--guides/source/getting_started.md10
-rw-r--r--guides/source/initialization.md2
-rw-r--r--guides/source/layouts_and_rendering.md2
-rw-r--r--guides/source/migrations.md10
-rw-r--r--guides/source/routing.md4
-rw-r--r--guides/source/ruby_on_rails_guides_guidelines.md2
-rw-r--r--guides/source/security.md2
-rw-r--r--guides/source/testing.md189
-rw-r--r--guides/source/upgrading_ruby_on_rails.md52
-rw-r--r--guides/source/working_with_javascript_in_rails.md1
28 files changed, 524 insertions, 236 deletions
diff --git a/guides/source/2_2_release_notes.md b/guides/source/2_2_release_notes.md
index cef82f3784..802455f612 100644
--- a/guides/source/2_2_release_notes.md
+++ b/guides/source/2_2_release_notes.md
@@ -31,20 +31,20 @@ Documentation
The internal documentation of Rails, in the form of code comments, has been improved in numerous places. In addition, the [Ruby on Rails Guides](http://guides.rubyonrails.org/) project is the definitive source for information on major Rails components. In its first official release, the Guides page includes:
-* [Getting Started with Rails](http://guides.rubyonrails.org/getting_started.html)
-* [Rails Database Migrations](http://guides.rubyonrails.org/migrations.html)
-* [Active Record Associations](http://guides.rubyonrails.org/association_basics.html)
-* [Active Record Query Interface](http://guides.rubyonrails.org/active_record_querying.html)
-* [Layouts and Rendering in Rails](http://guides.rubyonrails.org/layouts_and_rendering.html)
-* [Action View Form Helpers](http://guides.rubyonrails.org/form_helpers.html)
-* [Rails Routing from the Outside In](http://guides.rubyonrails.org/routing.html)
-* [Action Controller Overview](http://guides.rubyonrails.org/action_controller_overview.html)
-* [Rails Caching](http://guides.rubyonrails.org/caching_with_rails.html)
-* [A Guide to Testing Rails Applications](http://guides.rubyonrails.org/testing.html)
-* [Securing Rails Applications](http://guides.rubyonrails.org/security.html)
-* [Debugging Rails Applications](http://guides.rubyonrails.org/debugging_rails_applications.html)
-* [Performance Testing Rails Applications](http://guides.rubyonrails.org/performance_testing.html)
-* [The Basics of Creating Rails Plugins](http://guides.rubyonrails.org/plugins.html)
+* [Getting Started with Rails](getting_started.html)
+* [Rails Database Migrations](migrations.html)
+* [Active Record Associations](association_basics.html)
+* [Active Record Query Interface](active_record_querying.html)
+* [Layouts and Rendering in Rails](layouts_and_rendering.html)
+* [Action View Form Helpers](form_helpers.html)
+* [Rails Routing from the Outside In](routing.html)
+* [Action Controller Overview](action_controller_overview.html)
+* [Rails Caching](caching_with_rails.html)
+* [A Guide to Testing Rails Applications](testing.html)
+* [Securing Rails Applications](security.html)
+* [Debugging Rails Applications](debugging_rails_applications.html)
+* [Performance Testing Rails Applications](performance_testing.html)
+* [The Basics of Creating Rails Plugins](plugins.html)
All told, the Guides provide tens of thousands of words of guidance for beginning and intermediate Rails developers.
@@ -236,7 +236,7 @@ This will enable recognition of (among others) these routes:
* Lead Contributor: [S. Brent Faulkner](http://www.unwwwired.net/)
* More information:
- * [Rails Routing from the Outside In](http://guides.rubyonrails.org/routing.html#nested-resources)
+ * [Rails Routing from the Outside In](routing.html#nested-resources)
* [What's New in Edge Rails: Shallow Routes](http://ryandaigle.com/articles/2008/9/7/what-s-new-in-edge-rails-shallow-routes)
### Method Arrays for Member or Collection Routes
diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md
index 463da488f2..37afb25181 100644
--- a/guides/source/4_0_release_notes.md
+++ b/guides/source/4_0_release_notes.md
@@ -178,12 +178,6 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/activ
If migrating down, the given migration / block is run normally.
See the [Guide on Migration](https://github.com/rails/rails/blob/master/guides/source/migrations.md#reverting-previous-migrations)
-* Adds some metadata columns to `schema_migrations` table.
-
- * `migrated_at`
- * `fingerprint` - an md5 hash of the migration.
- * `name` - the filename minus version and extension.
-
* Adds PostgreSQL array type support. Any datatype can be used to create an array column, with full migration and schema dumper support.
* Add `Relation#load` to explicitly load the record and return `self`.
diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md
index e65f7e5b18..5e99063da8 100644
--- a/guides/source/action_controller_overview.md
+++ b/guides/source/action_controller_overview.md
@@ -39,7 +39,7 @@ class ClientsController < ApplicationController
end
```
-As an example, if a user goes to `/clients/new` in your application to add a new client, Rails will create an instance of `ClientsController` and run the `new` method. Note that the empty method from the example above could work just fine because Rails will by default render the `new.html.erb` view unless the action says otherwise. The `new` method could make available to the view a `@client` instance variable by creating a new `Client`:
+As an example, if a user goes to `/clients/new` in your application to add a new client, Rails will create an instance of `ClientsController` and run the `new` method. Note that the empty method from the example above would work just fine because Rails will by default render the `new.html.erb` view unless the action says otherwise. The `new` method could make available to the view a `@client` instance variable by creating a new `Client`:
```ruby
def new
@@ -113,21 +113,21 @@ To send a hash you include the key name inside the brackets:
</form>
```
-When this form is submitted, the value of `params[:client]` will be `{"name" => "Acme", "phone" => "12345", "address" => {"postcode" => "12345", "city" => "Carrot City"}}`. Note the nested hash in `params[:client][:address]`.
+When this form is submitted, the value of `params[:client]` will be `{ "name" => "Acme", "phone" => "12345", "address" => { "postcode" => "12345", "city" => "Carrot City" } }`. Note the nested hash in `params[:client][:address]`.
-Note that the `params` hash is actually an instance of `ActiveSupport::HashWithIndifferentAccess`, which acts like a hash that lets you use symbols and strings interchangeably as keys.
+Note that the `params` hash is actually an instance of `ActiveSupport::HashWithIndifferentAccess`, which acts like a hash but lets you use symbols and strings interchangeably as keys.
### JSON parameters
-If you're writing a web service application, you might find yourself more comfortable on accepting parameters in JSON format. Rails will automatically convert your parameters into `params` hash, which you'll be able to access like you would normally do with form data.
+If you're writing a web service application, you might find yourself more comfortable accepting parameters in JSON format. Rails will automatically convert your parameters into the `params` hash, which you can access as you would normally.
-So for example, if you are sending this JSON parameter:
+So for example, if you are sending this JSON content:
```json
{ "company": { "name": "acme", "address": "123 Carrot Street" } }
```
-You'll get `params[:company]` as `{ :name => "acme", "address" => "123 Carrot Street" }`.
+You'll get `params[:company]` as `{ "name" => "acme", "address" => "123 Carrot Street" }`.
Also, if you've turned on `config.wrap_parameters` in your initializer or calling `wrap_parameters` in your controller, you can safely omit the root element in the JSON parameter. The parameters will be cloned and wrapped in the key according to your controller's name by default. So the above parameter can be written as:
@@ -138,19 +138,19 @@ Also, if you've turned on `config.wrap_parameters` in your initializer or callin
And assume that you're sending the data to `CompaniesController`, it would then be wrapped in `:company` key like this:
```ruby
-{ :name => "acme", :address => "123 Carrot Street", :company => { :name => "acme", :address => "123 Carrot Street" }}
+{ :name => "acme", :address => "123 Carrot Street", :company => { :name => "acme", :address => "123 Carrot Street" } }
```
You can customize the name of the key or specific parameters you want to wrap by consulting the [API documentation](http://api.rubyonrails.org/classes/ActionController/ParamsWrapper.html)
-NOTE: A support for parsing XML parameters has been extracted into a gem named `actionpack-xml_parser`
+NOTE: Support for parsing XML parameters has been extracted into a gem named `actionpack-xml_parser`
### Routing Parameters
The `params` hash will always contain the `:controller` and `:action` keys, but you should use the methods `controller_name` and `action_name` instead to access these values. Any other parameters defined by the routing, such as `:id` will also be available. As an example, consider a listing of clients where the list can show either active or inactive clients. We can add a route which captures the `:status` parameter in a "pretty" URL:
```ruby
-match '/clients/:status' => 'clients#index', foo: "bar"
+match '/clients/:status' => 'clients#index', foo: 'bar'
```
In this case, when a user opens the URL `/clients/active`, `params[:status]` will be set to "active". When this route is used, `params[:foo]` will also be set to "bar" just like it was passed in the query string. In the same way `params[:action]` will contain "index".
@@ -173,7 +173,7 @@ If you define `default_url_options` in `ApplicationController`, as in the exampl
### Strong Parameters
-With strong parameters Action Controller parameters are forbidden to
+With strong parameters, Action Controller parameters are forbidden to
be used in Active Model mass assignments until they have been
whitelisted. This means you'll have to make a conscious choice about
which attributes to allow for mass updating and thus prevent
@@ -194,7 +194,7 @@ class PeopleController < ActionController::Base
# This will pass with flying colors as long as there's a person key
# in the parameters, otherwise it'll raise a
- # ActionController::MissingParameter exception, which will get
+ # ActionController::ParameterMissing exception, which will get
# caught by ActionController::Base and turned into that 400 Bad
# Request reply.
def update
@@ -232,15 +232,15 @@ The permitted scalar types are `String`, `Symbol`, `NilClass`,
`StringIO`, `IO`, `ActionDispatch::Http::UploadedFile` and
`Rack::Test::UploadedFile`.
-To declare that the value in `params+ must be an array of permitted
+To declare that the value in `params` must be an array of permitted
scalar values map the key to an empty array:
```ruby
params.permit(:id => [])
```
-To whitelist an entire hash of parameters, the `permit!+ method can be
-used
+To whitelist an entire hash of parameters, the `permit!` method can be
+used:
```ruby
params.require(:log_entry).permit!
@@ -269,6 +269,41 @@ permitted scalar values allowed), a `hobbies` attribute as an array of
permitted scalar values, and a `family` attribute which is restricted
to having a `name` (any permitted scalar values allowed, too).
+#### More Examples
+
+You want to also use the permitted attributes in the `new`
+action. This raises the problem that you can't use `require` on the
+root key because normally it does not exist when calling `new`:
+
+```ruby
+# using `fetch` you can supply a default and use
+# the Strong Parameters API from there.
+params.fetch(:blog, {}).permit(:title, :author)
+```
+
+`accepts_nested_attributes_for` allows you to update and destroy
+associated records. This is based on the `id` and `_destroy`
+parameters:
+
+```ruby
+# permit :id and :_destroy
+params.require(:author).permit(:name, books_attributes: [:title, :id, :_destroy])
+```
+
+Hashes with integer keys are treated differently and you can declare
+the attributes as if they were direct children. You get these kinds of
+parameters when you use `accepts_nested_attributes_for` in combination
+with a `has_many` association:
+
+```ruby
+# To whitelist the following data:
+# {"book" => {"title" => "Some Book",
+# "chapters_attributes" => { "1" => {"title" => "First Chapter"},
+# "2" => {"title" => "Second Chapter"}}}}
+
+params.require(:book).permit(:title, chapters_attributes: [:title])
+```
+
#### Outside the Scope of Strong Parameters
The strong parameter API was designed with the most common use cases
@@ -276,7 +311,7 @@ in mind. It is not meant as a silver bullet to handle all your
whitelisting problems. However you can easily mix the API with your
own code to adapt to your situation.
-Imagine a situation where you want to whitelist an attribute
+Imagine a scenario where you want to whitelist an attribute
containing a hash with any keys. Using strong parameters you can't
allow a hash with any keys but you can use a simple assignment to get
the job done:
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index 8720aae169..a0d962f9c4 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -403,7 +403,7 @@ If you wish to override the default delivery options (e.g. SMTP credentials) whi
```ruby
class UserMailer < ActionMailer::Base
- def welcome_email(user,company)
+ def welcome_email(user, company)
@user = user
@url = user_url(@user)
delivery_options = { user_name: company.smtp_user, password: company.smtp_password, address: company.smtp_host }
@@ -412,6 +412,19 @@ class UserMailer < ActionMailer::Base
end
```
+### Sending Emails without Template Rendering
+
+There may be cases in which you want to skip the template rendering step and supply the email body as a string. You can achieve this using the `:body` option.
+In such cases don't forget to add the `:content_type` option. Rails will default to `text/plain` otherwise.
+
+```ruby
+class UserMailer < ActionMailer::Base
+ def welcome_email(user, email_body)
+ mail(to: user.email, body: email_body, content_type: "text/html", subject: "Already rendered!")
+ end
+end
+```
+
Receiving Emails
----------------
@@ -551,31 +564,8 @@ config.action_mailer.smtp_settings = {
Mailer Testing
--------------
-By default Action Mailer does not send emails in the test environment. They are just added to the `ActionMailer::Base.deliveries` array.
-
-Testing mailers normally involves two things: One is that the mail was queued, and the other one that the email is correct. With that in mind, we could test our example mailer from above like so:
-
-```ruby
-class UserMailerTest < ActionMailer::TestCase
- def test_welcome_email
- user = users(:some_user_in_your_fixtures)
-
- # Send the email, then test that it got queued
- email = UserMailer.welcome_email(user).deliver
- assert !ActionMailer::Base.deliveries.empty?
-
- # Test the body of the sent email contains what we expect it to
- assert_equal [user.email], email.to
- assert_equal 'Welcome to My Awesome Site', email.subject
- assert_match "<h1>Welcome to example.com, #{user.name}</h1>", email.body.to_s
- assert_match 'you have joined to example.com community', email.body.to_s
- end
-end
-```
-
-In the test we send the email and store the returned object in the `email` variable. We then ensure that it was sent (the first assert), then, in the second batch of assertions, we ensure that the email does indeed contain what we expect.
-
-NOTE: The `ActionMailer::Base.deliveries` array is only reset automatically in `ActionMailer::TestCase` tests. If you want to have a clean slate outside Action Mailer tests, you can reset it manually with: `ActionMailer::Base.deliveries.clear`
+You can find detailed instructions on how to test your mailers in our
+[testing guide](testing.html#testing-your-mailers).
Intercepting Emails
-------------------
diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md
index 4cdac43a7e..3b5963efc2 100644
--- a/guides/source/action_view_overview.md
+++ b/guides/source/action_view_overview.md
@@ -492,7 +492,7 @@ image_path("edit.png") # => /assets/edit-2d1a2db63fc738690021fedb5a65b68e.png
#### image_url
-Computes the url to an image asset in the `app/asset/images` directory. This will call `image_path` internally and merge with your current host or your asset host.
+Computes the url to an image asset in the `app/assets/images` directory. This will call `image_path` internally and merge with your current host or your asset host.
```ruby
image_url("edit.png") # => http://www.example.com/assets/edit.png
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 0d0813c56a..2589accadd 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -76,6 +76,7 @@ The methods are:
* `reorder`
* `reverse_order`
* `select`
+* `distinct`
* `uniq`
* `where`
@@ -505,19 +506,15 @@ This code will generate SQL like this:
SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
```
-### NOT, LIKE, and NOT LIKE Conditions
+### NOT Conditions
-`NOT`, `LIKE`, and `NOT LIKE` SQL queries can be built by `where.not`, `where.like`, and `where.not_like` respectively.
+`NOT` SQL queries can be built by `where.not`.
```ruby
Post.where.not(author: author)
-
-Author.where.like(name: 'Nari%')
-
-Developer.where.not_like(name: 'Tenderl%')
```
-In other words, these sort of queries can be generated by calling `where` with no argument, then immediately chain with `not`, `like`, or `not_like` passing `where` conditions.
+In other words, this query can be generated by calling `where` with no argument, then immediately chain with `not` passing `where` conditions.
Ordering
--------
@@ -580,10 +577,10 @@ ActiveModel::MissingAttributeError: missing attribute: <attribute>
Where `<attribute>` is the attribute you asked for. The `id` method will not raise the `ActiveRecord::MissingAttributeError`, so just be careful when working with associations because they need the `id` method to function properly.
-If you would like to only grab a single record per unique value in a certain field, you can use `uniq`:
+If you would like to only grab a single record per unique value in a certain field, you can use `distinct`:
```ruby
-Client.select(:name).uniq
+Client.select(:name).distinct
```
This would generate SQL like:
@@ -595,10 +592,10 @@ SELECT DISTINCT name FROM clients
You can also remove the uniqueness constraint:
```ruby
-query = Client.select(:name).uniq
+query = Client.select(:name).distinct
# => Returns unique names
-query.uniq(false)
+query.distinct(false)
# => Returns all names, even if there are duplicates
```
@@ -970,7 +967,7 @@ SELECT categories.* FROM categories
INNER JOIN posts ON posts.category_id = categories.id
```
-Or, in English: "return a Category object for all categories with posts". Note that you will see duplicate categories if more than one post has the same category. If you want unique categories, you can use `Category.joins(:posts).select("distinct(categories.id)")`.
+Or, in English: "return a Category object for all categories with posts". Note that you will see duplicate categories if more than one post has the same category. If you want unique categories, you can use `Category.joins(:posts).uniq`.
#### Joining Multiple Associations
@@ -1196,6 +1193,61 @@ Using a class method is the preferred way to accept arguments for scopes. These
category.posts.created_before(time)
```
+### Merging of scopes
+
+Just like `where` clauses scopes are merged using `AND` conditions.
+
+```ruby
+class User < ActiveRecord::Base
+ scope :active, -> { where state: 'active' }
+ scope :inactive, -> { where state: 'inactive' }
+end
+
+```ruby
+User.active.inactive
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'inactive'
+```
+
+We can mix and match `scope` and `where` conditions and the final sql
+will have all conditions joined with `AND` .
+
+```ruby
+User.active.where(state: 'finished')
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'active' AND "users"."state" = 'finished'
+```
+
+If we do want the `last where clause` to win then `Relation#merge` can
+be used .
+
+```ruby
+User.active.merge(User.inactive)
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
+```
+
+One important caveat is that `default_scope` will be overridden by
+`scope` and `where` conditions.
+
+```ruby
+class User < ActiveRecord::Base
+ default_scope { where state: 'pending' }
+ scope :active, -> { where state: 'active' }
+ scope :inactive, -> { where state: 'inactive' }
+end
+
+User.all
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'pending'
+
+User.active
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'active'
+
+User.where(state: 'inactive')
+# => SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
+```
+
+As you can see above the `default_scope` is being overridden by both
+`scope` and `where` conditions.
+
+
### Applying a default scope
If we wish for a scope to be applied across all queries to the model we can use the
@@ -1242,7 +1294,7 @@ recommended that you use the block form of `unscoped`:
```ruby
Client.unscoped {
- Client.created_before(Time.zome.now)
+ Client.created_before(Time.zone.now)
}
```
@@ -1383,7 +1435,7 @@ Client.where(active: true).pluck(:id)
# SELECT id FROM clients WHERE active = 1
# => [1, 2, 3]
-Client.uniq.pluck(:role)
+Client.distinct.pluck(:role)
# SELECT DISTINCT role FROM clients
# => ['admin', 'member', 'guest']
@@ -1399,7 +1451,7 @@ Client.select(:id).map { |c| c.id }
# or
Client.select(:id).map(&:id)
# or
-Client.select(:id).map { |c| [c.id, c.name] }
+Client.select(:id, :name).map { |c| [c.id, c.name] }
```
with
diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md
index 32641d04c1..df39d3c5dc 100644
--- a/guides/source/active_record_validations.md
+++ b/guides/source/active_record_validations.md
@@ -530,6 +530,47 @@ field you should use `validates :field_name, inclusion: { in: [true, false] }`.
The default error message is _"can't be empty"_.
+### `absence`
+
+This helper validates that the specified attributes are absent. It uses the
+`present?` method to check if the value is not either nil or a blank string, that
+is, a string that is either empty or consists of whitespace.
+
+```ruby
+class Person < ActiveRecord::Base
+ validates :name, :login, :email, absence: true
+end
+```
+
+If you want to be sure that an association is absent, you'll need to test
+whether the associated object itself is absent, and not the foreign key used
+to map the association.
+
+```ruby
+class LineItem < ActiveRecord::Base
+ belongs_to :order
+ validates :order, absence: true
+end
+```
+
+In order to validate associated records whose absence is required, you must
+specify the `:inverse_of` option for the association:
+
+```ruby
+class Order < ActiveRecord::Base
+ has_many :line_items, inverse_of: :order
+end
+```
+
+If you validate the absence of an object associated via a `has_one` or
+`has_many` relationship, it will check that the object is neither `present?` nor
+`marked_for_destruction?`.
+
+Since `false.present?` is false, if you want to validate the absence of a boolean
+field you should use `validates :field_name, exclusion: { in: [true, false] }`.
+
+The default error message is _"must be blank"_.
+
### `uniqueness`
This helper validates that the attribute's value is unique right before the
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index 517db0d222..43529e3e96 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -1344,7 +1344,7 @@ The second argument, `indent_string`, specifies which indent string to use. The
"foo".indent(2, "\t") # => "\t\tfoo"
```
-While `indent_string` is tipically one space or tab, it may be any string.
+While `indent_string` is typically one space or tab, it may be any string.
The third argument, `indent_empty_lines`, is a flag that says whether empty lines should be indented. Default is false.
@@ -2198,7 +2198,7 @@ This method accepts three options:
* `:words_connector`: What is used to join the elements of arrays with 3 or more elements, except for the last two. Default is ", ".
* `:last_word_connector`: What is used to join the last items of an array with 3 or more elements. Default is ", and ".
-The defaults for these options can be localised, their keys are:
+The defaults for these options can be localized, their keys are:
| Option | I18n key |
| ---------------------- | ----------------------------------- |
diff --git a/guides/source/active_support_instrumentation.md b/guides/source/active_support_instrumentation.md
index 6b3be69942..38dbfd3152 100644
--- a/guides/source/active_support_instrumentation.md
+++ b/guides/source/active_support_instrumentation.md
@@ -273,7 +273,7 @@ Action Mailer
to: ["users@rails.com", "ddh@rails.com"],
from: ["me@rails.com"],
date: Sat, 10 Mar 2012 14:18:09 +0100,
- mail: "..." # ommitted for beverity
+ mail: "..." # omitted for brevity
}
```
@@ -299,7 +299,7 @@ Action Mailer
to: ["users@rails.com", "ddh@rails.com"],
from: ["me@rails.com"],
date: Sat, 10 Mar 2012 14:18:09 +0100,
- mail: "..." # ommitted for beverity
+ mail: "..." # omitted for brevity
}
```
@@ -428,7 +428,7 @@ end
```
Defining all those block arguments each time can be tedious. You can easily create an `ActiveSupport::Notifications::Event`
-from block args like this:
+from block arguments like this:
```ruby
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
@@ -442,7 +442,7 @@ ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*a
end
```
-Most times you only care about the data itself. Here is a shortuct to just get the data.
+Most times you only care about the data itself. Here is a shortcut to just get the data.
```ruby
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
@@ -450,7 +450,7 @@ ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*a
data # { extra: :information }
```
-You may also subscribe to events matching a regular expresssion. This enables you to subscribe to
+You may also subscribe to events matching a regular expression. This enables you to subscribe to
multiple events at once. Here's you could subscribe to everything from `ActionController`.
```ruby
@@ -465,7 +465,7 @@ Creating custom events
Adding your own events is easy as well. `ActiveSupport::Notifications` will take care of
all the heavy lifting for you. Simply call `instrument` with a `name`, `payload` and a block.
The notification will be sent after the block returns. `ActiveSupport` will generate the start and end times
-as well as the unique ID. All data passed into the `insturment` call will make it into the payload.
+as well as the unique ID. All data passed into the `instrument` call will make it into the payload.
Here's an example:
diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md
index e939606c88..448f0e1f9a 100644
--- a/guides/source/asset_pipeline.md
+++ b/guides/source/asset_pipeline.md
@@ -547,7 +547,35 @@ This directive is available if the core module that provides this feature was co
If you're compiling nginx with Phusion Passenger you'll need to pass that option when prompted.
-A robust configuration for Apache is possible but tricky; please Google around. (Or help update this Guide if you have a good example configuration for Apache.)
+Apache is also able to serve the [gzipped](http://en.wikipedia.org/wiki/Gzip) version of your assets; however, it requires a bit more work:
+
+```apache
+<LocationMatch "^/assets/.*$">
+ Header unset ETag
+ FileETag None
+
+ # RFC says only cache for 1 year
+ ExpiresActive On
+ ExpiresDefault "access plus 1 year"
+
+ RewriteEngine On
+ RewriteCond %{HTTP:Accept-Encoding} gzip
+ RewriteCond %{HTTP_USER_AGENT} !Konqueror
+ RewriteCond %{REQUEST_FILENAME}.gz -f
+ RewriteRule ^(.+).(css|js)$ $1.$2.gz [QSA,L]
+</LocationMatch>
+
+<FilesMatch \.css\.gz>
+ ForceType text/css
+</FilesMatch>
+
+<FilesMatch \.js\.gz>
+ ForceType application/javascript
+</FilesMatch>
+AddEncoding gzip .gz
+```
+
+NOTE: You will need to make sure `mod_headers`, `mod_mime` and `mod_rewrite` are loaded; otherwise, the above configuration will fail.
### Local Precompilation
@@ -740,7 +768,7 @@ end
```
Now that you have a `Template` class, it's time to associate it with an
-extenstion for template files:
+extension for template files:
```ruby
Sprockets.register_engine '.bang', BangBang::Template
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index dd59e2a8df..8d203d265a 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -572,7 +572,7 @@ end
These need to be backed up by a migration to create the `assemblies_parts` table. This table should be created without a primary key:
```ruby
-class CreateAssemblyPartJoinTable < ActiveRecord::Migration
+class CreateAssembliesPartsJoinTable < ActiveRecord::Migration
def change
create_table :assemblies_parts, id: false do |t|
t.integer :assembly_id
@@ -845,7 +845,7 @@ Counter cache columns are added to the containing model's list of read-only attr
##### `:dependent`
-If you set the `:dependent` option to `:destroy`, then deleting this object will call the `destroy` method on the associated object to delete that object. If you set the `:dependent` option to `:delete`, then deleting this object will delete the associated object _without_ calling its `destroy` method.
+If you set the `:dependent` option to `:destroy`, then deleting this object will call the `destroy` method on the associated object to delete that object. If you set the `:dependent` option to `:delete`, then deleting this object will delete the associated object _without_ calling its `destroy` method. If you set the `:dependent` option to `:restrict`, then attempting to delete this object will result in a `ActiveRecord::DeleteRestrictionError` if there are any associated objects.
WARNING: You should not specify this option on a `belongs_to` association that is connected with a `has_many` association on the other class. Doing so can lead to orphaned records in your database.
@@ -1109,7 +1109,7 @@ end
Controls what happens to the associated object when its owner is destroyed:
* `:destroy` causes the associated object to also be destroyed
-* `:delete` causes the asssociated object to be deleted directly from the database (so callbacks will not execute)
+* `:delete` causes the associated object to be deleted directly from the database (so callbacks will not execute)
* `:nullify` causes the foreign key to be set to `NULL`. Callbacks are not executed.
* `:restrict_with_exception` causes an exception to be raised if there is an associated record
* `:restrict_with_error` causes an error to be added to the owner if there is an associated object
@@ -1463,7 +1463,7 @@ end
Controls what happens to the associated objects when their owner is destroyed:
* `:destroy` causes all the associated objects to also be destroyed
-* `:delete_all` causes all the asssociated objects to be deleted directly from the database (so callbacks will not execute)
+* `:delete_all` causes all the associated objects to be deleted directly from the database (so callbacks will not execute)
* `:nullify` causes the foreign keys to be set to `NULL`. Callbacks are not executed.
* `:restrict_with_exception` causes an exception to be raised if there are any associated records
* `:restrict_with_error` causes an error to be added to the owner if there are any associated objects
@@ -1648,9 +1648,10 @@ The `select` method lets you override the SQL `SELECT` clause that is used to re
WARNING: If you specify your own `select`, be sure to include the primary key and foreign key columns of the associated model. If you do not, Rails will throw an error.
-##### `uniq`
+##### `distinct`
-Use the `uniq` method to keep the collection free of duplicates. This is mostly useful together with the `:through` option.
+Use the `distinct` method to keep the collection free of duplicates. This is
+mostly useful together with the `:through` option.
```ruby
class Person < ActiveRecord::Base
@@ -1666,14 +1667,15 @@ person.posts.inspect # => [#<Post id: 5, name: "a1">, #<Post id: 5, name: "a1">]
Reading.all.inspect # => [#<Reading id: 12, person_id: 5, post_id: 5>, #<Reading id: 13, person_id: 5, post_id: 5>]
```
-In the above case there are two readings and `person.posts` brings out both of them even though these records are pointing to the same post.
+In the above case there are two readings and `person.posts` brings out both of
+them even though these records are pointing to the same post.
-Now let's set `uniq`:
+Now let's set `distinct`:
```ruby
class Person
has_many :readings
- has_many :posts, -> { uniq }, through: :readings
+ has_many :posts, -> { distinct }, through: :readings
end
person = Person.create(name: 'Honda')
@@ -1684,7 +1686,29 @@ person.posts.inspect # => [#<Post id: 7, name: "a1">]
Reading.all.inspect # => [#<Reading id: 16, person_id: 7, post_id: 7>, #<Reading id: 17, person_id: 7, post_id: 7>]
```
-In the above case there are still two readings. However `person.posts` shows only one post because the collection loads only unique records.
+In the above case there are still two readings. However `person.posts` shows
+only one post because the collection loads only unique records.
+
+If you want to make sure that, upon insertion, all of the records in the
+persisted association are distinct (so that you can be sure that when you
+inspect the association that you will never find duplicate records), you should
+add a unique index on the table itself. For example, if you have a table named
+``person_posts`` and you want to make sure all the posts are unique, you could
+add the following in a migration:
+
+```ruby
+add_index :person_posts, :post, :unique => true
+```
+
+Note that checking for uniqueness using something like ``include?`` is subject
+to race conditions. Do not attempt to use ``include?`` to enforce distinctness
+in an association. For instance, using the post example from above, the
+following code would be racy because multiple users could be attempting this
+at the same time:
+
+```ruby
+person.posts << post unless person.posts.include?(post)
+```
#### When are Objects Saved?
diff --git a/guides/source/command_line.md b/guides/source/command_line.md
index 9d1fb03fab..4711186522 100644
--- a/guides/source/command_line.md
+++ b/guides/source/command_line.md
@@ -82,7 +82,7 @@ The server can be run on a different port using the `-p` option. The default dev
$ rails server -e production -p 4000
```
-The `-b` option binds Rails to the specified ip, by default it is 0.0.0.0. You can run a server as a daemon by passing a `-d` option.
+The `-b` option binds Rails to the specified IP, by default it is 0.0.0.0. You can run a server as a daemon by passing a `-d` option.
### `rails generate`
@@ -414,7 +414,7 @@ app/controllers/admin/users_controller.rb:
* [ 20] [TODO] any other way to do this?
* [132] [FIXME] high priority for next deploy
-app/model/school.rb:
+app/models/school.rb:
* [ 13] [OPTIMIZE] refactor this code to make it faster
* [ 17] [FIXME]
```
@@ -427,7 +427,7 @@ $ rake notes:fixme
app/controllers/admin/users_controller.rb:
* [132] high priority for next deploy
-app/model/school.rb:
+app/models/school.rb:
* [ 17]
```
@@ -436,7 +436,7 @@ You can also use custom annotations in your code and list them using `rake notes
```bash
$ rake notes:custom ANNOTATION=BUG
(in /home/foobar/commandsapp)
-app/model/post.rb:
+app/models/post.rb:
* [ 23] Have to fix this one before pushing!
```
@@ -448,7 +448,7 @@ By default, `rake notes` will look in the `app`, `config`, `lib`, `bin` and `tes
$ export SOURCE_ANNOTATION_DIRECTORIES='rspec,vendor'
$ rake notes
(in /home/foobar/commandsapp)
-app/model/user.rb:
+app/models/user.rb:
* [ 35] [FIXME] User should have a subscription at this point
rspec/model/user_spec.rb:
* [122] [TODO] Verify the user that has a subscription works
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index dbbeec7126..9ea493325d 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -646,7 +646,7 @@ Below is a comprehensive list of all the initializers found in Rails in the orde
* `active_support.initialize_time_zone` Sets the default time zone for the application based on the `config.time_zone` setting, which defaults to "UTC".
-* `active_support.initialize_beginning_of_week` Sets the default beginnig of week for the application based on `config.beginning_of_week` setting, which defaults to `:monday`.
+* `active_support.initialize_beginning_of_week` Sets the default beginning of week for the application based on `config.beginning_of_week` setting, which defaults to `:monday`.
* `action_dispatch.configure` Configures the `ActionDispatch::Http::URL.tld_length` to be set to the value of `config.action_dispatch.tld_length`.
@@ -698,7 +698,7 @@ Below is a comprehensive list of all the initializers found in Rails in the orde
* `engines_blank_point` Provides a point-in-initialization to hook into if you wish to do anything before engines are loaded. After this point, all railtie and engine initializers are run.
-* `add_generator_templates` Finds templates for generators at `lib/templates` for the application, railities and engines and adds these to the `config.generators.templates` setting, which will make the templates available for all generators to reference.
+* `add_generator_templates` Finds templates for generators at `lib/templates` for the application, railties and engines and adds these to the `config.generators.templates` setting, which will make the templates available for all generators to reference.
* `ensure_autoload_once_paths_as_subset` Ensures that the `config.autoload_once_paths` only contains paths from `config.autoload_paths`. If it contains extra paths, then an exception will be raised.
diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md
index 7909a00c47..0be9bb1ced 100644
--- a/guides/source/contributing_to_ruby_on_rails.md
+++ b/guides/source/contributing_to_ruby_on_rails.md
@@ -24,12 +24,20 @@ NOTE: Bugs in the most recent released version of Ruby on Rails are likely to ge
### Creating a Bug Report
-If you've found a problem in Ruby on Rails which is not a security risk, do a search in GitHub under [Issues](https://github.com/rails/rails/issues) in case it was already reported. If you find no issue addressing it you can [add a new one](https://github.com/rails/rails/issues/new). (See the next section for reporting security issues).
+If you've found a problem in Ruby on Rails which is not a security risk, do a search in GitHub under [Issues](https://github.com/rails/rails/issues) in case it was already reported. If you find no issue addressing it you can [add a new one](https://github.com/rails/rails/issues/new). (See the next section for reporting security issues.)
At the minimum, your issue report needs a title and descriptive text. But that's only a minimum. You should include as much relevant information as possible. You need at least to post the code sample that has the issue. Even better is to include a unit test that shows how the expected behavior is not occurring. Your goal should be to make it easy for yourself — and others — to replicate the bug and figure out a fix.
Then, don't get your hopes up! Unless you have a "Code Red, Mission Critical, the World is Coming to an End" kind of bug, you're creating this issue report in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the issue report will automatically see any activity or that others will jump to fix it. Creating an issue like this is mostly to help yourself start on the path of fixing the problem and for others to confirm it with an "I'm having this problem too" comment.
+### Create a Self-Contained gist for Active Record Issues
+
+If you are filing a bug report for Active Record, please use
+[this template for gems](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_gem.rb)
+if the bug is found in a published gem, and
+[this template for master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_master.rb)
+if the bug happens in the master branch.
+
### Special Treatment for Security Issues
WARNING: Please do not report security vulnerabilities with public GitHub issue reports. The [Rails security policy page](http://rubyonrails.org/security) details the procedure to follow for security issues.
@@ -53,6 +61,22 @@ The easiest and recommended way to get a development environment ready to hack i
In case you can't use the Rails development box, see section above, check [this other guide](development_dependencies_install.html).
+
+Running an Application Against Your Local Branch
+------------------------------------------------
+
+The `--dev` flag of `rails new` generates an application that uses your local
+branch:
+
+```bash
+$ cd rails
+$ bundle exec rails new ~/my-test-app --dev
+```
+
+The application generated in `~/my-test-app` runs against your local branch
+and in particular sees any modifications upon server reboot.
+
+
Testing Active Record
---------------------
@@ -190,7 +214,7 @@ $ cd rails
$ git checkout -b my_new_branch
```
-It doesn’t matter much what name you use, because this branch will only exist on your local computer and your personal repository on Github. It won't be part of the Rails Git repository.
+It doesn’t matter much what name you use, because this branch will only exist on your local computer and your personal repository on GitHub. It won't be part of the Rails Git repository.
### Write Your Code
@@ -201,6 +225,17 @@ Now get busy and add or edit code. You’re on your branch now, so you can write
* Include tests that fail without your code, and pass with it.
* Update the (surrounding) documentation, examples elsewhere, and the guides: whatever is affected by your contribution.
+It is not customary in Rails to run the full test suite before pushing
+changes. The railties test suite in particular takes a long time, and even
+more if the source code is mounted in `/vagrant` as happens in the recommended
+workflow with the [rails-dev-box](https://github.com/rails/rails-dev-box).
+
+As a compromise, test what your code obviously affects, and if the change is
+not in railties run the whole test suite of the affected component. If all is
+green that's enough to propose your contribution. We have [Travis CI](https
+://travis-ci.org/) as a safety net for catching unexpected breakages
+elsewhere.
+
TIP: Changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability of Rails will generally not be accepted.
### Follow the Coding Conventions
@@ -225,7 +260,7 @@ The above are guidelines — please use your best judgment in using them.
The CHANGELOG is an important part of every release. It keeps the list of changes for every Rails version.
-You should add an entry to the CHANGELOG of the framework that you modified if you're adding or removing a feature, commiting a bug fix or adding deprecation notices. Refactorings and documentation changes generally should not go to the CHANGELOG.
+You should add an entry to the CHANGELOG of the framework that you modified if you're adding or removing a feature, committing a bug fix or adding deprecation notices. Refactorings and documentation changes generally should not go to the CHANGELOG.
A CHANGELOG entry should summarize what was changed and should end with author's name. You can use multiple lines if you need more space and you can attach code examples indented with 4 spaces. If a change is related to a specific issue, you should attach issue's number. Here is an example CHANGELOG entry:
@@ -250,8 +285,6 @@ Your name can be added directly after the last word if you don't provide any cod
You should not be the only person who looks at the code before you submit it. You know at least one other Rails developer, right? Show them what you’re doing and ask for feedback. Doing this in private before you push a patch out publicly is the “smoke test” for a patch: if you can’t convince one other developer of the beauty of your code, you’re unlikely to convince the core team either.
-You might want also to check out the [RailsBridge BugMash](http://wiki.railsbridge.org/projects/railsbridge/wiki/BugMash) as a way to get involved in a group effort to improve Rails. This can help you get started and help you check your code when you're writing your first patches.
-
### Commit Your Changes
When you're happy with the code on your computer, you need to commit the changes to Git:
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index 5531dee343..6699098e51 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -23,7 +23,7 @@ One common task is to inspect the contents of a variable. In Rails, you can do t
### `debug`
-The `debug` helper will return a \<pre>-tag that renders the object using the YAML format. This will generate human-readable data from any object. For example, if you have this code in a view:
+The `debug` helper will return a \<pre> tag that renders the object using the YAML format. This will generate human-readable data from any object. For example, if you have this code in a view:
```html+erb
<%= debug @post %>
@@ -174,7 +174,7 @@ class PostsController < ApplicationController
end
```
-Here's an example of the log generated by this method:
+Here's an example of the log generated when this controller action is executed:
```
Processing PostsController#create (for 127.0.0.1 at 2008-09-08 11:52:54) [POST]
@@ -194,11 +194,11 @@ Redirected to #<Post:0x20af760>
Completed in 0.01224 (81 reqs/sec) | DB: 0.00044 (3%) | 302 Found [http://localhost/posts]
```
-Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels, to avoid filling your production logs with useless trivia.
+Adding extra logging like this makes it easy to search for unexpected or unusual behavior in your logs. If you add extra logging, be sure to make sensible use of log levels to avoid filling your production logs with useless trivia.
### Tagged Logging
-When running multi-user, multi-account applications, it’s often useful to be able to filter the logs using some custom rules. `TaggedLogging` in Active Support helps in doing exactly that by stamping log lines with subdomains, request ids, and anything else to aid debugging such applications.
+When running multi-user, multi-account applications, it’s often useful to be able to filter the logs using some custom rules. `TaggedLogging` in ActiveSupport helps in doing exactly that by stamping log lines with subdomains, request ids, and anything else to aid debugging such applications.
```ruby
logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
@@ -216,7 +216,7 @@ The debugger can also help you if you want to learn about the Rails source code
### Setup
-Rails uses the `debugger` gem to set breakpoints and step through live code. To install it, just run:
+You can use the `debugger` gem to set breakpoints and step through live code in Rails. To install it, just run:
```bash
$ gem install debugger
@@ -235,7 +235,7 @@ class PeopleController < ApplicationController
end
```
-If you see the message in the console or logs:
+If you see this message in the console or logs:
```
***** Debugger requested, but was not available: Start server with --debugger to enable *****
@@ -246,12 +246,12 @@ Make sure you have started your web server with the option `--debugger`:
```bash
$ rails server --debugger
=> Booting WEBrick
-=> Rails 3.0.0 application starting on http://0.0.0.0:3000
+=> Rails 3.2.13 application starting on http://0.0.0.0:3000
=> Debugger enabled
...
```
-TIP: In development mode, you can dynamically `require \'debugger\'` instead of restarting the server, if it was started without `--debugger`.
+TIP: In development mode, you can dynamically `require \'debugger\'` instead of restarting the server, even if it was started without `--debugger`.
### The Shell
@@ -266,7 +266,7 @@ For example:
(rdb:7)
```
-Now it's time to explore and dig into your application. A good place to start is by asking the debugger for help... so type: `help` (You didn't see that coming, right?)
+Now it's time to explore and dig into your application. A good place to start is by asking the debugger for help. Type: `help`
```
(rdb:7) help
@@ -281,7 +281,7 @@ condition down finish list ps save thread var
continue edit frame method putl set tmate where
```
-TIP: To view the help menu for any command use `help <command-name>` in active debug mode. For example: _`help var`_
+TIP: To view the help menu for any command use `help <command-name>` at the debugger prompt. For example: _`help var`_
The next command to learn is one of the most useful: `list`. You can abbreviate any debugging command by supplying just enough letters to distinguish them from other commands, so you can also use `l` for the `list` command.
@@ -289,7 +289,7 @@ This command shows you where you are in the code by printing 10 lines centered a
```
(rdb:7) list
-[1, 10] in /PathToProject/posts_controller.rb
+[1, 10] in /PathTo/project/app/controllers/posts_controller.rb
1 class PostsController < ApplicationController
2 # GET /posts
3 # GET /posts.json
@@ -325,7 +325,7 @@ On the other hand, to see the previous ten lines you should type `list-` (or `l-
```
(rdb:7) l-
-[1, 10] in /PathToProject/posts_controller.rb
+[1, 10] in /PathTo/project/app/controllers/posts_controller.rb
1 class PostsController < ApplicationController
2 # GET /posts
3 # GET /posts.json
@@ -343,7 +343,7 @@ Finally, to see where you are in the code again you can type `list=`
```
(rdb:7) list=
-[1, 10] in /PathToProject/posts_controller.rb
+[1, 10] in /PathTo/project/app/controllers/posts_controller.rb
1 class PostsController < ApplicationController
2 # GET /posts
3 # GET /posts.json
@@ -502,7 +502,7 @@ TIP: You can use the debugger while using `rails console`. Just remember to `req
```
$ rails console
-Loading development environment (Rails 3.1.0)
+Loading development environment (Rails 3.2.13)
>> require "debugger"
=> []
>> author = Author.first
diff --git a/guides/source/engines.md b/guides/source/engines.md
index 00939c4ff2..ac76f00832 100644
--- a/guides/source/engines.md
+++ b/guides/source/engines.md
@@ -676,7 +676,12 @@ There are now no strict dependencies on what the class is, only what the API for
Within an engine, there may come a time where you wish to use things such as initializers, internationalization or other configuration options. The great news is that these things are entirely possible because a Rails engine shares much the same functionality as a Rails application. In fact, a Rails application's functionality is actually a superset of what is provided by engines!
-If you wish to use an initializer — code that should run before the engine is loaded — the place for it is the `config/initializers` folder. This directory's functionality is explained in the [Initializers section](http://guides.rubyonrails.org/configuring.html#initializers) of the Configuring guide, and works precisely the same way as the `config/initializers` directory inside an application. Same goes for if you want to use a standard initializer.
+If you wish to use an initializer — code that should run before the engine is
+loaded — the place for it is the `config/initializers` folder. This directory's
+functionality is explained in the
+[Initializers section](configuring.html#initializers) of the Configuring guide,
+and works precisely the same way as the `config/initializers` directory inside
+an application. Same goes for if you want to use a standard initializer.
For locales, simply place the locale files in the `config/locales` directory, just like you would in an application.
@@ -918,7 +923,7 @@ initializer "blorgh.assets.precompile" do |app|
end
```
-For more information, read the [Asset Pipeline guide](http://guides.rubyonrails.org/asset_pipeline.html)
+For more information, read the [Asset Pipeline guide](asset_pipeline.html)
### Other gem dependencies
diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md
index b8681d493a..3f16ebcf1d 100644
--- a/guides/source/form_helpers.md
+++ b/guides/source/form_helpers.md
@@ -423,7 +423,7 @@ Whenever Rails sees that the internal value of an option being generated matches
TIP: The second argument to `options_for_select` must be exactly equal to the desired internal value. In particular if the value is the integer 2 you cannot pass "2" to `options_for_select` — you must pass 2. Be aware of values extracted from the `params` hash as they are all strings.
-WARNING: when `:inlude_blank` or `:prompt:` are not present, `:include_blank` is forced true if the select attribute `required` is true, display `size` is one and `multiple` is not true.
+WARNING: when `:include_blank` or `:prompt` are not present, `:include_blank` is forced true if the select attribute `required` is true, display `size` is one and `multiple` is not true.
You can add arbitrary attributes to the options using hashes:
@@ -906,7 +906,21 @@ If the associated object is already saved, `fields_for` autogenerates a hidden i
### The Controller
-You do not need to write any specific controller code to use nested attributes. Create and update records as you would with a simple form.
+As usual you need to
+[whitelist the parameters](action_controller_overview.html#strong-parameters) in
+the controller before you pass them to the model:
+
+```ruby
+def create
+ @person = Person.new(person_params)
+ # ...
+end
+
+private
+def person_params
+ params.require(:person).permit(:name, addresses_attributes: [:id, :kind, :street])
+end
+```
### Removing Objects
@@ -937,6 +951,16 @@ If the hash of attributes for an object contains the key `_destroy` with a value
<% end %>
```
+Don't forget to update the whitelisted params in your controller to also include
+the `_destroy` field:
+
+```ruby
+def person_params
+ params.require(:person).
+ permit(:name, addresses_attributes: [:id, :kind, :street, :_destroy])
+end
+```
+
### Preventing Empty Records
It is often useful to ignore sets of fields that the user has not filled in. You can control this by passing a `:reject_if` proc to `accepts_nested_attributes_for`. This proc will be called with each hash of attributes submitted by the form. If the proc returns `false` then Active Record will not build an associated object for that hash. The example below only tries to build an address if the `kind` attribute is set.
diff --git a/guides/source/generators.md b/guides/source/generators.md
index d7c789e2d8..a8a34d0ac4 100644
--- a/guides/source/generators.md
+++ b/guides/source/generators.md
@@ -589,11 +589,11 @@ Creates an initializer in the `config/initializers` directory of the application
initializer "begin.rb", "puts 'this is the beginning'"
```
-This method also takes a block:
+This method also takes a block, expected to return a string:
```ruby
initializer "begin.rb" do
- puts "Almost done!"
+ "puts 'this is the beginning'"
end
```
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 87f5e43157..3881bb1195 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -103,7 +103,7 @@ To verify that you have everything installed correctly, you should be able to ru
$ rails --version
```
-If it says something like "Rails 3.2.9", you are ready to continue.
+If it says something like "Rails 4.0.0", you are ready to continue.
### Creating the Blog Application
@@ -208,7 +208,7 @@ create app/assets/stylesheets/welcome.css.scss
Most important of these are of course the controller, located at `app/controllers/welcome_controller.rb` and the view, located at `app/views/welcome/index.html.erb`.
-Open the `app/views/welcome/index.html.erb` file in your text editor and edit it to contain a single line of code:
+Open the `app/views/welcome/index.html.erb` file in your text editor. Delete all of the existing code in the file, and replace it with the following single line of code:
```html
<h1>Hello, Rails!</h1>
@@ -278,7 +278,7 @@ With the route defined, requests can now be made to `/posts/new` in the applicat
![Another routing error, uninitialized constant PostsController](images/getting_started/routing_error_no_controller.png)
-This error is happening because this route need a controller to be defined. The route is attempting to find that controller so it can serve the request, but with the controller undefined, it just can't do that. The solution to this particular problem is simple: you need to create a controller called `PostsController`. You can do this by running this command:
+This error occurs because the route needs to have a controller defined in order to serve the request. The solution to this particular problem is simple: create a controller called `PostsController`. You can do this by running this command:
```bash
$ rails g controller posts
@@ -568,7 +568,7 @@ interested in. We also use an instance variable (prefixed by `@`) to
hold a reference to the post object. We do this because Rails will pass all instance
variables to the view.
-Now, create a new file `app/view/posts/show.html.erb` with the following
+Now, create a new file `app/views/posts/show.html.erb` with the following
content:
```html+erb
@@ -1761,7 +1761,7 @@ cannot be automatically detected by Rails and corrected.
Two very common sources of data that are not UTF-8:
-* Your text editor: Most text editors (such as Textmate), default to saving files as
+* Your text editor: Most text editors (such as TextMate), default to saving files as
UTF-8. If your text editor does not, this can result in special characters that you
enter in your templates (such as é) to appear as a diamond with a question mark inside
in the browser. This also applies to your i18n translation files.
diff --git a/guides/source/initialization.md b/guides/source/initialization.md
index 8ba5fa4601..412f2faaaa 100644
--- a/guides/source/initialization.md
+++ b/guides/source/initialization.md
@@ -266,7 +266,7 @@ def start
url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}"
puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}"
- puts "=> Call with -d to detach" unless options[:daemonize]
+ puts "=> Run `rails server -h` for more startup options"
trap(:INT) { exit }
puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md
index bfd1a7c61b..a3b3472701 100644
--- a/guides/source/layouts_and_rendering.md
+++ b/guides/source/layouts_and_rendering.md
@@ -363,7 +363,7 @@ You can use a symbol to defer the choice of layout until a request is processed:
```ruby
class ProductsController < ApplicationController
- layout "products_layout"
+ layout :products_layout
def show
@product = Product.find(params[:id])
diff --git a/guides/source/migrations.md b/guides/source/migrations.md
index 89ae564c24..086cf434d9 100644
--- a/guides/source/migrations.md
+++ b/guides/source/migrations.md
@@ -61,6 +61,10 @@ migrations are wrapped in a transaction. If the database does not support this
then when a migration fails the parts of it that succeeded will not be rolled
back. You will have to rollback the changes that were made by hand.
+NOTE: There are certain queries that can't run inside a transaction. If your
+adapter supports DDL transactions you can use `disable_ddl_transaction!` to
+disable them for a single migration.
+
If you wish for a migration to do something that Active Record doesn't know how
to reverse, you can use `reversible`:
@@ -180,7 +184,7 @@ end
```
If the migration name is of the form "CreateXXX" and is
-followed by a list of column names and types then a migration creating the table
+followed by a list of column names and types then a migration creating the table
XXX with the columns listed will be generated. For example:
```bash
@@ -827,7 +831,7 @@ end
```
```ruby
-# app/model/product.rb
+# app/models/product.rb
class Product < ActiveRecord::Base
validates :flag, presence: true
@@ -852,7 +856,7 @@ end
```
```ruby
-# app/model/product.rb
+# app/models/product.rb
class Product < ActiveRecord::Base
validates :flag, :fuzz, presence: true
diff --git a/guides/source/routing.md b/guides/source/routing.md
index d7a4a237ed..04098f0a5c 100644
--- a/guides/source/routing.md
+++ b/guides/source/routing.md
@@ -530,7 +530,7 @@ In particular, simple routing makes it very easy to map legacy URLs to new Rails
### Bound Parameters
-When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: `:controller` maps to the name of a controller in your application, and `:action` maps to the name of an action within that controller. For example, consider one of the default Rails routes:
+When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: `:controller` maps to the name of a controller in your application, and `:action` maps to the name of an action within that controller. For example, consider this route:
```ruby
get ':controller(/:action(/:id))'
@@ -850,7 +850,7 @@ resources :user_permissions, controller: 'admin/user_permissions'
This will route to the `Admin::UserPermissions` controller.
-NOTE: Only the directory notation is supported. specifying the
+NOTE: Only the directory notation is supported. Specifying the
controller with ruby constant notation (eg. `:controller =>
'Admin::UserPermissions'`) can lead to routing problems and results in
a warning.
diff --git a/guides/source/ruby_on_rails_guides_guidelines.md b/guides/source/ruby_on_rails_guides_guidelines.md
index a78711f4b2..136dfb4cae 100644
--- a/guides/source/ruby_on_rails_guides_guidelines.md
+++ b/guides/source/ruby_on_rails_guides_guidelines.md
@@ -65,7 +65,7 @@ HTML Guides
### Generation
-To generate all the guides, just `cd` into the **`guides`** directory, run `bundle install` and execute:
+To generate all the guides, just `cd` into the `guides` directory, run `bundle install` and execute:
```
bundle exec rake guides:generate
diff --git a/guides/source/security.md b/guides/source/security.md
index 769bd130be..d56ce47b3c 100644
--- a/guides/source/security.md
+++ b/guides/source/security.md
@@ -432,7 +432,7 @@ Depending on your web application, there may be more ways to hijack the user's a
INFO: _A CAPTCHA is a challenge-response test to determine that the response is not generated by a computer. It is often used to protect comment forms from automatic spam bots by asking the user to type the letters of a distorted image. The idea of a negative CAPTCHA is not for a user to prove that he is human, but reveal that a robot is a robot._
-But not only spam robots (bots) are a problem, but also automatic login bots. A popular CAPTCHA API is [reCAPTCHA](http://recaptcha.net/) which displays two distorted images of words from old books. It also adds an angled line, rather than a distorted background and high levels of warping on the text as earlier CAPTCHAs did, because the latter were broken. As a bonus, using reCAPTCHA helps to digitize old books. [ReCAPTCHA](http://ambethia.com/recaptcha/) is also a Rails plug-in with the same name as the API.
+But not only spam robots (bots) are a problem, but also automatic login bots. A popular CAPTCHA API is [reCAPTCHA](http://recaptcha.net/) which displays two distorted images of words from old books. It also adds an angled line, rather than a distorted background and high levels of warping on the text as earlier CAPTCHAs did, because the latter were broken. As a bonus, using reCAPTCHA helps to digitize old books. [ReCAPTCHA](https://github.com/ambethia/recaptcha/) is also a Rails plug-in with the same name as the API.
You will get two keys from the API, a public and a private key, which you have to put into your Rails environment. After that you can use the recaptcha_tags method in the view, and the verify_recaptcha method in the controller. Verify_recaptcha will return false if the validation fails.
The problem with CAPTCHAs is, they are annoying. Additionally, some visually impaired users have found certain kinds of distorted CAPTCHAs difficult to read. The idea of negative CAPTCHAs is not to ask a user to proof that he is human, but reveal that a spam robot is a bot.
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 540197e6e7..70061dc815 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -1,8 +1,7 @@
A Guide to Testing Rails Applications
=====================================
-This guide covers built-in mechanisms offered by Rails to test your
-application.
+This guide covers built-in mechanisms in Rails for testing your application.
After reading this guide, you will know:
@@ -38,11 +37,11 @@ Rails creates a `test` folder for you as soon as you create a Rails project usin
```bash
$ ls -F test
-
-fixtures/ functional/ integration/ test_helper.rb unit/
+controllers/ helpers/ mailers/ test_helper.rb
+fixtures/ integration/ models/
```
-The `unit` directory is meant to hold tests for your models, the `functional` directory is meant to hold tests for your controllers and the `integration` directory is meant to hold tests that involve any number of controllers interacting.
+The `models` directory is meant to hold tests for your models, the `controllers` directory is meant to hold tests for your controllers and the `integration` directory is meant to hold tests that involve any number of controllers interacting.
Fixtures are a way of organizing test data; they reside in the `fixtures` folder.
@@ -129,21 +128,20 @@ When you use `rails generate scaffold`, for a resource among other things it cre
$ rails generate scaffold post title:string body:text
...
create app/models/post.rb
-create test/models/post_test.rb
+create test/unit/post_test.rb
create test/fixtures/posts.yml
...
```
-The default test stub in `test/models/post_test.rb` looks like this:
+The default test stub in `test/unit/post_test.rb` looks like this:
```ruby
require 'test_helper'
class PostTest < ActiveSupport::TestCase
- # Replace this with your real tests.
- test "the truth" do
- assert true
- end
+ # test "the truth" do
+ # assert true
+ # end
end
```
@@ -224,34 +222,30 @@ TIP: You can see all these rake tasks and their descriptions by running `rake --
### Running Tests
-Running a test is as simple as invoking the file containing the test cases through Ruby:
+Running a test is as simple as invoking the file containing the test cases through `rails test` command.
```bash
-$ ruby -Itest test/models/post_test.rb
-
-Loaded suite models/post_test
-Started
+$ rails test test/models/post_test.rb
.
-Finished in 0.023513 seconds.
-1 tests, 1 assertions, 0 failures, 0 errors
-```
+Finished tests in 0.009262s, 107.9680 tests/s, 107.9680 assertions/s.
-This will run all the test methods from the test case. Note that `test_helper.rb` is in the `test` directory, hence this directory needs to be added to the load path using the `-I` switch.
+1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
+```
-You can also run a particular test method from the test case by using the `-n` switch with the `test method name`.
+You can also run a particular test method from the test case by running the test and using `-n` switch with the `test method name`.
```bash
-$ ruby -Itest test/models/post_test.rb -n test_the_truth
-
-Loaded suite models/post_test
-Started
+$ rails test test/models/post_test.rb -n test_the_truth
.
-Finished in 0.023513 seconds.
-1 tests, 1 assertions, 0 failures, 0 errors
+Finished tests in 0.009064s, 110.3266 tests/s, 110.3266 assertions/s.
+
+1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
```
+This will run all test methods from the test case. Note that `test_helper.rb` is in the `test` directory, hence this directory needs to be added to the load path using the `-I` switch.
+
The `.` (dot) above indicates a passing test. When a test fails you see an `F`; when a test throws an error you see an `E` in its place. The last line of the output is the summary.
To see how a test failure is reported, you can add a failing test to the `post_test.rb` test case.
@@ -266,17 +260,16 @@ end
Let us run this newly added test.
```bash
-$ ruby unit/post_test.rb -n test_should_not_save_post_without_title
-Loaded suite -e
-Started
+$ rails test test/models/post_test.rb -n test_should_not_save_post_without_title
F
-Finished in 0.102072 seconds.
+
+Finished tests in 0.044632s, 22.4054 tests/s, 22.4054 assertions/s.
1) Failure:
-test_should_not_save_post_without_title(PostTest) [/test/models/post_test.rb:6]:
-<false> is not true.
+test_should_not_save_post_without_title(PostTest) [test/models/post_test.rb:6]:
+Failed assertion, no message given.
-1 tests, 1 assertions, 1 failures, 0 errors
+1 tests, 1 assertions, 1 failures, 0 errors, 0 skips
```
In the output, `F` denotes a failure. You can see the corresponding trace shown under `1)` along with the name of the failing test. The next few lines contain the stack trace followed by a message which mentions the actual value and the expected value by the assertion. The default assertion messages provide just enough information to help pinpoint the error. To make the assertion failure message more readable, every assertion provides an optional message parameter, as shown here:
@@ -292,9 +285,8 @@ Running this test shows the friendlier assertion message:
```bash
1) Failure:
-test_should_not_save_post_without_title(PostTest) [/test/models/post_test.rb:6]:
-Saved the post without a title.
-<false> is not true.
+test_should_not_save_post_without_title(PostTest) [test/models/post_test.rb:6]:
+Saved the post without a title
```
Now to get this test to pass we can add a model level validation for the _title_ field.
@@ -308,13 +300,12 @@ end
Now the test should pass. Let us verify by running the test again:
```bash
-$ ruby unit/post_test.rb -n test_should_not_save_post_without_title
-Loaded suite unit/post_test
-Started
+$ rails test test/models/post_test.rb -n test_should_not_save_post_without_title
.
-Finished in 0.193608 seconds.
-1 tests, 1 assertions, 0 failures, 0 errors
+Finished tests in 0.047721s, 20.9551 tests/s, 20.9551 assertions/s.
+
+1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
```
Now, if you noticed, we first wrote a test which fails for a desired functionality, then we wrote some code which adds the functionality and finally we ensured that our test passes. This approach to software development is referred to as _Test-Driven Development_ (TDD).
@@ -334,18 +325,17 @@ end
Now you can see even more output in the console from running the tests:
```bash
-$ ruby unit/post_test.rb -n test_should_report_error
-Loaded suite -e
-Started
+$ rails test test/models/post_test.rb -n test_should_report_error
E
-Finished in 0.082603 seconds.
+
+Finished tests in 0.030974s, 32.2851 tests/s, 0.0000 assertions/s.
1) Error:
test_should_report_error(PostTest):
-NameError: undefined local variable or method `some_undefined_variable' for #<PostTest:0x249d354>
- /test/models/post_test.rb:6:in `test_should_report_error'
+NameError: undefined local variable or method `some_undefined_variable' for #<PostTest:0x007fe32e24afe0>
+ test/models/post_test.rb:10:in `block in <class:PostTest>'
-1 tests, 0 assertions, 0 failures, 1 errors
+1 tests, 0 assertions, 0 failures, 1 errors, 0 skips
```
Notice the 'E' in the output. It denotes a test with error.
@@ -511,6 +501,21 @@ You also have access to three instance variables in your functional tests:
* `@request` - The request
* `@response` - The response
+### Setting Headers and CGI variables
+
+Headers and cgi variables can be set directly on the `@request`
+instance variable:
+
+```ruby
+# setting a HTTP Header
+@request.headers["Accepts"] = "text/plain, text/html"
+get :index # simulate the request with custom header
+
+# setting a CGI variable
+@request.headers["HTTP_REFERER"] = "http://example.com/home"
+post :create # simulate the request with custom env variable
+```
+
### Testing Templates and Layouts
If you want to make sure that the response rendered the correct template and layout, you can use the `assert_template`
@@ -642,12 +647,9 @@ Here's what a freshly-generated integration test looks like:
require 'test_helper'
class UserFlowsTest < ActionDispatch::IntegrationTest
- fixtures :all
-
- # Replace this with your real tests.
- test "the truth" do
- assert true
- end
+ # test "the truth" do
+ # assert true
+ # end
end
```
@@ -688,9 +690,9 @@ class UserFlowsTest < ActionDispatch::IntegrationTest
get "/login"
assert_response :success
- post_via_redirect "/login", username: users(:avs).username, password: users(:avs).password
+ post_via_redirect "/login", username: users(:david).username, password: users(:david).password
assert_equal '/welcome', path
- assert_equal 'Welcome avs!', flash[:notice]
+ assert_equal 'Welcome david!', flash[:notice]
https!(false)
get "/posts/all"
@@ -713,12 +715,12 @@ class UserFlowsTest < ActionDispatch::IntegrationTest
test "login and browse site" do
# User avs logs in
- avs = login(:avs)
+ avs = login(:david)
# User guest logs in
guest = login(:guest)
# Both are now available in different sessions
- assert_equal 'Welcome avs!', avs.flash[:notice]
+ assert_equal 'Welcome david!', avs.flash[:notice]
assert_equal 'Welcome guest!', guest.flash[:notice]
# User avs can browse site
@@ -755,23 +757,28 @@ end
Rake Tasks for Running your Tests
---------------------------------
-You don't need to set up and run your tests by hand on a test-by-test basis. Rails comes with a number of rake tasks to help in testing. The table below lists all rake tasks that come along in the default Rakefile when you initiate a Rails project.
+You don't need to set up and run your tests by hand on a test-by-test basis. Rails comes with a number of commands to help in testing. The table below lists all commands that come along in the default Rakefile when you initiate a Rails project.
+
+| Tasks | Description |
+| ------------------------ | ----------- |
+| `rails test` | Runs all unit, functional and integration tests. You can also simply run `rails test` as Rails will run all the tests by default|
+| `rails test controllers` | Runs all the controller tests from `test/controllers`|
+| `rails test functionals` | Runs all the functional tests from `test/controllers`, `test/mailers`, and `test/functional`|
+| `rails test helpers` | Runs all the helper tests from `test/helpers`|
+| `rails test integration` | Runs all the integration tests from `test/integration`|
+| `rails test mailers` | Runs all the mailer tests from `test/mailers`|
+| `rails test models` | Runs all the model tests from `test/models`|
+| `rails test units` | Runs all the unit tests from `test/models`, `test/helpers`, and `test/unit`|
-| Tasks | Description |
-| ------------------------------- | ----------- |
-| `rake test` | Runs all unit, functional and integration tests. You can also simply run `rake` as the _test_ target is the default.|
-| `rake test:controllers` | Runs all the controller tests from `test/controllers`|
-| `rake test:functionals` | Runs all the functional tests from `test/controllers`, `test/mailers`, and `test/functional`|
-| `rake test:helpers` | Runs all the helper tests from `test/helpers`|
-| `rake test:integration` | Runs all the integration tests from `test/integration`|
-| `rake test:mailers` | Runs all the mailer tests from `test/mailers`|
-| `rake test:models` | Runs all the model tests from `test/models`|
-| `rake test:recent` | Tests recent changes|
-| `rake test:uncommitted` | Runs all the tests which are uncommitted. Supports Subversion and Git|
-| `rake test:units` | Runs all the unit tests from `test/models`, `test/helpers`, and `test/unit`|
+There're also some test commands which you can initiate by running rake tasks:
+| Tasks | Description |
+| ------------------------ | ----------- |
+| `rake test` | Runs all unit, functional and integration tests. You can also simply run `rake` as the _test_ target is the default.|
+| `rake test:recent` | Tests recent changes|
+| `rake test:uncommitted` | Runs all the tests which are uncommitted. Supports Subversion and Git|
-Brief Note About `Test::Unit`
+Brief Note About `MiniTest`
-----------------------------
Ruby ships with a boat load of libraries. Ruby 1.8 provides `Test::Unit`, a framework for unit testing in Ruby. All the basic assertions discussed above are actually defined in `Test::Unit::Assertions`. The class `ActiveSupport::TestCase` which we have been using in our unit and functional tests extends `Test::Unit::TestCase`, allowing
@@ -920,19 +927,24 @@ require 'test_helper'
class UserMailerTest < ActionMailer::TestCase
tests UserMailer
test "invite" do
- @expected.from = 'me@example.com'
- @expected.to = 'friend@example.com'
- @expected.subject = "You have been invited by #{@expected.from}"
- @expected.body = read_fixture('invite')
- @expected.date = Time.now
-
- assert_equal @expected.encoded, UserMailer.create_invite('me@example.com', 'friend@example.com', @expected.date).encoded
+ # Send the email, then test that it got queued
+ email = UserMailer.create_invite('me@example.com',
+ 'friend@example.com', Time.now).deliver
+ assert !ActionMailer::Base.deliveries.empty?
+
+ # Test the body of the sent email contains what we expect it to
+ assert_equal ['me@example.com'], email.from
+ assert_equal ['friend@example.com'], email.to
+ assert_equal 'You have been invited by me@example.com', email.subject
+ assert_equal read_fixture('invite').join, email.body.to_s
end
-
end
```
-In this test, `@expected` is an instance of `TMail::Mail` that you can use in your tests. It is defined in `ActionMailer::TestCase`. The test above uses `@expected` to construct an email, which it then asserts with email created by the custom mailer. The `invite` fixture is the body of the email and is used as the sample content to assert against. The helper `read_fixture` is used to read in the content from this file.
+In the test we send the email and store the returned object in the `email`
+variable. We then ensure that it was sent (the first assert), then, in the
+second batch of assertions, we ensure that the email does indeed contain what we
+expect. The helper `read_fixture` is used to read in the content from this file.
Here's the content of the `invite` fixture:
@@ -944,9 +956,17 @@ You have been invited.
Cheers!
```
-This is the right time to understand a little more about writing tests for your mailers. The line `ActionMailer::Base.delivery_method = :test` in `config/environments/test.rb` sets the delivery method to test mode so that email will not actually be delivered (useful to avoid spamming your users while testing) but instead it will be appended to an array (`ActionMailer::Base.deliveries`).
+This is the right time to understand a little more about writing tests for your
+mailers. The line `ActionMailer::Base.delivery_method = :test` in
+`config/environments/test.rb` sets the delivery method to test mode so that
+email will not actually be delivered (useful to avoid spamming your users while
+testing) but instead it will be appended to an array
+(`ActionMailer::Base.deliveries`).
-This way, emails are not actually sent, simply constructed. The precise content of the email can then be checked against what is expected, as in the example above.
+NOTE: The `ActionMailer::Base.deliveries` array is only reset automatically in
+`ActionMailer::TestCase` tests. If you want to have a clean slate outside Action
+Mailer tests, you can reset it manually with:
+`ActionMailer::Base.deliveries.clear`
### Functional Testing
@@ -977,5 +997,6 @@ The built-in `test/unit` based testing is not the only way to test Rails applica
* [NullDB](http://avdi.org/projects/nulldb/), a way to speed up testing by avoiding database use.
* [Factory Girl](https://github.com/thoughtbot/factory_girl/tree/master), a replacement for fixtures.
* [Machinist](https://github.com/notahat/machinist/tree/master), another replacement for fixtures.
+* [MiniTest::Spec Rails](https://github.com/metaskills/minitest-spec-rails), use the MiniTest::Spec DSL within your rails tests.
* [Shoulda](http://www.thoughtbot.com/projects/shoulda), an extension to `test/unit` with additional helpers, macros, and assertions.
* [RSpec](http://relishapp.com/rspec), a behavior-driven development framework
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 57945a256b..a8182617f3 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -31,6 +31,10 @@ If your application is currently on any version of Rails older than 3.2.x, you s
The following changes are meant for upgrading your application to Rails 4.0.
+### Gemfile
+
+Rails 4.0 removed the `assets` group from Gemfile. You'd need to remove that line from your Gemfile when upgrading.
+
### vendor/plugins
Rails 4.0 no longer supports loading plugins from `vendor/plugins`. You must replace any plugins by extracting them to gems and adding them to your Gemfile. If you choose not to make them gems, you can move them into, say, `lib/my_plugin/*` and add an appropriate initializer in `config/initializers/my_plugin.rb`.
@@ -43,7 +47,7 @@ Rails 4.0 no longer supports loading plugins from `vendor/plugins`. You must rep
* Rails 4.0 has changed how orders get stacked in `ActiveRecord::Relation`. In previous versions of Rails, the new order was applied after the previously defined order. But this is no longer true. Check [Active Record Query guide](active_record_querying.html#ordering) for more information.
-* Rails 4.0 has changed `serialized_attributes` and `attr_readonly` to class methods only. Now you shouldn't use instance methods, it's deprecated. You must change them, e.g. `self.serialized_attributes` to `self.class.serialized_attributes`.
+* Rails 4.0 has changed `serialized_attributes` and `attr_readonly` to class methods only. You shouldn't use instance methods since it's now deprecated. You should change them to use class methods, e.g. `self.serialized_attributes` to `self.class.serialized_attributes`.
* Rails 4.0 has removed `attr_accessible` and `attr_protected` feature in favor of Strong Parameters. You can use the [Protected Attributes gem](https://github.com/rails/protected_attributes) to a smoothly upgrade path.
@@ -65,9 +69,9 @@ Rails 4.0 extracted Active Resource to its own gem. If you still need the featur
### Active Model
-* Rails 4.0 has changed how errors attach with the `ActiveModel::Validations::ConfirmationValidator`. Now when confirmation validations fail the error will be attached to `:#{attribute}_confirmation` instead of `attribute`.
+* Rails 4.0 has changed how errors attach with the `ActiveModel::Validations::ConfirmationValidator`. Now when confirmation validations fail, the error will be attached to `:#{attribute}_confirmation` instead of `attribute`.
-* Rails 4.0 has changed `ActiveModel::Serializers::JSON.include_root_in_json` default value to `false`. Now, Active Model Serializers and Active Record objects have the same default behaviour. This means that you can comment or remove the following option in the `config/initializers/wrap_parameters.rb` file:
+* Rails 4.0 has changed `ActiveModel::Serializers::JSON.include_root_in_json` default value to `false`. Now, Active Model Serializers and Active Record objects have the same default behavior. This means that you can comment or remove the following option in the `config/initializers/wrap_parameters.rb` file:
```ruby
# Disable root element in JSON by default.
@@ -78,17 +82,32 @@ Rails 4.0 extracted Active Resource to its own gem. If you still need the featur
### Action Pack
-* Rails 4.0 introduces a new `UpgradeSignatureToEncryptionCookieStore` cookie store. This is useful for upgrading apps using the old default `CookieStore` to the new default `EncryptedCookieStore`. To use this transitional cookie store, you'll want to leave your existing `secret_token` in place, add a new `secret_key_base`, and change your `session_store` like so:
+* Rails 4.0 introduces `ActiveSupport::KeyGenerator` and uses this as a base from which to generate and verify signed cookies (among other things). Existing signed cookies generated with Rails 3.x will be transparently upgraded if you leave your existing `secret_token` in place and add the new `secret_key_base`.
```ruby
- # config/initializers/session_store.rb
- Myapp::Application.config.session_store :upgrade_signature_to_encryption_cookie_store, key: 'existing session key'
+ # config/initializers/secret_token.rb
+ Myapp::Application.config.secret_token = 'existing secret token'
+ Myapp::Application.config.secret_key_base = 'new secret key base'
+```
+
+Please note that you should wait to set `secret_key_base` until you have 100% of your userbase on Rails 4.x and are reasonably sure you will not need to rollback to Rails 3.x. This is because cookies signed based on the new `secret_key_base` in Rails 4.x are not backwards compatible with Rails 3.x. You are free to leave your existing `secret_token` in place, not set the new `secret_key_base`, and ignore the deprecation warnings until you are reasonably sure that your upgrade is otherwise complete.
+
+If you are relying on the ability for external applications or Javascript to be able to read your Rails app's signed session cookies (or signed cookies in general) you should not set `secret_key_base` until you have decoupled these concerns.
+
+* Rails 4.0 encrypts the contents of cookie-based sessions if `secret_key_base` has been set. Rails 3.x signed, but did not encrypt, the contents of cookie-based session. Signed cookies are "secure" in that they are verified to have been generated by your app and are tamper-proof. However, the contents can be viewed by end users, and encrypting the contents eliminates this caveat/concern without a significant performance penalty.
+
+As described above, existing signed cookies generated with Rails 3.x will be transparently upgraded if you leave your existing `secret_token` in place and add the new `secret_key_base`.
+```ruby
# config/initializers/secret_token.rb
Myapp::Application.config.secret_token = 'existing secret token'
Myapp::Application.config.secret_key_base = 'new secret key base'
```
+The same caveats apply here, too. You should wait to set `secret_key_base` until you have 100% of your userbase on Rails 4.x and are reasonably sure you will not need to rollback to Rails 3.x. You should also take care to make sure you are not relying on the ability to decode signed cookies generated by your app in external applications or Javascript before upgrading.
+
+Please read [Pull Request #9978](https://github.com/rails/rails/pull/9978) for details on the move to encrypted session cookies.
+
* Rails 4.0 removed the `ActionController::Base.asset_path` option. Use the assets pipeline feature.
* Rails 4.0 has deprecated `ActionController::Base.page_cache_extension` option. Use `ActionController::Base.default_static_extension` instead.
@@ -103,6 +122,23 @@ Rails 4.0 extracted Active Resource to its own gem. If you still need the featur
* Rails 4.0 changed how `assert_generates`, `assert_recognizes`, and `assert_routing` work. Now all these assertions raise `Assertion` instead of `ActionController::RoutingError`.
+* Rails 4.0 raises an `ArgumentError` if clashing named routes are defined. This can be triggered by explicitly defined named routes or by the `resources` method. Here are two examples that clash with routes named `example_path`:
+
+```ruby
+ get 'one' => 'test#example', as: :example
+ get 'two' => 'test#example', as: :example
+```
+
+```ruby
+ resources :examples
+ get 'clashing/:id' => 'test#example', as: :example
+```
+
+In the first case, you can simply avoid using the same name for multiple
+routes. In the second, you can use the `only` or `except` options provided by
+the `resources` method to restrict the routes created as detailed in the
+[Routing Guide](routing.html#restricting-the-routes-created).
+
* Rails 4.0 also changed the way unicode character routes are drawn. Now you can draw unicode character routes directly. If you already draw such routes, you must change them, for example:
```ruby
@@ -128,7 +164,7 @@ get 'こんにちは', controller: 'welcome', action: 'index'
get "/" => "root#index"
```
-* Rails 4.0 has removed ActionDispatch::BestStandardsSupport middleware, !DOCTYPE html already triggers standards mode per http://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx and ChromeFrame header has been moved to `config.action_dispatch.default_headers`
+* Rails 4.0 has removed `ActionDispatch::BestStandardsSupport` middleware, `<!DOCTYPE html>` already triggers standards mode per http://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx and ChromeFrame header has been moved to `config.action_dispatch.default_headers`.
Remember you must also remove any references to the middleware from your application code, for example:
@@ -284,7 +320,7 @@ config.assets.debug = true
Again, most of the changes below are for the asset pipeline. You can read more about these in the [Asset Pipeline](asset_pipeline.html) guide.
```ruby
-# Compress JavaScripts and CSS
+# Compress JavaScript and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
diff --git a/guides/source/working_with_javascript_in_rails.md b/guides/source/working_with_javascript_in_rails.md
index 7c4192ee26..ddefaf6ff8 100644
--- a/guides/source/working_with_javascript_in_rails.md
+++ b/guides/source/working_with_javascript_in_rails.md
@@ -394,3 +394,4 @@ Here are some helpful links to help you learn even more:
* [jquery-ujs list of external articles](https://github.com/rails/jquery-ujs/wiki/External-articles)
* [Rails 3 Remote Links and Forms: A Definitive Guide](http://www.alfajango.com/blog/rails-3-remote-links-and-forms/)
* [Railscasts: Unobtrusive JavaScript](http://railscasts.com/episodes/205-unobtrusive-javascript)
+* [Railscasts: Turbolinks](http://railscasts.com/episodes/390-turbolinks) \ No newline at end of file