aboutsummaryrefslogtreecommitdiffstats
path: root/guides
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2014-02-17 11:21:18 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2014-02-17 11:21:18 -0800
commitfe42effb11a97cf19777d7b0dba7e1e2dfd3316c (patch)
tree388f48bc682802cbcae53a0d570d2c8587bbb98b /guides
parent5ac2879b08b05b7f6eaebc5473e62b4576f84a3f (diff)
parent3e3ed1ede51f4d2f7f1d30b3754072b1121d5394 (diff)
downloadrails-fe42effb11a97cf19777d7b0dba7e1e2dfd3316c.tar.gz
rails-fe42effb11a97cf19777d7b0dba7e1e2dfd3316c.tar.bz2
rails-fe42effb11a97cf19777d7b0dba7e1e2dfd3316c.zip
Merge branch 'master' into adequaterecord
* master: (311 commits) Add a missing changelog entry for #13981 and #14035 Revert "Fixed plugin_generator test" implements new option :month_format_string for date select helpers [Closes #13618] add factory methods for empty alias trackers guarantee a list in the alias tracker so we can remove a conditional stop exposing table_joins make most parameters to the AliasTracker required make a singleton for AssociationScope pass the association and connection to the scope method pass the tracker down the stack and construct it in the scope method clean up add_constraints signature remove the reflection delegate remove klass delegator remove railties changes. fixes #14054 remove chain delegate remove scope_chain delegate Add verb to sanitization note fix path shown in mailer's templates updated Travis build status image url fix guide active_support_core_extensions. add Note to String#indent [ci skip] ... Conflicts: activerecord/lib/active_record/associations/join_dependency.rb activerecord/test/cases/associations/association_scope_test.rb
Diffstat (limited to 'guides')
-rw-r--r--guides/assets/images/getting_started/article_with_comments.pngbin0 -> 25229 bytes
-rw-r--r--guides/assets/images/getting_started/challenge.pngbin31976 -> 30248 bytes
-rw-r--r--guides/assets/images/getting_started/confirm_dialog.pngbin29542 -> 26420 bytes
-rw-r--r--guides/assets/images/getting_started/forbidden_attributes_for_new_article.pngbin0 -> 15598 bytes
-rw-r--r--guides/assets/images/getting_started/forbidden_attributes_for_new_post.pngbin19490 -> 0 bytes
-rw-r--r--guides/assets/images/getting_started/form_with_errors.pngbin14031 -> 18076 bytes
-rw-r--r--guides/assets/images/getting_started/index_action_with_edit_link.pngbin9772 -> 18024 bytes
-rw-r--r--guides/assets/images/getting_started/new_article.pngbin0 -> 9387 bytes
-rw-r--r--guides/assets/images/getting_started/new_post.pngbin5090 -> 0 bytes
-rw-r--r--guides/assets/images/getting_started/post_with_comments.pngbin18496 -> 0 bytes
-rw-r--r--guides/assets/images/getting_started/routing_error_no_controller.pngbin5519 -> 6108 bytes
-rw-r--r--guides/assets/images/getting_started/show_action_for_articles.png (renamed from guides/assets/images/getting_started/show_action_for_posts.png)bin2991 -> 2991 bytes
-rw-r--r--guides/assets/images/getting_started/template_is_missing_articles_new.pngbin0 -> 10138 bytes
-rw-r--r--guides/assets/images/getting_started/template_is_missing_posts_new.pngbin11688 -> 0 bytes
-rw-r--r--guides/assets/images/getting_started/undefined_method_post_path.pngbin9217 -> 0 bytes
-rw-r--r--guides/assets/images/getting_started/unknown_action_create_for_articles.pngbin0 -> 7594 bytes
-rw-r--r--guides/assets/images/getting_started/unknown_action_create_for_posts.pngbin6852 -> 0 bytes
-rw-r--r--guides/assets/images/getting_started/unknown_action_new_for_articles.pngbin0 -> 7858 bytes
-rw-r--r--guides/assets/images/getting_started/unknown_action_new_for_posts.pngbin6998 -> 0 bytes
-rw-r--r--guides/code/getting_started/Gemfile2
-rw-r--r--guides/code/getting_started/config/environments/production.rb2
-rw-r--r--guides/rails_guides/helpers.rb2
-rw-r--r--guides/source/3_0_release_notes.md2
-rw-r--r--guides/source/4_1_release_notes.md103
-rw-r--r--guides/source/action_controller_overview.md40
-rw-r--r--guides/source/action_mailer_basics.md10
-rw-r--r--guides/source/active_record_querying.md2
-rw-r--r--guides/source/active_record_validations.md20
-rw-r--r--guides/source/active_support_core_extensions.md2
-rw-r--r--guides/source/api_documentation_guidelines.md52
-rw-r--r--guides/source/asset_pipeline.md31
-rw-r--r--guides/source/association_basics.md13
-rw-r--r--guides/source/configuring.md41
-rw-r--r--guides/source/contributing_to_ruby_on_rails.md13
-rw-r--r--guides/source/documents.yaml2
-rw-r--r--guides/source/getting_started.md922
-rw-r--r--guides/source/i18n.md2
-rw-r--r--guides/source/initialization.md4
-rw-r--r--guides/source/layouts_and_rendering.md4
-rw-r--r--guides/source/migrations.md2
-rw-r--r--guides/source/routing.md2
-rw-r--r--guides/source/security.md45
-rw-r--r--guides/source/testing.md13
-rw-r--r--guides/source/upgrading_ruby_on_rails.md19
44 files changed, 832 insertions, 518 deletions
diff --git a/guides/assets/images/getting_started/article_with_comments.png b/guides/assets/images/getting_started/article_with_comments.png
new file mode 100644
index 0000000000..1918e9bf28
--- /dev/null
+++ b/guides/assets/images/getting_started/article_with_comments.png
Binary files differ
diff --git a/guides/assets/images/getting_started/challenge.png b/guides/assets/images/getting_started/challenge.png
index 4a30e49e6d..cc12162677 100644
--- a/guides/assets/images/getting_started/challenge.png
+++ b/guides/assets/images/getting_started/challenge.png
Binary files differ
diff --git a/guides/assets/images/getting_started/confirm_dialog.png b/guides/assets/images/getting_started/confirm_dialog.png
index 1a13eddd91..e57d4b409e 100644
--- a/guides/assets/images/getting_started/confirm_dialog.png
+++ b/guides/assets/images/getting_started/confirm_dialog.png
Binary files differ
diff --git a/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png b/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png
new file mode 100644
index 0000000000..e263f7f8b2
--- /dev/null
+++ b/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png
Binary files differ
diff --git a/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png b/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png
deleted file mode 100644
index 6c78e52173..0000000000
--- a/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png
+++ /dev/null
Binary files differ
diff --git a/guides/assets/images/getting_started/form_with_errors.png b/guides/assets/images/getting_started/form_with_errors.png
index 6910e1647e..04ff8b1e2d 100644
--- a/guides/assets/images/getting_started/form_with_errors.png
+++ b/guides/assets/images/getting_started/form_with_errors.png
Binary files differ
diff --git a/guides/assets/images/getting_started/index_action_with_edit_link.png b/guides/assets/images/getting_started/index_action_with_edit_link.png
index bf23cba231..22f994d993 100644
--- a/guides/assets/images/getting_started/index_action_with_edit_link.png
+++ b/guides/assets/images/getting_started/index_action_with_edit_link.png
Binary files differ
diff --git a/guides/assets/images/getting_started/new_article.png b/guides/assets/images/getting_started/new_article.png
new file mode 100644
index 0000000000..89fc0b2605
--- /dev/null
+++ b/guides/assets/images/getting_started/new_article.png
Binary files differ
diff --git a/guides/assets/images/getting_started/new_post.png b/guides/assets/images/getting_started/new_post.png
deleted file mode 100644
index b20b0192d4..0000000000
--- a/guides/assets/images/getting_started/new_post.png
+++ /dev/null
Binary files differ
diff --git a/guides/assets/images/getting_started/post_with_comments.png b/guides/assets/images/getting_started/post_with_comments.png
deleted file mode 100644
index e13095ff8f..0000000000
--- a/guides/assets/images/getting_started/post_with_comments.png
+++ /dev/null
Binary files differ
diff --git a/guides/assets/images/getting_started/routing_error_no_controller.png b/guides/assets/images/getting_started/routing_error_no_controller.png
index 35ee4f348f..ae83b6a68c 100644
--- a/guides/assets/images/getting_started/routing_error_no_controller.png
+++ b/guides/assets/images/getting_started/routing_error_no_controller.png
Binary files differ
diff --git a/guides/assets/images/getting_started/show_action_for_posts.png b/guides/assets/images/getting_started/show_action_for_articles.png
index 9467df6a07..9467df6a07 100644
--- a/guides/assets/images/getting_started/show_action_for_posts.png
+++ b/guides/assets/images/getting_started/show_action_for_articles.png
Binary files differ
diff --git a/guides/assets/images/getting_started/template_is_missing_articles_new.png b/guides/assets/images/getting_started/template_is_missing_articles_new.png
new file mode 100644
index 0000000000..ba630cfc23
--- /dev/null
+++ b/guides/assets/images/getting_started/template_is_missing_articles_new.png
Binary files differ
diff --git a/guides/assets/images/getting_started/template_is_missing_posts_new.png b/guides/assets/images/getting_started/template_is_missing_posts_new.png
deleted file mode 100644
index f03db05fb8..0000000000
--- a/guides/assets/images/getting_started/template_is_missing_posts_new.png
+++ /dev/null
Binary files differ
diff --git a/guides/assets/images/getting_started/undefined_method_post_path.png b/guides/assets/images/getting_started/undefined_method_post_path.png
deleted file mode 100644
index c29cb2f54f..0000000000
--- a/guides/assets/images/getting_started/undefined_method_post_path.png
+++ /dev/null
Binary files differ
diff --git a/guides/assets/images/getting_started/unknown_action_create_for_articles.png b/guides/assets/images/getting_started/unknown_action_create_for_articles.png
new file mode 100644
index 0000000000..ed89c4f3d7
--- /dev/null
+++ b/guides/assets/images/getting_started/unknown_action_create_for_articles.png
Binary files differ
diff --git a/guides/assets/images/getting_started/unknown_action_create_for_posts.png b/guides/assets/images/getting_started/unknown_action_create_for_posts.png
deleted file mode 100644
index 8fdd4c574a..0000000000
--- a/guides/assets/images/getting_started/unknown_action_create_for_posts.png
+++ /dev/null
Binary files differ
diff --git a/guides/assets/images/getting_started/unknown_action_new_for_articles.png b/guides/assets/images/getting_started/unknown_action_new_for_articles.png
new file mode 100644
index 0000000000..e8f2b9a16a
--- /dev/null
+++ b/guides/assets/images/getting_started/unknown_action_new_for_articles.png
Binary files differ
diff --git a/guides/assets/images/getting_started/unknown_action_new_for_posts.png b/guides/assets/images/getting_started/unknown_action_new_for_posts.png
deleted file mode 100644
index 7e72feee38..0000000000
--- a/guides/assets/images/getting_started/unknown_action_new_for_posts.png
+++ /dev/null
Binary files differ
diff --git a/guides/code/getting_started/Gemfile b/guides/code/getting_started/Gemfile
index a2155c43b9..ecb6e7aa1a 100644
--- a/guides/code/getting_started/Gemfile
+++ b/guides/code/getting_started/Gemfile
@@ -23,7 +23,7 @@ gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
-# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/jonleighton/spring
+# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring', group: :development
# Use ActiveModel has_secure_password
diff --git a/guides/code/getting_started/config/environments/production.rb b/guides/code/getting_started/config/environments/production.rb
index 93d44723fb..8c514e065e 100644
--- a/guides/code/getting_started/config/environments/production.rb
+++ b/guides/code/getting_started/config/environments/production.rb
@@ -5,7 +5,7 @@ Blog::Application.configure do
config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and
- # your application in memory, allowing both thread web servers
+ # your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true
diff --git a/guides/rails_guides/helpers.rb b/guides/rails_guides/helpers.rb
index 760b196abd..169453400f 100644
--- a/guides/rails_guides/helpers.rb
+++ b/guides/rails_guides/helpers.rb
@@ -1,3 +1,5 @@
+require 'yaml'
+
module RailsGuides
module Helpers
def guide(name, url, options = {}, &block)
diff --git a/guides/source/3_0_release_notes.md b/guides/source/3_0_release_notes.md
index cf9d694de7..dd81ec58f9 100644
--- a/guides/source/3_0_release_notes.md
+++ b/guides/source/3_0_release_notes.md
@@ -574,7 +574,7 @@ The following methods have been removed because they are no longer used in the f
Action Mailer
-------------
-Action Mailer has been given a new API with TMail being replaced out with the new [Mail](http://github.com/mikel/mail) as the Email library. Action Mailer itself has been given an almost complete re-write with pretty much every line of code touched. The result is that Action Mailer now simply inherits from Abstract Controller and wraps the Mail gem in a Rails DSL. This reduces the amount of code and duplication of other libraries in Action Mailer considerably.
+Action Mailer has been given a new API with TMail being replaced out with the new [Mail](http://github.com/mikel/mail) as the email library. Action Mailer itself has been given an almost complete re-write with pretty much every line of code touched. The result is that Action Mailer now simply inherits from Abstract Controller and wraps the Mail gem in a Rails DSL. This reduces the amount of code and duplication of other libraries in Action Mailer considerably.
* All mailers are now in `app/mailers` by default.
* Can now send email using new API with three methods: `attachments`, `headers` and `mail`.
diff --git a/guides/source/4_1_release_notes.md b/guides/source/4_1_release_notes.md
index 924e5d90db..8fcfc71351 100644
--- a/guides/source/4_1_release_notes.md
+++ b/guides/source/4_1_release_notes.md
@@ -64,7 +64,7 @@ Spring is running:
```
Have a look at the
-[Spring README](https://github.com/jonleighton/spring/blob/master/README.md) to
+[Spring README](https://github.com/rails/spring/blob/master/README.md) to
see all available features.
See the [Upgrading Ruby on Rails](upgrading_ruby_on_rails.html#spring)
@@ -175,6 +175,8 @@ conversation.active? # => false
conversation.status # => "archived"
Conversation.archived # => Relation for all archived Conversations
+
+Conversation.statuses # => { "active" => 0, "archived" => 1 }
```
See its
@@ -241,6 +243,7 @@ unless they use `xhr`. Upgrade your tests to be explicit about expecting
XmlHttpRequests. Instead of `post :create, format: :js`, switch to the explicit
`xhr :post, :create, format: :js`.
+
Railties
--------
@@ -267,7 +270,7 @@ for detailed changes.
### Notable changes
* The [Spring application
- preloader](https://github.com/jonleighton/spring) is now installed
+ preloader](https://github.com/rails/spring) is now installed
by default for new applications. It uses the development group of
the Gemfile, so will not be installed in
production. ([Pull Request](https://github.com/rails/rails/pull/12958))
@@ -278,7 +281,7 @@ for detailed changes.
* Exposed `MiddlewareStack#unshift` to environment
configuration. ([Pull Request](https://github.com/rails/rails/pull/12479))
-* Add `Application#message_verifier` method to return a message
+* Added `Application#message_verifier` method to return a message
verifier. ([Pull Request](https://github.com/rails/rails/pull/12995))
* The `test_help.rb` file which is required by the default generated test
@@ -288,6 +291,7 @@ for detailed changes.
with `config.active_record.maintain_test_schema = false`. ([Pull
Request](https://github.com/rails/rails/pull/13528))
+
Action Pack
-----------
@@ -335,6 +339,16 @@ for detailed changes.
* Separated Action View completely from Action
Pack. ([Pull Request](https://github.com/rails/rails/pull/11032))
+* Log which keys were affected by deep
+ munge. ([Pull Request](https://github.com/rails/rails/pull/13813))
+
+* New config option `config.action_dispatch.perform_deep_munge` to opt out of
+ params "deep munging" that was used to address security vulnerability
+ CVE-2013-0155. ([Pull Request](https://github.com/rails/rails/pull/13188))
+
+* New config option `config.action_dispatch.cookies_serializer` for specifying
+ a serializer for the signed and encrypted cookie jars. (Pull Requests [1](https://github.com/rails/rails/pull/13692), [2](https://github.com/rails/rails/pull/13945) / [More Details](upgrading_ruby_on_rails.html#cookies-serializer))
+
Action Mailer
-------------
@@ -344,9 +358,13 @@ for detailed changes.
### Notable changes
+* Added mailer previews feature based on 37 Signals mail_view
+ gem. ([Commit](https://github.com/rails/rails/commit/d6dec7fcb6b8fddf8c170182d4fe64ecfc7b2261))
+
* Instrument the generation of Action Mailer messages. The time it takes to
generate a message is written to the log. ([Pull Request](https://github.com/rails/rails/pull/12556))
+
Active Record
-------------
@@ -411,6 +429,8 @@ for detailed changes.
* Remove implicit join references that were deprecated in 4.0.
* Removed `activerecord-deprecated_finders` as a dependency.
+ Please see [the gem README](https://github.com/rails/activerecord-deprecated_finders#active-record-deprecated-finders)
+ for more info.
* Removed usage of `implicit_readonly`. Please use `readonly` method
explicitly to mark records as
@@ -420,11 +440,6 @@ for detailed changes.
* Deprecated `quoted_locking_column` method, which isn't used anywhere.
-* Deprecated the delegation of Array bang methods for associations.
- To use them, instead first call `#to_a` on the association to access the
- array to be acted
- on. ([Pull Request](https://github.com/rails/rails/pull/12129))
-
* Deprecated `ConnectionAdapters::SchemaStatements#distinct`,
as it is no longer used by internals. ([Pull Request](https://github.com/rails/rails/pull/10556))
@@ -498,7 +513,32 @@ for detailed changes.
object. Helper methods used by multiple fixtures should be defined on modules
included in `ActiveRecord::FixtureSet.context_class`. ([Pull Request](https://github.com/rails/rails/pull/13022))
-* Don't create or drop the test database if RAILS_ENV is specified explicitly.
+* Don't create or drop the test database if RAILS_ENV is specified
+ explicitly. ([Pull Request](https://github.com/rails/rails/pull/13629))
+
+* `Relation` no longer has mutator methods like `#map!` and `#delete_if`. Convert
+ to an `Array` by calling `#to_a` before using these methods. ([Pull Request](https://github.com/rails/rails/pull/13314))
+
+* `find_in_batches`, `find_each`, `Result#each` and `Enumerable#index_by` now
+ return an `Enumerator` that can calculate its
+ size. ([Pull Request](https://github.com/rails/rails/pull/13938))
+
+* `scope`, `enum` and Associations now raise on "dangerous" name
+ conflicts. ([Pull Request](https://github.com/rails/rails/pull/13450),
+ [Pull Request](https://github.com/rails/rails/pull/13896))
+
+* `second` through `fifth` methods act like the `first`
+ finder. ([Pull Request](https://github.com/rails/rails/pull/13757))
+
+* Make `touch` fire the `after_commit` and `after_rollback`
+ callbacks. ([Pull Request](https://github.com/rails/rails/pull/12031))
+
+* Enable partial indexes for `sqlite >=
+ 3.8.0`. ([Pull Request](https://github.com/rails/rails/pull/13350))
+
+* Make `change_column_null`
+ revertable. ([Commit](https://github.com/rails/rails/commit/724509a9d5322ff502aefa90dd282ba33a281a96))
+
Active Model
------------
@@ -517,6 +557,13 @@ for detailed changes.
* Added new API methods `reset_changes` and `changes_applied` to
`ActiveModel::Dirty` that control changes state.
+* Ability to specify multiple contexts when defining a
+ validation. ([Pull Request](https://github.com/rails/rails/pull/13754))
+
+* `attribute_changed?` now accepts a hash to check if the attribute was changed
+ `:from` and/or `:to` a given
+ value. ([Pull Request](https://github.com/rails/rails/pull/13131))
+
Active Support
--------------
@@ -567,6 +614,12 @@ for detailed changes.
* Removed deprecated `assert_present` and `assert_blank` methods, use `assert
object.blank?` and `assert object.present?` instead.
+* Remove deprecated `#filter` method for filter objects, use the corresponding
+ method instead (e.g. `#before` for a before filter).
+
+* Removed 'cow' => 'kine' irregular inflection from default
+ inflections. ([Commit](https://github.com/rails/rails/commit/c300dca9963bda78b8f358dbcb59cabcdc5e1dc9))
+
### Deprecations
* Deprecated `Numeric#{ago,until,since,from_now}`, the user is expected to
@@ -583,11 +636,14 @@ for detailed changes.
[More Details](upgrading_ruby_on_rails.html#changes-in-json-handling))
* Deprecated `ActiveSupport.encode_big_decimal_as_string` option. This feature has
- been extracetd into the [activesupport-json_encoder](https://github.com/rails/activesupport-json_encoder)
+ been extracted into the [activesupport-json_encoder](https://github.com/rails/activesupport-json_encoder)
gem.
([Pull Request](https://github.com/rails/rails/pull/13060) /
[More Details](upgrading_ruby_on_rails.html#changes-in-json-handling))
+* Deprecate custom `BigDecimal`
+ serialization. ([Pull Request](https://github.com/rails/rails/pull/13911))
+
### Notable changes
* `ActiveSupport`'s JSON encoder has been rewritten to take advantage of the
@@ -604,6 +660,10 @@ for detailed changes.
`Time.now` and
`Date.today`. ([Pull Request](https://github.com/rails/rails/pull/12824))
+* Added `ActiveSupport::Testing::TimeHelpers#travel_back`. This method returns
+ the current time to the original state, by removing the stubs added by `travel`
+ and `travel_to`. ([Pull Request](https://github.com/rails/rails/pull/13884))
+
* Added `Numeric#in_milliseconds`, like `1.hour.in_milliseconds`, so we can feed
them to JavaScript functions like
`getTime()`. ([Commit](https://github.com/rails/rails/commit/423249504a2b468d7a273cbe6accf4f21cb0e643))
@@ -613,11 +673,30 @@ for detailed changes.
`at_middle_of_day` as
aliases. ([Pull Request](https://github.com/rails/rails/pull/10879))
+* Added `Date#all_week/month/quarter/year` for generating date
+ ranges. ([Pull Request](https://github.com/rails/rails/pull/9685))
+
+* Added `Time.zone.yesterday` and
+ `Time.zone.tomorrow`. ([Pull Request](https://github.com/rails/rails/pull/12822))
+
* Added `String#remove(pattern)` as a short-hand for the common pattern of
`String#gsub(pattern,'')`. ([Commit](https://github.com/rails/rails/commit/5da23a3f921f0a4a3139495d2779ab0d3bd4cb5f))
-* Removed 'cow' => 'kine' irregular inflection from default
- inflections. ([Commit](https://github.com/rails/rails/commit/c300dca9963bda78b8f358dbcb59cabcdc5e1dc9))
+* Added `Hash#compact` and `Hash#compact!` for removing items with nil value
+ from hash. ([Pull Request](https://github.com/rails/rails/pull/13632))
+
+* `blank?` and `present?` commit to return
+ singletons. ([Commit](https://github.com/rails/rails/commit/126dc47665c65cd129967cbd8a5926dddd0aa514))
+
+* Default the new `I18n.enforce_available_locales` config to `true`, meaning
+ `I18n` will make sure that all locales passed to it must be declared in the
+ `available_locales`
+ list. ([Pull Request](https://github.com/rails/rails/commit/8e21ae37ad9fef6b7393a84f9b5f2e18a831e49a))
+
+* Introduce Module#concerning: a natural, low-ceremony way to separate
+ responsibilities within a
+ class. ([Commit](https://github.com/rails/rails/commit/1eee0ca6de975b42524105a59e0521d18b38ab81))
+
Credits
-------
diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md
index f394daa6aa..222d86afe9 100644
--- a/guides/source/action_controller_overview.md
+++ b/guides/source/action_controller_overview.md
@@ -112,6 +112,10 @@ NOTE: The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&id
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.
+NOTE: Values such as `[]`, `[nil]` or `[nil, nil, ...]` in `params` are replaced
+with `nil` for security reasons by default. See [Security Guide](security.html#unsafe-query-generation)
+for more information.
+
To send a hash you include the key name inside the brackets:
```html
@@ -568,6 +572,38 @@ end
Note that while for session values you set the key to `nil`, to delete a cookie value you should use `cookies.delete(:key)`.
+Rails also provides a signed cookie jar and an encrypted cookie jar for storing
+sensitive data. The signed cookie jar appends a cryptographic signature on the
+cookie values to protect their integrity. The encrypted cookie jar encrypts the
+values in addition to signing them, so that they cannot be read by the end user.
+Refer to the [API documentation](http://api.rubyonrails.org/classes/ActionDispatch/Cookies.html)
+for more details.
+
+These special cookie jars use a serializer to serialize the assigned values into
+strings and deserializes them into Ruby objects on read.
+
+You can specify what serializer to use:
+
+```ruby
+Rails.application.config.action_dispatch.cookies_serializer = :json
+```
+
+The default serializer for new applications is `:json`. For compatibility with
+old applications with existing cookies, `:marshal` is used when `serializer`
+option is not specified.
+
+You may also set this option to `:hybrid`, in which case Rails would transparently
+deserialize existing (`Marshal`-serialized) cookies on read and re-write them in
+the `JSON` format. This is useful for migrating existing applications to the
+`:json` serializer.
+
+It is also possible to pass a custom serializer that responds to `load` and
+`dump`:
+
+```ruby
+Rails.application.config.action_dispatch.cookies_serializer = MyCustomSerializer
+```
+
Rendering XML and JSON data
---------------------------
@@ -683,7 +719,7 @@ class ApplicationController < ActionController::Base
end
class LoginFilter
- def self.filter(controller)
+ def self.before(controller)
unless controller.send(:logged_in?)
controller.flash[:error] = "You must be logged in to access this section"
controller.redirect_to controller.new_login_url
@@ -692,7 +728,7 @@ class LoginFilter
end
```
-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.
+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.
Request Forgery Protection
--------------------------
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index 61fd762304..6dc7fb1606 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -138,7 +138,7 @@ When you call the `mail` method now, Action Mailer will detect the two templates
Mailers are really just another way to render a view. Instead of rendering a
view and sending out the HTTP protocol, they are just sending it out through the
-Email protocols instead. Due to this, it makes sense to just have your
+email protocols instead. Due to this, it makes sense to just have your
controller tell the Mailer to send an email when a user is successfully created.
Setting this up is painfully simple.
@@ -164,7 +164,7 @@ class UsersController < ApplicationController
respond_to do |format|
if @user.save
- # Tell the UserMailer to send a welcome Email after save
+ # Tell the UserMailer to send a welcome email after save
UserMailer.welcome_email(@user).deliver
format.html { redirect_to(@user, notice: 'User was successfully created.') }
@@ -611,7 +611,7 @@ files (environment.rb, production.rb, etc...)
|`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>|
|`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>|
|`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.|
-|`delivery_method`|Defines a delivery method. Possible values are `:smtp` (default), `:sendmail`, `:file` and `:test`.|
+|`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.|
|`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.|
|`deliveries`|Keeps an array of all the emails sent out through the Action Mailer with delivery_method :test. Most useful for unit and functional testing.|
|`default_options`|Allows you to set default values for the `mail` method options (`:from`, `:reply_to`, etc.).|
@@ -639,8 +639,8 @@ config.action_mailer.default_options = {from: 'no-reply@example.com'}
### Action Mailer Configuration for Gmail
-As Action Mailer now uses the Mail gem, this becomes as simple as adding to your
-`config/environments/$RAILS_ENV.rb` file:
+As Action Mailer now uses the [Mail gem](https://github.com/mikel/mail), this
+becomes as simple as adding to your `config/environments/$RAILS_ENV.rb` file:
```ruby
config.action_mailer.delivery_method = :smtp
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 3783be50c0..d164b08d93 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -1455,7 +1455,7 @@ If you'd like to use your own SQL to find records in a table you can use `find_b
```ruby
Client.find_by_sql("SELECT * FROM clients
INNER JOIN orders ON clients.id = orders.client_id
- ORDER clients.created_at desc")
+ ORDER BY clients.created_at desc")
```
`find_by_sql` provides you with a simple way of making custom calls to the database and retrieving instantiated objects.
diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md
index efa826e8df..a483a6dd24 100644
--- a/guides/source/active_record_validations.md
+++ b/guides/source/active_record_validations.md
@@ -575,7 +575,9 @@ This helper validates that the attribute's value is unique right before the
object gets saved. It does not create a uniqueness constraint in the database,
so it may happen that two different database connections create two records
with the same value for a column that you intend to be unique. To avoid that,
-you must create a unique index in your database.
+you must create a unique index on both columns in your database. See
+[the MySQL manual](http://dev.mysql.com/doc/refman/5.6/en/multiple-column-indexes.html)
+for more details about multiple column indexes.
```ruby
class Account < ActiveRecord::Base
@@ -616,10 +618,6 @@ The default error message is _"has already been taken"_.
This helper passes the record to a separate class for validation.
```ruby
-class Person < ActiveRecord::Base
- validates_with GoodnessValidator
-end
-
class GoodnessValidator < ActiveModel::Validator
def validate(record)
if record.first_name == "Evil"
@@ -627,6 +625,10 @@ class GoodnessValidator < ActiveModel::Validator
end
end
end
+
+class Person < ActiveRecord::Base
+ validates_with GoodnessValidator
+end
```
NOTE: Errors added to `record.errors[:base]` relate to the state of the record
@@ -644,10 +646,6 @@ Like all other validations, `validates_with` takes the `:if`, `:unless` and
validator class as `options`:
```ruby
-class Person < ActiveRecord::Base
- validates_with GoodnessValidator, fields: [:first_name, :last_name]
-end
-
class GoodnessValidator < ActiveModel::Validator
def validate(record)
if options[:fields].any?{|field| record.send(field) == "Evil" }
@@ -655,6 +653,10 @@ class GoodnessValidator < ActiveModel::Validator
end
end
end
+
+class Person < ActiveRecord::Base
+ validates_with GoodnessValidator, fields: [:first_name, :last_name]
+end
```
Note that the validator will be initialized *only once* for the whole application
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index 59dfefd22f..2ad09f599b 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -1403,6 +1403,8 @@ The third argument, `indent_empty_lines`, is a flag that says whether empty line
The `indent!` method performs indentation in-place.
+NOTE: Defined in `active_support/core_ext/string/indent.rb`.
+
### Access
#### `at(position)`
diff --git a/guides/source/api_documentation_guidelines.md b/guides/source/api_documentation_guidelines.md
index 311cc23cf0..295c471db9 100644
--- a/guides/source/api_documentation_guidelines.md
+++ b/guides/source/api_documentation_guidelines.md
@@ -128,6 +128,53 @@ On the other hand, regular comments do not use an arrow:
# polymorphic_url(record) # same as comment_url(record)
```
+Booleans
+--------
+
+In predicates and flags prefer documenting boolean semantics over exact values.
+
+When "true" or "false" are used as defined in Ruby use regular font. The
+singletons `true` and `false` need fixed-width font. Please avoid terms like
+"truthy", Ruby defines what is true and false in the language, and thus those
+words have a technical meaning and need no substitutes.
+
+As a rule of thumb, do not document singletons unless absolutely necessary. That
+prevents artificial constructs like `!!` or ternaries, allows refactors, and the
+code does not need to rely on the exact values returned by methods being called
+in the implementation.
+
+For example:
+
+```markdown
+`config.action_mailer.perform_deliveries` specifies whether mail will actually be delivered and is true by default
+```
+
+the user does not need to know which is the actual default value of the flag,
+and so we only document its boolean semantics.
+
+An example with a predicate:
+
+```ruby
+# Returns true if the collection is empty.
+#
+# If the collection has been loaded
+# it is equivalent to <tt>collection.size.zero?</tt>. If the
+# collection has not been loaded, it is equivalent to
+# <tt>collection.exists?</tt>. If the collection has not already been
+# loaded and you are going to fetch the records anyway it is better to
+# check <tt>collection.length.zero?</tt>.
+def empty?
+ if loaded?
+ size.zero?
+ else
+ @target.blank? && !scope.exists?
+ end
+end
+```
+
+The API is careful not to commit to any particular value, the method has
+predicate semantics, that's enough.
+
Filenames
---------
@@ -163,7 +210,10 @@ class Array
end
```
-WARNING: Using a pair of `+...+` for fixed-width font only works with **words**; that is: anything matching `\A\w+\z`. For anything else use `<tt>...</tt>`, notably symbols, setters, inline snippets, etc.
+WARNING: Using `+...+` for fixed-width font only works with simple content like
+ordinary method names, symbols, paths (with forward slashes), etc. Please use
+`<tt>...</tt>` for everything else, notably class or module names with a
+namespace as in `<tt>ActiveRecord::Base</tt>`.
### Regular Font
diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md
index bce5d6c55f..fa2e57ff92 100644
--- a/guides/source/asset_pipeline.md
+++ b/guides/source/asset_pipeline.md
@@ -496,16 +496,11 @@ In this example, `require_self` is used. This puts the CSS contained within the
file (if any) at the precise location of the `require_self` call. If
`require_self` is called more than once, only the last call is respected.
-NOTE. If you want to use multiple Sass files, you should generally use the [Sass
-`@import`
-rule](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import) instead
-of these Sprockets directives. Using Sprockets directives all Sass files exist
-within their own scope, making variables or mixins only available within the
-document they were defined in. You can do file globbing as well using
-`@import "*"`, and `@import "**/*"` to add the whole tree equivalent to how
-`require_tree` works. Check the [sass-rails
-documentation](https://github.com/rails/sass-rails#features) for more info and
-important caveats.
+NOTE. If you want to use multiple Sass files, you should generally use the [Sass `@import` rule](http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import)
+instead of these Sprockets directives. Using Sprockets directives all Sass files exist within
+their own scope, making variables or mixins only available within the document they were defined in.
+You can do file globbing as well using `@import "*"`, and `@import "**/*"` to add the whole tree
+equivalent to how `require_tree` works. Check the [sass-rails documentation](https://github.com/rails/sass-rails#features) for more info and important caveats.
You can have as many manifest files as you need. For example, the `admin.css`
and `admin.js` manifest could contain the JS and CSS files that are used for the
@@ -938,7 +933,7 @@ Customizing the Pipeline
### CSS Compression
-There is currently one option for compressing CSS, YUI. The [YUI CSS
+One of the options for compressing CSS is YUI. The [YUI CSS
compressor](http://yui.github.io/yuicompressor/css.html) provides
minification.
@@ -948,6 +943,11 @@ gem.
```ruby
config.assets.css_compressor = :yui
```
+The other option for compressing CSS if you have the sass-rails gem installed is
+
+```ruby
+config.assets.css_compressor = :sass
+```
### JavaScript Compression
@@ -1018,7 +1018,8 @@ The X-Sendfile header is a directive to the web server to ignore the response
from the application, and instead serve a specified file from disk. This option
is off by default, but can be enabled if your server supports it. When enabled,
this passes responsibility for serving the file to the web server, which is
-faster.
+faster. Have a look at [send_file](http://api.rubyonrails.org/classes/ActionController/DataStreaming.html#method-i-send_file)
+on how to use this feature.
Apache and nginx support this option, which can be enabled in
`config/environments/production.rb`:
@@ -1033,6 +1034,10 @@ option, take care to paste this configuration option only into `production.rb`
and any other environments you define with production behavior (not
`application.rb`).
+TIP: For further details have a look at the docs of your production web server:
+- [Apache](https://tn123.org/mod_xsendfile/)
+- [Nginx](http://wiki.nginx.org/XSendfile)
+
Assets Cache Store
------------------
@@ -1145,7 +1150,7 @@ config.assets.digest = true
```
Rails 4 no longer sets default config values for Sprockets in `test.rb`, so
-`test.rb` now requies Sprockets configuration. The old defaults in the test
+`test.rb` now requires Sprockets configuration. The old defaults in the test
environment are: `config.assets.compile = true`, `config.assets.compress =
false`, `config.assets.debug = false` and `config.assets.digest = false`.
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index 9867d2dc3f..5ec6ae0f21 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -490,6 +490,19 @@ end
With this setup, you can retrieve `@employee.subordinates` and `@employee.manager`.
+In your migrations/schema, you will add a references column to the model itself.
+
+```ruby
+class CreateEmployees < ActiveRecord::Migration
+ def change
+ create_table :employees do |t|
+ t.references :manager
+ t.timestamps
+ end
+ end
+end
+```
+
Tips, Tricks, and Warnings
--------------------------
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 412aecadd5..7b72e27b96 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -292,6 +292,12 @@ All these configuration options are delegated to the `I18n` library.
* `config.active_record.maintain_test_schema` is a boolean value which controls whether Active Record should try to keep your test database schema up-to-date with `db/schema.rb` (or `db/structure.sql`) when you run your tests. The default is true.
+* `config.active_record.dump_schema_after_migration` is a flag which
+ controls whether or not schema dump should happen (`db/schema.rb` or
+ `db/structure.sql`) when you run migrations. This is set to false in
+ `config/environments/production.rb` which is generated by Rails. The
+ default value is true if this configuration is not set.
+
The MySQL adapter adds one additional configuration option:
* `ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans` controls whether Active Record will consider all `tinyint(1)` columns in a MySQL database to be booleans and is true by default.
@@ -352,6 +358,10 @@ value. Defaults to `'encrypted cookie'`.
* `config.action_dispatch.encrypted_signed_cookie_salt` sets the signed
encrypted cookies salt value. Defaults to `'signed encrypted cookie'`.
+* `config.action_dispatch.perform_deep_munge` configures whether `deep_munge`
+ method should be performed on the parameters. See [Security Guide](security.html#unsafe-query-generation)
+ for more information. It defaults to true.
+
* `ActionDispatch::Callbacks.before` takes a block of code to run before the request.
* `ActionDispatch::Callbacks.to_prepare` takes a block to run after `ActionDispatch::Callbacks.before`, but before the request. Runs for every request in `development` mode, but only once for `production` or environments with `cache_classes` set to `true`.
@@ -374,7 +384,7 @@ encrypted cookies salt value. Defaults to `'signed encrypted cookie'`.
* `config.action_view.logger` accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Action View. Set to `nil` to disable logging.
-* `config.action_view.erb_trim_mode` gives the trim mode to be used by ERB. It defaults to `'-'`. See the [ERB documentation](http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/) for more information.
+* `config.action_view.erb_trim_mode` gives the trim mode to be used by ERB. It defaults to `'-'`, which turns on trimming of tail spaces and newline when using `<%= -%>` or `<%= =%>`. See the [Erubis documentation](http://www.kuwata-lab.com/erubis/users-guide.06.html#topics-trimspaces) for more information.
* `config.action_view.embed_authenticity_token_in_remote_forms` allows you to set the default behavior for `authenticity_token` in forms with `:remote => true`. By default it's set to false, which means that remote forms will not include `authenticity_token`, which is helpful when you're fragment-caching the form. Remote forms get the authenticity from the `meta` tag, so embedding is unnecessary unless you support browsers without JavaScript. In such case you can either pass `:authenticity_token => true` as a form option or set this config setting to `true`
@@ -386,6 +396,8 @@ encrypted cookies salt value. Defaults to `'signed encrypted cookie'`.
The default setting is `true`, which uses the partial at `/admin/posts/_post.erb`. Setting the value to `false` would render `/posts/_post.erb`, which is the same behavior as rendering from a non-namespaced controller such as `PostsController`.
+* `config.action_view.raise_on_missing_translations` determines whether an error should be raised for missing translations
+
### Configuring Action Mailer
There are a number of settings available on `config.action_mailer`:
@@ -406,17 +418,25 @@ There are a number of settings available on `config.action_mailer`:
* `config.action_mailer.raise_delivery_errors` specifies whether to raise an error if email delivery cannot be completed. It defaults to true.
-* `config.action_mailer.delivery_method` defines the delivery method. The allowed values are `:smtp` (default), `:sendmail`, and `:test`.
+* `config.action_mailer.delivery_method` defines the delivery method and defaults to `:smtp`. See the [configuration section in the Action Mailer guide](http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration) for more info.
* `config.action_mailer.perform_deliveries` specifies whether mail will actually be delivered and is true by default. It can be convenient to set it to false for testing.
* `config.action_mailer.default_options` configures Action Mailer defaults. Use to set options like `from` or `reply_to` for every mailer. These default to:
```ruby
- :mime_version => "1.0",
- :charset => "UTF-8",
- :content_type => "text/plain",
- :parts_order => [ "text/plain", "text/enriched", "text/html" ]
+ mime_version: "1.0",
+ charset: "UTF-8",
+ content_type: "text/plain",
+ parts_order: ["text/plain", "text/enriched", "text/html"]
+ ```
+
+ Assign a hash to set additional options:
+
+ ```ruby
+ config.action_mailer.default_options = {
+ from: "noreply@example.com"
+ }
```
* `config.action_mailer.observers` registers observers which will be notified when mail is delivered.
@@ -441,6 +461,8 @@ There are a few configuration options available in Active Support:
* `config.active_support.use_standard_json_time_format` enables or disables serializing dates to ISO 8601 format. Defaults to `true`.
+* `config.active_support.time_precision` sets the precision of JSON encoded time values. Defaults to `3`.
+
* `ActiveSupport::Logger.silencer` is set to `false` to disable the ability to silence logging in a block. The default is `true`.
* `ActiveSupport::Cache::Store.logger` specifies the logger to use within cache store operations.
@@ -451,7 +473,6 @@ There are a few configuration options available in Active Support:
* `ActiveSupport::Deprecation.silenced` sets whether or not to display deprecation warnings.
-* `ActiveSupport::Logger.silencer` is set to `false` to disable the ability to silence logging in a block. The default is `true`.
### Configuring a Database
@@ -554,7 +575,7 @@ $ rails runner 'puts ActiveRecord::Base.connections'
Since pool is not in the `ENV['DATABASE_URL']` provided connection information its information is merged in. Since `adapter` is duplicate, the `ENV['DATABASE_URL']` connection information wins.
-The only way to explicitly not use the connection information in `ENV['DATABASE_URL']` is to specify an explicit URL connectinon using the `"url"` sub key:
+The only way to explicitly not use the connection information in `ENV['DATABASE_URL']` is to specify an explicit URL connection using the `"url"` sub key:
```
$ cat config/database.yml
@@ -700,7 +721,7 @@ Rails will now prepend "/app1" when generating links.
#### Using Passenger
-Passenger makes it easiy to run your application in a subdirectory. You can find
+Passenger makes it easy to run your application in a subdirectory. You can find
the relevant configuration in the
[passenger manual](http://www.modrails.com/documentation/Users%20guide%20Apache.html#deploying_rails_to_sub_uri).
@@ -918,4 +939,4 @@ ActiveRecord::ConnectionTimeoutError - could not obtain a database connection wi
If you get the above error, you might want to increase the size of connection
pool by incrementing the `pool` option in `database.yml`
-NOTE. If you have enabled `Rails.threadsafe!` mode then there could be a chance that several threads may be accessing multiple connections simultaneously. So depending on your current request load, you could very well have multiple threads contending for a limited amount of connections.
+NOTE. As Rails is multi-threaded by default, there could be a chance that several threads may be accessing multiple connections simultaneously. So depending on your current request load, you could very well have multiple threads contending for a limited amount of connections.
diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md
index 814237ba22..36e3862c6b 100644
--- a/guides/source/contributing_to_ruby_on_rails.md
+++ b/guides/source/contributing_to_ruby_on_rails.md
@@ -136,7 +136,7 @@ You can invoke `test_jdbcmysql`, `test_jdbcsqlite3` or `test_jdbcpostgresql` als
The test suite runs with warnings enabled. Ideally, Ruby on Rails should issue no warnings, but there may be a few, as well as some from third-party libraries. Please ignore (or fix!) them, if any, and submit patches that do not issue new warnings.
-As of this writing (December, 2010) they are especially noisy with Ruby 1.9. If you are sure about what you are doing and would like to have a more clear output, there's a way to override the flag:
+If you are sure about what you are doing and would like to have a more clear output, there's a way to override the flag:
```bash
$ RUBYOPT=-W0 bundle exec rake test
@@ -201,7 +201,8 @@ If your comment simply says "+1", then odds are that other reviewers aren't goin
Contributing to the Rails Documentation
---------------------------------------
-Ruby on Rails has two main sets of documentation: the guides help you in learning about Ruby on Rails, and the API is a reference.
+Ruby on Rails has two main sets of documentation: the guides, which help you
+learn about Ruby on Rails, and the API, which serves as a reference.
You can help improve the Rails guides by making them more coherent, consistent or readable, adding missing information, correcting factual errors, fixing typos, or bringing it up to date with the latest edge Rails. To get involved in the translation of Rails guides, please see [Translating Rails Guides](https://wiki.github.com/rails/docrails/translating-rails-guides).
@@ -258,10 +259,10 @@ more if the source code is mounted in `/vagrant` as happens in the recommended
workflow with the [rails-dev-box](https://github.com/rails/rails-dev-box).
As a compromise, test what your code obviously affects, and if the change is
-not in railties run the whole test suite of the affected component. If all is
-green that's enough to propose your contribution. We have [Travis CI](https://travis-ci.org/rails/rails)
-as a safety net for catching unexpected breakages
-elsewhere.
+not in railties, run the whole test suite of the affected component. If all
+tests are passing, that's enough to propose your contribution. We have
+[Travis CI](https://travis-ci.org/rails/rails) as a safety net for catching
+unexpected breakages elsewhere.
TIP: Changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability of Rails will generally not be accepted.
diff --git a/guides/source/documents.yaml b/guides/source/documents.yaml
index ae47744e31..e4653b47fc 100644
--- a/guides/source/documents.yaml
+++ b/guides/source/documents.yaml
@@ -117,7 +117,7 @@
name: The Rails Initialization Process
work_in_progress: true
url: initialization.html
- description: This guide explains the internals of the Rails initialization process as of Rails 3.1
+ description: This guide explains the internals of the Rails initialization process as of Rails 4
-
name: Extending Rails
documents:
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index dbcedba800..53d2a9b55b 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -21,19 +21,22 @@ application from scratch. It does not assume that you have any prior experience
with Rails. However, to get the most out of it, you need to have some
prerequisites installed:
-* The [Ruby](http://www.ruby-lang.org/en/downloads) language version 1.9.3 or newer
-* The [RubyGems](http://rubygems.org) packaging system
- * To learn more about RubyGems, please read the [RubyGems Guides](http://guides.rubygems.org)
-* A working installation of the [SQLite3 Database](http://www.sqlite.org)
+* The [Ruby](http://www.ruby-lang.org/en/downloads) language version 1.9.3 or newer.
+* The [RubyGems](http://rubygems.org) packaging system, which is installed with Ruby
+ versions 1.9 and later. To learn more about RubyGems, please read the [RubyGems Guides](http://guides.rubygems.org).
+* A working installation of the [SQLite3 Database](http://www.sqlite.org).
Rails is a web application framework running on the Ruby programming language.
If you have no prior experience with Ruby, you will find a very steep learning
-curve diving straight into Rails. There are some good free resources on the
-Internet for learning Ruby, including:
+curve diving straight into Rails. There are several curated lists of online resources
+for learning Ruby:
-* [Mr. Neighborly's Humble Little Ruby Book](http://www.humblelittlerubybook.com)
-* [Programming Ruby](http://www.ruby-doc.org/docs/ProgrammingRuby/)
-* [Why's (Poignant) Guide to Ruby](http://mislav.uniqpath.com/poignant-guide/)
+* [Official Ruby Programming Language website](https://www.ruby-lang.org/en/documentation/)
+* [reSRC's List of Free Programming Books](http://resrc.io/list/10/list-of-free-programming-books/#ruby)
+
+Be aware that some resources, while still excellent, cover versions of Ruby as old as
+1.6, and commonly 1.8, and will not include some syntax that you will see in day-to-day
+development with Rails.
What is Rails?
--------------
@@ -54,11 +57,13 @@ learned elsewhere, you may have a less happy experience.
The Rails philosophy includes two major guiding principles:
-* DRY - "Don't Repeat Yourself" - suggests that writing the same code over and
- over again is a bad thing.
-* Convention Over Configuration - means that Rails makes assumptions about what
- you want to do and how you're going to do it, rather than requiring you to
- specify every little thing through endless configuration files.
+* **Don't Repeat Yourself:** DRY is a principle of software development which
+ states that "Every piece of knowledge must have a single, unambiguous, authoritative
+ representation within a system." By not writing the same information over and over
+ again, our code is more maintainable, more extensible, and less buggy.
+* **Convention Over Configuration:** Rails has opinions about the best way to do many
+ things in a web application, and defaults to this set of conventions, rather than
+ require that you specify every minutiae through endless configuration files.
Creating a New Rails Project
----------------------------
@@ -73,9 +78,9 @@ By following along with this guide, you'll create a Rails project called
(very) simple weblog. Before you can start building the application, you need to
make sure that you have Rails itself installed.
-TIP: The examples below use `#` and `$` to denote superuser and regular
-user terminal prompts respectively in a UNIX-like OS. If you are using
-Windows, your prompt will look something like `c:\source_code>`
+TIP: The examples below use `$` to represent your terminal prompt in a UNIX-like OS,
+though it may have been customized to appear differently. If you are using Windows,
+your prompt will look something like `c:\source_code>`
### Installing Rails
@@ -84,21 +89,35 @@ Open up a command line prompt. On Mac OS X open Terminal.app, on Windows choose
dollar sign `$` should be run in the command line. Verify that you have a
current version of Ruby installed:
+TIP. A number of tools exist to help you quickly install Ruby and Ruby
+on Rails on your system. Windows users can use [Rails Installer](http://railsinstaller.org),
+while Mac OS X users can use [Rails One Click](http://railsoneclick.com).
+
```bash
$ ruby -v
ruby 2.0.0p353
```
+If you don't have Ruby installed have a look at
+[ruby-lang.org](https://www.ruby-lang.org/en/downloads/) for possible ways to
+install Ruby on your platform.
+
+Many popular UNIX-like OSes ship with an acceptable version of SQLite3. Windows
+users and others can find installation instructions at [the SQLite3 website](http://www.sqlite.org).
+Verify that it is correctly installed and in your PATH:
+
+```bash
+$ sqlite3 --version
+```
+
+The program should report its version.
+
To install Rails, use the `gem install` command provided by RubyGems:
```bash
$ gem install rails
```
-TIP. A number of tools exist to help you quickly install Ruby and Ruby
-on Rails on your system. Windows users can use [Rails Installer](http://railsinstaller.org),
-while Mac OS X users can use [Rails One Click](http://railsoneclick.com).
-
To verify that you have everything installed correctly, you should be able to
run the following:
@@ -143,20 +162,20 @@ of the files and folders that Rails created by default:
| File/Folder | Purpose |
| ----------- | ------- |
-|app|Contains the controllers, models, views, helpers, mailers and assets for your application. You'll focus on this folder for the remainder of this guide.|
-|bin|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.|
+|app/|Contains the controllers, models, views, helpers, mailers and assets for your application. You'll focus on this folder for the remainder of this guide.|
+|bin/|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.|
|config/|Configure your application's routes, database, and more. This is covered in more detail in [Configuring Rails Applications](configuring.html).|
|config.ru|Rack configuration for Rack based servers used to start the application.|
-|db|Contains your current database schema, as well as the database migrations.|
+|db/|Contains your current database schema, as well as the database migrations.|
|Gemfile<br>Gemfile.lock|These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see [the Bundler website](http://gembundler.com).|
-|lib|Extended modules for your application.|
-|log|Application log files.|
-|public|The only folder seen by the world as-is. Contains static files and compiled assets.|
+|lib/|Extended modules for your application.|
+|log/|Application log files.|
+|public/|The only folder seen by the world as-is. Contains static files and compiled assets.|
|Rakefile|This file locates and loads tasks that can be run from the command line. The task definitions are defined throughout the components of Rails. Rather than changing Rakefile, you should add your own tasks by adding files to the lib/tasks directory of your application.|
|README.rdoc|This is a brief instruction manual for your application. You should edit this file to tell others what your application does, how to set it up, and so on.|
-|test|Unit tests, fixtures, and other test apparatus. These are covered in [Testing Rails Applications](testing.html).|
-|tmp|Temporary files (like cache, pid, and session files).|
-|vendor|A place for all third-party code. In a typical Rails application this includes vendored gems.|
+|test/|Unit tests, fixtures, and other test apparatus. These are covered in [Testing Rails Applications](testing.html).|
+|tmp/|Temporary files (like cache, pid, and session files).|
+|vendor/|A place for all third-party code. In a typical Rails application this includes vendored gems.|
Hello, Rails!
-------------
@@ -315,18 +334,19 @@ Now that you've seen how to create a controller, an action and a view, let's
create something with a bit more substance.
In the Blog application, you will now create a new _resource_. A resource is the
-term used for a collection of similar objects, such as posts, people or animals.
+term used for a collection of similar objects, such as articles, people or
+animals.
You can create, read, update and destroy items for a resource and these
operations are referred to as _CRUD_ operations.
Rails provides a `resources` method which can be used to declare a standard REST
-resource. Here's what `config/routes.rb` should look like after the _post resource_
-is declared.
+resource. Here's what `config/routes.rb` should look like after the
+_article resource_ is declared.
```ruby
Blog::Application.routes.draw do
- resources :posts
+ resources :articles
root 'welcome#index'
end
@@ -335,88 +355,91 @@ end
If you run `rake routes`, you'll see that it has defined routes for all the
standard RESTful actions. The meaning of the prefix column (and other columns)
will be seen later, but for now notice that Rails has inferred the
-singular form `post` and makes meaningful use of the distinction.
+singular form `article` and makes meaningful use of the distinction.
```bash
$ rake routes
- Prefix Verb URI Pattern Controller#Action
- posts GET /posts(.:format) posts#index
- POST /posts(.:format) posts#create
- new_post GET /posts/new(.:format) posts#new
-edit_post GET /posts/:id/edit(.:format) posts#edit
- post GET /posts/:id(.:format) posts#show
- PATCH /posts/:id(.:format) posts#update
- PUT /posts/:id(.:format) posts#update
- DELETE /posts/:id(.:format) posts#destroy
- root / welcome#index
-```
-
-In the next section, you will add the ability to create new posts in your
+ Prefix Verb URI Pattern Controller#Action
+ articles GET /articles(.:format) articles#index
+ POST /articles(.:format) articles#create
+ new_article GET /articles/new(.:format) articles#new
+edit_article GET /articles/:id/edit(.:format) articles#edit
+ article GET /articles/:id(.:format) articles#show
+ PATCH /articles/:id(.:format) articles#update
+ PUT /articles/:id(.:format) articles#update
+ DELETE /articles/:id(.:format) articles#destroy
+ root GET / welcome#index
+```
+
+In the next section, you will add the ability to create new articles in your
application and be able to view them. This is the "C" and the "R" from CRUD:
creation and reading. The form for doing this will look like this:
-![The new post form](images/getting_started/new_post.png)
+![The new article form](images/getting_started/new_article.png)
It will look a little basic for now, but that's ok. We'll look at improving the
styling for it afterwards.
### Laying down the ground work
-The first thing that you are going to need to create a new post within the
-application is a place to do that. A great place for that would be at `/posts/new`.
-With the route already defined, requests can now be made to `/posts/new` in the
-application. Navigate to <http://localhost:3000/posts/new> and you'll see a
-routing error:
+Firstly, you need a place within the application to create a new article. A
+great place for that would be at `/articles/new`. With the route already
+defined, requests can now be made to `/articles/new` in the application.
+Navigate to <http://localhost:3000/articles/new> and you'll see a routing
+error:
-![Another routing error, uninitialized constant PostsController](images/getting_started/routing_error_no_controller.png)
+![Another routing error, uninitialized constant ArticlesController](images/getting_started/routing_error_no_controller.png)
This error occurs because the route needs to have a controller defined in order
to serve the request. The solution to this particular problem is simple: create
-a controller called `PostsController`. You can do this by running this command:
+a controller called `ArticlesController`. You can do this by running this
+command:
```bash
-$ rails g controller posts
+$ rails g controller articles
```
-If you open up the newly generated `app/controllers/posts_controller.rb` you'll
-see a fairly empty controller:
+If you open up the newly generated `app/controllers/articles_controller.rb`
+you'll see a fairly empty controller:
```ruby
-class PostsController < ApplicationController
+class ArticlesController < ApplicationController
end
```
-A controller is simply a class that is defined to inherit from `ApplicationController`.
+A controller is simply a class that is defined to inherit from
+`ApplicationController`.
It's inside this class that you'll define methods that will become the actions
-for this controller. These actions will perform CRUD operations on the posts
+for this controller. These actions will perform CRUD operations on the articles
within our system.
-NOTE: There are `public`, `private` and `protected` methods in Ruby,
+NOTE: There are `public`, `private` and `protected` methods in Ruby,
but only `public` methods can be actions for controllers.
For more details check out [Programming Ruby](http://www.ruby-doc.org/docs/ProgrammingRuby/).
-If you refresh <http://localhost:3000/posts/new> now, you'll get a new error:
+If you refresh <http://localhost:3000/articles/new> now, you'll get a new error:
-![Unknown action new for PostsController!](images/getting_started/unknown_action_new_for_posts.png)
+![Unknown action new for ArticlesController!](images/getting_started/unknown_action_new_for_articles.png)
-This error indicates that Rails cannot find the `new` action inside the `PostsController`
-that you just generated. This is because when controllers are generated in Rails
-they are empty by default, unless you tell it your wanted actions during the
-generation process.
+This error indicates that Rails cannot find the `new` action inside the
+`ArticlesController` that you just generated. This is because when controllers
+are generated in Rails they are empty by default, unless you tell it
+your wanted actions during the generation process.
To manually define an action inside a controller, all you need to do is to
-define a new method inside the controller. Open `app/controllers/posts_controller.rb`
-and inside the `PostsController` class, define a `new` method like this:
+define a new method inside the controller.
+Open `app/controllers/articles_controller.rb` and inside the `ArticlesController`
+class, define a `new` method like this:
```ruby
def new
end
```
-With the `new` method defined in `PostsController`, if you refresh <http://localhost:3000/posts/new>
-you'll see another error:
+With the `new` method defined in `ArticlesController`, if you refresh
+<http://localhost:3000/articles/new> you'll see another error:
-![Template is missing for posts/new](images/getting_started/template_is_missing_posts_new.png)
+![Template is missing for articles/new](images/getting_started/template_is_missing_articles_new.png)
You're getting this error now because Rails expects plain actions like this one
to have views associated with them to display their information. With no view
@@ -426,16 +449,16 @@ In the above image, the bottom line has been truncated. Let's see what the full
thing looks like:
<blockquote>
-Missing template posts/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
+Missing template articles/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"
</blockquote>
That's quite a lot of text! Let's quickly go through and understand what each
part of it does.
The first part identifies what template is missing. In this case, it's the
-`posts/new` template. Rails will first look for this template. If not found,
+`articles/new` template. Rails will first look for this template. If not found,
then it will attempt to load a template called `application/new`. It looks for
-one here because the `PostsController` inherits from `ApplicationController`.
+one here because the `ArticlesController` inherits from `ApplicationController`.
The next part of the message contains a hash. The `:locale` key in this hash
simply indicates what spoken language template should be retrieved. By default,
@@ -451,34 +474,35 @@ Templates within a basic Rails application like this are kept in a single
location, but in more complex applications it could be many different paths.
The simplest template that would work in this case would be one located at
-`app/views/posts/new.html.erb`. The extension of this file name is key: the
+`app/views/articles/new.html.erb`. The extension of this file name is key: the
first extension is the _format_ of the template, and the second extension is the
_handler_ that will be used. Rails is attempting to find a template called
-`posts/new` within `app/views` for the application. The format for this template
-can only be `html` and the handler must be one of `erb`, `builder` or `coffee`.
-Because you want to create a new HTML form, you will be using the `ERB`
-language. Therefore the file should be called `posts/new.html.erb` and needs to
-be located inside the `app/views` directory of the application.
+`articles/new` within `app/views` for the application. The format for this
+template can only be `html` and the handler must be one of `erb`, `builder` or
+`coffee`. Because you want to create a new HTML form, you will be using the `ERB`
+language. Therefore the file should be called `articles/new.html.erb` and needs
+to be located inside the `app/views` directory of the application.
-Go ahead now and create a new file at `app/views/posts/new.html.erb` and write
-this content in it:
+Go ahead now and create a new file at `app/views/articles/new.html.erb` and
+write this content in it:
```html
-<h1>New Post</h1>
+<h1>New Article</h1>
```
-When you refresh <http://localhost:3000/posts/new> you'll now see that the page
-has a title. The route, controller, action and view are now working
-harmoniously! It's time to create the form for a new post.
+When you refresh <http://localhost:3000/articles/new> you'll now see that the
+page has a title. The route, controller, action and view are now working
+harmoniously! It's time to create the form for a new article.
### The first form
To create a form within this template, you will use a <em>form
builder</em>. The primary form builder for Rails is provided by a helper
-method called `form_for`. To use this method, add this code into `app/views/posts/new.html.erb`:
+method called `form_for`. To use this method, add this code into
+`app/views/articles/new.html.erb`:
```html+erb
-<%= form_for :post do |f| %>
+<%= form_for :article do |f| %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
@@ -499,71 +523,72 @@ If you refresh the page now, you'll see the exact same form as in the example.
Building forms in Rails is really just that easy!
When you call `form_for`, you pass it an identifying object for this
-form. In this case, it's the symbol `:post`. This tells the `form_for`
+form. In this case, it's the symbol `:article`. This tells the `form_for`
helper what this form is for. Inside the block for this method, the
`FormBuilder` object - represented by `f` - is used to build two labels and two
-text fields, one each for the title and text of a post. Finally, a call to
+text fields, one each for the title and text of an article. Finally, a call to
`submit` on the `f` object will create a submit button for the form.
There's one problem with this form though. If you inspect the HTML that is
generated, by viewing the source of the page, you will see that the `action`
-attribute for the form is pointing at `/posts/new`. This is a problem because
+attribute for the form is pointing at `/articles/new`. This is a problem because
this route goes to the very page that you're on right at the moment, and that
-route should only be used to display the form for a new post.
+route should only be used to display the form for a new article.
The form needs to use a different URL in order to go somewhere else.
This can be done quite simply with the `:url` option of `form_for`.
Typically in Rails, the action that is used for new form submissions
like this is called "create", and so the form should be pointed to that action.
-Edit the `form_for` line inside `app/views/posts/new.html.erb` to look like this:
+Edit the `form_for` line inside `app/views/articles/new.html.erb` to look like
+this:
```html+erb
-<%= form_for :post, url: posts_path do |f| %>
+<%= form_for :article, url: articles_path do |f| %>
```
-In this example, the `posts_path` helper is passed to the `:url` option.
+In this example, the `articles_path` helper is passed to the `:url` option.
To see what Rails will do with this, we look back at the output of
`rake routes`:
```bash
$ rake routes
- Prefix Verb URI Pattern Controller#Action
- posts GET /posts(.:format) posts#index
- POST /posts(.:format) posts#create
- new_post GET /posts/new(.:format) posts#new
-edit_post GET /posts/:id/edit(.:format) posts#edit
- post GET /posts/:id(.:format) posts#show
- PATCH /posts/:id(.:format) posts#update
- PUT /posts/:id(.:format) posts#update
- DELETE /posts/:id(.:format) posts#destroy
- root / welcome#index
-```
-
-The `posts_path` helper tells Rails to point the form
-to the URI Pattern associated with the `posts` prefix; and
+ Prefix Verb URI Pattern Controller#Action
+ articles GET /articles(.:format) articles#index
+ POST /articles(.:format) articles#create
+ new_article GET /articles/new(.:format) articles#new
+edit_article GET /articles/:id/edit(.:format) articles#edit
+ article GET /articles/:id(.:format) articles#show
+ PATCH /articles/:id(.:format) articles#update
+ PUT /articles/:id(.:format) articles#update
+ DELETE /articles/:id(.:format) articles#destroy
+ root GET / welcome#index
+```
+
+The `articles_path` helper tells Rails to point the form
+to the URI Pattern associated with the `articles` prefix; and
the form will (by default) send a `POST` request
to that route. This is associated with the
-`create` action of the current controller, the `PostsController`.
+`create` action of the current controller, the `ArticlesController`.
With the form and its associated route defined, you will be able to fill in the
form and then click the submit button to begin the process of creating a new
-post, so go ahead and do that. When you submit the form, you should see a
+article, so go ahead and do that. When you submit the form, you should see a
familiar error:
-![Unknown action create for PostsController](images/getting_started/unknown_action_create_for_posts.png)
+![Unknown action create for ArticlesController](images/getting_started/unknown_action_create_for_articles.png)
-You now need to create the `create` action within the `PostsController` for this
-to work.
+You now need to create the `create` action within the `ArticlesController` for
+this to work.
-### Creating posts
+### Creating articles
To make the "Unknown action" go away, you can define a `create` action within
-the `PostsController` class in `app/controllers/posts_controller.rb`, underneath
-the `new` action:
+the `ArticlesController` class in `app/controllers/articles_controller.rb`,
+underneath the `new` action:
```ruby
-class PostsController < ApplicationController
+class ArticlesController < ApplicationController
def new
end
@@ -574,7 +599,7 @@ end
If you re-submit the form now, you'll see another familiar error: a template is
missing. That's ok, we can ignore that for now. What the `create` action should
-be doing is saving our new post to a database.
+be doing is saving our new article to the database.
When a form is submitted, the fields of the form are sent to Rails as
_parameters_. These parameters can then be referenced inside the controller
@@ -583,12 +608,12 @@ look like, change the `create` action to this:
```ruby
def create
- render text: params[:post].inspect
+ render text: params[:article].inspect
end
```
The `render` method here is taking a very simple hash with a key of `text` and
-value of `params[:post].inspect`. The `params` method is the object which
+value of `params[:article].inspect`. The `params` method is the object which
represents the parameters (or fields) coming in from the form. The `params`
method returns an `ActiveSupport::HashWithIndifferentAccess` object, which
allows you to access the keys of the hash using either strings or symbols. In
@@ -598,14 +623,14 @@ If you re-submit the form one more time you'll now no longer get the missing
template error. Instead, you'll see something that looks like the following:
```ruby
-{"title"=>"First post!", "text"=>"This is my first post."}
+{"title"=>"First article!", "text"=>"This is my first article."}
```
-This action is now displaying the parameters for the post that are coming in
+This action is now displaying the parameters for the article that are coming in
from the form. However, this isn't really all that helpful. Yes, you can see the
parameters but nothing in particular is being done with them.
-### Creating the Post model
+### Creating the Article model
Models in Rails use a singular name, and their corresponding database tables use
a plural name. Rails provides a generator for creating models, which
@@ -613,17 +638,17 @@ most Rails developers tend to use when creating new models.
To create the new model, run this command in your terminal:
```bash
-$ rails generate model Post title:string text:text
+$ rails generate model Article title:string text:text
```
-With that command we told Rails that we want a `Post` model, together
+With that command we told Rails that we want a `Article` model, together
with a _title_ attribute of type string, and a _text_ attribute
-of type text. Those attributes are automatically added to the `posts`
-table in the database and mapped to the `Post` model.
+of type text. Those attributes are automatically added to the `articles`
+table in the database and mapped to the `Article` model.
Rails responded by creating a bunch of files. For
-now, we're only interested in `app/models/post.rb` and
-`db/migrate/20120419084633_create_posts.rb` (your name could be a bit
+now, we're only interested in `app/models/article.rb` and
+`db/migrate/20140120191729_create_articles.rb` (your name could be a bit
different). The latter is responsible
for creating the database structure, which is what we'll look at next.
@@ -642,13 +667,13 @@ and it's possible to undo a migration after it's been applied to your database.
Migration filenames include a timestamp to ensure that they're processed in the
order that they were created.
-If you look in the `db/migrate/20120419084633_create_posts.rb` file (remember,
+If you look in the `db/migrate/20140120191729_create_articles.rb` file (remember,
yours will have a slightly different name), here's what you'll find:
```ruby
-class CreatePosts < ActiveRecord::Migration
+class CreateArticles < ActiveRecord::Migration
def change
- create_table :posts do |t|
+ create_table :articles do |t|
t.string :title
t.text :text
@@ -658,12 +683,12 @@ class CreatePosts < ActiveRecord::Migration
end
```
-The above migration creates a method named `change` which will be called when you
-run this migration. The action defined in this method is also reversible, which
-means Rails knows how to reverse the change made by this migration, in case you
-want to reverse it later. When you run this migration it will create a
-`posts` table with one string column and a text column. It also creates two
-timestamp fields to allow Rails to track post creation and update times.
+The above migration creates a method named `change` which will be called when
+you run this migration. The action defined in this method is also reversible,
+which means Rails knows how to reverse the change made by this migration,
+in case you want to reverse it later. When you run this migration it will create
+an `articles` table with one string column and a text column. It also creates
+two timestamp fields to allow Rails to track article creation and update times.
TIP: For more information about migrations, refer to [Rails Database
Migrations](migrations.html).
@@ -674,14 +699,14 @@ At this point, you can use a rake command to run the migration:
$ rake db:migrate
```
-Rails will execute this migration command and tell you it created the Posts
+Rails will execute this migration command and tell you it created the Articles
table.
```bash
-== CreatePosts: migrating ====================================================
--- create_table(:posts)
+== CreateArticles: migrating ==================================================
+-- create_table(:articles)
-> 0.0019s
-== CreatePosts: migrated (0.0020s) ===========================================
+== CreateArticles: migrated (0.0020s) =========================================
```
NOTE. Because you're working in the development environment by default, this
@@ -692,34 +717,35 @@ invoking the command: `rake db:migrate RAILS_ENV=production`.
### Saving data in the controller
-Back in `PostsController`, we need to change the `create` action
-to use the new `Post` model to save the data in the database. Open `app/controllers/posts_controller.rb`
-and change the `create` action to look like this:
+Back in `ArticlesController`, we need to change the `create` action
+to use the new `Article` model to save the data in the database.
+Open `app/controllers/articles_controller.rb` and change the `create` action to
+look like this:
```ruby
def create
- @post = Post.new(params[:post])
+ @article = Article.new(params[:article])
- @post.save
- redirect_to @post
+ @article.save
+ redirect_to @article
end
```
Here's what's going on: every Rails model can be initialized with its
respective attributes, which are automatically mapped to the respective
database columns. In the first line we do just that
-(remember that `params[:post]` contains the attributes we're interested in).
-Then, `@post.save` is responsible for saving the model in the database.
+(remember that `params[:article]` contains the attributes we're interested in).
+Then, `@article.save` is responsible for saving the model in the database.
Finally, we redirect the user to the `show` action, which we'll define later.
-TIP: As we'll see later, `@post.save` returns a boolean indicating
-whether the model was saved or not.
+TIP: As we'll see later, `@article.save` returns a boolean indicating
+whether the article was saved or not.
If you now go to
-<http://localhost:3000/posts/new> you'll *almost* be able to create a post. Try
-it! You should get an error that looks like this:
+<http://localhost:3000/articles/new> you'll *almost* be able to create an
+article. Try it! You should get an error that looks like this:
-![Forbidden attributes for new post](images/getting_started/forbidden_attributes_for_new_post.png)
+![Forbidden attributes for new article](images/getting_started/forbidden_attributes_for_new_article.png)
Rails has several security features that help you write secure applications,
and you're running into one of them now. This one is called
@@ -730,28 +756,28 @@ look like this:
```ruby
def create
- @post = Post.new(post_params)
+ @article = Article.new(article_params)
- @post.save
- redirect_to @post
+ @article.save
+ redirect_to @article
end
private
- def post_params
- params.require(:post).permit(:title, :text)
+ def article_params
+ params.require(:article).permit(:title, :text)
end
```
See the `permit`? It allows us to accept both `title` and `text` in this
action.
-TIP: Note that `def post_params` is private. This new approach prevents an
+TIP: Note that `def article_params` is private. This new approach prevents an
attacker from setting the model's attributes by manipulating the hash passed to
the model.
For more information, refer to
-[this blog post about Strong Parameters](http://weblog.rubyonrails.org/2012/3/21/strong-parameters/).
+[this blog article about Strong Parameters](http://weblog.rubyonrails.org/2012/3/21/strong-parameters/).
-### Showing Posts
+### Showing Articles
If you submit the form again now, Rails will complain about not finding
the `show` action. That's not very useful though, so let's add the
@@ -761,68 +787,70 @@ As we have seen in the output of `rake routes`, the route for `show` action is
as follows:
```
-post GET /posts/:id(.:format) posts#show
+article GET /articles/:id(.:format) articles#show
```
The special syntax `:id` tells rails that this route expects an `:id`
-parameter, which in our case will be the id of the post.
+parameter, which in our case will be the id of the article.
As we did before, we need to add the `show` action in
-`app/controllers/posts_controller.rb` and its respective view.
+`app/controllers/articles_controller.rb` and its respective view.
```ruby
def show
- @post = Post.find(params[:id])
+ @article = Article.find(params[:id])
end
```
-A couple of things to note. We use `Post.find` to find the post we're
+A couple of things to note. We use `Article.find` to find the article we're
interested in, passing in `params[:id]` to get the `:id` parameter from the
request. We also use an instance variable (prefixed by `@`) to hold a
-reference to the post object. We do this because Rails will pass all instance
+reference to the article object. We do this because Rails will pass all instance
variables to the view.
-Now, create a new file `app/views/posts/show.html.erb` with the following
+Now, create a new file `app/views/articles/show.html.erb` with the following
content:
```html+erb
<p>
<strong>Title:</strong>
- <%= @post.title %>
+ <%= @article.title %>
</p>
<p>
<strong>Text:</strong>
- <%= @post.text %>
+ <%= @article.text %>
</p>
```
-With this change, you should finally be able to create new posts.
-Visit <http://localhost:3000/posts/new> and give it a try!
+With this change, you should finally be able to create new articles.
+Visit <http://localhost:3000/articles/new> and give it a try!
-![Show action for posts](images/getting_started/show_action_for_posts.png)
+![Show action for articles](images/getting_started/show_action_for_articles.png)
-### Listing all posts
+### Listing all articles
-We still need a way to list all our posts, so let's do that.
+We still need a way to list all our articles, so let's do that.
The route for this as per output of `rake routes` is:
```
-posts GET /posts(.:format) posts#index
+articles GET /articles(.:format) articles#index
```
-Add the corresponding `index` action for that route inside the `PostsController` in the `app/controllers/posts_controller.rb` file:
+Add the corresponding `index` action for that route inside the
+`ArticlesController` in the `app/controllers/articles_controller.rb` file:
```ruby
def index
- @posts = Post.all
+ @articles = Article.all
end
```
-And then finally, add view for this action, located at `app/views/posts/index.html.erb`:
+And then finally, add view for this action, located at
+`app/views/articles/index.html.erb`:
```html+erb
-<h1>Listing posts</h1>
+<h1>Listing articles</h1>
<table>
<tr>
@@ -830,70 +858,71 @@ And then finally, add view for this action, located at `app/views/posts/index.ht
<th>Text</th>
</tr>
- <% @posts.each do |post| %>
+ <% @articles.each do |article| %>
<tr>
- <td><%= post.title %></td>
- <td><%= post.text %></td>
+ <td><%= article.title %></td>
+ <td><%= article.text %></td>
</tr>
<% end %>
</table>
```
-Now if you go to `http://localhost:3000/posts` you will see a list of all the
-posts that you have created.
+Now if you go to `http://localhost:3000/articles` you will see a list of all the
+articles that you have created.
### Adding links
-You can now create, show, and list posts. Now let's add some links to
+You can now create, show, and list articles. Now let's add some links to
navigate through pages.
Open `app/views/welcome/index.html.erb` and modify it as follows:
```html+erb
<h1>Hello, Rails!</h1>
-<%= link_to 'My Blog', controller: 'posts' %>
+<%= link_to 'My Blog', controller: 'articles' %>
```
The `link_to` method is one of Rails' built-in view helpers. It creates a
hyperlink based on text to display and where to go - in this case, to the path
-for posts.
+for articles.
-Let's add links to the other views as well, starting with adding this "New Post"
-link to `app/views/posts/index.html.erb`, placing it above the `<table>` tag:
+Let's add links to the other views as well, starting with adding this
+"New Article" link to `app/views/articles/index.html.erb`, placing it above the
+`<table>` tag:
```erb
-<%= link_to 'New post', new_post_path %>
+<%= link_to 'New article', new_article_path %>
```
-This link will allow you to bring up the form that lets you create a new post.
-You should also add a link to this template - `app/views/posts/new.html.erb` -
-to go back to the `index` action. Do this by adding this underneath the form in
-this template:
+This link will allow you to bring up the form that lets you create a new article.
+
+Also add a link in `app/views/articles/new.html.erb`, underneath the form, to
+go back to the `index` action:
```erb
-<%= form_for :post do |f| %>
+<%= form_for :article do |f| %>
...
<% end %>
-<%= link_to 'Back', posts_path %>
+<%= link_to 'Back', articles_path %>
```
-Finally, add another link to the `app/views/posts/show.html.erb` template to go
-back to the `index` action as well, so that people who are viewing a single post
-can go back and view the whole list again:
+Finally, add another link to the `app/views/articles/show.html.erb` template to
+go back to the `index` action as well, so that people who are viewing a single
+article can go back and view the whole list again:
```html+erb
<p>
<strong>Title:</strong>
- <%= @post.title %>
+ <%= @article.title %>
</p>
<p>
<strong>Text:</strong>
- <%= @post.text %>
+ <%= @article.text %>
</p>
-<%= link_to 'Back', posts_path %>
+<%= link_to 'Back', articles_path %>
```
TIP: If you want to link to an action in the same controller, you don't
@@ -906,87 +935,88 @@ and restart the web server when a change is made.
### Adding Some Validation
-The model file, `app/models/post.rb` is about as simple as it can get:
+The model file, `app/models/article.rb` is about as simple as it can get:
```ruby
-class Post < ActiveRecord::Base
+class Article < ActiveRecord::Base
end
```
-There isn't much to this file - but note that the `Post` class inherits from
+There isn't much to this file - but note that the `Article` class inherits from
`ActiveRecord::Base`. Active Record supplies a great deal of functionality to
your Rails models for free, including basic database CRUD (Create, Read, Update,
Destroy) operations, data validation, as well as sophisticated search support
and the ability to relate multiple models to one another.
Rails includes methods to help you validate the data that you send to models.
-Open the `app/models/post.rb` file and edit it:
+Open the `app/models/article.rb` file and edit it:
```ruby
-class Post < ActiveRecord::Base
+class Article < ActiveRecord::Base
validates :title, presence: true,
length: { minimum: 5 }
end
```
-These changes will ensure that all posts have a title that is at least five
+These changes will ensure that all articles have a title that is at least five
characters long. Rails can validate a variety of conditions in a model,
including the presence or uniqueness of columns, their format, and the
existence of associated objects. Validations are covered in detail in [Active
Record Validations](active_record_validations.html)
-With the validation now in place, when you call `@post.save` on an invalid
-post, it will return `false`. If you open `app/controllers/posts_controller.rb`
-again, you'll notice that we don't check the result of calling `@post.save`
-inside the `create` action. If `@post.save` fails in this situation, we need to
-show the form back to the user. To do this, change the `new` and `create`
-actions inside `app/controllers/posts_controller.rb` to these:
+With the validation now in place, when you call `@article.save` on an invalid
+article, it will return `false`. If you open
+`app/controllers/articles_controller.rb` again, you'll notice that we don't
+check the result of calling `@article.save` inside the `create` action.
+If `@article.save` fails in this situation, we need to show the form back to the
+user. To do this, change the `new` and `create` actions inside
+`app/controllers/articles_controller.rb` to these:
```ruby
def new
- @post = Post.new
+ @article = Article.new
end
def create
- @post = Post.new(post_params)
+ @article = Article.new(article_params)
- if @post.save
- redirect_to @post
+ if @article.save
+ redirect_to @article
else
render 'new'
end
end
private
- def post_params
- params.require(:post).permit(:title, :text)
+ def article_params
+ params.require(:article).permit(:title, :text)
end
```
-The `new` action is now creating a new instance variable called `@post`, and
+The `new` action is now creating a new instance variable called `@article`, and
you'll see why that is in just a few moments.
Notice that inside the `create` action we use `render` instead of `redirect_to`
-when `save` returns `false`. The `render` method is used so that the `@post`
+when `save` returns `false`. The `render` method is used so that the `@article`
object is passed back to the `new` template when it is rendered. This rendering
-is done within the same request as the form submission, whereas the `redirect_to`
-will tell the browser to issue another request.
+is done within the same request as the form submission, whereas the
+`redirect_to` will tell the browser to issue another request.
If you reload
-<http://localhost:3000/posts/new> and
-try to save a post without a title, Rails will send you back to the
+<http://localhost:3000/articles/new> and
+try to save an article without a title, Rails will send you back to the
form, but that's not very useful. You need to tell the user that
something went wrong. To do that, you'll modify
-`app/views/posts/new.html.erb` to check for error messages:
+`app/views/articles/new.html.erb` to check for error messages:
```html+erb
-<%= form_for :post, url: posts_path do |f| %>
- <% if @post.errors.any? %>
+<%= form_for :article, url: articles_path do |f| %>
+ <% if @article.errors.any? %>
<div id="error_explanation">
- <h2><%= pluralize(@post.errors.count, "error") %> prohibited
- this post from being saved:</h2>
+ <h2><%= pluralize(@article.errors.count, "error") %> prohibited
+ this article from being saved:</h2>
<ul>
- <% @post.errors.full_messages.each do |msg| %>
+ <% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
@@ -1007,57 +1037,58 @@ something went wrong. To do that, you'll modify
</p>
<% end %>
-<%= link_to 'Back', posts_path %>
+<%= link_to 'Back', articles_path %>
```
A few things are going on. We check if there are any errors with
-`@post.errors.any?`, and in that case we show a list of all
-errors with `@post.errors.full_messages`.
+`@article.errors.any?`, and in that case we show a list of all
+errors with `@article.errors.full_messages`.
`pluralize` is a rails helper that takes a number and a string as its
arguments. If the number is greater than one, the string will be automatically
pluralized.
-The reason why we added `@post = Post.new` in the `PostsController` is that
-otherwise `@post` would be `nil` in our view, and calling
-`@post.errors.any?` would throw an error.
+The reason why we added `@article = Article.new` in the `ArticlesController` is
+that otherwise `@article` would be `nil` in our view, and calling
+`@article.errors.any?` would throw an error.
TIP: Rails automatically wraps fields that contain an error with a div
with class `field_with_errors`. You can define a css rule to make them
standout.
-Now you'll get a nice error message when saving a post without title when you
-attempt to do just that on the new post form [(http://localhost:3000/posts/new)](http://localhost:3000/posts/new).
+Now you'll get a nice error message when saving an article without title when
+you attempt to do just that on the new article form
+[(http://localhost:3000/articles/new)](http://localhost:3000/articles/new).
![Form With Errors](images/getting_started/form_with_errors.png)
-### Updating Posts
+### Updating Articles
We've covered the "CR" part of CRUD. Now let's focus on the "U" part, updating
-posts.
+articles.
-The first step we'll take is adding an `edit` action to the `PostsController`.
+The first step we'll take is adding an `edit` action to the `ArticlesController`.
```ruby
def edit
- @post = Post.find(params[:id])
+ @article = Article.find(params[:id])
end
```
The view will contain a form similar to the one we used when creating
-new posts. Create a file called `app/views/posts/edit.html.erb` and make
+new articles. Create a file called `app/views/articles/edit.html.erb` and make
it look as follows:
```html+erb
-<h1>Editing post</h1>
+<h1>Editing article</h1>
-<%= form_for :post, url: post_path(@post), method: :patch do |f| %>
- <% if @post.errors.any? %>
+<%= form_for :article, url: article_path(@article), method: :patch do |f| %>
+ <% if @article.errors.any? %>
<div id="error_explanation">
- <h2><%= pluralize(@post.errors.count, "error") %> prohibited
- this post from being saved:</h2>
+ <h2><%= pluralize(@article.errors.count, "error") %> prohibited
+ this article from being saved:</h2>
<ul>
- <% @post.errors.full_messages.each do |msg| %>
+ <% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
@@ -1078,7 +1109,7 @@ it look as follows:
</p>
<% end %>
-<%= link_to 'Back', posts_path %>
+<%= link_to 'Back', articles_path %>
```
This time we point the form to the `update` action, which is not defined yet
@@ -1088,42 +1119,48 @@ The `method: :patch` option tells Rails that we want this form to be submitted
via the `PATCH` HTTP method which is the HTTP method you're expected to use to
**update** resources according to the REST protocol.
-TIP: By default forms built with the _form_for_ helper are sent via `POST`.
+The first parameter of the `form_tag` can be an object, say, `@article` which would
+cause the helper to fill in the form with the fields of the object. Passing in a
+symbol (`:article`) with the same name as the instance variable (`@article`) also
+automagically leads to the same behavior. This is what is happening here. More details
+can be found in [form_for documentation](http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for).
-Next we need to create the `update` action in `app/controllers/posts_controller.rb`:
+Next we need to create the `update` action in
+`app/controllers/articles_controller.rb`:
```ruby
def update
- @post = Post.find(params[:id])
+ @article = Article.find(params[:id])
- if @post.update(post_params)
- redirect_to @post
+ if @article.update(article_params)
+ redirect_to @article
else
render 'edit'
end
end
private
- def post_params
- params.require(:post).permit(:title, :text)
+ def article_params
+ params.require(:article).permit(:title, :text)
end
```
The new method, `update`, is used when you want to update a record
that already exists, and it accepts a hash containing the attributes
that you want to update. As before, if there was an error updating the
-post we want to show the form back to the user.
+article we want to show the form back to the user.
-We reuse the `post_params` method that we defined earlier for the create action.
+We reuse the `article_params` method that we defined earlier for the create
+action.
TIP: You don't need to pass all attributes to `update`. For
-example, if you'd call `@post.update(title: 'A new title')`
+example, if you'd call `@article.update(title: 'A new title')`
Rails would only update the `title` attribute, leaving all other
attributes untouched.
Finally, we want to show a link to the `edit` action in the list of all the
-posts, so let's add that now to `app/views/posts/index.html.erb` to make it
-appear next to the "Show" link:
+articles, so let's add that now to `app/views/articles/index.html.erb` to make
+it appear next to the "Show" link:
```html+erb
<table>
@@ -1133,26 +1170,26 @@ appear next to the "Show" link:
<th colspan="2"></th>
</tr>
-<% @posts.each do |post| %>
+<% @articles.each do |article| %>
<tr>
- <td><%= post.title %></td>
- <td><%= post.text %></td>
- <td><%= link_to 'Show', post_path(post) %></td>
- <td><%= link_to 'Edit', edit_post_path(post) %></td>
+ <td><%= article.title %></td>
+ <td><%= article.text %></td>
+ <td><%= link_to 'Show', article_path(article) %></td>
+ <td><%= link_to 'Edit', edit_article_path(article) %></td>
</tr>
<% end %>
</table>
```
-And we'll also add one to the `app/views/posts/show.html.erb` template as well,
-so that there's also an "Edit" link on a post's page. Add this at the bottom of
-the template:
+And we'll also add one to the `app/views/articles/show.html.erb` template as
+well, so that there's also an "Edit" link on an article's page. Add this at the
+bottom of the template:
```html+erb
...
-<%= link_to 'Back', posts_path %>
-| <%= link_to 'Edit', edit_post_path(@post) %>
+<%= link_to 'Back', articles_path %>
+| <%= link_to 'Edit', edit_article_path(@article) %>
```
And here's how our app looks so far:
@@ -1169,17 +1206,17 @@ underscore.
TIP: You can read more about partials in the
[Layouts and Rendering in Rails](layouts_and_rendering.html) guide.
-Create a new file `app/views/posts/_form.html.erb` with the following
+Create a new file `app/views/articles/_form.html.erb` with the following
content:
```html+erb
-<%= form_for @post do |f| %>
- <% if @post.errors.any? %>
+<%= form_for @article do |f| %>
+ <% if @article.errors.any? %>
<div id="error_explanation">
- <h2><%= pluralize(@post.errors.count, "error") %> prohibited
- this post from being saved:</h2>
+ <h2><%= pluralize(@article.errors.count, "error") %> prohibited
+ this article from being saved:</h2>
<ul>
- <% @post.errors.full_messages.each do |msg| %>
+ <% @article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
@@ -1203,41 +1240,41 @@ content:
Everything except for the `form_for` declaration remained the same.
The reason we can use this shorter, simpler `form_for` declaration
-to stand in for either of the other forms is that `@post` is a *resource*
+to stand in for either of the other forms is that `@article` is a *resource*
corresponding to a full set of RESTful routes, and Rails is able to infer
which URI and method to use.
For more information about this use of `form_for`, see
[Resource-oriented style](//api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for-label-Resource-oriented+style).
-Now, let's update the `app/views/posts/new.html.erb` view to use this new
+Now, let's update the `app/views/articles/new.html.erb` view to use this new
partial, rewriting it completely:
```html+erb
-<h1>New post</h1>
+<h1>New article</h1>
<%= render 'form' %>
-<%= link_to 'Back', posts_path %>
+<%= link_to 'Back', articles_path %>
```
-Then do the same for the `app/views/posts/edit.html.erb` view:
+Then do the same for the `app/views/articles/edit.html.erb` view:
```html+erb
-<h1>Edit post</h1>
+<h1>Edit article</h1>
<%= render 'form' %>
-<%= link_to 'Back', posts_path %>
+<%= link_to 'Back', articles_path %>
```
-### Deleting Posts
+### Deleting Articles
-We're now ready to cover the "D" part of CRUD, deleting posts from the
+We're now ready to cover the "D" part of CRUD, deleting articles from the
database. Following the REST convention, the route for
-deleting posts as per output of `rake routes` is:
+deleting articles as per output of `rake routes` is:
```ruby
-DELETE /posts/:id(.:format) posts#destroy
+DELETE /articles/:id(.:format) articles#destroy
```
The `delete` routing method should be used for routes that destroy
@@ -1245,19 +1282,19 @@ resources. If this was left as a typical `get` route, it could be possible for
people to craft malicious URLs like this:
```html
-<a href='http://example.com/posts/1/destroy'>look at this cat!</a>
+<a href='http://example.com/articles/1/destroy'>look at this cat!</a>
```
We use the `delete` method for destroying resources, and this route is mapped to
-the `destroy` action inside `app/controllers/posts_controller.rb`, which doesn't
-exist yet, but is provided below:
+the `destroy` action inside `app/controllers/articles_controller.rb`, which
+doesn't exist yet, but is provided below:
```ruby
def destroy
- @post = Post.find(params[:id])
- @post.destroy
+ @article = Article.find(params[:id])
+ @article.destroy
- redirect_to posts_path
+ redirect_to articles_path
end
```
@@ -1266,12 +1303,12 @@ them from the database. Note that we don't need to add a view for this
action since we're redirecting to the `index` action.
Finally, add a 'Destroy' link to your `index` action template
-(`app/views/posts/index.html.erb`) to wrap everything
+(`app/views/articles/index.html.erb`) to wrap everything
together.
```html+erb
-<h1>Listing Posts</h1>
-<%= link_to 'New post', new_post_path %>
+<h1>Listing Articles</h1>
+<%= link_to 'New article', new_article_path %>
<table>
<tr>
<th>Title</th>
@@ -1279,13 +1316,13 @@ together.
<th colspan="3"></th>
</tr>
-<% @posts.each do |post| %>
+<% @articles.each do |article| %>
<tr>
- <td><%= post.title %></td>
- <td><%= post.text %></td>
- <td><%= link_to 'Show', post_path(post) %></td>
- <td><%= link_to 'Edit', edit_post_path(post) %></td>
- <td><%= link_to 'Destroy', post_path(post),
+ <td><%= article.title %></td>
+ <td><%= article.text %></td>
+ <td><%= link_to 'Show', article_path(article) %></td>
+ <td><%= link_to 'Edit', edit_article_path(article) %></td>
+ <td><%= link_to 'Destroy', article_path(article),
method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
@@ -1304,7 +1341,7 @@ Without this file, the confirmation dialog box wouldn't appear.
![Confirm Dialog](images/getting_started/confirm_dialog.png)
Congratulations, you can now create, show, list, update and destroy
-posts.
+articles.
TIP: In general, Rails encourages the use of resources objects in place
of declaring routes manually.
@@ -1315,23 +1352,23 @@ Adding a Second Model
---------------------
It's time to add a second model to the application. The second model will handle
-comments on posts.
+comments on articles.
### Generating a Model
We're going to see the same generator that we used before when creating
-the `Post` model. This time we'll create a `Comment` model to hold
-reference of post comments. Run this command in your terminal:
+the `Article` model. This time we'll create a `Comment` model to hold
+reference of article comments. Run this command in your terminal:
```bash
-$ rails generate model Comment commenter:string body:text post:references
+$ rails generate model Comment commenter:string body:text article:references
```
This command will generate four files:
| File | Purpose |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
-| db/migrate/20100207235629_create_comments.rb | Migration to create the comments table in your database (your name will include a different timestamp) |
+| db/migrate/20140120201010_create_comments.rb | Migration to create the comments table in your database (your name will include a different timestamp) |
| app/models/comment.rb | The Comment model |
| test/models/comment_test.rb | Testing harness for the comments model |
| test/fixtures/comments.yml | Sample comments for use in testing |
@@ -1340,12 +1377,12 @@ First, take a look at `app/models/comment.rb`:
```ruby
class Comment < ActiveRecord::Base
- belongs_to :post
+ belongs_to :article
end
```
-This is very similar to the `Post` model that you saw earlier. The difference
-is the line `belongs_to :post`, which sets up an Active Record _association_.
+This is very similar to the `Article` model that you saw earlier. The difference
+is the line `belongs_to :article`, which sets up an Active Record _association_.
You'll learn a little about associations in the next section of this guide.
In addition to the model, Rails has also made a migration to create the
@@ -1357,7 +1394,9 @@ class CreateComments < ActiveRecord::Migration
create_table :comments do |t|
t.string :commenter
t.text :body
- t.references :post, index: true
+
+ # this line adds an integer column called `article_id`.
+ t.references :article, index: true
t.timestamps
end
@@ -1386,26 +1425,27 @@ run against the current database, so in this case you will just see:
### Associating Models
Active Record associations let you easily declare the relationship between two
-models. In the case of comments and posts, you could write out the relationships
-this way:
+models. In the case of comments and articles, you could write out the
+relationships this way:
-* Each comment belongs to one post.
-* One post can have many comments.
+* Each comment belongs to one article.
+* One article can have many comments.
In fact, this is very close to the syntax that Rails uses to declare this
association. You've already seen the line of code inside the `Comment` model
-(app/models/comment.rb) that makes each comment belong to a Post:
+(app/models/comment.rb) that makes each comment belong to an Article:
```ruby
class Comment < ActiveRecord::Base
- belongs_to :post
+ belongs_to :article
end
```
-You'll need to edit `app/models/post.rb` to add the other side of the association:
+You'll need to edit `app/models/article.rb` to add the other side of the
+association:
```ruby
-class Post < ActiveRecord::Base
+class Article < ActiveRecord::Base
has_many :comments
validates :title, presence: true,
length: { minimum: 5 }
@@ -1413,29 +1453,31 @@ end
```
These two declarations enable a good bit of automatic behavior. For example, if
-you have an instance variable `@post` containing a post, you can retrieve all
-the comments belonging to that post as an array using `@post.comments`.
+you have an instance variable `@article` containing an article, you can retrieve
+all the comments belonging to that article as an array using
+`@article.comments`.
TIP: For more information on Active Record associations, see the [Active Record
Associations](association_basics.html) guide.
### Adding a Route for Comments
-As with the `welcome` controller, we will need to add a route so that Rails knows
-where we would like to navigate to see `comments`. Open up the
+As with the `welcome` controller, we will need to add a route so that Rails
+knows where we would like to navigate to see `comments`. Open up the
`config/routes.rb` file again, and edit it as follows:
```ruby
-resources :posts do
+resources :articles do
resources :comments
end
```
-This creates `comments` as a _nested resource_ within `posts`. This is another
-part of capturing the hierarchical relationship that exists between posts and
-comments.
+This creates `comments` as a _nested resource_ within `articles`. This is
+another part of capturing the hierarchical relationship that exists between
+articles and comments.
-TIP: For more information on routing, see the [Rails Routing](routing.html) guide.
+TIP: For more information on routing, see the [Rails Routing](routing.html)
+guide.
### Generating a Controller
@@ -1459,27 +1501,27 @@ This creates six files and one empty directory:
| app/assets/stylesheets/comment.css.scss | Cascading style sheet for the controller |
Like with any blog, our readers will create their comments directly after
-reading the post, and once they have added their comment, will be sent back to
-the post show page to see their comment now listed. Due to this, our
+reading the article, and once they have added their comment, will be sent back
+to the article show page to see their comment now listed. Due to this, our
`CommentsController` is there to provide a method to create comments and delete
spam comments when they arrive.
-So first, we'll wire up the Post show template
-(`app/views/posts/show.html.erb`) to let us make a new comment:
+So first, we'll wire up the Article show template
+(`app/views/articles/show.html.erb`) to let us make a new comment:
```html+erb
<p>
<strong>Title:</strong>
- <%= @post.title %>
+ <%= @article.title %>
</p>
<p>
<strong>Text:</strong>
- <%= @post.text %>
+ <%= @article.text %>
</p>
<h2>Add a comment:</h2>
-<%= form_for([@post, @post.comments.build]) do |f| %>
+<%= form_for([@article, @article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
@@ -1493,22 +1535,22 @@ So first, we'll wire up the Post show template
</p>
<% end %>
-<%= link_to 'Back', posts_path %>
-| <%= link_to 'Edit', edit_post_path(@post) %>
+<%= link_to 'Back', articles_path %>
+| <%= link_to 'Edit', edit_article_path(@article) %>
```
-This adds a form on the `Post` show page that creates a new comment by
+This adds a form on the `Article` show page that creates a new comment by
calling the `CommentsController` `create` action. The `form_for` call here uses
-an array, which will build a nested route, such as `/posts/1/comments`.
+an array, which will build a nested route, such as `/articles/1/comments`.
Let's wire up the `create` in `app/controllers/comments_controller.rb`:
```ruby
class CommentsController < ApplicationController
def create
- @post = Post.find(params[:post_id])
- @comment = @post.comments.create(comment_params)
- redirect_to post_path(@post)
+ @article = Article.find(params[:article_id])
+ @comment = @article.comments.create(comment_params)
+ redirect_to article_path(@article)
end
private
@@ -1518,35 +1560,36 @@ class CommentsController < ApplicationController
end
```
-You'll see a bit more complexity here than you did in the controller for posts.
-That's a side-effect of the nesting that you've set up. Each request for a
-comment has to keep track of the post to which the comment is attached, thus the
-initial call to the `find` method of the `Post` model to get the post in question.
+You'll see a bit more complexity here than you did in the controller for
+articles. That's a side-effect of the nesting that you've set up. Each request
+for a comment has to keep track of the article to which the comment is attached,
+thus the initial call to the `find` method of the `Article` model to get the
+article in question.
In addition, the code takes advantage of some of the methods available for an
-association. We use the `create` method on `@post.comments` to create and save
-the comment. This will automatically link the comment so that it belongs to that
-particular post.
+association. We use the `create` method on `@article.comments` to create and
+save the comment. This will automatically link the comment so that it belongs to
+that particular article.
-Once we have made the new comment, we send the user back to the original post
-using the `post_path(@post)` helper. As we have already seen, this calls the
-`show` action of the `PostsController` which in turn renders the `show.html.erb`
-template. This is where we want the comment to show, so let's add that to the
-`app/views/posts/show.html.erb`.
+Once we have made the new comment, we send the user back to the original article
+using the `article_path(@article)` helper. As we have already seen, this calls
+the `show` action of the `ArticlesController` which in turn renders the
+`show.html.erb` template. This is where we want the comment to show, so let's
+add that to the `app/views/articles/show.html.erb`.
```html+erb
<p>
<strong>Title:</strong>
- <%= @post.title %>
+ <%= @article.title %>
</p>
<p>
<strong>Text:</strong>
- <%= @post.text %>
+ <%= @article.text %>
</p>
<h2>Comments</h2>
-<% @post.comments.each do |comment| %>
+<% @article.comments.each do |comment| %>
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
@@ -1559,7 +1602,7 @@ template. This is where we want the comment to show, so let's add that to the
<% end %>
<h2>Add a comment:</h2>
-<%= form_for([@post, @post.comments.build]) do |f| %>
+<%= form_for([@article, @article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
@@ -1573,26 +1616,26 @@ template. This is where we want the comment to show, so let's add that to the
</p>
<% end %>
-<%= link_to 'Edit Post', edit_post_path(@post) %> |
-<%= link_to 'Back to Posts', posts_path %>
+<%= link_to 'Edit Article', edit_article_path(@article) %> |
+<%= link_to 'Back to Articles', articles_path %>
```
-Now you can add posts and comments to your blog and have them show up in the
+Now you can add articles and comments to your blog and have them show up in the
right places.
-![Post with Comments](images/getting_started/post_with_comments.png)
+![Article with Comments](images/getting_started/article_with_comments.png)
Refactoring
-----------
-Now that we have posts and comments working, take a look at the
-`app/views/posts/show.html.erb` template. It is getting long and awkward. We can
-use partials to clean it up.
+Now that we have articles and comments working, take a look at the
+`app/views/articles/show.html.erb` template. It is getting long and awkward. We
+can use partials to clean it up.
### Rendering Partial Collections
-First, we will make a comment partial to extract showing all the comments for the
-post. Create the file `app/views/comments/_comment.html.erb` and put the
+First, we will make a comment partial to extract showing all the comments for
+the article. Create the file `app/views/comments/_comment.html.erb` and put the
following into it:
```html+erb
@@ -1607,25 +1650,25 @@ following into it:
</p>
```
-Then you can change `app/views/posts/show.html.erb` to look like the
+Then you can change `app/views/articles/show.html.erb` to look like the
following:
```html+erb
<p>
<strong>Title:</strong>
- <%= @post.title %>
+ <%= @article.title %>
</p>
<p>
<strong>Text:</strong>
- <%= @post.text %>
+ <%= @article.text %>
</p>
<h2>Comments</h2>
-<%= render @post.comments %>
+<%= render @article.comments %>
<h2>Add a comment:</h2>
-<%= form_for([@post, @post.comments.build]) do |f| %>
+<%= form_for([@article, @article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
@@ -1639,13 +1682,13 @@ following:
</p>
<% end %>
-<%= link_to 'Edit Post', edit_post_path(@post) %> |
-<%= link_to 'Back to Posts', posts_path %>
+<%= link_to 'Edit Article', edit_article_path(@article) %> |
+<%= link_to 'Back to Articles', articles_path %>
```
This will now render the partial in `app/views/comments/_comment.html.erb` once
-for each comment that is in the `@post.comments` collection. As the `render`
-method iterates over the `@post.comments` collection, it assigns each
+for each comment that is in the `@article.comments` collection. As the `render`
+method iterates over the `@article.comments` collection, it assigns each
comment to a local variable named the same as the partial, in this case
`comment` which is then available in the partial for us to show.
@@ -1655,7 +1698,7 @@ Let us also move that new comment section out to its own partial. Again, you
create a file `app/views/comments/_form.html.erb` containing:
```html+erb
-<%= form_for([@post, @post.comments.build]) do |f| %>
+<%= form_for([@article, @article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
@@ -1670,27 +1713,27 @@ create a file `app/views/comments/_form.html.erb` containing:
<% end %>
```
-Then you make the `app/views/posts/show.html.erb` look like the following:
+Then you make the `app/views/articles/show.html.erb` look like the following:
```html+erb
<p>
<strong>Title:</strong>
- <%= @post.title %>
+ <%= @article.title %>
</p>
<p>
<strong>Text:</strong>
- <%= @post.text %>
+ <%= @article.text %>
</p>
<h2>Comments</h2>
-<%= render @post.comments %>
+<%= render @article.comments %>
<h2>Add a comment:</h2>
<%= render "comments/form" %>
-<%= link_to 'Edit Post', edit_post_path(@post) %> |
-<%= link_to 'Back to Posts', posts_path %>
+<%= link_to 'Edit Article', edit_article_path(@article) %> |
+<%= link_to 'Back to Articles', articles_path %>
```
The second render just defines the partial template we want to render,
@@ -1698,8 +1741,8 @@ The second render just defines the partial template we want to render,
string and realize that you want to render the `_form.html.erb` file in
the `app/views/comments` directory.
-The `@post` object is available to any partials rendered in the view because we
-defined it as an instance variable.
+The `@article` object is available to any partials rendered in the view because
+we defined it as an instance variable.
Deleting Comments
-----------------
@@ -1723,30 +1766,30 @@ So first, let's add the delete link in the
</p>
<p>
- <%= link_to 'Destroy Comment', [comment.post, comment],
+ <%= link_to 'Destroy Comment', [comment.article, comment],
method: :delete,
data: { confirm: 'Are you sure?' } %>
</p>
```
Clicking this new "Destroy Comment" link will fire off a `DELETE
-/posts/:post_id/comments/:id` to our `CommentsController`, which can then use
-this to find the comment we want to delete, so let's add a `destroy` action to our
-controller (`app/controllers/comments_controller.rb`):
+/articles/:article_id/comments/:id` to our `CommentsController`, which can then
+use this to find the comment we want to delete, so let's add a `destroy` action
+to our controller (`app/controllers/comments_controller.rb`):
```ruby
class CommentsController < ApplicationController
def create
- @post = Post.find(params[:post_id])
- @comment = @post.comments.create(comment_params)
- redirect_to post_path(@post)
+ @article = Article.find(params[:article_id])
+ @comment = @article.comments.create(comment_params)
+ redirect_to article_path(@article)
end
def destroy
- @post = Post.find(params[:post_id])
- @comment = @post.comments.find(params[:id])
+ @article = Article.find(params[:article_id])
+ @comment = @article.comments.find(params[:id])
@comment.destroy
- redirect_to post_path(@post)
+ redirect_to article_path(@article)
end
private
@@ -1756,20 +1799,20 @@ class CommentsController < ApplicationController
end
```
-The `destroy` action will find the post we are looking at, locate the comment
-within the `@post.comments` collection, and then remove it from the
-database and send us back to the show action for the post.
+The `destroy` action will find the article we are looking at, locate the comment
+within the `@article.comments` collection, and then remove it from the
+database and send us back to the show action for the article.
### Deleting Associated Objects
-If you delete a post then its associated comments will also need to be deleted.
-Otherwise they would simply occupy space in the database. Rails allows you to
-use the `dependent` option of an association to achieve this. Modify the Post
-model, `app/models/post.rb`, as follows:
+If you delete an article then its associated comments will also need to be
+deleted. Otherwise they would simply occupy space in the database. Rails allows
+you to use the `dependent` option of an association to achieve this. Modify the
+Article model, `app/models/article.rb`, as follows:
```ruby
-class Post < ActiveRecord::Base
+class Article < ActiveRecord::Base
has_many :comments, dependent: :destroy
validates :title, presence: true,
length: { minimum: 5 }
@@ -1782,33 +1825,34 @@ Security
### Basic Authentication
If you were to publish your blog online, anybody would be able to add, edit and
-delete posts or delete comments.
+delete articles or delete comments.
Rails provides a very simple HTTP authentication system that will work nicely in
this situation.
-In the `PostsController` we need to have a way to block access to the various
+In the `ArticlesController` we need to have a way to block access to the various
actions if the person is not authenticated, here we can use the Rails
`http_basic_authenticate_with` method, allowing access to the requested
action if that method allows it.
To use the authentication system, we specify it at the top of our
-`PostsController`, in this case, we want the user to be authenticated on every
-action, except for `index` and `show`, so we write that in `app/controllers/posts_controller.rb`:
+`ArticlesController`, in this case, we want the user to be authenticated on
+every action, except for `index` and `show`, so we write that in
+`app/controllers/articles_controller.rb`:
```ruby
-class PostsController < ApplicationController
+class ArticlesController < ApplicationController
http_basic_authenticate_with name: "dhh", password: "secret", except: [:index, :show]
def index
- @posts = Post.all
+ @articles = Article.all
end
# snipped for brevity
```
-We also only want to allow authenticated users to delete comments, so in the
+We also want to allow only authenticated users to delete comments, so in the
`CommentsController` (`app/controllers/comments_controller.rb`) we write:
```ruby
@@ -1817,21 +1861,22 @@ class CommentsController < ApplicationController
http_basic_authenticate_with name: "dhh", password: "secret", only: :destroy
def create
- @post = Post.find(params[:post_id])
+ @article = Article.find(params[:article_id])
...
end
# snipped for brevity
```
-Now if you try to create a new post, you will be greeted with a basic HTTP
+Now if you try to create a new article, you will be greeted with a basic HTTP
Authentication challenge
![Basic HTTP Authentication Challenge](images/getting_started/challenge.png)
Other authentication methods are available for Rails applications. Two popular
-authentication add-ons for Rails are the [Devise](https://github.com/plataformatec/devise)
-rails engine and the [Authlogic](https://github.com/binarylogic/authlogic) gem,
+authentication add-ons for Rails are the
+[Devise](https://github.com/plataformatec/devise) rails engine and
+the [Authlogic](https://github.com/binarylogic/authlogic) gem,
along with a number of others.
@@ -1887,15 +1932,16 @@ cannot be automatically detected by Rails and corrected.
Two very common sources of data that are not UTF-8:
-* Your text editor: Most text editors (such as TextMate), default to saving files as
- UTF-8. If your text editor does not, this can result in special characters that you
- enter in your templates (such as é) to appear as a diamond with a question mark inside
- in the browser. This also applies to your i18n translation files.
- Most editors that do not already default to UTF-8 (such as some versions of
- Dreamweaver) offer a way to change the default to UTF-8. Do so.
-* Your database: Rails defaults to converting data from your database into UTF-8 at
- the boundary. However, if your database is not using UTF-8 internally, it may not
- be able to store all characters that your users enter. For instance, if your database
- is using Latin-1 internally, and your user enters a Russian, Hebrew, or Japanese
- character, the data will be lost forever once it enters the database. If possible,
- use UTF-8 as the internal storage of your database.
+* Your text editor: Most text editors (such as TextMate), default to saving
+ files as UTF-8. If your text editor does not, this can result in special
+ characters that you enter in your templates (such as é) to appear as a diamond
+ with a question mark inside in the browser. This also applies to your i18n
+ translation files. Most editors that do not already default to UTF-8 (such as
+ some versions of Dreamweaver) offer a way to change the default to UTF-8. Do
+ so.
+* Your database: Rails defaults to converting data from your database into UTF-8
+ at the boundary. However, if your database is not using UTF-8 internally, it
+ may not be able to store all characters that your users enter. For instance,
+ if your database is using Latin-1 internally, and your user enters a Russian,
+ Hebrew, or Japanese character, the data will be lost forever once it enters
+ the database. If possible, use UTF-8 as the internal storage of your database.
diff --git a/guides/source/i18n.md b/guides/source/i18n.md
index 8dfb17a681..d72717fa3b 100644
--- a/guides/source/i18n.md
+++ b/guides/source/i18n.md
@@ -214,7 +214,7 @@ This approach has almost the same set of advantages as setting the locale from t
Getting the locale from `params` and setting it accordingly is not hard; including it in every URL and thus **passing it through the requests** is. To include an explicit option in every URL (e.g. `link_to( books_url(locale: I18n.locale))`) would be tedious and probably impossible, of course.
-Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its [`ApplicationController#default_url_options`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000515, which is useful precisely in this scenario: it enables us to set "defaults" for [`url_for`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000503) and helper methods dependent on it (by implementing/overriding this method).
+Rails contains infrastructure for "centralizing dynamic decisions about the URLs" in its [`ApplicationController#default_url_options`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000515), which is useful precisely in this scenario: it enables us to set "defaults" for [`url_for`](http://api.rubyonrails.org/classes/ActionController/Base.html#M000503) and helper methods dependent on it (by implementing/overriding this method).
We can include something like this in our `ApplicationController` then:
diff --git a/guides/source/initialization.md b/guides/source/initialization.md
index 5e2e0ad3e3..ec3cec5c6f 100644
--- a/guides/source/initialization.md
+++ b/guides/source/initialization.md
@@ -270,7 +270,7 @@ def parse_options(args)
options = default_options
# Don't evaluate CGI ISINDEX parameters.
- # http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
+ # http://www.meb.uni-bonn.de/docs/cgi/cl.html
args.clear if ENV.include?("REQUEST_METHOD")
options.merge! opt_parser.parse! args
@@ -522,7 +522,7 @@ I18n and Rails configuration are all being defined here.
### Back to `config/environment.rb`
The rest of `config/application.rb` defines the configuration for the
-`Rails::Application` which will be used once the application is fully
+`Rails::Application` which will be used once the application is fully
initialized. When `config/application.rb` has finished loading Rails and defined
the application namespace, we go back to `config/environment.rb`,
where the application is initialized. For example, if the application was called
diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md
index c72b584ed6..93e25d619e 100644
--- a/guides/source/layouts_and_rendering.md
+++ b/guides/source/layouts_and_rendering.md
@@ -1119,11 +1119,11 @@ With this change, you can access an instance of the `@products` collection as th
You can also pass in arbitrary local variables to any partial you are rendering with the `locals: {}` option:
```erb
-<%= render partial: "products", collection: @products,
+<%= render partial: "product", collection: @products,
as: :item, locals: {title: "Products Page"} %>
```
-Would render a partial `_products.html.erb` once for each instance of `product` in the `@products` instance variable passing the instance to the partial as a local variable called `item` and to each partial, make the local variable `title` available with the value `Products Page`.
+In this case, the partial will have access to a local variable `title` with the value "Products Page".
TIP: Rails also makes a counter variable available within a partial called by the collection, named after the member of the collection followed by `_counter`. For example, if you're rendering `@products`, within the partial you can refer to `product_counter` to tell you how many times the partial has been rendered. This does not work in conjunction with the `as: :value` option.
diff --git a/guides/source/migrations.md b/guides/source/migrations.md
index 5d5c2724b1..64c4e1e07e 100644
--- a/guides/source/migrations.md
+++ b/guides/source/migrations.md
@@ -642,7 +642,7 @@ method for all the migrations that have not yet been run. If there are
no such migrations, it exits. It will run these migrations in order based
on the date of the migration.
-Note that running the `db:migrate` also invokes the `db:schema:dump` task, which
+Note that running the `db:migrate` task also invokes the `db:schema:dump` task, which
will update your `db/schema.rb` file to match the structure of your database.
If you specify a target version, Active Record will run the required migrations
diff --git a/guides/source/routing.md b/guides/source/routing.md
index 70d4722068..9c495bf09d 100644
--- a/guides/source/routing.md
+++ b/guides/source/routing.md
@@ -631,7 +631,7 @@ This will define a `user_path` method that will be available in controllers, hel
### HTTP Verb Constraints
-In general, you should use the `get`, `post`, `put` and `delete` methods to constrain a route to a particular verb. You can use the `match` method with the `:via` option to match multiple verbs at once:
+In general, you should use the `get`, `post`, `put`, `patch` and `delete` methods to constrain a route to a particular verb. You can use the `match` method with the `:via` option to match multiple verbs at once:
```ruby
match 'photos', to: 'photos#show', via: [:get, :post]
diff --git a/guides/source/security.md b/guides/source/security.md
index cffe7c85f1..ece431dae7 100644
--- a/guides/source/security.md
+++ b/guides/source/security.md
@@ -549,7 +549,7 @@ Injection is very tricky, because the same code or parameter can be malicious in
### Whitelists versus Blacklists
-NOTE: _When sanitizing, protecting or verifying something, whitelists over blacklists._
+NOTE: _When sanitizing, protecting or verifying something, prefer whitelists over blacklists._
A blacklist can be a list of bad e-mail addresses, non-public actions or bad HTML tags. This is opposed to a whitelist which lists the good e-mail addresses, public actions, good HTML tags and so on. Although sometimes it is not possible to create a whitelist (in a SPAM filter, for example), _prefer to use whitelist approaches_:
@@ -915,6 +915,49 @@ Content-Type: text/html
Under certain circumstances this would present the malicious HTML to the victim. However, this only seems to work with Keep-Alive connections (and many browsers are using one-time connections). But you can't rely on this. _In any case this is a serious bug, and you should update your Rails to version 2.0.5 or 2.1.2 to eliminate Header Injection (and thus response splitting) risks._
+Unsafe Query Generation
+-----------------------
+
+Due to the way Active Record interprets parameters in combination with the way
+that Rack parses query parameters it was possible to issue unexpected database
+queries with `IS NULL` where clauses. As a response to that security issue
+([CVE-2012-2660](https://groups.google.com/forum/#!searchin/rubyonrails-security/deep_munge/rubyonrails-security/8SA-M3as7A8/Mr9fi9X4kNgJ),
+[CVE-2012-2694](https://groups.google.com/forum/#!searchin/rubyonrails-security/deep_munge/rubyonrails-security/jILZ34tAHF4/7x0hLH-o0-IJ)
+and [CVE-2013-0155](https://groups.google.com/forum/#!searchin/rubyonrails-security/CVE-2012-2660/rubyonrails-security/c7jT-EeN9eI/L0u4e87zYGMJ))
+`deep_munge` method was introduced as a solution to keep Rails secure by default.
+
+Example of vulnerable code that could be used by attacker, if `deep_munge`
+wasn't performed is:
+
+```ruby
+unless params[:token].nil?
+ user = User.find_by_token(params[:token])
+ user.reset_password!
+end
+```
+
+When `params[:token]` is one of: `[]`, `[nil]`, `[nil, nil, ...]` or
+`['foo', nil]` it will bypass the test for `nil`, but `IS NULL` or
+`IN ('foo', NULL)` where clauses still will be added to the SQL query.
+
+To keep rails secure by default, `deep_munge` replaces some of the values with
+`nil`. Below table shows what the parameters look like based on `JSON` sent in
+request:
+
+| JSON | Parameters |
+|-----------------------------------|--------------------------|
+| `{ "person": null }` | `{ :person => nil }` |
+| `{ "person": [] }` | `{ :person => nil }` |
+| `{ "person": [null] }` | `{ :person => nil }` |
+| `{ "person": [null, null, ...] }` | `{ :person => nil }` |
+| `{ "person": ["foo", null] }` | `{ :person => ["foo"] }` |
+
+It is possible to return to old behaviour and disable `deep_munge` configuring
+your application if you are aware of the risk and know how to handle it:
+
+```ruby
+config.action_dispatch.perform_deep_munge = false
+```
Default Headers
---------------
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 33cd3e868b..07f3aad1e6 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -339,7 +339,7 @@ NOTE: The execution of each test method stops as soon as any error or an asserti
When a test fails you are presented with the corresponding backtrace. By default
Rails filters that backtrace and will only print lines relevant to your
-application. This eliminates the framwork noise and helps to focus on your
+application. This eliminates the framework noise and helps to focus on your
code. However there are situations when you want to see the full
backtrace. simply set the `BACKTRACE` environment variable to enable this
behavior:
@@ -401,8 +401,8 @@ Rails adds some custom assertions of its own to the `test/unit` framework:
| `assert_no_difference(expressions, message = nil, &amp;block)` | Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
| `assert_recognizes(expected_options, path, extras={}, message=nil)` | Asserts that the routing of the given path was handled correctly and that the parsed options (given in the expected_options hash) match path. Basically, it asserts that Rails recognizes the route given by expected_options.|
| `assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)` | Asserts that the provided options can be used to generate the provided path. This is the inverse of assert_recognizes. The extras parameter is used to tell the request the names and values of additional request parameters that would be in a query string. The message parameter allows you to specify a custom error message for assertion failures.|
-| `assert_response(type, message = nil)` | Asserts that the response comes with a specific status code. You can specify `:success` to indicate 200-299, `:redirect` to indicate 300-399, `:missing` to indicate 404, or `:error` to match the 500-599 range|
-| `assert_redirected_to(options = {}, message=nil)` | Assert that the redirection options passed in match those of the redirect called in the latest action. This match can be partial, such that `assert_redirected_to(controller: "weblog")` will also match the redirection of `redirect_to(controller: "weblog", action: "show")` and so on.|
+| `assert_response(type, message = nil)` | Asserts that the response comes with a specific status code. You can specify `:success` to indicate 200-299, `:redirect` to indicate 300-399, `:missing` to indicate 404, or `:error` to match the 500-599 range. You can also pass an explicit status number or its symbolic equivalent. For more information, see [full list of status codes](http://rubydoc.info/github/rack/rack/master/Rack/Utils#HTTP_STATUS_CODES-constant) and how their [mapping](http://rubydoc.info/github/rack/rack/master/Rack/Utils#SYMBOL_TO_STATUS_CODE-constant) works.|
+| `assert_redirected_to(options = {}, message=nil)` | Assert that the redirection options passed in match those of the redirect called in the latest action. This match can be partial, such that `assert_redirected_to(controller: "weblog")` will also match the redirection of `redirect_to(controller: "weblog", action: "show")` and so on. You can also pass named routes such as `assert_redirected_to root_path` and Active Record objects such as `assert_redirected_to @article`.|
| `assert_template(expected = nil, message=nil)` | Asserts that the request was rendered with the appropriate template file.|
You'll see the usage of some of these assertions in the next chapter.
@@ -518,8 +518,10 @@ You also have access to three instance variables in your functional tests:
### Setting Headers and CGI variables
-Headers and cgi variables can be set directly on the `@request`
-instance variable:
+[HTTP headers](http://tools.ietf.org/search/rfc2616#section-5.3)
+and
+[CGI variables](http://tools.ietf.org/search/rfc3875#section-4.1)
+can be set directly on the `@request` instance variable:
```ruby
# setting a HTTP Header
@@ -937,7 +939,6 @@ Here's a unit test to test a mailer named `UserMailer` whose action `invite` is
require 'test_helper'
class UserMailerTest < ActionMailer::TestCase
- tests UserMailer
test "invite" do
# Send the email, then test that it got queued
email = UserMailer.create_invite('me@example.com',
diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md
index ab8cabe48d..8aae3bbc1a 100644
--- a/guides/source/upgrading_ruby_on_rails.md
+++ b/guides/source/upgrading_ruby_on_rails.md
@@ -62,7 +62,7 @@ If you want to use Spring as your application preloader you need to:
NOTE: User defined rake tasks will run in the `development` environment by
default. If you want them to run in other environments consult the
-[Spring README](https://github.com/jonleighton/spring#rake).
+[Spring README](https://github.com/rails/spring#rake).
### `config/secrets.yml`
@@ -98,6 +98,19 @@ If your test helper contains a call to
is now done automatically when you `require 'test_help'`, although
leaving this line in your helper is not harmful in any way.
+### Cookies serializer
+
+Applications created before Rails 4.1 uses `Marshal` to serialize cookie values into
+the signed and encrypted cookie jars. If you want to use the new `JSON`-based format
+in your application, you can add an initializer file with the following content:
+
+ ```ruby
+ Rails.application.config.cookies_serializer :hybrid
+ ```
+
+This would transparently migrate your existing `Marshal`-serialized cookies into the
+new `JSON`-based format.
+
### Changes in JSON handling
There are a few major changes related to JSON handling in Rails 4.1.
@@ -148,7 +161,7 @@ part of the rewrite, the following features have been removed from the encoder:
2. Support for the `encode_json` hook
3. Option to encode `BigDecimal` objects as numbers instead of strings
-If you application depends on one of these features, you can get them back by
+If your application depends on one of these features, you can get them back by
adding the [`activesupport-json_encoder`](https://github.com/rails/activesupport-json_encoder)
gem to your Gemfile.
@@ -320,7 +333,7 @@ being used, you can update your form to use the `PUT` method instead:
<%= form_for [ :update_name, @user ], method: :put do |f| %>
```
-For more on PATCH and why this change was made, see [this post](http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-the-new-primary-http-method-for-updates/)
+For more on PATCH and why this change was made, see [this post](http://weblog.rubyonrails.org/2012/2/26/edge-rails-patch-is-the-new-primary-http-method-for-updates/)
on the Rails blog.
#### A note about media types