rails 4.0.0.beta1 → 4.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rails might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +78 -0
- data/guides/CHANGELOG.md +3 -0
- data/guides/assets/images/getting_started/unknown_action_create_for_posts.png +0 -0
- data/guides/bug_report_templates/active_record_gem.rb +37 -0
- data/guides/bug_report_templates/active_record_master.rb +48 -0
- data/guides/code/getting_started/Gemfile +16 -11
- data/guides/code/getting_started/app/controllers/comments_controller.rb +2 -2
- data/guides/code/getting_started/app/controllers/posts_controller.rb +2 -2
- data/guides/code/getting_started/config/application.rb +3 -2
- data/guides/code/getting_started/config/initializers/session_store.rb +1 -1
- data/guides/code/getting_started/config/routes.rb +2 -2
- data/guides/code/getting_started/public/404.html +41 -10
- data/guides/code/getting_started/public/422.html +42 -10
- data/guides/code/getting_started/public/500.html +41 -10
- data/guides/rails_guides/markdown/renderer.rb +1 -1
- data/guides/source/2_2_release_notes.md +15 -15
- data/guides/source/4_0_release_notes.md +1 -7
- data/guides/source/action_controller_overview.md +176 -22
- data/guides/source/action_mailer_basics.md +246 -141
- data/guides/source/action_view_overview.md +3 -8
- data/guides/source/active_record_basics.md +98 -95
- data/guides/source/active_record_querying.md +90 -17
- data/guides/source/active_record_validations.md +41 -0
- data/guides/source/active_support_core_extensions.md +23 -3
- data/guides/source/active_support_instrumentation.md +6 -6
- data/guides/source/asset_pipeline.md +1 -1
- data/guides/source/association_basics.md +34 -10
- data/guides/source/caching_with_rails.md +2 -7
- data/guides/source/command_line.md +7 -7
- data/guides/source/configuring.md +3 -3
- data/guides/source/contributing_to_ruby_on_rails.md +38 -5
- data/guides/source/credits.html.erb +1 -1
- data/guides/source/debugging_rails_applications.md +19 -22
- data/guides/source/development_dependencies_install.md +2 -2
- data/guides/source/documents.yaml +5 -1
- data/guides/source/engines.md +21 -16
- data/guides/source/form_helpers.md +28 -7
- data/guides/source/generators.md +2 -2
- data/guides/source/getting_started.md +14 -13
- data/guides/source/i18n.md +22 -0
- data/guides/source/initialization.md +1 -1
- data/guides/source/layouts_and_rendering.md +60 -4
- data/guides/source/migrations.md +27 -2
- data/guides/source/rails_application_templates.md +11 -11
- data/guides/source/rails_on_rack.md +9 -6
- data/guides/source/routing.md +19 -3
- data/guides/source/ruby_on_rails_guides_guidelines.md +1 -1
- data/guides/source/security.md +2 -2
- data/guides/source/testing.md +106 -85
- data/guides/source/upgrading_ruby_on_rails.md +112 -9
- data/guides/source/working_with_javascript_in_rails.md +1 -0
- metadata +17 -16
- data/README.rdoc +0 -77
- data/guides/code/getting_started/app/assets/images/rails.png +0 -0
@@ -65,7 +65,7 @@ HTML
|
|
65
65
|
# if a bulleted list follows the first item is not rendered
|
66
66
|
# as a list item, but as a paragraph starting with a plain
|
67
67
|
# asterisk.
|
68
|
-
body.gsub(/^(TIP|IMPORTANT|CAUTION|WARNING|NOTE|INFO|TODO)[.:](.*?)(\n(?=\n)|\Z)/m) do
|
68
|
+
body.gsub(/^(TIP|IMPORTANT|CAUTION|WARNING|NOTE|INFO|TODO)[.:](.*?)(\n(?=\n)|\Z)/m) do
|
69
69
|
css_class = case $1
|
70
70
|
when 'CAUTION', 'IMPORTANT'
|
71
71
|
'warning'
|
@@ -31,20 +31,20 @@ Documentation
|
|
31
31
|
|
32
32
|
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:
|
33
33
|
|
34
|
-
* [Getting Started with Rails](
|
35
|
-
* [Rails Database Migrations](
|
36
|
-
* [Active Record Associations](
|
37
|
-
* [Active Record Query Interface](
|
38
|
-
* [Layouts and Rendering in Rails](
|
39
|
-
* [Action View Form Helpers](
|
40
|
-
* [Rails Routing from the Outside In](
|
41
|
-
* [Action Controller Overview](
|
42
|
-
* [Rails Caching](
|
43
|
-
* [A Guide to Testing Rails Applications](
|
44
|
-
* [Securing Rails Applications](
|
45
|
-
* [Debugging Rails Applications](
|
46
|
-
* [Performance Testing Rails Applications](
|
47
|
-
* [The Basics of Creating Rails Plugins](
|
34
|
+
* [Getting Started with Rails](getting_started.html)
|
35
|
+
* [Rails Database Migrations](migrations.html)
|
36
|
+
* [Active Record Associations](association_basics.html)
|
37
|
+
* [Active Record Query Interface](active_record_querying.html)
|
38
|
+
* [Layouts and Rendering in Rails](layouts_and_rendering.html)
|
39
|
+
* [Action View Form Helpers](form_helpers.html)
|
40
|
+
* [Rails Routing from the Outside In](routing.html)
|
41
|
+
* [Action Controller Overview](action_controller_overview.html)
|
42
|
+
* [Rails Caching](caching_with_rails.html)
|
43
|
+
* [A Guide to Testing Rails Applications](testing.html)
|
44
|
+
* [Securing Rails Applications](security.html)
|
45
|
+
* [Debugging Rails Applications](debugging_rails_applications.html)
|
46
|
+
* [Performance Testing Rails Applications](performance_testing.html)
|
47
|
+
* [The Basics of Creating Rails Plugins](plugins.html)
|
48
48
|
|
49
49
|
All told, the Guides provide tens of thousands of words of guidance for beginning and intermediate Rails developers.
|
50
50
|
|
@@ -236,7 +236,7 @@ This will enable recognition of (among others) these routes:
|
|
236
236
|
|
237
237
|
* Lead Contributor: [S. Brent Faulkner](http://www.unwwwired.net/)
|
238
238
|
* More information:
|
239
|
-
* [Rails Routing from the Outside In](
|
239
|
+
* [Rails Routing from the Outside In](routing.html#nested-resources)
|
240
240
|
* [What's New in Edge Rails: Shallow Routes](http://ryandaigle.com/articles/2008/9/7/what-s-new-in-edge-rails-shallow-routes)
|
241
241
|
|
242
242
|
### Method Arrays for Member or Collection Routes
|
@@ -113,7 +113,7 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/activ
|
|
113
113
|
|
114
114
|
* Add `ActiveModel::ForbiddenAttributesProtection`, a simple module to protect attributes from mass assignment when non-permitted attributes are passed.
|
115
115
|
|
116
|
-
* Added `ActiveModel::Model`, a mixin to make Ruby objects work with
|
116
|
+
* Added `ActiveModel::Model`, a mixin to make Ruby objects work with ActionPack out of box.
|
117
117
|
|
118
118
|
### Deprecations
|
119
119
|
|
@@ -178,12 +178,6 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/activ
|
|
178
178
|
If migrating down, the given migration / block is run normally.
|
179
179
|
See the [Guide on Migration](https://github.com/rails/rails/blob/master/guides/source/migrations.md#reverting-previous-migrations)
|
180
180
|
|
181
|
-
* Adds some metadata columns to `schema_migrations` table.
|
182
|
-
|
183
|
-
* `migrated_at`
|
184
|
-
* `fingerprint` - an md5 hash of the migration.
|
185
|
-
* `name` - the filename minus version and extension.
|
186
|
-
|
187
181
|
* Adds PostgreSQL array type support. Any datatype can be used to create an array column, with full migration and schema dumper support.
|
188
182
|
|
189
183
|
* Add `Relation#load` to explicitly load the record and return `self`.
|
@@ -6,6 +6,7 @@ In this guide you will learn how controllers work and how they fit into the requ
|
|
6
6
|
After reading this guide, you will know:
|
7
7
|
|
8
8
|
* How to follow the flow of a request through a controller.
|
9
|
+
* How to restrict parameters passed to your controller.
|
9
10
|
* Why and how to store data in the session or cookies.
|
10
11
|
* How to work with filters to execute code during request processing.
|
11
12
|
* How to use Action Controller's built-in HTTP authentication.
|
@@ -26,6 +27,16 @@ A controller can thus be thought of as a middle man between models and views. It
|
|
26
27
|
|
27
28
|
NOTE: For more details on the routing process, see [Rails Routing from the Outside In](routing.html).
|
28
29
|
|
30
|
+
Controller Naming Convention
|
31
|
+
----------------------------
|
32
|
+
|
33
|
+
The naming convention of controllers in Rails favors pluralization of the last word in the controller's name, although it is not strictly required (e.g. `ApplicationController`). For example, `ClientsController` is preferable to `ClientController`, `SiteAdminsController` is preferable to `SiteAdminController` or `SitesAdminsController`, and so on.
|
34
|
+
|
35
|
+
Following this convention will allow you to use the default route generators (e.g. `resources`, etc) without needing to qualify each `:path` or `:controller`, and keeps URL and path helpers' usage consistent throughout your application. See [Layouts & Rendering Guide](layouts_and_rendering.html) for more details.
|
36
|
+
|
37
|
+
NOTE: The controller naming convention differs from the naming convention of models, which expected to be named in singular form.
|
38
|
+
|
39
|
+
|
29
40
|
Methods and Actions
|
30
41
|
-------------------
|
31
42
|
|
@@ -38,7 +49,7 @@ class ClientsController < ApplicationController
|
|
38
49
|
end
|
39
50
|
```
|
40
51
|
|
41
|
-
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
|
52
|
+
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`:
|
42
53
|
|
43
54
|
```ruby
|
44
55
|
def new
|
@@ -112,21 +123,21 @@ To send a hash you include the key name inside the brackets:
|
|
112
123
|
</form>
|
113
124
|
```
|
114
125
|
|
115
|
-
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]`.
|
126
|
+
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]`.
|
116
127
|
|
117
|
-
Note that the `params` hash is actually an instance of `ActiveSupport::HashWithIndifferentAccess`, which acts like a hash
|
128
|
+
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.
|
118
129
|
|
119
130
|
### JSON parameters
|
120
131
|
|
121
|
-
If you're writing a web service application, you might find yourself more comfortable
|
132
|
+
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.
|
122
133
|
|
123
|
-
So for example, if you are sending this JSON
|
134
|
+
So for example, if you are sending this JSON content:
|
124
135
|
|
125
136
|
```json
|
126
137
|
{ "company": { "name": "acme", "address": "123 Carrot Street" } }
|
127
138
|
```
|
128
139
|
|
129
|
-
You'll get `params[:company]` as `{
|
140
|
+
You'll get `params[:company]` as `{ "name" => "acme", "address" => "123 Carrot Street" }`.
|
130
141
|
|
131
142
|
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:
|
132
143
|
|
@@ -137,19 +148,19 @@ Also, if you've turned on `config.wrap_parameters` in your initializer or callin
|
|
137
148
|
And assume that you're sending the data to `CompaniesController`, it would then be wrapped in `:company` key like this:
|
138
149
|
|
139
150
|
```ruby
|
140
|
-
{ :name => "acme", :address => "123 Carrot Street", :company => { :name => "acme", :address => "123 Carrot Street" }}
|
151
|
+
{ :name => "acme", :address => "123 Carrot Street", :company => { :name => "acme", :address => "123 Carrot Street" } }
|
141
152
|
```
|
142
153
|
|
143
154
|
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)
|
144
155
|
|
145
|
-
NOTE:
|
156
|
+
NOTE: Support for parsing XML parameters has been extracted into a gem named `actionpack-xml_parser`
|
146
157
|
|
147
158
|
### Routing Parameters
|
148
159
|
|
149
160
|
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:
|
150
161
|
|
151
162
|
```ruby
|
152
|
-
match '/clients/:status' => 'clients#index', foo:
|
163
|
+
match '/clients/:status' => 'clients#index', foo: 'bar'
|
153
164
|
```
|
154
165
|
|
155
166
|
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".
|
@@ -170,6 +181,158 @@ These options will be used as a starting point when generating URLs, so it's pos
|
|
170
181
|
|
171
182
|
If you define `default_url_options` in `ApplicationController`, as in the example above, it would be used for all URL generation. The method can also be defined in one specific controller, in which case it only affects URLs generated there.
|
172
183
|
|
184
|
+
### Strong Parameters
|
185
|
+
|
186
|
+
With strong parameters, Action Controller parameters are forbidden to
|
187
|
+
be used in Active Model mass assignments until they have been
|
188
|
+
whitelisted. This means you'll have to make a conscious choice about
|
189
|
+
which attributes to allow for mass updating and thus prevent
|
190
|
+
accidentally exposing that which shouldn't be exposed.
|
191
|
+
|
192
|
+
In addition, parameters can be marked as required and flow through a
|
193
|
+
predefined raise/rescue flow to end up as a 400 Bad Request with no
|
194
|
+
effort.
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
class PeopleController < ActionController::Base
|
198
|
+
# This will raise an ActiveModel::ForbiddenAttributes exception
|
199
|
+
# because it's using mass assignment without an explicit permit
|
200
|
+
# step.
|
201
|
+
def create
|
202
|
+
Person.create(params[:person])
|
203
|
+
end
|
204
|
+
|
205
|
+
# This will pass with flying colors as long as there's a person key
|
206
|
+
# in the parameters, otherwise it'll raise a
|
207
|
+
# ActionController::ParameterMissing exception, which will get
|
208
|
+
# caught by ActionController::Base and turned into that 400 Bad
|
209
|
+
# Request reply.
|
210
|
+
def update
|
211
|
+
person = current_account.people.find(params[:id])
|
212
|
+
person.update_attributes!(person_params)
|
213
|
+
redirect_to person
|
214
|
+
end
|
215
|
+
|
216
|
+
private
|
217
|
+
# Using a private method to encapsulate the permissible parameters
|
218
|
+
# is just a good pattern since you'll be able to reuse the same
|
219
|
+
# permit list between create and update. Also, you can specialize
|
220
|
+
# this method with per-user checking of permissible attributes.
|
221
|
+
def person_params
|
222
|
+
params.require(:person).permit(:name, :age)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
```
|
226
|
+
|
227
|
+
#### Permitted Scalar Values
|
228
|
+
|
229
|
+
Given
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
params.permit(:id)
|
233
|
+
```
|
234
|
+
|
235
|
+
the key `:id` will pass the whitelisting if it appears in `params` and
|
236
|
+
it has a permitted scalar value associated. Otherwise the key is going
|
237
|
+
to be filtered out, so arrays, hashes, or any other objects cannot be
|
238
|
+
injected.
|
239
|
+
|
240
|
+
The permitted scalar types are `String`, `Symbol`, `NilClass`,
|
241
|
+
`Numeric`, `TrueClass`, `FalseClass`, `Date`, `Time`, `DateTime`,
|
242
|
+
`StringIO`, `IO`, `ActionDispatch::Http::UploadedFile` and
|
243
|
+
`Rack::Test::UploadedFile`.
|
244
|
+
|
245
|
+
To declare that the value in `params` must be an array of permitted
|
246
|
+
scalar values map the key to an empty array:
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
params.permit(:id => [])
|
250
|
+
```
|
251
|
+
|
252
|
+
To whitelist an entire hash of parameters, the `permit!` method can be
|
253
|
+
used:
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
params.require(:log_entry).permit!
|
257
|
+
```
|
258
|
+
|
259
|
+
This will mark the `:log_entry` parameters hash and any subhash of it
|
260
|
+
permitted. Extreme care should be taken when using `permit!` as it
|
261
|
+
will allow all current and future model attributes to be
|
262
|
+
mass-assigned.
|
263
|
+
|
264
|
+
#### Nested Parameters
|
265
|
+
|
266
|
+
You can also use permit on nested parameters, like:
|
267
|
+
|
268
|
+
```ruby
|
269
|
+
params.permit(:name, {:emails => []},
|
270
|
+
:friends => [ :name,
|
271
|
+
{ :family => [ :name ], :hobbies => [] }])
|
272
|
+
```
|
273
|
+
|
274
|
+
This declaration whitelists the `name`, `emails` and `friends`
|
275
|
+
attributes. It is expected that `emails` will be an array of permitted
|
276
|
+
scalar values and that `friends` will be an array of resources with
|
277
|
+
specific attributes : they should have a `name` attribute (any
|
278
|
+
permitted scalar values allowed), a `hobbies` attribute as an array of
|
279
|
+
permitted scalar values, and a `family` attribute which is restricted
|
280
|
+
to having a `name` (any permitted scalar values allowed, too).
|
281
|
+
|
282
|
+
#### More Examples
|
283
|
+
|
284
|
+
You want to also use the permitted attributes in the `new`
|
285
|
+
action. This raises the problem that you can't use `require` on the
|
286
|
+
root key because normally it does not exist when calling `new`:
|
287
|
+
|
288
|
+
```ruby
|
289
|
+
# using `fetch` you can supply a default and use
|
290
|
+
# the Strong Parameters API from there.
|
291
|
+
params.fetch(:blog, {}).permit(:title, :author)
|
292
|
+
```
|
293
|
+
|
294
|
+
`accepts_nested_attributes_for` allows you to update and destroy
|
295
|
+
associated records. This is based on the `id` and `_destroy`
|
296
|
+
parameters:
|
297
|
+
|
298
|
+
```ruby
|
299
|
+
# permit :id and :_destroy
|
300
|
+
params.require(:author).permit(:name, books_attributes: [:title, :id, :_destroy])
|
301
|
+
```
|
302
|
+
|
303
|
+
Hashes with integer keys are treated differently and you can declare
|
304
|
+
the attributes as if they were direct children. You get these kinds of
|
305
|
+
parameters when you use `accepts_nested_attributes_for` in combination
|
306
|
+
with a `has_many` association:
|
307
|
+
|
308
|
+
```ruby
|
309
|
+
# To whitelist the following data:
|
310
|
+
# {"book" => {"title" => "Some Book",
|
311
|
+
# "chapters_attributes" => { "1" => {"title" => "First Chapter"},
|
312
|
+
# "2" => {"title" => "Second Chapter"}}}}
|
313
|
+
|
314
|
+
params.require(:book).permit(:title, chapters_attributes: [:title])
|
315
|
+
```
|
316
|
+
|
317
|
+
#### Outside the Scope of Strong Parameters
|
318
|
+
|
319
|
+
The strong parameter API was designed with the most common use cases
|
320
|
+
in mind. It is not meant as a silver bullet to handle all your
|
321
|
+
whitelisting problems. However you can easily mix the API with your
|
322
|
+
own code to adapt to your situation.
|
323
|
+
|
324
|
+
Imagine a scenario where you want to whitelist an attribute
|
325
|
+
containing a hash with any keys. Using strong parameters you can't
|
326
|
+
allow a hash with any keys but you can use a simple assignment to get
|
327
|
+
the job done:
|
328
|
+
|
329
|
+
```ruby
|
330
|
+
def product_params
|
331
|
+
params.require(:product).permit(:name).tap do |whitelisted|
|
332
|
+
whitelisted[:data] = params[:product][:data]
|
333
|
+
end
|
334
|
+
end
|
335
|
+
```
|
173
336
|
|
174
337
|
Session
|
175
338
|
-------
|
@@ -408,7 +571,7 @@ Note that while for session values you set the key to `nil`, to delete a cookie
|
|
408
571
|
Rendering xml and json data
|
409
572
|
---------------------------
|
410
573
|
|
411
|
-
ActionController makes it extremely easy to render `xml` or `json` data. If you
|
574
|
+
ActionController makes it extremely easy to render `xml` or `json` data. If you've generated a controller using scaffolding, it would look something like this:
|
412
575
|
|
413
576
|
```ruby
|
414
577
|
class UsersController < ApplicationController
|
@@ -423,7 +586,7 @@ class UsersController < ApplicationController
|
|
423
586
|
end
|
424
587
|
```
|
425
588
|
|
426
|
-
|
589
|
+
You may notice in the above code that we're using `render xml: @users`, not `render xml: @users.to_xml`. If the object is not a String, then Rails will automatically invoke `to_xml` for us.
|
427
590
|
|
428
591
|
Filters
|
429
592
|
-------
|
@@ -446,15 +609,6 @@ class ApplicationController < ActionController::Base
|
|
446
609
|
redirect_to new_login_url # halts request cycle
|
447
610
|
end
|
448
611
|
end
|
449
|
-
|
450
|
-
# The logged_in? method simply returns true if the user is logged
|
451
|
-
# in and false otherwise. It does this by "booleanizing" the
|
452
|
-
# current_user method we created previously using a double ! operator.
|
453
|
-
# Note that this is not common in Ruby and is discouraged unless you
|
454
|
-
# really mean to convert something into true or false.
|
455
|
-
def logged_in?
|
456
|
-
!!current_user
|
457
|
-
end
|
458
612
|
end
|
459
613
|
```
|
460
614
|
|
@@ -635,7 +789,7 @@ Rails comes with two built-in HTTP authentication mechanisms:
|
|
635
789
|
HTTP basic authentication is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, consider an administration section which will only be available by entering a username and a password into the browser's HTTP basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, `http_basic_authenticate_with`.
|
636
790
|
|
637
791
|
```ruby
|
638
|
-
class
|
792
|
+
class AdminsController < ApplicationController
|
639
793
|
http_basic_authenticate_with name: "humbaba", password: "5baa61e4"
|
640
794
|
end
|
641
795
|
```
|
@@ -647,7 +801,7 @@ With this in place, you can create namespaced controllers that inherit from `Adm
|
|
647
801
|
HTTP digest authentication is superior to the basic authentication as it does not require the client to send an unencrypted password over the network (though HTTP basic authentication is safe over HTTPS). Using digest authentication with Rails is quite easy and only requires using one method, `authenticate_or_request_with_http_digest`.
|
648
802
|
|
649
803
|
```ruby
|
650
|
-
class
|
804
|
+
class AdminsController < ApplicationController
|
651
805
|
USERS = { "lifo" => "world" }
|
652
806
|
|
653
807
|
before_action :authenticate
|
@@ -1,7 +1,9 @@
|
|
1
1
|
Action Mailer Basics
|
2
2
|
====================
|
3
3
|
|
4
|
-
This guide should provide you with all you need to get started in sending and
|
4
|
+
This guide should provide you with all you need to get started in sending and
|
5
|
+
receiving emails from and to your application, and many internals of Action
|
6
|
+
Mailer. It also covers how to test your mailers.
|
5
7
|
|
6
8
|
After reading this guide, you will know:
|
7
9
|
|
@@ -9,17 +11,19 @@ After reading this guide, you will know:
|
|
9
11
|
* How to generate and edit an Action Mailer class and mailer view.
|
10
12
|
* How to configure Action Mailer for your environment.
|
11
13
|
* How to test your Action Mailer classes.
|
14
|
+
|
12
15
|
--------------------------------------------------------------------------------
|
13
16
|
|
14
17
|
Introduction
|
15
18
|
------------
|
16
19
|
|
17
|
-
Action Mailer allows you to send emails from your application using
|
20
|
+
Action Mailer allows you to send emails from your application using mailer classes and views. Mailers work very similarly to controllers. They inherit from `ActionMailer::Base` and live in `app/mailers`, and they have associated views that appear in `app/views`.
|
18
21
|
|
19
22
|
Sending Emails
|
20
23
|
--------------
|
21
24
|
|
22
|
-
This section will provide a step-by-step guide to creating a mailer and its
|
25
|
+
This section will provide a step-by-step guide to creating a mailer and its
|
26
|
+
views.
|
23
27
|
|
24
28
|
### Walkthrough to Generating a Mailer
|
25
29
|
|
@@ -34,10 +38,25 @@ invoke test_unit
|
|
34
38
|
create test/mailers/user_mailer_test.rb
|
35
39
|
```
|
36
40
|
|
37
|
-
|
41
|
+
As you can see, you can generate mailers just like you use other generators with
|
42
|
+
Rails. Mailers are conceptually similar to controllers, and so we get a mailer,
|
43
|
+
a directory for views, and a test.
|
44
|
+
|
45
|
+
If you didn't want to use a generator, you could create your own file inside of
|
46
|
+
app/mailers, just make sure that it inherits from `ActionMailer::Base`:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
class MyMailer < ActionMailer::Base
|
50
|
+
end
|
51
|
+
```
|
38
52
|
|
39
53
|
#### Edit the Mailer
|
40
54
|
|
55
|
+
Mailers are very similar to Rails controllers. They also have methods called
|
56
|
+
"actions" and use views to structure the content. Where a controller generates
|
57
|
+
content like HTML to send back to the client, a Mailer creates a message to be
|
58
|
+
delivered via email.
|
59
|
+
|
41
60
|
`app/mailers/user_mailer.rb` contains an empty mailer:
|
42
61
|
|
43
62
|
```ruby
|
@@ -46,7 +65,8 @@ class UserMailer < ActionMailer::Base
|
|
46
65
|
end
|
47
66
|
```
|
48
67
|
|
49
|
-
Let's add a method called `welcome_email`, that will send an email to the user's
|
68
|
+
Let's add a method called `welcome_email`, that will send an email to the user's
|
69
|
+
registered email address:
|
50
70
|
|
51
71
|
```ruby
|
52
72
|
class UserMailer < ActionMailer::Base
|
@@ -55,21 +75,25 @@ class UserMailer < ActionMailer::Base
|
|
55
75
|
def welcome_email(user)
|
56
76
|
@user = user
|
57
77
|
@url = 'http://example.com/login'
|
58
|
-
mail(to: user.email, subject: 'Welcome to My Awesome Site')
|
78
|
+
mail(to: @user.email, subject: 'Welcome to My Awesome Site')
|
59
79
|
end
|
60
80
|
end
|
61
81
|
```
|
62
82
|
|
63
|
-
Here is a quick explanation of the items presented in the preceding method. For
|
83
|
+
Here is a quick explanation of the items presented in the preceding method. For
|
84
|
+
a full list of all available options, please have a look further down at the
|
85
|
+
Complete List of Action Mailer user-settable attributes section.
|
64
86
|
|
65
|
-
* `default Hash` - This is a hash of default values for any email you send
|
87
|
+
* `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.
|
66
88
|
* `mail` - The actual email message, we are passing the `:to` and `:subject` headers in.
|
67
89
|
|
68
|
-
Just like controllers, any instance variables we define in the method become
|
90
|
+
Just like controllers, any instance variables we define in the method become
|
91
|
+
available for use in the views.
|
69
92
|
|
70
93
|
#### Create a Mailer View
|
71
94
|
|
72
|
-
Create a file called `welcome_email.html.erb` in `app/views/user_mailer/`. This
|
95
|
+
Create a file called `welcome_email.html.erb` in `app/views/user_mailer/`. This
|
96
|
+
will be the template used for the email, formatted in HTML:
|
73
97
|
|
74
98
|
```html+erb
|
75
99
|
<!DOCTYPE html>
|
@@ -91,7 +115,9 @@ Create a file called `welcome_email.html.erb` in `app/views/user_mailer/`. This
|
|
91
115
|
</html>
|
92
116
|
```
|
93
117
|
|
94
|
-
|
118
|
+
Let's also make a text part for this email. Not all clients prefer HTML emails,
|
119
|
+
and so sending both is best practice. To do this, create a file called
|
120
|
+
`welcome_email.text.erb` in `app/views/user_mailer/`:
|
95
121
|
|
96
122
|
```erb
|
97
123
|
Welcome to example.com, <%= @user.name %>
|
@@ -105,22 +131,29 @@ To login to the site, just follow this link: <%= @url %>.
|
|
105
131
|
Thanks for joining and have a great day!
|
106
132
|
```
|
107
133
|
|
108
|
-
When you call the `mail` method now, Action Mailer will detect the two templates
|
134
|
+
When you call the `mail` method now, Action Mailer will detect the two templates
|
135
|
+
(text and HTML) and automatically generate a `multipart/alternative` email.
|
109
136
|
|
110
|
-
####
|
137
|
+
#### Calling the Mailer
|
111
138
|
|
112
|
-
|
139
|
+
Mailers are really just another way to render a view. Instead of rendering a
|
140
|
+
view and sending out the HTTP protocol, they are just sending it out through the
|
141
|
+
Email protocols instead. Due to this, it makes sense to just have your
|
142
|
+
controller tell the Mailer to send an email when a user is successfully created.
|
113
143
|
|
114
144
|
Setting this up is painfully simple.
|
115
145
|
|
116
|
-
First
|
146
|
+
First, let's create a simple `User` scaffold:
|
117
147
|
|
118
148
|
```bash
|
119
|
-
$ rails generate scaffold user name
|
149
|
+
$ rails generate scaffold user name email login
|
120
150
|
$ rake db:migrate
|
121
151
|
```
|
122
152
|
|
123
|
-
Now that we have a user model to play with, we will just edit the
|
153
|
+
Now that we have a user model to play with, we will just edit the
|
154
|
+
`app/controllers/users_controller.rb` make it instruct the UserMailer to deliver
|
155
|
+
an email to the newly created user by editing the create action and inserting a
|
156
|
+
call to `UserMailer.welcome_email` right after the user is successfully saved:
|
124
157
|
|
125
158
|
```ruby
|
126
159
|
class UsersController < ApplicationController
|
@@ -145,63 +178,50 @@ class UsersController < ApplicationController
|
|
145
178
|
end
|
146
179
|
```
|
147
180
|
|
148
|
-
|
149
|
-
|
150
|
-
The method `welcome_email` returns a `Mail::Message` object which can then just be told `deliver` to send itself out.
|
181
|
+
The method `welcome_email` returns a `Mail::Message` object which can then just
|
182
|
+
be told `deliver` to send itself out.
|
151
183
|
|
152
184
|
### Auto encoding header values
|
153
185
|
|
154
|
-
Action Mailer
|
155
|
-
|
156
|
-
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.
|
186
|
+
Action Mailer handles the auto encoding of multibyte characters inside of
|
187
|
+
headers and bodies.
|
157
188
|
|
158
|
-
For more complex examples such as defining alternate character sets or
|
189
|
+
For more complex examples such as defining alternate character sets or
|
190
|
+
self-encoding text first, please refer to the
|
191
|
+
[Mail](https://github.com/mikel/mail) library.
|
159
192
|
|
160
193
|
### Complete List of Action Mailer Methods
|
161
194
|
|
162
|
-
There are just three methods that you need to send pretty much any email
|
195
|
+
There are just three methods that you need to send pretty much any email
|
196
|
+
message:
|
163
197
|
|
164
|
-
* `headers` - Specifies any header on the email you want. You can pass a hash of
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
* Defining a header field as a parameter to the `mail` method:
|
173
|
-
|
174
|
-
```ruby
|
175
|
-
mail('X-Spam' => value)
|
176
|
-
```
|
177
|
-
|
178
|
-
* Passing in a key value assignment to the `headers` method:
|
179
|
-
|
180
|
-
```ruby
|
181
|
-
headers['X-Spam'] = value
|
182
|
-
```
|
183
|
-
|
184
|
-
* Passing a hash of key value pairs to the `headers` method:
|
185
|
-
|
186
|
-
```ruby
|
187
|
-
headers {'X-Spam' => value, 'X-Special' => another_value}
|
188
|
-
```
|
189
|
-
|
190
|
-
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`.
|
198
|
+
* `headers` - Specifies any header on the email you want. You can pass a hash of
|
199
|
+
header field names and value pairs, or you can call `headers[:field_name] =
|
200
|
+
'value'`.
|
201
|
+
* `attachments` - Allows you to add attachments to your email. For example,
|
202
|
+
`attachments['file-name.jpg'] = File.read('file-name.jpg')`.
|
203
|
+
* `mail` - Sends the actual email itself. You can pass in headers as a hash to
|
204
|
+
the mail method as a parameter, mail will then create an email, either plain
|
205
|
+
text, or multipart, depending on what email templates you have defined.
|
191
206
|
|
192
207
|
#### Adding Attachments
|
193
208
|
|
194
|
-
|
209
|
+
Action Mailer makes it very easy to add attachments.
|
195
210
|
|
196
|
-
* Pass the file name and content and Action Mailer and the
|
211
|
+
* Pass the file name and content and Action Mailer and the
|
212
|
+
[Mail gem](https://github.com/mikel/mail) will automatically guess the
|
213
|
+
mime_type, set the encoding and create the attachment.
|
197
214
|
|
198
215
|
```ruby
|
199
216
|
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
|
200
217
|
```
|
201
218
|
|
202
|
-
NOTE: Mail will automatically Base64 encode an attachment. If you want something
|
219
|
+
NOTE: Mail will automatically Base64 encode an attachment. If you want something
|
220
|
+
different, encode your content and pass in the encoded content and encoding in a
|
221
|
+
`Hash` to the `attachments` method.
|
203
222
|
|
204
|
-
* Pass the file name and specify headers and content and Action Mailer and Mail
|
223
|
+
* Pass the file name and specify headers and content and Action Mailer and Mail
|
224
|
+
will use the settings you pass in.
|
205
225
|
|
206
226
|
```ruby
|
207
227
|
encoded_content = SpecialEncode(File.read('/path/to/filename.jpg'))
|
@@ -210,13 +230,14 @@ NOTE: Mail will automatically Base64 encode an attachment. If you want something
|
|
210
230
|
content: encoded_content }
|
211
231
|
```
|
212
232
|
|
213
|
-
NOTE: If you specify an encoding, Mail will assume that your content is already
|
233
|
+
NOTE: If you specify an encoding, Mail will assume that your content is already
|
234
|
+
encoded and not try to Base64 encode it.
|
214
235
|
|
215
236
|
#### Making Inline Attachments
|
216
237
|
|
217
238
|
Action Mailer 3.0 makes inline attachments, which involved a lot of hacking in pre 3.0 versions, much simpler and trivial as they should be.
|
218
239
|
|
219
|
-
*
|
240
|
+
* First, to tell Mail to turn an attachment into an inline attachment, you just call `#inline` on the attachments method within your Mailer:
|
220
241
|
|
221
242
|
```ruby
|
222
243
|
def welcome
|
@@ -224,7 +245,9 @@ Action Mailer 3.0 makes inline attachments, which involved a lot of hacking in p
|
|
224
245
|
end
|
225
246
|
```
|
226
247
|
|
227
|
-
* Then in your view, you can just reference `attachments
|
248
|
+
* Then in your view, you can just reference `attachments` as a hash and specify
|
249
|
+
which attachment you want to show, calling `url` on it and then passing the
|
250
|
+
result into the `image_tag` method:
|
228
251
|
|
229
252
|
```html+erb
|
230
253
|
<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
|
|
232
255
|
<%= image_tag attachments['image.jpg'].url %>
|
233
256
|
```
|
234
257
|
|
235
|
-
* As this is a standard call to `image_tag` you can pass in an options hash
|
258
|
+
* As this is a standard call to `image_tag` you can pass in an options hash
|
259
|
+
after the attachment URL as you could for any other image:
|
236
260
|
|
237
261
|
```html+erb
|
238
262
|
<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
|
|
243
267
|
|
244
268
|
#### Sending Email To Multiple Recipients
|
245
269
|
|
246
|
-
It is possible to send email to one or more recipients in one email (e.g.,
|
270
|
+
It is possible to send email to one or more recipients in one email (e.g.,
|
271
|
+
informing all admins of a new signup) by setting the list of emails to the `:to`
|
272
|
+
key. The list of emails can be an array of email addresses or a single string
|
273
|
+
with the addresses separated by commas.
|
247
274
|
|
248
275
|
```ruby
|
249
276
|
class AdminMailer < ActionMailer::Base
|
@@ -257,12 +284,14 @@ class AdminMailer < ActionMailer::Base
|
|
257
284
|
end
|
258
285
|
```
|
259
286
|
|
260
|
-
The same format can be used to set carbon copy (Cc:) and blind carbon copy
|
287
|
+
The same format can be used to set carbon copy (Cc:) and blind carbon copy
|
288
|
+
(Bcc:) recipients, by using the `:cc` and `:bcc` keys respectively.
|
261
289
|
|
262
290
|
#### Sending Email With Name
|
263
291
|
|
264
|
-
Sometimes you wish to show the name of the person instead of just their email
|
265
|
-
|
292
|
+
Sometimes you wish to show the name of the person instead of just their email
|
293
|
+
address when they receive the email. The trick to doing that is to format the
|
294
|
+
email address in the format `"Full Name <email>"`.
|
266
295
|
|
267
296
|
```ruby
|
268
297
|
def welcome_email(user)
|
@@ -274,7 +303,11 @@ end
|
|
274
303
|
|
275
304
|
### Mailer Views
|
276
305
|
|
277
|
-
Mailer views are located in the `app/views/name_of_mailer_class` directory. The
|
306
|
+
Mailer views are located in the `app/views/name_of_mailer_class` directory. The
|
307
|
+
specific mailer view is known to the class because its name is the same as the
|
308
|
+
mailer method. In our example from above, our mailer view for the
|
309
|
+
`welcome_email` method will be in `app/views/user_mailer/welcome_email.html.erb`
|
310
|
+
for the HTML version and `welcome_email.text.erb` for the plain text version.
|
278
311
|
|
279
312
|
To change the default mailer view for your action you do something like:
|
280
313
|
|
@@ -285,7 +318,7 @@ class UserMailer < ActionMailer::Base
|
|
285
318
|
def welcome_email(user)
|
286
319
|
@user = user
|
287
320
|
@url = 'http://example.com/login'
|
288
|
-
mail(to: user.email,
|
321
|
+
mail(to: @user.email,
|
289
322
|
subject: 'Welcome to My Awesome Site',
|
290
323
|
template_path: 'notifications',
|
291
324
|
template_name: 'another')
|
@@ -293,9 +326,12 @@ class UserMailer < ActionMailer::Base
|
|
293
326
|
end
|
294
327
|
```
|
295
328
|
|
296
|
-
In this case it will look for templates at `app/views/notifications` with name
|
329
|
+
In this case it will look for templates at `app/views/notifications` with name
|
330
|
+
`another`. You can also specify an array of paths for `template_path`, and they
|
331
|
+
will be searched in order.
|
297
332
|
|
298
|
-
If you want more flexibility you can also pass a block and render specific
|
333
|
+
If you want more flexibility you can also pass a block and render specific
|
334
|
+
templates or even render inline or text without using a template file:
|
299
335
|
|
300
336
|
```ruby
|
301
337
|
class UserMailer < ActionMailer::Base
|
@@ -304,23 +340,28 @@ class UserMailer < ActionMailer::Base
|
|
304
340
|
def welcome_email(user)
|
305
341
|
@user = user
|
306
342
|
@url = 'http://example.com/login'
|
307
|
-
mail(to: user.email,
|
343
|
+
mail(to: @user.email,
|
308
344
|
subject: 'Welcome to My Awesome Site') do |format|
|
309
345
|
format.html { render 'another_template' }
|
310
346
|
format.text { render text: 'Render text' }
|
311
347
|
end
|
312
348
|
end
|
313
|
-
|
314
349
|
end
|
315
350
|
```
|
316
351
|
|
317
|
-
This will render the template 'another_template.html.erb' for the HTML part and
|
352
|
+
This will render the template 'another_template.html.erb' for the HTML part and
|
353
|
+
use the rendered text for the text part. The render command is the same one used
|
354
|
+
inside of Action Controller, so you can use all the same options, such as
|
355
|
+
`:text`, `:inline` etc.
|
318
356
|
|
319
357
|
### Action Mailer Layouts
|
320
358
|
|
321
|
-
Just like controller views, you can also have mailer layouts. The layout name
|
359
|
+
Just like controller views, you can also have mailer layouts. The layout name
|
360
|
+
needs to be the same as your mailer, such as `user_mailer.html.erb` and
|
361
|
+
`user_mailer.text.erb` to be automatically recognized by your mailer as a
|
362
|
+
layout.
|
322
363
|
|
323
|
-
In order to use a different file
|
364
|
+
In order to use a different file, call `layout` in your mailer:
|
324
365
|
|
325
366
|
```ruby
|
326
367
|
class UserMailer < ActionMailer::Base
|
@@ -328,9 +369,11 @@ class UserMailer < ActionMailer::Base
|
|
328
369
|
end
|
329
370
|
```
|
330
371
|
|
331
|
-
Just like with controller views, use `yield` to render the view inside the
|
372
|
+
Just like with controller views, use `yield` to render the view inside the
|
373
|
+
layout.
|
332
374
|
|
333
|
-
You can also pass in a `layout: 'layout_name'` option to the render call inside
|
375
|
+
You can also pass in a `layout: 'layout_name'` option to the render call inside
|
376
|
+
the format block to specify different layouts for different actions:
|
334
377
|
|
335
378
|
```ruby
|
336
379
|
class UserMailer < ActionMailer::Base
|
@@ -343,13 +386,37 @@ class UserMailer < ActionMailer::Base
|
|
343
386
|
end
|
344
387
|
```
|
345
388
|
|
346
|
-
Will render the HTML part using the `my_layout.html.erb` file and the text part
|
389
|
+
Will render the HTML part using the `my_layout.html.erb` file and the text part
|
390
|
+
with the usual `user_mailer.text.erb` file if it exists.
|
347
391
|
|
348
392
|
### Generating URLs in Action Mailer Views
|
349
393
|
|
350
|
-
|
394
|
+
Unlike controllers, the mailer instance doesn't have any context about the
|
395
|
+
incoming request so you'll need to provide the `:host` parameter yourself.
|
396
|
+
|
397
|
+
As the `:host` usually is consistent across the application you can configure it
|
398
|
+
globally in `config/application.rb`:
|
399
|
+
|
400
|
+
```ruby
|
401
|
+
config.action_mailer.default_url_options = { host: 'example.com' }
|
402
|
+
```
|
403
|
+
|
404
|
+
#### generating URLs with `url_for`
|
405
|
+
|
406
|
+
You need to pass the `only_path: false` option when using `url_for`. This will
|
407
|
+
ensure that absolute URLs are generated because the `url_for` view helper will,
|
408
|
+
by default, generate relative URLs when a `:host` option isn't explicitly
|
409
|
+
provided.
|
410
|
+
|
411
|
+
```erb
|
412
|
+
<%= url_for(controller: 'welcome',
|
413
|
+
action: 'greeting',
|
414
|
+
only_path: false) %>
|
415
|
+
```
|
416
|
+
|
417
|
+
If you did not configure the `:host` option globally make sure to pass it to
|
418
|
+
`url_for`.
|
351
419
|
|
352
|
-
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`:
|
353
420
|
|
354
421
|
```erb
|
355
422
|
<%= url_for(host: 'example.com',
|
@@ -357,27 +424,32 @@ Unlike controllers, the mailer instance doesn't have any context about the incom
|
|
357
424
|
action: 'greeting') %>
|
358
425
|
```
|
359
426
|
|
360
|
-
When
|
427
|
+
NOTE: When you explicitly pass the `:host` Rails will always generate absolute
|
428
|
+
URLs, so there is no need to pass `only_path: false`.
|
361
429
|
|
362
|
-
|
363
|
-
<%= user_url(@user, host: 'example.com') %>
|
364
|
-
```
|
430
|
+
#### generating URLs with named routes
|
365
431
|
|
366
|
-
Email clients have no web context and so paths have no base URL to form complete
|
432
|
+
Email clients have no web context and so paths have no base URL to form complete
|
433
|
+
web addresses. Thus, you should always use the "_url" variant of named route
|
434
|
+
helpers.
|
367
435
|
|
368
|
-
|
436
|
+
If you did not configure the `:host` option globally make sure to pass it to the
|
437
|
+
url helper.
|
369
438
|
|
370
|
-
```
|
371
|
-
|
439
|
+
```erb
|
440
|
+
<%= user_url(@user, host: 'example.com') %>
|
372
441
|
```
|
373
442
|
|
374
|
-
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.
|
375
|
-
|
376
443
|
### Sending Multipart Emails
|
377
444
|
|
378
|
-
Action Mailer will automatically send multipart emails if you have different
|
445
|
+
Action Mailer will automatically send multipart emails if you have different
|
446
|
+
templates for the same action. So, for our UserMailer example, if you have
|
447
|
+
`welcome_email.text.erb` and `welcome_email.html.erb` in
|
448
|
+
`app/views/user_mailer`, Action Mailer will automatically send a multipart email
|
449
|
+
with the HTML and text versions setup as different parts.
|
379
450
|
|
380
|
-
The order of the parts getting inserted is determined by the `:parts_order`
|
451
|
+
The order of the parts getting inserted is determined by the `:parts_order`
|
452
|
+
inside of the `ActionMailer::Base.default` method.
|
381
453
|
|
382
454
|
### Sending Emails with Attachments
|
383
455
|
|
@@ -389,25 +461,51 @@ class UserMailer < ActionMailer::Base
|
|
389
461
|
@user = user
|
390
462
|
@url = user_url(@user)
|
391
463
|
attachments['terms.pdf'] = File.read('/path/terms.pdf')
|
392
|
-
mail(to: user.email,
|
464
|
+
mail(to: @user.email,
|
393
465
|
subject: 'Please see the Terms and Conditions attached')
|
394
466
|
end
|
395
467
|
end
|
396
468
|
```
|
397
469
|
|
398
|
-
The above will send a multipart email with an attachment, properly nested with
|
470
|
+
The above will send a multipart email with an attachment, properly nested with
|
471
|
+
the top level being `multipart/mixed` and the first part being a
|
472
|
+
`multipart/alternative` containing the plain text and HTML email messages.
|
399
473
|
|
400
474
|
### Sending Emails with Dynamic Delivery Options
|
401
475
|
|
402
|
-
If you wish to override the default delivery options (e.g. SMTP credentials)
|
476
|
+
If you wish to override the default delivery options (e.g. SMTP credentials)
|
477
|
+
while delivering emails, you can do this using `delivery_method_options` in the
|
478
|
+
mailer action.
|
403
479
|
|
404
480
|
```ruby
|
405
481
|
class UserMailer < ActionMailer::Base
|
406
|
-
def welcome_email(user,company)
|
482
|
+
def welcome_email(user, company)
|
407
483
|
@user = user
|
408
484
|
@url = user_url(@user)
|
409
|
-
delivery_options = { user_name: company.smtp_user,
|
410
|
-
|
485
|
+
delivery_options = { user_name: company.smtp_user,
|
486
|
+
password: company.smtp_password,
|
487
|
+
address: company.smtp_host }
|
488
|
+
mail(to: @user.email,
|
489
|
+
subject: "Please see the Terms and Conditions attached",
|
490
|
+
delivery_method_options: delivery_options)
|
491
|
+
end
|
492
|
+
end
|
493
|
+
```
|
494
|
+
|
495
|
+
### Sending Emails without Template Rendering
|
496
|
+
|
497
|
+
There may be cases in which you want to skip the template rendering step and
|
498
|
+
supply the email body as a string. You can achieve this using the `:body`
|
499
|
+
option. In such cases don't forget to add the `:content_type` option. Rails
|
500
|
+
will default to `text/plain` otherwise.
|
501
|
+
|
502
|
+
```ruby
|
503
|
+
class UserMailer < ActionMailer::Base
|
504
|
+
def welcome_email(user, email_body)
|
505
|
+
mail(to: user.email,
|
506
|
+
body: email_body,
|
507
|
+
content_type: "text/html",
|
508
|
+
subject: "Already rendered!")
|
411
509
|
end
|
412
510
|
end
|
413
511
|
```
|
@@ -415,13 +513,21 @@ end
|
|
415
513
|
Receiving Emails
|
416
514
|
----------------
|
417
515
|
|
418
|
-
Receiving and parsing emails with Action Mailer can be a rather complex
|
516
|
+
Receiving and parsing emails with Action Mailer can be a rather complex
|
517
|
+
endeavor. Before your email reaches your Rails app, you would have had to
|
518
|
+
configure your system to somehow forward emails to your app, which needs to be
|
519
|
+
listening for that. So, to receive emails in your Rails app you'll need to:
|
419
520
|
|
420
521
|
* Implement a `receive` method in your mailer.
|
421
522
|
|
422
|
-
* Configure your email server to forward emails from the address(es) you would
|
523
|
+
* Configure your email server to forward emails from the address(es) you would
|
524
|
+
like your app to receive to `/path/to/app/bin/rails runner
|
525
|
+
'UserMailer.receive(STDIN.read)'`.
|
423
526
|
|
424
|
-
Once a method called `receive` is defined in any mailer, Action Mailer will
|
527
|
+
Once a method called `receive` is defined in any mailer, Action Mailer will
|
528
|
+
parse the raw incoming email into an email object, decode it, instantiate a new
|
529
|
+
mailer, and pass the email object to the mailer `receive` instance
|
530
|
+
method. Here's an example:
|
425
531
|
|
426
532
|
```ruby
|
427
533
|
class UserMailer < ActionMailer::Base
|
@@ -447,17 +553,23 @@ end
|
|
447
553
|
Action Mailer Callbacks
|
448
554
|
---------------------------
|
449
555
|
|
450
|
-
Action Mailer allows for you to specify a `before_action`, `after_action` and
|
556
|
+
Action Mailer allows for you to specify a `before_action`, `after_action` and
|
557
|
+
`around_action`.
|
451
558
|
|
452
|
-
* Filters can be specified with a block or a symbol to a method in the mailer
|
559
|
+
* Filters can be specified with a block or a symbol to a method in the mailer
|
560
|
+
class similar to controllers.
|
453
561
|
|
454
|
-
* You could use a `before_action` to
|
562
|
+
* You could use a `before_action` to populate the mail object with defaults,
|
563
|
+
delivery_method_options or insert default headers and attachments.
|
455
564
|
|
456
|
-
* You could use an `after_action` to do similar setup as a `before_action` but
|
565
|
+
* You could use an `after_action` to do similar setup as a `before_action` but
|
566
|
+
using instance variables set in your mailer action.
|
457
567
|
|
458
568
|
```ruby
|
459
569
|
class UserMailer < ActionMailer::Base
|
460
|
-
after_action :set_delivery_options,
|
570
|
+
after_action :set_delivery_options,
|
571
|
+
:prevent_delivery_to_guests,
|
572
|
+
:set_business_headers
|
461
573
|
|
462
574
|
def feedback_message(business, user)
|
463
575
|
@business = business
|
@@ -473,7 +585,8 @@ class UserMailer < ActionMailer::Base
|
|
473
585
|
private
|
474
586
|
|
475
587
|
def set_delivery_options
|
476
|
-
# You have access to the mail instance
|
588
|
+
# You have access to the mail instance,
|
589
|
+
# @business and @user instance variables here
|
477
590
|
if @business && @business.has_smtp_settings?
|
478
591
|
mail.delivery_method.settings.merge!(@business.smtp_settings)
|
479
592
|
end
|
@@ -498,16 +611,17 @@ end
|
|
498
611
|
Using Action Mailer Helpers
|
499
612
|
---------------------------
|
500
613
|
|
501
|
-
Action Mailer now just inherits from
|
614
|
+
Action Mailer now just inherits from `AbstractController`, so you have access to
|
615
|
+
the same generic helpers as you do in Action Controller.
|
502
616
|
|
503
617
|
Action Mailer Configuration
|
504
618
|
---------------------------
|
505
619
|
|
506
|
-
The following configuration options are best made in one of the environment
|
620
|
+
The following configuration options are best made in one of the environment
|
621
|
+
files (environment.rb, production.rb, etc...)
|
507
622
|
|
508
623
|
| Configuration | Description |
|
509
624
|
|---------------|-------------|
|
510
|
-
|`template_root`|Determines the base from which template references will be made.|
|
511
625
|
|`logger`|Generates information on the mailing run if available. Can be set to `nil` for no logging. Compatible with both Ruby's own `Logger` and `Log4r` loggers.|
|
512
626
|
|`smtp_settings`|Allows detailed configuration for `:smtp` delivery method:<ul><li>`:address` - Allows you to use a remote mail server. Just change it from its default "localhost" setting.</li><li>`:port` - On the off chance that your mail server doesn't run on port 25, you can change it.</li><li>`:domain` - If you need to specify a HELO domain, you can do it here.</li><li>`:user_name` - If your mail server requires authentication, set the username in this setting.</li><li>`:password` - If your mail server requires authentication, set the password in this setting.</li><li>`:authentication` - If your mail server requires authentication, you need to specify the authentication type here. This is a symbol and one of `:plain`, `:login`, `:cram_md5`.</li><li>`:enable_starttls_auto` - Set this to `false` if there is a problem with your server certificate that you cannot resolve.</li></ul>|
|
513
627
|
|`sendmail_settings`|Allows you to override options for the `:sendmail` delivery method.<ul><li>`:location` - The location of the sendmail executable. Defaults to `/usr/sbin/sendmail`.</li><li>`:arguments` - The command line arguments to be passed to sendmail. Defaults to `-i -t`.</li></ul>|
|
@@ -517,9 +631,14 @@ The following configuration options are best made in one of the environment file
|
|
517
631
|
|`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.|
|
518
632
|
|`default_options`|Allows you to set default values for the `mail` method options (`:from`, `:reply_to`, etc.).|
|
519
633
|
|
634
|
+
For a complete writeup of possible configurations see the
|
635
|
+
[Action Mailer section](configuring.html#configuring-action-mailer) in
|
636
|
+
our Configuring Rails Applications guide.
|
637
|
+
|
520
638
|
### Example Action Mailer Configuration
|
521
639
|
|
522
|
-
An example would be adding the following to your appropriate
|
640
|
+
An example would be adding the following to your appropriate
|
641
|
+
`config/environments/$RAILS_ENV.rb` file:
|
523
642
|
|
524
643
|
```ruby
|
525
644
|
config.action_mailer.delivery_method = :sendmail
|
@@ -530,19 +649,20 @@ config.action_mailer.delivery_method = :sendmail
|
|
530
649
|
# }
|
531
650
|
config.action_mailer.perform_deliveries = true
|
532
651
|
config.action_mailer.raise_delivery_errors = true
|
533
|
-
config.action_mailer.default_options = {from: 'no-replay@example.
|
652
|
+
config.action_mailer.default_options = {from: 'no-replay@example.com'}
|
534
653
|
```
|
535
654
|
|
536
|
-
### Action Mailer Configuration for
|
655
|
+
### Action Mailer Configuration for Gmail
|
537
656
|
|
538
|
-
As Action Mailer now uses the Mail gem, this becomes as simple as adding to your
|
657
|
+
As Action Mailer now uses the Mail gem, this becomes as simple as adding to your
|
658
|
+
`config/environments/$RAILS_ENV.rb` file:
|
539
659
|
|
540
660
|
```ruby
|
541
661
|
config.action_mailer.delivery_method = :smtp
|
542
662
|
config.action_mailer.smtp_settings = {
|
543
663
|
address: 'smtp.gmail.com',
|
544
664
|
port: 587,
|
545
|
-
domain: '
|
665
|
+
domain: 'example.com',
|
546
666
|
user_name: '<username>',
|
547
667
|
password: '<password>',
|
548
668
|
authentication: 'plain',
|
@@ -552,35 +672,15 @@ config.action_mailer.smtp_settings = {
|
|
552
672
|
Mailer Testing
|
553
673
|
--------------
|
554
674
|
|
555
|
-
|
556
|
-
|
557
|
-
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:
|
558
|
-
|
559
|
-
```ruby
|
560
|
-
class UserMailerTest < ActionMailer::TestCase
|
561
|
-
def test_welcome_email
|
562
|
-
user = users(:some_user_in_your_fixtures)
|
563
|
-
|
564
|
-
# Send the email, then test that it got queued
|
565
|
-
email = UserMailer.welcome_email(user).deliver
|
566
|
-
assert !ActionMailer::Base.deliveries.empty?
|
567
|
-
|
568
|
-
# Test the body of the sent email contains what we expect it to
|
569
|
-
assert_equal [user.email], email.to
|
570
|
-
assert_equal 'Welcome to My Awesome Site', email.subject
|
571
|
-
assert_match "<h1>Welcome to example.com, #{user.name}</h1>", email.body.to_s
|
572
|
-
assert_match 'you have joined to example.com community', email.body.to_s
|
573
|
-
end
|
574
|
-
end
|
575
|
-
```
|
576
|
-
|
577
|
-
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.
|
578
|
-
|
579
|
-
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`
|
675
|
+
You can find detailed instructions on how to test your mailers in the
|
676
|
+
[testing guide](testing.html#testing-your-mailers).
|
580
677
|
|
581
678
|
Intercepting Emails
|
582
679
|
-------------------
|
583
|
-
There are situations where you need to edit an email before it's
|
680
|
+
There are situations where you need to edit an email before it's
|
681
|
+
delivered. Fortunately Action Mailer provides hooks to intercept every
|
682
|
+
email. You can register an interceptor to make modifications to mail messages
|
683
|
+
right before they are handed to the delivery agents.
|
584
684
|
|
585
685
|
```ruby
|
586
686
|
class SandboxEmailInterceptor
|
@@ -590,10 +690,15 @@ class SandboxEmailInterceptor
|
|
590
690
|
end
|
591
691
|
```
|
592
692
|
|
593
|
-
Before the interceptor can do its job you need to register it with the Action
|
693
|
+
Before the interceptor can do its job you need to register it with the Action
|
694
|
+
Mailer framework. You can do this in an initializer file
|
695
|
+
`config/initializers/sandbox_email_interceptor.rb`
|
594
696
|
|
595
697
|
```ruby
|
596
698
|
ActionMailer::Base.register_interceptor(SandboxEmailInterceptor) if Rails.env.staging?
|
597
699
|
```
|
598
700
|
|
599
|
-
NOTE: The example above uses a custom environment called "staging" for a
|
701
|
+
NOTE: The example above uses a custom environment called "staging" for a
|
702
|
+
production like server but for testing purposes. You can read
|
703
|
+
[Creating Rails environments](./configuring.html#creating-rails-environments)
|
704
|
+
for more information about custom Rails environments.
|