aboutsummaryrefslogtreecommitdiffstats
path: root/guides
diff options
context:
space:
mode:
Diffstat (limited to 'guides')
-rw-r--r--guides/bug_report_templates/active_record_gem.rb37
-rw-r--r--guides/bug_report_templates/active_record_master.rb48
-rw-r--r--guides/code/getting_started/Gemfile2
-rw-r--r--guides/code/getting_started/app/assets/images/rails.pngbin6646 -> 0 bytes
-rw-r--r--guides/code/getting_started/config/initializers/session_store.rb2
-rw-r--r--guides/source/action_mailer_basics.md338
-rw-r--r--guides/source/active_support_core_extensions.md2
-rw-r--r--guides/source/asset_pipeline.md30
-rw-r--r--guides/source/association_basics.md36
-rw-r--r--guides/source/contributing_to_ruby_on_rails.md10
-rw-r--r--guides/source/documents.yaml1
-rw-r--r--guides/source/testing.md30
-rw-r--r--guides/source/upgrading_ruby_on_rails.md37
13 files changed, 381 insertions, 192 deletions
diff --git a/guides/bug_report_templates/active_record_gem.rb b/guides/bug_report_templates/active_record_gem.rb
new file mode 100644
index 0000000000..2c63342572
--- /dev/null
+++ b/guides/bug_report_templates/active_record_gem.rb
@@ -0,0 +1,37 @@
+# Activate the gem you are reporting the issue against.
+gem 'activerecord', '3.2.11'
+require 'active_record'
+require 'minitest/autorun'
+require 'logger'
+
+# This connection will do for database-independent bug reports.
+ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
+ActiveRecord::Base.logger = Logger.new(STDOUT)
+
+ActiveRecord::Schema.define do
+ create_table :posts do |t|
+ end
+
+ create_table :comments do |t|
+ t.integer :post_id
+ end
+end
+
+class Post < ActiveRecord::Base
+ has_many :comments
+end
+
+class Comment < ActiveRecord::Base
+ belongs_to :post
+end
+
+class BugTest < MiniTest::Unit::TestCase
+ def test_association_stuff
+ post = Post.create!
+ post.comments << Comment.create!
+
+ assert_equal 1, post.comments.count
+ assert_equal 1, Comment.count
+ assert_equal post.id, Comment.first.post.id
+ end
+end
diff --git a/guides/bug_report_templates/active_record_master.rb b/guides/bug_report_templates/active_record_master.rb
new file mode 100644
index 0000000000..68069cdd8d
--- /dev/null
+++ b/guides/bug_report_templates/active_record_master.rb
@@ -0,0 +1,48 @@
+unless File.exists?('Gemfile')
+ File.write('Gemfile', <<-GEMFILE)
+ source 'https://rubygems.org'
+ gem 'rails', github: 'rails/rails'
+ gem 'sqlite3'
+ GEMFILE
+
+ system 'bundle'
+end
+
+require 'bundler'
+Bundler.setup(:default)
+
+require 'active_record'
+require 'minitest/autorun'
+require 'logger'
+
+# This connection will do for database-independent bug reports.
+ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
+ActiveRecord::Base.logger = Logger.new(STDOUT)
+
+ActiveRecord::Schema.define do
+ create_table :posts do |t|
+ end
+
+ create_table :comments do |t|
+ t.integer :post_id
+ end
+end
+
+class Post < ActiveRecord::Base
+ has_many :comments
+end
+
+class Comment < ActiveRecord::Base
+ belongs_to :post
+end
+
+class BugTest < MiniTest::Unit::TestCase
+ def test_association_stuff
+ post = Post.create!
+ post.comments << Comment.create!
+
+ assert_equal 1, post.comments.count
+ assert_equal 1, Comment.count
+ assert_equal post.id, Comment.first.post.id
+ end
+end
diff --git a/guides/code/getting_started/Gemfile b/guides/code/getting_started/Gemfile
index 5b574cfc1d..f06fc65de6 100644
--- a/guides/code/getting_started/Gemfile
+++ b/guides/code/getting_started/Gemfile
@@ -23,7 +23,7 @@ gem 'turbolinks'
group :doc do
# bundle exec rake doc:rails generates the API under doc/api.
- gem 'sdoc'
+ gem 'sdoc', require: false
end
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
diff --git a/guides/code/getting_started/app/assets/images/rails.png b/guides/code/getting_started/app/assets/images/rails.png
deleted file mode 100644
index d5edc04e65..0000000000
--- a/guides/code/getting_started/app/assets/images/rails.png
+++ /dev/null
Binary files differ
diff --git a/guides/code/getting_started/config/initializers/session_store.rb b/guides/code/getting_started/config/initializers/session_store.rb
index 2e37d93799..3b2ca93ab9 100644
--- a/guides/code/getting_started/config/initializers/session_store.rb
+++ b/guides/code/getting_started/config/initializers/session_store.rb
@@ -1,3 +1,3 @@
# Be sure to restart your server when you modify this file.
-Blog::Application.config.session_store :encrypted_cookie_store, key: '_blog_session'
+Blog::Application.config.session_store :cookie_store, key: '_blog_session'
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index 698fe30722..ec7b8d4e17 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -1,7 +1,9 @@
Action Mailer Basics
====================
-This guide should provide you with all you need to get started in sending and receiving emails from and to your application, and many internals of Action Mailer. It also covers how to test your mailers.
+This guide should provide you with all you need to get started in sending and
+receiving emails from and to your application, and many internals of Action
+Mailer. It also covers how to test your mailers.
After reading this guide, you will know:
@@ -9,6 +11,7 @@ After reading this guide, you will know:
* How to generate and edit an Action Mailer class and mailer view.
* How to configure Action Mailer for your environment.
* How to test your Action Mailer classes.
+
--------------------------------------------------------------------------------
Introduction
@@ -19,7 +22,8 @@ Action Mailer allows you to send emails from your application using mailer class
Sending Emails
--------------
-This section will provide a step-by-step guide to creating a mailer and its views.
+This section will provide a step-by-step guide to creating a mailer and its
+views.
### Walkthrough to Generating a Mailer
@@ -34,10 +38,25 @@ invoke test_unit
create test/mailers/user_mailer_test.rb
```
-A mailer, a views subdirectory, and tests were created.
+As you can see, you can generate mailers just like you use other generators with
+Rails. Mailers are conceptually similar to controllers, and so we get a mailer,
+a directory for views, and a test.
+
+If you didn't want to use a generator, you could create your own file inside of
+app/mailers, just make sure that it inherits from `ActionMailer::Base`:
+
+```ruby
+class MyMailer < ActionMailer::Base
+end
+```
#### Edit the Mailer
+Mailers are very similar to Rails controllers. They also have methods called
+"actions" and use views to structure the content. Where a controller generates
+content like HTML to send back to the client, a Mailer creates a message to be
+delivered via email.
+
`app/mailers/user_mailer.rb` contains an empty mailer:
```ruby
@@ -46,7 +65,8 @@ class UserMailer < ActionMailer::Base
end
```
-Let's add a method called `welcome_email` that will send an email to the user's registered email address:
+Let's add a method called `welcome_email`, that will send an email to the user's
+registered email address:
```ruby
class UserMailer < ActionMailer::Base
@@ -55,21 +75,25 @@ class UserMailer < ActionMailer::Base
def welcome_email(user)
@user = user
@url = 'http://example.com/login'
- mail(to: user.email, subject: 'Welcome to My Awesome Site')
+ mail(to: @user.email, subject: 'Welcome to My Awesome Site')
end
end
```
-Here is a quick explanation of the items presented in the preceding method. For a full list of all available options, please have a look further down at the Complete List of Action Mailer user-settable attributes section.
+Here is a quick explanation of the items presented in the preceding method. For
+a full list of all available options, please have a look further down at the
+Complete List of Action Mailer user-settable attributes section.
* `default Hash` - This is a hash of default values for any email you send from this mailer. In this case we are setting the `:from` header to a value for all messages in this class. This can be overridden on a per-email basis.
* `mail` - The actual email message, we are passing the `:to` and `:subject` headers in.
-Just like controllers, any instance variables we define in the method become available for use in the views.
+Just like controllers, any instance variables we define in the method become
+available for use in the views.
#### Create a Mailer View
-Create a file called `welcome_email.html.erb` in `app/views/user_mailer/`. This will be the template used for the email, formatted in HTML:
+Create a file called `welcome_email.html.erb` in `app/views/user_mailer/`. This
+will be the template used for the email, formatted in HTML:
```html+erb
<!DOCTYPE html>
@@ -91,7 +115,9 @@ Create a file called `welcome_email.html.erb` in `app/views/user_mailer/`. This
</html>
```
-It is also a good idea to make a text template for this email. To do this, create a file called `welcome_email.text.erb` in `app/views/user_mailer/`:
+Let's also make a text part for this email. Not all clients prefer HTML emails,
+and so sending both is best practice. To do this, create a file called
+`welcome_email.text.erb` in `app/views/user_mailer/`:
```erb
Welcome to example.com, <%= @user.name %>
@@ -105,11 +131,15 @@ To login to the site, just follow this link: <%= @url %>.
Thanks for joining and have a great day!
```
-When you call the `mail` method now, Action Mailer will detect the two templates (text and HTML) and automatically generate a `multipart/alternative` email.
+When you call the `mail` method now, Action Mailer will detect the two templates
+(text and HTML) and automatically generate a `multipart/alternative` email.
-#### Wire It Up So That the System Sends the Email When a User Signs Up
+#### Calling the Mailer
-There are several ways to do this. Some people create Rails Observers to fire off emails when things change in your application, others do it using model callbacks. However, mailers are really just another way to render a view. Instead of rendering a view and sending out the HTTP protocol, they are just sending it out through the Email protocol instead. Due to this, it makes sense to just have your controller tell the mailer to send an email when a user is successfully created.
+Mailers are really just another way to render a view. Instead of rendering a
+view and sending out the HTTP protocol, they are just sending it out through the
+Email protocols instead. Due to this, it makes sense to just have your
+controller tell the Mailer to send an email when a user is successfully created.
Setting this up is painfully simple.
@@ -120,7 +150,10 @@ $ rails generate scaffold user name email login
$ rake db:migrate
```
-Now that we have a user model to play with, we will just edit the `app/controllers/users_controller.rb` to make it instruct the UserMailer to deliver an email to the newly created user by editing the create action and inserting a call to `UserMailer.welcome_email` right after the user is successfully saved:
+Now that we have a user model to play with, we will just edit the
+`app/controllers/users_controller.rb` make it instruct the UserMailer to deliver
+an email to the newly created user by editing the create action and inserting a
+call to `UserMailer.welcome_email` right after the user is successfully saved:
```ruby
class UsersController < ApplicationController
@@ -145,63 +178,50 @@ class UsersController < ApplicationController
end
```
-This provides a simple implementation that does not require the registering of observers or creation of model callbacks.
-
-The method `welcome_email` returns a `Mail::Message` object which can then just be told `deliver` to send itself out.
+The method `welcome_email` returns a `Mail::Message` object which can then just
+be told `deliver` to send itself out.
### Auto encoding header values
-Action Mailer now handles the auto encoding of multibyte characters inside of headers and bodies.
-
-If you are using UTF-8 as your character set, you do not have to do anything special, just go ahead and send in UTF-8 data to the address fields, subject, keywords, filenames or body of the email and Action Mailer will auto encode it into quoted printable for you in the case of a header field or Base64 encode any body parts that are non US-ASCII.
+Action Mailer handles the auto encoding of multibyte characters inside of
+headers and bodies.
-For more complex examples such as defining alternate character sets or self-encoding text first, please refer to the Mail library.
+For more complex examples such as defining alternate character sets or
+self-encoding text first, please refer to the
+[Mail](https://github.com/mikel/mail) library.
### Complete List of Action Mailer Methods
-There are just three methods that you need to send pretty much any email message:
-
-* `headers` - Specifies any header on the email you want. You can pass a hash of header field names and value pairs, or you can call `headers[:field_name] = 'value'`.
-* `attachments` - Allows you to add attachments to your email. For example, `attachments['file-name.jpg'] = File.read('file-name.jpg')`.
-* `mail` - Sends the actual email itself. You can pass in headers as a hash to the mail method as a parameter, mail will then create an email, either plain text, or multipart, depending on what email templates you have defined.
+There are just three methods that you need to send pretty much any email
+message:
-#### Custom Headers
-
-Defining custom headers are simple, you can do it one of three ways:
-
-* Defining a header field as a parameter to the `mail` method:
-
- ```ruby
- mail('X-Spam' => value)
- ```
-
-* Passing in a key value assignment to the `headers` method:
-
- ```ruby
- headers['X-Spam'] = value
- ```
-
-* Passing a hash of key value pairs to the `headers` method:
-
- ```ruby
- headers {'X-Spam' => value, 'X-Special' => another_value}
- ```
-
-TIP: All `X-Value` headers per the RFC2822 can appear more than once. If you want to delete an `X-Value` header, you need to assign it a value of `nil`.
+* `headers` - Specifies any header on the email you want. You can pass a hash of
+ header field names and value pairs, or you can call `headers[:field_name] =
+ 'value'`.
+* `attachments` - Allows you to add attachments to your email. For example,
+ `attachments['file-name.jpg'] = File.read('file-name.jpg')`.
+* `mail` - Sends the actual email itself. You can pass in headers as a hash to
+ the mail method as a parameter, mail will then create an email, either plain
+ text, or multipart, depending on what email templates you have defined.
#### Adding Attachments
-Adding attachments has been simplified in Action Mailer 3.0.
+Action Mailer makes it very easy to add attachments.
-* Pass the file name and content and Action Mailer and the Mail gem will automatically guess the mime_type, set the encoding and create the attachment.
+* Pass the file name and content and Action Mailer and the
+ [Mail gem](https://github.com/mikel/mail) will automatically guess the
+ mime_type, set the encoding and create the attachment.
```ruby
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
```
-NOTE: Mail will automatically Base64 encode an attachment. If you want something different, pre-encode your content and pass in the encoded content and encoding in a `Hash` to the `attachments` method.
+NOTE: Mail will automatically Base64 encode an attachment. If you want something
+different, encode your content and pass in the encoded content and encoding in a
+`Hash` to the `attachments` method.
-* Pass the file name and specify headers and content and Action Mailer and Mail will use the settings you pass in.
+* Pass the file name and specify headers and content and Action Mailer and Mail
+ will use the settings you pass in.
```ruby
encoded_content = SpecialEncode(File.read('/path/to/filename.jpg'))
@@ -210,7 +230,8 @@ NOTE: Mail will automatically Base64 encode an attachment. If you want something
content: encoded_content }
```
-NOTE: If you specify an encoding, Mail will assume that your content is already encoded and not try to Base64 encode it.
+NOTE: If you specify an encoding, Mail will assume that your content is already
+encoded and not try to Base64 encode it.
#### Making Inline Attachments
@@ -224,7 +245,9 @@ Action Mailer 3.0 makes inline attachments, which involved a lot of hacking in p
end
```
-* Then in your view, you can just reference `attachments[]` as a hash and specify which attachment you want to show, calling `url` on it and then passing the result into the `image_tag` method:
+* Then in your view, you can just reference `attachments` as a hash and specify
+ which attachment you want to show, calling `url` on it and then passing the
+ result into the `image_tag` method:
```html+erb
<p>Hello there, this is our image</p>
@@ -232,7 +255,8 @@ Action Mailer 3.0 makes inline attachments, which involved a lot of hacking in p
<%= image_tag attachments['image.jpg'].url %>
```
-* As this is a standard call to `image_tag` you can pass in an options hash after the attachment URL as you could for any other image:
+* As this is a standard call to `image_tag` you can pass in an options hash
+ after the attachment URL as you could for any other image:
```html+erb
<p>Hello there, this is our image</p>
@@ -243,7 +267,10 @@ Action Mailer 3.0 makes inline attachments, which involved a lot of hacking in p
#### Sending Email To Multiple Recipients
-It is possible to send email to one or more recipients in one email (e.g., informing all admins of a new signup) by setting the list of emails to the `:to` key. The list of emails can be an array of email addresses or a single string with the addresses separated by commas.
+It is possible to send email to one or more recipients in one email (e.g.,
+informing all admins of a new signup) by setting the list of emails to the `:to`
+key. The list of emails can be an array of email addresses or a single string
+with the addresses separated by commas.
```ruby
class AdminMailer < ActionMailer::Base
@@ -257,12 +284,14 @@ class AdminMailer < ActionMailer::Base
end
```
-The same format can be used to set carbon copy (Cc:) and blind carbon copy (Bcc:) recipients, by using the `:cc` and `:bcc` keys respectively.
+The same format can be used to set carbon copy (Cc:) and blind carbon copy
+(Bcc:) recipients, by using the `:cc` and `:bcc` keys respectively.
#### Sending Email With Name
-Sometimes you wish to show the name of the person instead of just their email address when they receive the email. The trick to doing that is
-to format the email address in the format `"Full Name <email>"`.
+Sometimes you wish to show the name of the person instead of just their email
+address when they receive the email. The trick to doing that is to format the
+email address in the format `"Full Name <email>"`.
```ruby
def welcome_email(user)
@@ -274,7 +303,11 @@ end
### Mailer Views
-Mailer views are located in the `app/views/name_of_mailer_class` directory. The specific mailer view is known to the class because its name is the same as the mailer method. In our example from above, our mailer view for the `welcome_email` method will be in `app/views/user_mailer/welcome_email.html.erb` for the HTML version and `welcome_email.text.erb` for the plain text version.
+Mailer views are located in the `app/views/name_of_mailer_class` directory. The
+specific mailer view is known to the class because its name is the same as the
+mailer method. In our example from above, our mailer view for the
+`welcome_email` method will be in `app/views/user_mailer/welcome_email.html.erb`
+for the HTML version and `welcome_email.text.erb` for the plain text version.
To change the default mailer view for your action you do something like:
@@ -285,7 +318,7 @@ class UserMailer < ActionMailer::Base
def welcome_email(user)
@user = user
@url = 'http://example.com/login'
- mail(to: user.email,
+ mail(to: @user.email,
subject: 'Welcome to My Awesome Site',
template_path: 'notifications',
template_name: 'another')
@@ -293,9 +326,12 @@ class UserMailer < ActionMailer::Base
end
```
-In this case it will look for templates at `app/views/notifications` with name `another`. You can also specify an array of paths for `template_path`, and they will be searched in order.
+In this case it will look for templates at `app/views/notifications` with name
+`another`. You can also specify an array of paths for `template_path`, and they
+will be searched in order.
-If you want more flexibility you can also pass a block and render specific templates or even render inline or text without using a template file:
+If you want more flexibility you can also pass a block and render specific
+templates or even render inline or text without using a template file:
```ruby
class UserMailer < ActionMailer::Base
@@ -304,21 +340,26 @@ class UserMailer < ActionMailer::Base
def welcome_email(user)
@user = user
@url = 'http://example.com/login'
- mail(to: user.email,
+ mail(to: @user.email,
subject: 'Welcome to My Awesome Site') do |format|
format.html { render 'another_template' }
format.text { render text: 'Render text' }
end
end
-
end
```
-This will render the template 'another_template.html.erb' for the HTML part and use the rendered text for the text part. The render command is the same one used inside of Action Controller, so you can use all the same options, such as `:text`, `:inline` etc.
+This will render the template 'another_template.html.erb' for the HTML part and
+use the rendered text for the text part. The render command is the same one used
+inside of Action Controller, so you can use all the same options, such as
+`:text`, `:inline` etc.
### Action Mailer Layouts
-Just like controller views, you can also have mailer layouts. The layout name needs to be the same as your mailer, such as `user_mailer.html.erb` and `user_mailer.text.erb` to be automatically recognized by your mailer as a layout.
+Just like controller views, you can also have mailer layouts. The layout name
+needs to be the same as your mailer, such as `user_mailer.html.erb` and
+`user_mailer.text.erb` to be automatically recognized by your mailer as a
+layout.
In order to use a different file, call `layout` in your mailer:
@@ -328,9 +369,11 @@ class UserMailer < ActionMailer::Base
end
```
-Just like with controller views, use `yield` to render the view inside the layout.
+Just like with controller views, use `yield` to render the view inside the
+layout.
-You can also pass in a `layout: 'layout_name'` option to the render call inside the format block to specify different layouts for different actions:
+You can also pass in a `layout: 'layout_name'` option to the render call inside
+the format block to specify different layouts for different actions:
```ruby
class UserMailer < ActionMailer::Base
@@ -343,13 +386,37 @@ class UserMailer < ActionMailer::Base
end
```
-Will render the HTML template using the `my_layout.html.erb` file and the text template with the usual `user_mailer.text.erb` file if it exists.
+Will render the HTML part using the `my_layout.html.erb` file and the text part
+with the usual `user_mailer.text.erb` file if it exists.
### Generating URLs in Action Mailer Views
-URLs can be generated in mailer views using `url_for` or named routes.
+Unlike controllers, the mailer instance doesn't have any context about the
+incoming request so you'll need to provide the `:host` parameter yourself.
+
+As the `:host` usually is consistent across the application you can configure it
+globally in `config/application.rb`:
+
+```ruby
+config.action_mailer.default_url_options = { host: 'example.com' }
+```
+
+#### generating URLs with `url_for`
+
+You need to pass the `only_path: false` option when using `url_for`. This will
+ensure that absolute URLs are generated because the `url_for` view helper will,
+by default, generate relative URLs when a `:host` option isn't explicitly
+provided.
+
+```erb
+<%= url_for(controller: 'welcome',
+ action: 'greeting',
+ only_path: false) %>
+```
+
+If you did not configure the `:host` option globally make sure to pass it to
+`url_for`.
-Unlike controllers, the mailer instance doesn't have any context about the incoming request so you'll need to provide the `:host`, `:controller`, and `:action`:
```erb
<%= url_for(host: 'example.com',
@@ -357,27 +424,32 @@ Unlike controllers, the mailer instance doesn't have any context about the incom
action: 'greeting') %>
```
-When using named routes you only need to supply the `:host`:
+NOTE: When you explicitly pass the `:host` Rails will always generate absolute
+URLs, so there is no need to pass `only_path: false`.
-```erb
-<%= user_url(@user, host: 'example.com') %>
-```
+#### generating URLs with named routes
-Email clients have no web context and so paths have no base URL to form complete web addresses. Thus, when using named routes only the "_url" variant makes sense.
+Email clients have no web context and so paths have no base URL to form complete
+web addresses. Thus, you should always use the "_url" variant of named route
+helpers.
-It is also possible to set a default host that will be used in all mailers by setting the `:host` option as a configuration option in `config/application.rb`:
+If you did not configure the `:host` option globally make sure to pass it to the
+url helper.
-```ruby
-config.action_mailer.default_url_options = { host: 'example.com' }
+```erb
+<%= user_url(@user, host: 'example.com') %>
```
-If you use this setting, you should pass the `only_path: false` option when using `url_for`. This will ensure that absolute URLs are generated because the `url_for` view helper will, by default, generate relative URLs when a `:host` option isn't explicitly provided.
-
### Sending Multipart Emails
-Action Mailer will automatically send multipart emails if you have different templates for the same action. So, for our UserMailer example, if you have `welcome_email.text.erb` and `welcome_email.html.erb` in `app/views/user_mailer`, Action Mailer will automatically send a multipart email with the HTML and text versions setup as different parts.
+Action Mailer will automatically send multipart emails if you have different
+templates for the same action. So, for our UserMailer example, if you have
+`welcome_email.text.erb` and `welcome_email.html.erb` in
+`app/views/user_mailer`, Action Mailer will automatically send a multipart email
+with the HTML and text versions setup as different parts.
-The order of the parts getting inserted is determined by the `:parts_order` inside of the `ActionMailer::Base.default` method.
+The order of the parts getting inserted is determined by the `:parts_order`
+inside of the `ActionMailer::Base.default` method.
### Sending Emails with Attachments
@@ -389,38 +461,51 @@ class UserMailer < ActionMailer::Base
@user = user
@url = user_url(@user)
attachments['terms.pdf'] = File.read('/path/terms.pdf')
- mail(to: user.email,
+ mail(to: @user.email,
subject: 'Please see the Terms and Conditions attached')
end
end
```
-The above will send a multipart email with an attachment, properly nested with the top level being `multipart/mixed` and the first part being a `multipart/alternative` containing the plain text and HTML email messages.
+The above will send a multipart email with an attachment, properly nested with
+the top level being `multipart/mixed` and the first part being a
+`multipart/alternative` containing the plain text and HTML email messages.
### Sending Emails with Dynamic Delivery Options
-If you wish to override the default delivery options (e.g. SMTP credentials) while delivering emails, you can do this using `delivery_method_options` in the mailer action.
+If you wish to override the default delivery options (e.g. SMTP credentials)
+while delivering emails, you can do this using `delivery_method_options` in the
+mailer action.
```ruby
class UserMailer < ActionMailer::Base
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 }
- mail(to: user.email, subject: "Please see the Terms and Conditions attached", delivery_method_options: delivery_options)
+ delivery_options = { user_name: company.smtp_user,
+ password: company.smtp_password,
+ address: company.smtp_host }
+ mail(to: @user.email,
+ subject: "Please see the Terms and Conditions attached",
+ delivery_method_options: delivery_options)
end
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.
+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!")
+ mail(to: user.email,
+ body: email_body,
+ content_type: "text/html",
+ subject: "Already rendered!")
end
end
```
@@ -428,13 +513,21 @@ end
Receiving Emails
----------------
-Receiving and parsing emails with Action Mailer can be a rather complex endeavor. Before your email reaches your Rails app, you would have had to configure your system to somehow forward emails to your app, which needs to be listening for that. So, to receive emails in your Rails app you'll need to:
+Receiving and parsing emails with Action Mailer can be a rather complex
+endeavor. Before your email reaches your Rails app, you would have had to
+configure your system to somehow forward emails to your app, which needs to be
+listening for that. So, to receive emails in your Rails app you'll need to:
* Implement a `receive` method in your mailer.
-* Configure your email server to forward emails from the address(es) you would like your app to receive to `/path/to/app/bin/rails runner 'UserMailer.receive(STDIN.read)'`.
+* Configure your email server to forward emails from the address(es) you would
+ like your app to receive to `/path/to/app/bin/rails runner
+ 'UserMailer.receive(STDIN.read)'`.
-Once a method called `receive` is defined in any mailer, Action Mailer will parse the raw incoming email into an email object, decode it, instantiate a new mailer, and pass the email object to the mailer `receive` instance method. Here's an example:
+Once a method called `receive` is defined in any mailer, Action Mailer will
+parse the raw incoming email into an email object, decode it, instantiate a new
+mailer, and pass the email object to the mailer `receive` instance
+method. Here's an example:
```ruby
class UserMailer < ActionMailer::Base
@@ -460,17 +553,23 @@ end
Action Mailer Callbacks
---------------------------
-Action Mailer allows for you to specify a `before_action`, `after_action` and `around_action`.
+Action Mailer allows for you to specify a `before_action`, `after_action` and
+`around_action`.
-* Filters can be specified with a block or a symbol to a method in the mailer class similar to controllers.
+* Filters can be specified with a block or a symbol to a method in the mailer
+ class similar to controllers.
-* You could use a `before_action` to prepopulate the mail object with defaults, delivery_method_options or insert default headers and attachments.
+* You could use a `before_action` to populate the mail object with defaults,
+ delivery_method_options or insert default headers and attachments.
-* You could use an `after_action` to do similar setup as a `before_action` but using instance variables set in your mailer action.
+* You could use an `after_action` to do similar setup as a `before_action` but
+ using instance variables set in your mailer action.
```ruby
class UserMailer < ActionMailer::Base
- after_action :set_delivery_options, :prevent_delivery_to_guests, :set_business_headers
+ after_action :set_delivery_options,
+ :prevent_delivery_to_guests,
+ :set_business_headers
def feedback_message(business, user)
@business = business
@@ -486,7 +585,8 @@ class UserMailer < ActionMailer::Base
private
def set_delivery_options
- # You have access to the mail instance and @business and @user instance variables here
+ # You have access to the mail instance,
+ # @business and @user instance variables here
if @business && @business.has_smtp_settings?
mail.delivery_method.settings.merge!(@business.smtp_settings)
end
@@ -511,12 +611,14 @@ end
Using Action Mailer Helpers
---------------------------
-Action Mailer now just inherits from Abstract Controller, so you have access to the same generic helpers as you do in Action Controller.
+Action Mailer now just inherits from `AbstractController`, so you have access to
+the same generic helpers as you do in Action Controller.
Action Mailer Configuration
---------------------------
-The following configuration options are best made in one of the environment files (environment.rb, production.rb, etc...)
+The following configuration options are best made in one of the environment
+files (environment.rb, production.rb, etc...)
| Configuration | Description |
|---------------|-------------|
@@ -529,9 +631,14 @@ The following configuration options are best made in one of the environment file
|`deliveries`|Keeps an array of all the emails sent out through the Action Mailer with delivery_method :test. Most useful for unit and functional testing.|
|`default_options`|Allows you to set default values for the `mail` method options (`:from`, `:reply_to`, etc.).|
+For a complete writeup of possible configurations see the
+[Action Mailer section](configuring.html#configuring-action-mailer) in
+our Configuring Rails Applications guide.
+
### Example Action Mailer Configuration
-An example would be adding the following to your appropriate `config/environments/$RAILS_ENV.rb` file:
+An example would be adding the following to your appropriate
+`config/environments/$RAILS_ENV.rb` file:
```ruby
config.action_mailer.delivery_method = :sendmail
@@ -542,19 +649,20 @@ config.action_mailer.delivery_method = :sendmail
# }
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
-config.action_mailer.default_options = {from: 'no-replay@example.org'}
+config.action_mailer.default_options = {from: 'no-replay@example.com'}
```
-### Action Mailer Configuration for GMail
+### Action Mailer Configuration for Gmail
-As Action Mailer uses the Mail gem, this becomes as simple as adding to your `config/environments/$RAILS_ENV.rb` file:
+As Action Mailer now uses the Mail gem, this becomes as simple as adding to your
+`config/environments/$RAILS_ENV.rb` file:
```ruby
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.gmail.com',
port: 587,
- domain: 'baci.lindsaar.net',
+ domain: 'example.com',
user_name: '<username>',
password: '<password>',
authentication: 'plain',
@@ -569,7 +677,10 @@ You can find detailed instructions on how to test your mailers in the
Intercepting Emails
-------------------
-There are situations where you need to edit an email before it's delivered. Fortunately Action Mailer provides hooks to intercept every email. You can register an interceptor to make modifications to mail messages right before they are handed to the delivery agents.
+There are situations where you need to edit an email before it's
+delivered. Fortunately Action Mailer provides hooks to intercept every
+email. You can register an interceptor to make modifications to mail messages
+right before they are handed to the delivery agents.
```ruby
class SandboxEmailInterceptor
@@ -579,10 +690,15 @@ class SandboxEmailInterceptor
end
```
-Before the interceptor can do its job you need to register it with the Action Mailer framework. You can do this in an initializer file `config/initializers/sandbox_email_interceptor.rb`
+Before the interceptor can do its job you need to register it with the Action
+Mailer framework. You can do this in an initializer file
+`config/initializers/sandbox_email_interceptor.rb`
```ruby
ActionMailer::Base.register_interceptor(SandboxEmailInterceptor) if Rails.env.staging?
```
-NOTE: The example above uses a custom environment called "staging" for a production like server but for testing purposes. You can read [Creating Rails environments](./configuring.html#creating-rails-environments) for more information about custom Rails environments.
+NOTE: The example above uses a custom environment called "staging" for a
+production like server but for testing purposes. You can read
+[Creating Rails environments](./configuring.html#creating-rails-environments)
+for more information about custom Rails environments.
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index 43529e3e96..101a4f5b42 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -1039,6 +1039,8 @@ For convenience `class_attribute` also defines an instance predicate which is th
When `:instance_reader` is `false`, the instance predicate returns a `NoMethodError` just like the reader method.
+If you do not want the instance predicate, pass `instance_predicate: false` and it will not be defined.
+
NOTE: Defined in `active_support/core_ext/class/attribute.rb`
#### `cattr_reader`, `cattr_writer`, and `cattr_accessor`
diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md
index 448f0e1f9a..43df544e28 100644
--- a/guides/source/asset_pipeline.md
+++ b/guides/source/asset_pipeline.md
@@ -547,35 +547,7 @@ 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.
-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.
+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.)
### Local Precompilation
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index 18d9f5c562..8d203d265a 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -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/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md
index b6363bdfb1..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.
diff --git a/guides/source/documents.yaml b/guides/source/documents.yaml
index 91357ec284..1b16f4e516 100644
--- a/guides/source/documents.yaml
+++ b/guides/source/documents.yaml
@@ -73,7 +73,6 @@
-
name: Action Mailer Basics
url: action_mailer_basics.html
- work_in_progress: true
description: This guide describes how to use Action Mailer to send and receive emails.
-
name: Testing Rails Applications
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 95b342efd4..4c0a61bc5e 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -222,10 +222,10 @@ 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 `rails test` command.
+Running a test is as simple as invoking the file containing the test cases through `rake test` command.
```bash
-$ rails test test/models/post_test.rb
+$ rake test test/models/post_test.rb
.
Finished tests in 0.009262s, 107.9680 tests/s, 107.9680 assertions/s.
@@ -233,10 +233,10 @@ Finished tests in 0.009262s, 107.9680 tests/s, 107.9680 assertions/s.
1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
```
-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`.
+You can also run a particular test method from the test case by running the test and providing the `test method name`.
```bash
-$ rails test test/models/post_test.rb -n test_the_truth
+$ rake test test/models/post_test.rb test_the_truth
.
Finished tests in 0.009064s, 110.3266 tests/s, 110.3266 assertions/s.
@@ -260,7 +260,7 @@ end
Let us run this newly added test.
```bash
-$ rails test test/models/post_test.rb -n test_should_not_save_post_without_title
+$ rake test test/models/post_test.rb test_should_not_save_post_without_title
F
Finished tests in 0.044632s, 22.4054 tests/s, 22.4054 assertions/s.
@@ -300,7 +300,7 @@ end
Now the test should pass. Let us verify by running the test again:
```bash
-$ rails test test/models/post_test.rb -n test_should_not_save_post_without_title
+$ rake test test/models/post_test.rb test_should_not_save_post_without_title
.
Finished tests in 0.047721s, 20.9551 tests/s, 20.9551 assertions/s.
@@ -325,7 +325,7 @@ end
Now you can see even more output in the console from running the tests:
```bash
-$ rails test test/models/post_test.rb -n test_should_report_error
+$ rake test test/models/post_test.rb test_should_report_error
E
Finished tests in 0.030974s, 32.2851 tests/s, 0.0000 assertions/s.
@@ -761,14 +761,14 @@ You don't need to set up and run your tests by hand on a test-by-test basis. Rai
| 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`|
+| `rake test` | Runs all unit, functional and integration tests. You can also simply run `rake test` as Rails will run all the tests by 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: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:
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index 385aa3c51b..51d6775c3e 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -33,29 +33,7 @@ The following changes are meant for upgrading your application to Rails 4.0.
### Gemfile
-Rails 4.0 removed the *group :assets* from Gemfile (now you can use only :test, :development and/or :production groups). So change your Gemfile from:
-```ruby
-group :assets do
- gem 'sass-rails', '~> 4.0.0.beta1'
- gem 'coffee-rails', '~> 4.0.0.beta1'
-
- # See https://github.com/sstephenson/execjs#readme for more supported runtimes
- # gem 'therubyracer', platforms: :ruby
-
- gem 'uglifier', '>= 1.0.3'
-end
-```
-to:
-```ruby
-gem 'sass-rails', '~> 4.0.0.beta1'
-gem 'coffee-rails', '~> 4.0.0.beta1'
-
-# See https://github.com/sstephenson/execjs#readme for more supported runtimes
-# gem 'therubyracer', platforms: :ruby
-
-gem 'uglifier', '>= 1.0.3'
-```
-**note:** don't removing the *group assets* from the Gemfile will cause your assets stop compiling
+Rails 4.0 removed the `assets` group from Gemfile. You'd need to remove that line from your Gemfile when upgrading.
### vendor/plugins
@@ -114,17 +92,22 @@ Rails 4.0 extracted Active Resource to its own gem. If you still need the featur
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.
-* 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` which leverages the new `ActiveSupport::KeyGenerator`. 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:
+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.
-```ruby
- # config/initializers/session_store.rb
- Myapp::Application.config.session_store :upgrade_signature_to_encryption_cookie_store, key: 'existing session key'
+* 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.