rails 4.0.13 → 4.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +22 -17
  3. data/guides/CHANGELOG.md +68 -34
  4. data/guides/assets/images/edge_badge.png +0 -0
  5. data/guides/assets/images/feature_tile.gif +0 -0
  6. data/guides/assets/images/footer_tile.gif +0 -0
  7. data/guides/assets/images/fxn.png +0 -0
  8. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  9. data/guides/assets/images/getting_started/challenge.png +0 -0
  10. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  11. data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
  12. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  13. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  14. data/guides/assets/images/getting_started/new_article.png +0 -0
  15. data/guides/assets/images/getting_started/rails_welcome.png +0 -0
  16. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  17. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  18. data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
  19. data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
  20. data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
  21. data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
  22. data/guides/assets/images/header_tile.gif +0 -0
  23. data/guides/assets/images/icons/README +1 -1
  24. data/guides/assets/images/icons/callouts/11.png +0 -0
  25. data/guides/assets/images/icons/callouts/12.png +0 -0
  26. data/guides/assets/images/icons/callouts/13.png +0 -0
  27. data/guides/assets/images/icons/callouts/15.png +0 -0
  28. data/guides/assets/images/icons/caution.png +0 -0
  29. data/guides/assets/images/icons/example.png +0 -0
  30. data/guides/assets/images/radar.png +0 -0
  31. data/guides/assets/images/rails4_features.png +0 -0
  32. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  33. data/guides/assets/images/vijaydev.jpg +0 -0
  34. data/guides/assets/javascripts/guides.js +30 -34
  35. data/guides/assets/stylesheets/main.css +2 -1
  36. data/guides/assets/stylesheets/print.css +1 -1
  37. data/guides/bug_report_templates/action_controller_gem.rb +9 -4
  38. data/guides/bug_report_templates/action_controller_master.rb +4 -2
  39. data/guides/bug_report_templates/active_record_gem.rb +5 -2
  40. data/guides/bug_report_templates/active_record_master.rb +2 -1
  41. data/guides/bug_report_templates/generic_gem.rb +15 -0
  42. data/guides/bug_report_templates/generic_master.rb +26 -0
  43. data/guides/code/getting_started/Gemfile +21 -24
  44. data/guides/code/getting_started/Gemfile.lock +78 -73
  45. data/guides/code/getting_started/Rakefile +1 -1
  46. data/guides/code/getting_started/app/assets/javascripts/application.js +1 -2
  47. data/guides/code/getting_started/app/views/layouts/application.html.erb +2 -2
  48. data/guides/code/getting_started/config/environment.rb +1 -1
  49. data/guides/code/getting_started/config/environments/development.rb +2 -2
  50. data/guides/code/getting_started/config/environments/production.rb +3 -3
  51. data/guides/code/getting_started/config/environments/test.rb +2 -2
  52. data/guides/code/getting_started/config/initializers/secret_token.rb +1 -1
  53. data/guides/code/getting_started/config/initializers/session_store.rb +1 -1
  54. data/guides/code/getting_started/config/routes.rb +1 -1
  55. data/guides/code/getting_started/config.ru +1 -1
  56. data/guides/code/getting_started/public/404.html +2 -0
  57. data/guides/code/getting_started/public/422.html +2 -0
  58. data/guides/code/getting_started/public/500.html +2 -0
  59. data/guides/code/getting_started/test/test_helper.rb +0 -3
  60. data/guides/rails_guides/helpers.rb +3 -1
  61. data/guides/source/2_2_release_notes.md +2 -2
  62. data/guides/source/2_3_release_notes.md +8 -8
  63. data/guides/source/3_0_release_notes.md +2 -3
  64. data/guides/source/3_1_release_notes.md +2 -2
  65. data/guides/source/3_2_release_notes.md +12 -12
  66. data/guides/source/4_0_release_notes.md +79 -46
  67. data/guides/source/4_1_release_notes.md +731 -0
  68. data/guides/source/_welcome.html.erb +5 -2
  69. data/guides/source/action_controller_overview.md +189 -40
  70. data/guides/source/action_mailer_basics.md +27 -27
  71. data/guides/source/action_view_overview.md +131 -20
  72. data/guides/source/active_model_basics.md +6 -6
  73. data/guides/source/active_record_basics.md +15 -15
  74. data/guides/source/active_record_callbacks.md +18 -16
  75. data/guides/source/active_record_querying.md +93 -51
  76. data/guides/source/active_record_validations.md +26 -24
  77. data/guides/source/active_support_core_extensions.md +72 -118
  78. data/guides/source/active_support_instrumentation.md +13 -4
  79. data/guides/source/api_documentation_guidelines.md +104 -6
  80. data/guides/source/asset_pipeline.md +573 -244
  81. data/guides/source/association_basics.md +94 -22
  82. data/guides/source/caching_with_rails.md +15 -6
  83. data/guides/source/command_line.md +55 -46
  84. data/guides/source/configuring.md +248 -52
  85. data/guides/source/contributing_to_ruby_on_rails.md +18 -17
  86. data/guides/source/credits.html.erb +2 -2
  87. data/guides/source/debugging_rails_applications.md +39 -8
  88. data/guides/source/development_dependencies_install.md +91 -8
  89. data/guides/source/documents.yaml +4 -0
  90. data/guides/source/engines.md +678 -232
  91. data/guides/source/form_helpers.md +53 -35
  92. data/guides/source/generators.md +19 -15
  93. data/guides/source/getting_started.md +758 -497
  94. data/guides/source/i18n.md +64 -28
  95. data/guides/source/index.html.erb +1 -1
  96. data/guides/source/initialization.md +155 -58
  97. data/guides/source/kindle/toc.html.erb +1 -1
  98. data/guides/source/layout.html.erb +2 -2
  99. data/guides/source/layouts_and_rendering.md +59 -26
  100. data/guides/source/maintenance_policy.md +3 -3
  101. data/guides/source/migrations.md +101 -62
  102. data/guides/source/nested_model_forms.md +3 -3
  103. data/guides/source/plugins.md +34 -31
  104. data/guides/source/rails_application_templates.md +27 -8
  105. data/guides/source/rails_on_rack.md +41 -58
  106. data/guides/source/routing.md +115 -104
  107. data/guides/source/ruby_on_rails_guides_guidelines.md +2 -2
  108. data/guides/source/security.md +81 -36
  109. data/guides/source/testing.md +56 -79
  110. data/guides/source/upgrading_ruby_on_rails.md +531 -21
  111. data/guides/source/working_with_javascript_in_rails.md +19 -11
  112. metadata +51 -23
  113. data/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png +0 -0
  114. data/guides/assets/images/getting_started/new_post.png +0 -0
  115. data/guides/assets/images/getting_started/post_with_comments.png +0 -0
  116. data/guides/assets/images/getting_started/show_action_for_posts.png +0 -0
  117. data/guides/assets/images/getting_started/template_is_missing_posts_new.png +0 -0
  118. data/guides/assets/images/getting_started/undefined_method_post_path.png +0 -0
  119. data/guides/assets/images/getting_started/unknown_action_create_for_posts.png +0 -0
  120. data/guides/assets/images/getting_started/unknown_action_new_for_posts.png +0 -0
  121. data/guides/assets/images/jaimeiniesta.jpg +0 -0
  122. data/guides/source/kindle/KINDLE.md +0 -26
@@ -10,12 +10,15 @@
10
10
  </p>
11
11
  <% else %>
12
12
  <p>
13
- These are the new guides for Rails 4.0 based on <a href="https://github.com/rails/rails/tree/<%= @version %>"><%= @version %></a>.
13
+ These are the new guides for Rails 4.1 based on <a href="https://github.com/rails/rails/tree/<%= @version %>"><%= @version %></a>.
14
14
  These guides are designed to make you immediately productive with Rails, and to help you understand how all of the pieces fit together.
15
15
  </p>
16
16
  <% end %>
17
17
  <p>
18
- The guides for Rails 3.2.x are available at <a href="http://guides.rubyonrails.org/v3.2.18/">http://guides.rubyonrails.org/v3.2.18/</a>.
18
+ The guides for Rails 4.0.x are available at <a href="http://guides.rubyonrails.org/v4.0.8/">http://guides.rubyonrails.org/v4.0.8/</a>.
19
+ </p>
20
+ <p>
21
+ The guides for Rails 3.2.x are available at <a href="http://guides.rubyonrails.org/v3.2.19/">http://guides.rubyonrails.org/v3.2.19/</a>.
19
22
  </p>
20
23
  <p>
21
24
  The guides for Rails 2.3.x are available at <a href="http://guides.rubyonrails.org/v2.3.11/">http://guides.rubyonrails.org/v2.3.11/</a>.
@@ -112,6 +112,10 @@ NOTE: The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&id
112
112
 
113
113
  The value of `params[:ids]` will now be `["1", "2", "3"]`. Note that parameter values are always strings; Rails makes no attempt to guess or cast the type.
114
114
 
115
+ NOTE: Values such as `[]`, `[nil]` or `[nil, nil, ...]` in `params` are replaced
116
+ with `nil` for security reasons by default. See [Security Guide](security.html#unsafe-query-generation)
117
+ for more information.
118
+
115
119
  To send a hash you include the key name inside the brackets:
116
120
 
117
121
  ```html
@@ -129,7 +133,7 @@ Note that the `params` hash is actually an instance of `ActiveSupport::HashWithI
129
133
 
130
134
  ### JSON parameters
131
135
 
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.
136
+ If you're writing a web service application, you might find yourself more comfortable accepting parameters in JSON format. If the "Content-Type" header of your request is set to "application/json", Rails will automatically convert your parameters into the `params` hash, which you can access as you would normally.
133
137
 
134
138
  So for example, if you are sending this JSON content:
135
139
 
@@ -209,7 +213,7 @@ class PeopleController < ActionController::Base
209
213
  # Request reply.
210
214
  def update
211
215
  person = current_account.people.find(params[:id])
212
- person.update_attributes!(person_params)
216
+ person.update!(person_params)
213
217
  redirect_to person
214
218
  end
215
219
 
@@ -257,7 +261,7 @@ params.require(:log_entry).permit!
257
261
  ```
258
262
 
259
263
  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
264
+ permitted. Extreme care should be taken when using `permit!` as it
261
265
  will allow all current and future model attributes to be
262
266
  mass-assigned.
263
267
 
@@ -346,11 +350,11 @@ Your application has a session for each user in which you can store small amount
346
350
 
347
351
  All session stores use a cookie to store a unique ID for each session (you must use a cookie, Rails will not allow you to pass the session ID in the URL as this is less secure).
348
352
 
349
- For most stores, this ID is used to look up the session data on the server, e.g. in a database table. There is one exception, and that is the default and recommended session store - the CookieStore - which stores all session data in the cookie itself (the ID is still available to you if you need it). This has the advantage of being very lightweight and it requires zero setup in a new application in order to use the session. The cookie data is cryptographically signed to make it tamper-proof, but it is not encrypted, so anyone with access to it can read its contents but not edit it (Rails will not accept it if it has been edited).
353
+ For most stores, this ID is used to look up the session data on the server, e.g. in a database table. There is one exception, and that is the default and recommended session store - the CookieStore - which stores all session data in the cookie itself (the ID is still available to you if you need it). This has the advantage of being very lightweight and it requires zero setup in a new application in order to use the session. The cookie data is cryptographically signed to make it tamper-proof. And it is also encrypted so anyone with access to it can't read its contents. (Rails will not accept it if it has been edited).
350
354
 
351
- The CookieStore can store around 4kB of data much less than the others but this is usually enough. Storing large amounts of data in the session is discouraged no matter which session store your application uses. You should especially avoid storing complex objects (anything other than basic Ruby objects, the most common example being model instances) in the session, as the server might not be able to reassemble them between requests, which will result in an error.
355
+ The CookieStore can store around 4kB of data - much less than the others - but this is usually enough. Storing large amounts of data in the session is discouraged no matter which session store your application uses. You should especially avoid storing complex objects (anything other than basic Ruby objects, the most common example being model instances) in the session, as the server might not be able to reassemble them between requests, which will result in an error.
352
356
 
353
- If your user sessions don't store critical data or don't need to be around for long periods (for instance if you just use the flash for messaging), you can consider using ActionDispatch::Session::CacheStore. This will store sessions using the cache implementation you have configured for your application. The advantage of this is that you can use your existing cache infrastructure for storing sessions without requiring any additional setup or administration. The downside, of course, is that the sessions will be ephemeral and could disappear at any time.
357
+ If your user sessions don't store critical data or don't need to be around for long periods (for instance if you just use the flash for messaging), you can consider using `ActionDispatch::Session::CacheStore`. This will store sessions using the cache implementation you have configured for your application. The advantage of this is that you can use your existing cache infrastructure for storing sessions without requiring any additional setup or administration. The downside, of course, is that the sessions will be ephemeral and could disappear at any time.
354
358
 
355
359
  Read more about session storage in the [Security Guide](security.html).
356
360
 
@@ -360,21 +364,21 @@ If you need a different session storage mechanism, you can change it in the `con
360
364
  # Use the database for sessions instead of the cookie-based default,
361
365
  # which shouldn't be used to store highly confidential information
362
366
  # (create the session table with "rails g active_record:session_migration")
363
- # YourApp::Application.config.session_store :active_record_store
367
+ # Rails.application.config.session_store :active_record_store
364
368
  ```
365
369
 
366
370
  Rails sets up a session key (the name of the cookie) when signing the session data. These can also be changed in `config/initializers/session_store.rb`:
367
371
 
368
372
  ```ruby
369
373
  # Be sure to restart your server when you modify this file.
370
- YourApp::Application.config.session_store :cookie_store, key: '_your_app_session'
374
+ Rails.application.config.session_store :cookie_store, key: '_your_app_session'
371
375
  ```
372
376
 
373
377
  You can also pass a `:domain` key and specify the domain name for the cookie:
374
378
 
375
379
  ```ruby
376
380
  # Be sure to restart your server when you modify this file.
377
- YourApp::Application.config.session_store :cookie_store, key: '_your_app_session', domain: ".example.com"
381
+ Rails.application.config.session_store :cookie_store, key: '_your_app_session', domain: ".example.com"
378
382
  ```
379
383
 
380
384
  Rails sets up (for the CookieStore) a secret key used for signing the session data. This can be changed in `config/initializers/secret_token.rb`
@@ -538,7 +542,7 @@ end
538
542
  Cookies
539
543
  -------
540
544
 
541
- Your application can store small amounts of data on the client called cookies that will be persisted across requests and even sessions. Rails provides easy access to cookies via the `cookies` method, which much like the `session` works like a hash:
545
+ Your application can store small amounts of data on the client - called cookies - that will be persisted across requests and even sessions. Rails provides easy access to cookies via the `cookies` method, which - much like the `session` - works like a hash:
542
546
 
543
547
  ```ruby
544
548
  class CommentsController < ApplicationController
@@ -568,10 +572,66 @@ end
568
572
 
569
573
  Note that while for session values you set the key to `nil`, to delete a cookie value you should use `cookies.delete(:key)`.
570
574
 
571
- Rendering xml and json data
575
+ Rails also provides a signed cookie jar and an encrypted cookie jar for storing
576
+ sensitive data. The signed cookie jar appends a cryptographic signature on the
577
+ cookie values to protect their integrity. The encrypted cookie jar encrypts the
578
+ values in addition to signing them, so that they cannot be read by the end user.
579
+ Refer to the [API documentation](http://api.rubyonrails.org/classes/ActionDispatch/Cookies.html)
580
+ for more details.
581
+
582
+ These special cookie jars use a serializer to serialize the assigned values into
583
+ strings and deserializes them into Ruby objects on read.
584
+
585
+ You can specify what serializer to use:
586
+
587
+ ```ruby
588
+ Rails.application.config.action_dispatch.cookies_serializer = :json
589
+ ```
590
+
591
+ The default serializer for new applications is `:json`. For compatibility with
592
+ old applications with existing cookies, `:marshal` is used when `serializer`
593
+ option is not specified.
594
+
595
+ You may also set this option to `:hybrid`, in which case Rails would transparently
596
+ deserialize existing (`Marshal`-serialized) cookies on read and re-write them in
597
+ the `JSON` format. This is useful for migrating existing applications to the
598
+ `:json` serializer.
599
+
600
+ It is also possible to pass a custom serializer that responds to `load` and
601
+ `dump`:
602
+
603
+ ```ruby
604
+ Rails.application.config.action_dispatch.cookies_serializer = MyCustomSerializer
605
+ ```
606
+
607
+ When using the `:json` or `:hybrid` serializer, you should beware that not all
608
+ Ruby objects can be serialized as JSON. For example, `Date` and `Time` objects
609
+ will be serialized as strings, and `Hash`es will have their keys stringified.
610
+
611
+ ```ruby
612
+ class CookiesController < ApplicationController
613
+ def set_cookie
614
+ cookies.encrypted[:expiration_date] = Date.tomorrow # => Thu, 20 Mar 2014
615
+ redirect_to action: 'read_cookie'
616
+ end
617
+
618
+ def read_cookie
619
+ cookies.encrypted[:expiration_date] # => "2014-03-20"
620
+ end
621
+ end
622
+ ```
623
+
624
+ It's advisable that you only store simple data (strings and numbers) in cookies.
625
+ If you have to store complex objects, you would need to handle the conversion
626
+ manually when reading the values on subsequent requests.
627
+
628
+ If you use the cookie session store, this would apply to the `session` and
629
+ `flash` hash as well.
630
+
631
+ Rendering XML and JSON data
572
632
  ---------------------------
573
633
 
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:
634
+ 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:
575
635
 
576
636
  ```ruby
577
637
  class UsersController < ApplicationController
@@ -665,14 +725,17 @@ The first is to use a block directly with the *_action methods. The block receiv
665
725
  ```ruby
666
726
  class ApplicationController < ActionController::Base
667
727
  before_action do |controller|
668
- redirect_to new_login_url unless controller.send(:logged_in?)
728
+ unless controller.send(:logged_in?)
729
+ flash[:error] = "You must be logged in to access this section"
730
+ redirect_to new_login_url
731
+ end
669
732
  end
670
733
  end
671
734
  ```
672
735
 
673
736
  Note that the filter in this case uses `send` because the `logged_in?` method is private and the filter is not run in the scope of the controller. This is not the recommended way to implement this particular filter, but in more simple cases it might be useful.
674
737
 
675
- The second way is to use a class (actually, any object that responds to the right methods will do) to handle the filtering. This is useful in cases that are more complex and can not be implemented in a readable and reusable way using the two other methods. As an example, you could rewrite the login filter again to use a class:
738
+ The second way is to use a class (actually, any object that responds to the right methods will do) to handle the filtering. This is useful in cases that are more complex and cannot be implemented in a readable and reusable way using the two other methods. As an example, you could rewrite the login filter again to use a class:
676
739
 
677
740
  ```ruby
678
741
  class ApplicationController < ActionController::Base
@@ -680,16 +743,16 @@ class ApplicationController < ActionController::Base
680
743
  end
681
744
 
682
745
  class LoginFilter
683
- def self.filter(controller)
746
+ def self.before(controller)
684
747
  unless controller.send(:logged_in?)
685
- controller.flash[:error] = "You must be logged in"
748
+ controller.flash[:error] = "You must be logged in to access this section"
686
749
  controller.redirect_to controller.new_login_url
687
750
  end
688
751
  end
689
752
  end
690
753
  ```
691
754
 
692
- Again, this is not an ideal example for this filter, because it's not run in the scope of the controller but gets the controller passed as an argument. The filter class has a class method `filter` which gets run before or after the action, depending on if it's a before or after filter. Classes used as around filters can also use the same `filter` method, which will get run in the same way. The method must `yield` to execute the action. Alternatively, it can have both a `before` and an `after` method that are run before and after the action.
755
+ Again, this is not an ideal example for this filter, because it's not run in the scope of the controller but gets the controller passed as an argument. The filter class must implement a method with the same name as the filter, so for the `before_action` filter the class must implement a `before` method, and so on. The `around` method must `yield` to execute the action.
693
756
 
694
757
  Request Forgery Protection
695
758
  --------------------------
@@ -794,7 +857,7 @@ class AdminsController < ApplicationController
794
857
  end
795
858
  ```
796
859
 
797
- With this in place, you can create namespaced controllers that inherit from `AdminController`. The filter will thus be run for all actions in those controllers, protecting them with HTTP basic authentication.
860
+ With this in place, you can create namespaced controllers that inherit from `AdminsController`. The filter will thus be run for all actions in those controllers, protecting them with HTTP basic authentication.
798
861
 
799
862
  ### HTTP Digest Authentication
800
863
 
@@ -808,11 +871,11 @@ class AdminsController < ApplicationController
808
871
 
809
872
  private
810
873
 
811
- def authenticate
812
- authenticate_or_request_with_http_digest do |username|
813
- USERS[username]
874
+ def authenticate
875
+ authenticate_or_request_with_http_digest do |username|
876
+ USERS[username]
877
+ end
814
878
  end
815
- end
816
879
  end
817
880
  ```
818
881
 
@@ -839,13 +902,13 @@ class ClientsController < ApplicationController
839
902
 
840
903
  private
841
904
 
842
- def generate_pdf(client)
843
- Prawn::Document.new do
844
- text client.name, align: :center
845
- text "Address: #{client.address}"
846
- text "Email: #{client.email}"
847
- end.render
848
- end
905
+ def generate_pdf(client)
906
+ Prawn::Document.new do
907
+ text client.name, align: :center
908
+ text "Address: #{client.address}"
909
+ text "Email: #{client.email}"
910
+ end.render
911
+ end
849
912
  end
850
913
  ```
851
914
 
@@ -907,6 +970,92 @@ Now the user can request to get a PDF version of a client just by adding ".pdf"
907
970
  GET /clients/1.pdf
908
971
  ```
909
972
 
973
+ ### Live Streaming of Arbitrary Data
974
+
975
+ Rails allows you to stream more than just files. In fact, you can stream anything
976
+ you would like in a response object. The `ActionController::Live` module allows
977
+ you to create a persistent connection with a browser. Using this module, you will
978
+ be able to send arbitrary data to the browser at specific points in time.
979
+
980
+ #### Incorporating Live Streaming
981
+
982
+ Including `ActionController::Live` inside of your controller class will provide
983
+ all actions inside of the controller the ability to stream data. You can mix in
984
+ the module like so:
985
+
986
+ ```ruby
987
+ class MyController < ActionController::Base
988
+ include ActionController::Live
989
+
990
+ def stream
991
+ response.headers['Content-Type'] = 'text/event-stream'
992
+ 100.times {
993
+ response.stream.write "hello world\n"
994
+ sleep 1
995
+ }
996
+ ensure
997
+ response.stream.close
998
+ end
999
+ end
1000
+ ```
1001
+
1002
+ The above code will keep a persistent connection with the browser and send 100
1003
+ messages of `"hello world\n"`, each one second apart.
1004
+
1005
+ There are a couple of things to notice in the above example. We need to make
1006
+ sure to close the response stream. Forgetting to close the stream will leave
1007
+ the socket open forever. We also have to set the content type to `text/event-stream`
1008
+ before we write to the response stream. This is because headers cannot be written
1009
+ after the response has been committed (when `response.committed` returns a truthy
1010
+ value), which occurs when you `write` or `commit` the response stream.
1011
+
1012
+ #### Example Usage
1013
+
1014
+ Let's suppose that you were making a Karaoke machine and a user wants to get the
1015
+ lyrics for a particular song. Each `Song` has a particular number of lines and
1016
+ each line takes time `num_beats` to finish singing.
1017
+
1018
+ If we wanted to return the lyrics in Karaoke fashion (only sending the line when
1019
+ the singer has finished the previous line), then we could use `ActionController::Live`
1020
+ as follows:
1021
+
1022
+ ```ruby
1023
+ class LyricsController < ActionController::Base
1024
+ include ActionController::Live
1025
+
1026
+ def show
1027
+ response.headers['Content-Type'] = 'text/event-stream'
1028
+ song = Song.find(params[:id])
1029
+
1030
+ song.each do |line|
1031
+ response.stream.write line.lyrics
1032
+ sleep line.num_beats
1033
+ end
1034
+ ensure
1035
+ response.stream.close
1036
+ end
1037
+ end
1038
+ ```
1039
+
1040
+ The above code sends the next line only after the singer has completed the previous
1041
+ line.
1042
+
1043
+ #### Streaming Considerations
1044
+
1045
+ Streaming arbitrary data is an extremely powerful tool. As shown in the previous
1046
+ examples, you can choose when and what to send across a response stream. However,
1047
+ you should also note the following things:
1048
+
1049
+ * Each response stream creates a new thread and copies over the thread local
1050
+ variables from the original thread. Having too many thread local variables can
1051
+ negatively impact performance. Similarly, a large number of threads can also
1052
+ hinder performance.
1053
+ * Failing to close the response stream will leave the corresponding socket open
1054
+ forever. Make sure to call `close` whenever you are using a response stream.
1055
+ * WEBrick servers buffer all responses, and so including `ActionController::Live`
1056
+ will not work. You must use a web server which does not automatically buffer
1057
+ responses.
1058
+
910
1059
  Log Filtering
911
1060
  -------------
912
1061
 
@@ -962,9 +1111,9 @@ class ApplicationController < ActionController::Base
962
1111
 
963
1112
  private
964
1113
 
965
- def record_not_found
966
- render text: "404 Not Found", status: 404
967
- end
1114
+ def record_not_found
1115
+ render plain: "404 Not Found", status: 404
1116
+ end
968
1117
  end
969
1118
  ```
970
1119
 
@@ -976,10 +1125,10 @@ class ApplicationController < ActionController::Base
976
1125
 
977
1126
  private
978
1127
 
979
- def user_not_authorized
980
- flash[:error] = "You don't have access to this section."
981
- redirect_to :back
982
- end
1128
+ def user_not_authorized
1129
+ flash[:error] = "You don't have access to this section."
1130
+ redirect_to :back
1131
+ end
983
1132
  end
984
1133
 
985
1134
  class ClientsController < ApplicationController
@@ -993,10 +1142,10 @@ class ClientsController < ApplicationController
993
1142
 
994
1143
  private
995
1144
 
996
- # If the user is not authorized, just throw the exception.
997
- def check_authorization
998
- raise User::NotAuthorized unless current_user.admin?
999
- end
1145
+ # If the user is not authorized, just throw the exception.
1146
+ def check_authorization
1147
+ raise User::NotAuthorized unless current_user.admin?
1148
+ end
1000
1149
  end
1001
1150
  ```
1002
1151
 
@@ -30,7 +30,7 @@ views.
30
30
  #### Create the Mailer
31
31
 
32
32
  ```bash
33
- $ rails generate mailer UserMailer
33
+ $ bin/rails generate mailer UserMailer
34
34
  create app/mailers/user_mailer.rb
35
35
  invoke erb
36
36
  create app/views/user_mailer
@@ -105,7 +105,7 @@ will be the template used for the email, formatted in HTML:
105
105
  <h1>Welcome to example.com, <%= @user.name %></h1>
106
106
  <p>
107
107
  You have successfully signed up to example.com,
108
- your username is: <%= @user.login %>.<br/>
108
+ your username is: <%= @user.login %>.<br>
109
109
  </p>
110
110
  <p>
111
111
  To login to the site, just follow this link: <%= @url %>.
@@ -138,7 +138,7 @@ When you call the `mail` method now, Action Mailer will detect the two templates
138
138
 
139
139
  Mailers are really just another way to render a view. Instead of rendering a
140
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
141
+ email protocols instead. Due to this, it makes sense to just have your
142
142
  controller tell the Mailer to send an email when a user is successfully created.
143
143
 
144
144
  Setting this up is painfully simple.
@@ -146,8 +146,8 @@ Setting this up is painfully simple.
146
146
  First, let's create a simple `User` scaffold:
147
147
 
148
148
  ```bash
149
- $ rails generate scaffold user name email login
150
- $ rake db:migrate
149
+ $ bin/rails generate scaffold user name email login
150
+ $ bin/rake db:migrate
151
151
  ```
152
152
 
153
153
  Now that we have a user model to play with, we will just edit the
@@ -164,7 +164,7 @@ class UsersController < ApplicationController
164
164
 
165
165
  respond_to do |format|
166
166
  if @user.save
167
- # Tell the UserMailer to send a welcome Email after save
167
+ # Tell the UserMailer to send a welcome email after save
168
168
  UserMailer.welcome_email(@user).deliver
169
169
 
170
170
  format.html { redirect_to(@user, notice: 'User was successfully created.') }
@@ -378,7 +378,7 @@ Just like with controller views, use `yield` to render the view inside the
378
378
  layout.
379
379
 
380
380
  You can also pass in a `layout: 'layout_name'` option to the render call inside
381
- the format block to specify different layouts for different actions:
381
+ the format block to specify different layouts for different formats:
382
382
 
383
383
  ```ruby
384
384
  class UserMailer < ActionMailer::Base
@@ -481,7 +481,7 @@ end
481
481
 
482
482
  There may be cases in which you want to skip the template rendering step and
483
483
  supply the email body as a string. You can achieve this using the `:body`
484
- option. In such cases don't forget to add the `:content_type` option. Rails
484
+ option. In such cases don't forget to add the `:content_type` option. Rails
485
485
  will default to `text/plain` otherwise.
486
486
 
487
487
  ```ruby
@@ -569,25 +569,25 @@ class UserMailer < ActionMailer::Base
569
569
 
570
570
  private
571
571
 
572
- def set_delivery_options
573
- # You have access to the mail instance,
574
- # @business and @user instance variables here
575
- if @business && @business.has_smtp_settings?
576
- mail.delivery_method.settings.merge!(@business.smtp_settings)
572
+ def set_delivery_options
573
+ # You have access to the mail instance,
574
+ # @business and @user instance variables here
575
+ if @business && @business.has_smtp_settings?
576
+ mail.delivery_method.settings.merge!(@business.smtp_settings)
577
+ end
577
578
  end
578
- end
579
579
 
580
- def prevent_delivery_to_guests
581
- if @user && @user.guest?
582
- mail.perform_deliveries = false
580
+ def prevent_delivery_to_guests
581
+ if @user && @user.guest?
582
+ mail.perform_deliveries = false
583
+ end
583
584
  end
584
- end
585
585
 
586
- def set_business_headers
587
- if @business
588
- headers["X-SMTPAPI-CATEGORY"] = @business.code
586
+ def set_business_headers
587
+ if @business
588
+ headers["X-SMTPAPI-CATEGORY"] = @business.code
589
+ end
589
590
  end
590
- end
591
591
  end
592
592
  ```
593
593
 
@@ -608,10 +608,10 @@ files (environment.rb, production.rb, etc...)
608
608
  | Configuration | Description |
609
609
  |---------------|-------------|
610
610
  |`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.|
611
- |`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>|
611
+ |`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>|
612
612
  |`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>|
613
613
  |`raise_delivery_errors`|Whether or not errors should be raised if the email fails to be delivered. This only works if the external email server is configured for immediate delivery.|
614
- |`delivery_method`|Defines a delivery method. Possible values are `:smtp` (default), `:sendmail`, `:file` and `:test`.|
614
+ |`delivery_method`|Defines a delivery method. Possible values are:<ul><li>`:smtp` (default), can be configured by using `config.action_mailer.smtp_settings`.</li><li>`:sendmail`, can be configured by using `config.action_mailer.sendmail_settings`.</li><li>`:file`: save emails to files; can be configured by using `config.action_mailer.file_settings`.</li><li>`:test`: save emails to `ActionMailer::Base.deliveries` array.</li></ul>See [API docs](http://api.rubyonrails.org/classes/ActionMailer/Base.html) for more info.|
615
615
  |`perform_deliveries`|Determines whether deliveries are actually carried out when the `deliver` method is invoked on the Mail message. By default they are, but this can be turned off to help functional testing.|
616
616
  |`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.|
617
617
  |`default_options`|Allows you to set default values for the `mail` method options (`:from`, `:reply_to`, etc.).|
@@ -634,13 +634,13 @@ config.action_mailer.delivery_method = :sendmail
634
634
  # }
635
635
  config.action_mailer.perform_deliveries = true
636
636
  config.action_mailer.raise_delivery_errors = true
637
- config.action_mailer.default_options = {from: 'no-replay@example.com'}
637
+ config.action_mailer.default_options = {from: 'no-reply@example.com'}
638
638
  ```
639
639
 
640
640
  ### Action Mailer Configuration for Gmail
641
641
 
642
- As Action Mailer now uses the Mail gem, this becomes as simple as adding to your
643
- `config/environments/$RAILS_ENV.rb` file:
642
+ As Action Mailer now uses the [Mail gem](https://github.com/mikel/mail), this
643
+ becomes as simple as adding to your `config/environments/$RAILS_ENV.rb` file:
644
644
 
645
645
  ```ruby
646
646
  config.action_mailer.delivery_method = :smtp