aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2010-12-15 20:18:36 +0100
committerXavier Noria <fxn@hashref.com>2010-12-15 20:18:36 +0100
commit3c9486f487384f65dfadae0b2f9045157963cbd9 (patch)
treefb2747d40ea33b29b238a66795dea5ae9b531332
parent5d78b4c6f7829498e5d2a8cd4fceca0e24a3f64e (diff)
parent80382c7465af27194dc9644b8ba4c4ad458b7ef7 (diff)
downloadrails-3c9486f487384f65dfadae0b2f9045157963cbd9.tar.gz
rails-3c9486f487384f65dfadae0b2f9045157963cbd9.tar.bz2
rails-3c9486f487384f65dfadae0b2f9045157963cbd9.zip
Merge branch 'master' of git://github.com/lifo/docrails
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb44
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb6
-rw-r--r--railties/guides/source/action_mailer_basics.textile14
-rw-r--r--railties/guides/source/active_record_validations_callbacks.textile2
-rw-r--r--railties/guides/source/active_support_core_extensions.textile43
-rw-r--r--railties/guides/source/generators.textile10
-rw-r--r--railties/guides/source/initialization.textile514
-rw-r--r--railties/guides/source/layouts_and_rendering.textile24
-rw-r--r--railties/guides/source/performance_testing.textile2
-rw-r--r--railties/guides/source/routing.textile2
-rw-r--r--railties/guides/source/security.textile4
12 files changed, 496 insertions, 171 deletions
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 430fcdbe07..f65a294eca 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -458,6 +458,18 @@ module ActionDispatch
super
end
+ # Used to scope a set of routes to particular constraints.
+ #
+ # Take the following route definition as an example:
+ #
+ # scope :path => ":account_id", :as => "account" do
+ # resources :projects
+ # end
+ #
+ # This generates helpers such as +account_projects_path+, just like +resources+ does.
+ # The difference here being that the routes generated are like /rails/projects/2,
+ # rather than /accounts/rails/projects/2.
+ #
# === Supported options
# [:module]
# If you want to route /posts (without the prefix /admin) to
@@ -558,13 +570,13 @@ module ActionDispatch
#
# This generates the following routes:
#
- # admin_posts GET /admin/posts(.:format) {:action=>"index", :controller=>"admin/posts"}
- # admin_posts POST /admin/posts(.:format) {:action=>"create", :controller=>"admin/posts"}
- # new_admin_post GET /admin/posts/new(.:format) {:action=>"new", :controller=>"admin/posts"}
- # edit_admin_post GET /admin/posts/:id/edit(.:format) {:action=>"edit", :controller=>"admin/posts"}
- # admin_post GET /admin/posts/:id(.:format) {:action=>"show", :controller=>"admin/posts"}
- # admin_post PUT /admin/posts/:id(.:format) {:action=>"update", :controller=>"admin/posts"}
- # admin_post DELETE /admin/posts/:id(.:format) {:action=>"destroy", :controller=>"admin/posts"}
+ # admin_posts GET /admin/posts(.:format) {:action=>"index", :controller=>"admin/posts"}
+ # admin_posts POST /admin/posts(.:format) {:action=>"create", :controller=>"admin/posts"}
+ # new_admin_post GET /admin/posts/new(.:format) {:action=>"new", :controller=>"admin/posts"}
+ # edit_admin_post GET /admin/posts/:id/edit(.:format) {:action=>"edit", :controller=>"admin/posts"}
+ # admin_post GET /admin/posts/:id(.:format) {:action=>"show", :controller=>"admin/posts"}
+ # admin_post PUT /admin/posts/:id(.:format) {:action=>"update", :controller=>"admin/posts"}
+ # admin_post DELETE /admin/posts/:id(.:format) {:action=>"destroy", :controller=>"admin/posts"}
# === Supported options
#
# The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+ options all default to the name of the namespace.
@@ -572,24 +584,24 @@ module ActionDispatch
# [:path]
# The path prefix for the routes.
#
- # namespace :admin, :path => "sekret" do
- # resources :posts
- # end
+ # namespace :admin, :path => "sekret" do
+ # resources :posts
+ # end
#
# All routes for the above +resources+ will be accessible through +/sekret/posts+, rather than +/admin/posts+
#
# [:module]
# The namespace for the controllers.
#
- # namespace :admin, :module => "sekret" do
- # resources :posts
- # end
+ # namespace :admin, :module => "sekret" do
+ # resources :posts
+ # end
#
# The +PostsController+ here should go in the +Sekret+ namespace and so it should be defined like this:
#
- # class Sekret::PostsController < ApplicationController
- # # code go here
- # end
+ # class Sekret::PostsController < ApplicationController
+ # # code go here
+ # end
#
# [:as]
# Changes the name used in routing helpers for this namespace.
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index ef5bbd8ae3..6f0e2c99ba 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -1115,7 +1115,7 @@ module ActionView
include InstanceTagMethods
end
- class FormBuilder #:nodoc:
+ class FormBuilder
# The methods which wrap a form helper call.
class_attribute :field_helpers
self.field_helpers = (FormHelper.instance_method_names - ['form_for'])
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index 50f065f03d..9500e85e8b 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -68,7 +68,7 @@ module ActionView
# * Any other key creates standard HTML attributes for the tag.
#
# ==== Examples
- # select_tag "people", options_from_collection_for_select(@people, "name", "id")
+ # select_tag "people", options_from_collection_for_select(@people, "id", "name")
# # <select id="people" name="people"><option value="1">David</option></select>
#
# select_tag "people", "<option>David</option>"
@@ -112,6 +112,7 @@ module ActionView
# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.
# * <tt>:size</tt> - The number of visible characters that will fit in the input.
# * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.
+ # * <tt>:placeholder</tt> - The text contained in the field by default which is removed when the field receives focus.
# * Any other key creates standard HTML attributes for the tag.
#
# ==== Examples
@@ -121,6 +122,9 @@ module ActionView
# text_field_tag 'query', 'Enter your search query here'
# # => <input id="query" name="query" type="text" value="Enter your search query here" />
#
+ # text_field_tag 'search', nil, :placeholder => 'Enter search term...'
+ # # => <input id="search" name="search" placeholder="Enter search term..." type="text" />
+ #
# text_field_tag 'request', nil, :class => 'special_input'
# # => <input class="special_input" id="request" name="request" type="text" />
#
diff --git a/railties/guides/source/action_mailer_basics.textile b/railties/guides/source/action_mailer_basics.textile
index b75c528a33..b77a0be37b 100644
--- a/railties/guides/source/action_mailer_basics.textile
+++ b/railties/guides/source/action_mailer_basics.textile
@@ -144,7 +144,7 @@ This provides a much simpler implementation that does not require the registerin
The method +welcome_email+ returns a Mail::Message object which can then just be told +deliver+ to send itself out.
-NOTE: In previous versions of Rails, you would call +deliver_welcome_email+ or +create_welcome_email+ however in Rails 3.0 this has been deprecated in favour of just calling the method name itself.
+NOTE: In previous versions of Rails, you would call +deliver_welcome_email+ or +create_welcome_email+. This has been deprecated in Rails 3.0 in favour of just calling the method name itself.
WARNING: Sending out one email should only take a fraction of a second, if you are planning on sending out many emails, or you have a slow domain resolution service, you might want to investigate using a background process like delayed job.
@@ -154,7 +154,7 @@ Action Mailer now handles the auto encoding of multibyte characters inside of he
If you are using UTF-8 as your character set, you do not have to do anything special, just go ahead and send in UTF-8 data to the address fields, subject, keywords, filenames or body of the email and ActionMailer will auto encode it into quoted printable for you in the case of a header field or Base64 encode any body parts that are non US-ASCII.
-For more complex examples, such as defining alternate character sets or self encoding text first, please refer to the Mail library.
+For more complex examples such as defining alternate character sets or self encoding text first, please refer to the Mail library.
h4. Complete List of Action Mailer Methods
@@ -213,9 +213,7 @@ NOTE: If you specify an encoding, Mail will assume that your content is already
h5. Making Inline Attachments
-Inline attachments are now possible in ActionMailer. While previously in the pre 3.0 version of Rails, you could do inline attachments, it involved a lot of hacking and determination to pull it off.
-
-ActionMailer now makes inline attachments as trivial as they should be.
+ActionMailer 3.0 makes inline attachments, which involved a lot of hacking in pre 3.0 versions, much simpler and trivial as they should be.
* Firstly, to tell Mail to turn an attachment into an inline attachment, you just call <tt>#inline</tt> on the attachments method within your Mailer:
@@ -274,7 +272,7 @@ to format the email address in the format <tt>"Name &lt;email&gt;"</tt>.
h4. Mailer Views
-Mailer views are located in the +app/views/name_of_mailer_class+ directory. The specific mailer view is known to the class because it's name is the same as the mailer method. So for example, in our example from above, our mailer view for the +welcome_email+ method will be in +app/views/user_mailer/welcome_email.html.erb+ for the HTML version and +welcome_email.text.erb+ for the plain text version.
+Mailer views are located in the +app/views/name_of_mailer_class+ directory. The specific mailer view is known to the class because its name is the same as the mailer method. In our example from above, our mailer view for the +welcome_email+ method will be in +app/views/user_mailer/welcome_email.html.erb+ for the HTML version and +welcome_email.text.erb+ for the plain text version.
To change the default mailer view for your action you do something like:
@@ -441,7 +439,7 @@ h3. Action Mailer Configuration
The following configuration options are best made in one of the environment files (environment.rb, production.rb, etc...)
|template_root|Determines the base from which template references will be made.|
-|logger|The logger is used for generating information on the mailing run if available. Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.|
+|logger|Generates information on the mailing run if available. Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.|
|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></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.|
@@ -504,7 +502,7 @@ class UserMailerTest < ActionMailer::TestCase
end
</ruby>
-In the test we send the email and store the returned object in the +email+ variable. We then ensure that it was sent (the first assert), then, in the second batch of assertions, we ensure that the email does indeed contain the what we expect.
+In the test we send the email and store the returned object in the +email+ variable. We then ensure that it was sent (the first assert), then, in the second batch of assertions, we ensure that the email does indeed contain what we expect.
h3. Changelog
diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile
index 0824ba450c..a15571fe58 100644
--- a/railties/guides/source/active_record_validations_callbacks.textile
+++ b/railties/guides/source/active_record_validations_callbacks.textile
@@ -414,7 +414,7 @@ class Person < ActiveRecord::Base
validates_with GoodnessValidator
end
-class GoodnessValidator < ActiveRecord::Validator
+class GoodnessValidator < ActiveModel::Validator
def validate
if record.first_name == "Evil"
record.errors[:base] << "This person is evil"
diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index 7333a81cf9..2e295aec3d 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/railties/guides/source/active_support_core_extensions.textile
@@ -3359,6 +3359,49 @@ The auxiliary file is written in a standard directory for temporary files, but y
NOTE: Defined in +active_support/core_ext/file/atomic.rb+.
+h3. Extensions to +Logger+
+
+h4. +around_[level]+
+
+Takes two arguments, a +before_message+ and +after_message+ and calls the current level method on the +Logger+ instance, passing in the +before_message+, then the specified message, then the +after_message+:
+
+<ruby>
+ logger = Logger.new("log/development.log")
+ logger.around_info("before", "after") { |logger| logger.info("during") }
+</ruby>
+
+h4. +silence+
+
+Silences every log level lesser to the specified one for the duration of the given block. Log level orders are: debug, info, error and fatal.
+
+<ruby>
+ logger = Logger.new("log/development.log")
+ logger.silence(Logger::INFO) do
+ logger.debug("In space, no one can hear you scream.")
+ logger.info("Scream all you want, small mailman!")
+ end
+</ruby>
+
+h4. +datetime_format=+
+
+Modifies the datetime format output by the formatter class associated with this logger. If the formatter class does not have a +datetime_format+ method then this is ignored.
+
+<ruby>
+ class Logger::FormatWithTime < Logger::Formatter
+ cattr_accessor(:datetime_format) { "%Y%m%d%H%m%S" }
+
+ def self.call(severity, timestamp, progname, msg)
+ "#{timestamp.strftime(datetime_format)} -- #{String === msg ? msg : msg.inspect}\n"
+ end
+ end
+
+ logger = Logger.new("log/development.log")
+ logger.formatter = Logger::FormatWithTime
+ logger.info("<- is the current time")
+</ruby>
+
+NOTE: Defined in +active_support/core_ext/logger.rb+.
+
h3. Extensions to +NameError+
Active Support adds +missing_name?+ to +NameError+, which tests whether the exception was raised because of the name passed as argument.
diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile
index ee3891c43b..6945f6f9bb 100644
--- a/railties/guides/source/generators.textile
+++ b/railties/guides/source/generators.textile
@@ -208,16 +208,16 @@ end
If we generate another resource with the scaffold generator, we can see that neither stylesheets nor fixtures are created anymore. If you want to customize it further, for example to use DataMapper and RSpec instead of Active Record and TestUnit, it's just a matter of adding their gems to your application and configuring your generators.
-To demonstrate this, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator:
+To demonstrate this, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator within the rails namespace, as this is where rails searches for generators used as hooks:
<shell>
-$ rails generate generator my_helper
+$ rails generate generator rails/my_helper
</shell>
After that, we can delete both the +templates+ directory and the +source_root+ class method from our new generators, because we are not going to need them. So our new generator looks like the following:
<ruby>
-class MyHelperGenerator < Rails::Generators::NamedBase
+class Rails::MyHelperGenerator < Rails::Generators::NamedBase
def create_helper_file
create_file "app/helpers/#{file_name}_helper.rb", <<-FILE
module #{class_name}Helper
@@ -270,7 +270,7 @@ Since Rails 3.0, this is easy to do due to the hooks concept. Our new helper doe
To do that, we can change the generator this way:
<ruby>
-class MyHelperGenerator < Rails::Generators::NamedBase
+class Rails::MyHelperGenerator < Rails::Generators::NamedBase
def create_helper_file
create_file "app/helpers/#{file_name}_helper.rb", <<-FILE
module #{class_name}Helper
@@ -283,7 +283,7 @@ end
end
</ruby>
-Now, when the helper generator is invoked and TestUnit is configured as the test framework, it will try to invoke both +MyHelper::Generators::TestUnitGenerator+ and +TestUnit::Generators::MyHelperGenerator+. Since none of those are defined, we can tell our generator to invoke +TestUnit::Generators::HelperGenerator+ instead, which is defined since it's a Rails generator. To do that, we just need to add:
+Now, when the helper generator is invoked and TestUnit is configured as the test framework, it will try to invoke both +Rails::TestUnitGenerator+ and +TestUnit::MyHelperGenerator+. Since none of those are defined, we can tell our generator to invoke +TestUnit::Generators::HelperGenerator+ instead, which is defined since it's a Rails generator. To do that, we just need to add:
<ruby>
# Search for :helper instead of :my_helper
diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile
index 4cc5f3843f..72e10191f9 100644
--- a/railties/guides/source/initialization.textile
+++ b/railties/guides/source/initialization.textile
@@ -1,79 +1,140 @@
h2. The Rails Initialization Process
-This guide explains how the initialization process in Rails works as of Rails 3.
+This guide explains the internals of the initialization process in Rails works as of Rails 3.1. It is an extremely in-depth guide and recommended for advanced Rails developers.
* Using +rails server+
* Using Passenger
endprologue.
-This guide first describes the process of +rails server+ then explains the Passenger + Rack method, before delving into the common initialize pattern these two go through.
+This guide goes through every single file, class and method call that is required to boot up the Ruby on Rails stack for a default Rails 3.1 application, explaining each part in detail a long the way. For this guide, we will be focusing on how the two most common methods (+rails server+ and Passenger) boot a Rails application.
+
+NOTE: Paths in this guide are relative to Rails or a Rails application unless otherwise specified.
h3. Launch!
As of Rails 3, +script/server+ has become +rails server+. This was done to centralize all rails related commands to one common file.
-The actual +rails+ command is kept in _railties/bin/rails_ and goes like this:
+h4. +bin/rails+
+
+The actual +rails+ command is kept in _bin/rails_ at the and goes like this:
<ruby>
- require 'rbconfig'
+ #!/usr/bin/env ruby
- module Rails
- module ScriptRailsLoader
- RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"]
- SCRIPT_RAILS = File.join('script', 'rails')
-
- def self.exec_script_rails!
- cwd = Dir.pwd
- exec RUBY, SCRIPT_RAILS, *ARGV if File.exists?(SCRIPT_RAILS)
- Dir.chdir("..") do
- # Recurse in a chdir block: if the search fails we want to be sure
- # the application is generated in the original working directory.
- exec_script_rails! unless cwd == Dir.pwd
- end
- rescue SystemCallError
- # could not chdir, no problem just return
- end
- end
+ begin
+ require "rails/cli"
+ rescue LoadError
+ railties_path = File.expand_path('../../railties/lib', __FILE__)
+ $:.unshift(railties_path)
+ require "rails/cli"
end
+</ruby>
- Rails::ScriptRailsLoader.exec_script_rails!
+This file will attempt to load +rails/cli+ and if it cannot find it then add the +railties/lib+ path to the load path (+$:+) and will then try to require it again.
- railties_path = File.expand_path('../../lib', __FILE__)
- $:.unshift(railties_path) if File.directory?(railties_path) && !$:.include?(railties_path)
+h4. +railites/lib/rails/cli.rb+
+
+This file looks like this:
+
+<ruby>
+ require 'rbconfig'
+ require 'rails/script_rails_loader'
+
+ # If we are inside a Rails application this method performs an exec and thus
+ # the rest of this script is not run.
+ Rails::ScriptRailsLoader.exec_script_rails!
require 'rails/ruby_version_check'
Signal.trap("INT") { puts; exit }
- require 'rails/commands/application'
+ if ARGV.first == 'plugin'
+ ARGV.shift
+ require 'rails/commands/plugin_new'
+ else
+ require 'rails/commands/application'
+ end
</ruby>
-The +Rails::ScriptRailsLoader+ module here defines two constants: +RUBY+ and +SCRIPT_RAILS+. +RUBY+ is the full path to your ruby executable, on a Snow Leopard system it's _/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby_. +SCRIPT_RAILS+ is simply _script/rails_. When +exec_script_rails+ is invoked, this will attempt to +exec+ the _rails_ file in the _script_ directory using the path to your Ruby executable, +RUBY+. If +exec+ is invoked, the program will stop at this point. If the _script/rails_ file doesn't exist in the current directory, Rails will recurse upwards until it finds it by calling +exec_script_rails+ from inside the +Dir.chdir("..")+. This is handy if you're currently in one of the sub-directories of the rails application and wish to launch a server or a console.
+The +rbconfig+ file here is out of Ruby's standard library and provides us with the +RbConfig+ class which contains useful information dependent on how Ruby was compiled. We'll see this in use in +railties/lib/rails/script_rails_loader+.
+
+<ruby>
+require 'pathname'
+
+module Rails
+ module ScriptRailsLoader
+ RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"]
+ SCRIPT_RAILS = File.join('script', 'rails')
+ ...
-If Rails cannot execute _script/rails_ then it will fall back to the standard +rails+ command task of generating an application.
+ end
+end
+</ruby>
+
+The +rails/script_rails_loader+ file uses +RbConfig::Config+ to gather up the +bin_dir+ and +ruby_install_name+ values for the configuration which will result in a path such as +/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby+, which is the default path on Mac OS X. If you're running Windows the path may be something such as +C:/Ruby192/bin/ruby+. Anyway, the path on your system may be different, but the point of this is that it will point at the known ruby executable location for your install. The +RbConfig::CONFIG["EXEEXT"]+ will suffix this path with ".exe" if the script is running on Windows. This constant is used later on in +exec_script_rails!+. As for the +SCRIPT_RAILS+ console, we'll see that when we get to the +in_rails_application?+ method.
-In +script/rails+ we see the following:
+Back in +rails/cli+, the next line is this:
<ruby>
- #!/usr/bin/env ruby
- # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
+ Rails::ScriptRailsLoader.exec_script_rails!
+</ruby>
- APP_PATH = File.expand_path('../../config/application', __FILE__)
- require File.expand_path('../../config/boot', __FILE__)
- require 'rails/commands'
+This method is defined in +rails/script_rails_loader+ like this:
+
+<ruby>
+ def self.exec_script_rails!
+ cwd = Dir.pwd
+ return unless in_rails_application? || in_rails_application_subdirectory?
+ exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
+ Dir.chdir("..") do
+ # Recurse in a chdir block: if the search fails we want to be sure
+ # the application is generated in the original working directory.
+ exec_script_rails! unless cwd == Dir.pwd
+ end
+ rescue SystemCallError
+ # could not chdir, no problem just return
+ end
</ruby>
-This obviously defines a couple of constants to some pretty important files, _config/environment.rb_, _config/boot.rb_ and _config/application.rb_ all within the context of +__FILE__+ which is of course +script/rails+ in the root of your application. Then it goes on to +require BOOT_PATH+ which leads us onto _config/boot.rb_.
+This method will first check if the current working directory (+cwd+) is a Rails application or is a subdirectory of one. The way to determine this is defined in the +in_rails_application?+ method like this:
-h3. Passenger
+<ruby>
+ def self.in_rails_application?
+ File.exists?(SCRIPT_RAILS)
+ end
+</ruby>
-Before we dive into what _config/boot.rb_ encompasses, we'll just glimpse at what Passenger does enough to get an understanding of how it requires a Rails application.
+The +SCRIPT_RAILS+ constant defined earlier is used here, with +File.exists?+ checking for its presence in the current directory. If this method returns +false+, then +in_rails_application_subdirectory?+ will be used:
+
+<ruby>
+ def self.in_rails_application_subdirectory?(path = Pathname.new(Dir.pwd))
+ File.exists?(File.join(path, SCRIPT_RAILS)) || !path.root? && in_rails_application_subdirectory?(path.parent)
+ end
+</ruby>
+
+This climbs the directory tree until it reaches a path which contains a +script/rails+ file. If a directory is reached which contains this file then this line will run:
+
+<ruby>
+ exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
+</ruby>
+
+This is effectively the same as doing +ruby script/rails [arguments]+. Where +[arguments]+ at this point in time is simply "server".
+
+h4. +script/rails+
+
+This file looks like this:
+
+<ruby>
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
+ require File.expand_path('../../config/boot', __FILE__)
+ require 'rails/commands'
+</ruby>
-Passenger will require _config/environment.rb_ by way of its +PhusionPassenger::Railz::ApplicationSpawner#preload_application+ method. _config/environment.rb_ requires _config/application.rb_ which requires _config/boot.rb_. That's how the Rails boot process begins with Passenger in a nutshell.
+The +APP_PATH+ constant here will be used later in +rails/commands+. The +config/boot+ file that +script/rails+ references is the +config/boot.rb+ file in our application which is responsible for loading Bundler and setting it up.
-h3. _config/boot.rb_
+h4. +config/boot.rb+
-_config/boot.rb_ is the first stop for everything for initializing your application. This boot process does quite a bit of work for you and so this section attempts to go in-depth enough to explain what each of the pieces does.
++config/boot.rb+ contains this:
<ruby>
require 'rubygems'
@@ -91,134 +152,345 @@ _config/boot.rb_ is the first stop for everything for initializing your applicat
end if File.exist?(gemfile)
</ruby>
-h3. Bundled Rails (3.x)
+In a standard Rails application, there's a +Gemfile+ which declares all dependencies of the application. +config/boot.rb+ sets +ENV["BUNDLE_GEMFILE"]+ to the location of this file, then requires Bundler and calls +Bundler.setup+ which adds the dependencies of the application (including all the Rails parts) to the load path, making them available for the application to load. The gems that a Rails 3.1 application depends on are as follows:
+
+* abstract (1.0.0)
+* actionmailer (3.1.0.beta)
+* actionpack (3.1.0.beta)
+* activemodel (3.1.0.beta)
+* activerecord (3.1.0.beta)
+* activeresource (3.1.0.beta)
+* activesupport (3.1.0.beta)
+* arel (2.0.7)
+* builder (3.0.0)
+* bundler (1.0.6)
+* erubis (2.6.6)
+* i18n (0.5.0)
+* mail (2.2.12)
+* mime-types (1.16)
+* polyglot (0.3.1)
+* rack (1.2.1)
+* rack-cache (0.5.3)
+* rack-mount (0.6.13)
+* rack-test (0.5.6)
+* rails (3.1.0.beta)
+* railties (3.1.0.beta)
+* rake (0.8.7)
+* sqlite3-ruby (1.3.2)
+* thor (0.14.6)
+* treetop (1.4.9)
+* tzinfo (0.3.23)
+
+h4. +rails/commands.rb+
+
+Once +config/boot.rb+ has finished, the next file that is required is +rails/commands+ which will execute a command based on the arguments passed in. In this case, the +ARGV+ array simply contains +server+ which is extracted into the +command+ variable using these lines:
+
+<ruby>
+ aliases = {
+ "g" => "generate",
+ "c" => "console",
+ "s" => "server",
+ "db" => "dbconsole"
+ }
+
+ command = ARGV.shift
+ command = aliases[command] || command
+</ruby>
+
+If we used <tt>s</tt> rather than +server+, Rails will use the +aliases+ defined in the file and match them to their respective commands. With the +server+ command, Rails will run this code:
+
+<ruby>
+ when 'server'
+ # Change to the application's path if there is no config.ru file in current dir.
+ # This allows us to run script/rails server from other directories, but still get
+ # the main config.ru and properly set the tmp directory.
+ Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))
+
+ require 'rails/commands/server'
+ Rails::Server.new.tap { |server|
+ # We need to require application after the server sets environment,
+ # otherwise the --environment option given to the server won't propagate.
+ require APP_PATH
+ Dir.chdir(Rails.application.root)
+ server.start
+ }
+</ruby>
+
+This file will change into the root of the directory (a path two directories back from +APP_PATH+ which points at +config/application.rb+), but only if the +config.ru+ file isn't found. This then requires +rails/commands/server+ which requires +action_dispatch+ and sets up the +Rails::Server+ class.
+
+h4. +actionpack/lib/action_dispatch.rb+
+
+Action Dispatch is the routing component of the Rails framework. It depends on Active Support, +actionpack/lib/action_pack.rb+ and +Rack+ being available. The first thing required here is +active_support+.
+
+h4. +active_support/lib/active_support.rb+
+
+This file begins with requiring +active_support/lib/active_support/dependencies/autoload.rb+ which redefines Ruby's +autoload+ method to have a little more extra behaviour especially in regards to eager autoloading. Eager autoloading is the loading of all required classes and will happen when the +config.cache_classes+ setting is +true+.
+The +active_support/lib/active_support/version.rb+ that is also required here simply defines an +ActiveSupport::VERSION+ constant which defines a couple of constants inside this module, the main constant of this is +ActiveSupport::VERSION::STRING+ which returns the current version of ActiveSupport.
-Rails 3 now uses Bundler and the README for the project explains it better than I could:
+The +active_support/lib/active_support.rb+ file simply defines the +ActiveSupport+ module and some autoloads (eager and of the normal variety) for it.
-> "Bundler is a tool that manages gem dependencies for your ruby application. It takes a gem manifest file and is able to fetch, download, and install the gems and all child dependencies specified in this manifest. It can manage any update to the gem manifest file and update the bundle's gems accordingly. It also lets you run any ruby code in context of the bundle's gem environment."
+h4. +actionpack/lib/action_dispatch.rb+ cont'd.
-Now with Rails 3 we have a Gemfile which defines the basics our application needs to get going:
+Now back to +action_pack/lib/action_dispatch.rb+. The next +require+ in this file is one for +action_pack+, which simply calls +action_pack/version.rb+ which defines +ActionPack::VERSION+ and the constants, much like +ActiveSpport+ does.
+
+After this line, there's a require to +active_model+ which simply defines autoloads for the +ActiveModel+ part of Rails and sets up the +ActiveModel+ module which is used later on.
+
+The last of the requires is to +rack+, which like the +active_model+ and +active_support+ requires before it, sets up the +Rack+ module as well as the autoloads for constants within it.
+
+Finally in +action_dispatch.rb+ the +ActionDispatch+ module and *its* autoloads are declared.
+
+h4. +rails/commands/server.rb+
+
+The +Rails::Server+ class is defined in this file as inheriting from +Rack::Server+. When +Rails::Server.new+ is called, this calls the +initialize+ method in +rails/commands/server.rb+:
<ruby>
- source 'http://rubygems.org'
+ def initialize(*)
+ super
+ set_environment
+ end
+</ruby>
- gem 'rails', '3.0.0'
+Firstly, +super+ is called which calls the +initialize+ method on +Rack::Server+.
- # Bundle edge Rails instead:
- # gem 'rails', :git => 'git://github.com/rails/rails.git'
+h4. Rack: +lib/rack/server.rb+
- gem 'sqlite3-ruby', :require => 'sqlite3'
++Rack::Server+ is responsible for providing a common server interface for all Rack-based applications, which Rails is now a part of.
- # Use unicorn as the web server
- # gem 'unicorn'
+The +initialize+ method in +Rack::Server+ simply sets a couple of variables:
- # Deploy with Capistrano
- # gem 'capistrano'
+<ruby>
+ def initialize(options = nil)
+ @options = options
+ @app = options[:app] if options && options[:app]
+ end
+</ruby>
- # Bundle the extra gems:
- # gem 'bj'
- # gem 'nokogiri'
- # gem 'sqlite3-ruby', :require => 'sqlite3'
- # gem 'aws-s3', :require => 'aws/s3'
+In this case, +options+ will be +nil+ so nothing happens in this method.
- # Bundle gems for certain environments:
- # gem 'rspec', :group => :test
- # group :test do
- # gem 'webrat'
- # end
+After +super+ has finished in +Rack::Server+, we jump back to +rails/commands/server.rb+. At this point, +set_environment+ is called within the context of the +Rails::Server+ object and this method doesn't appear to do much at first glance:
+<ruby>
+ def set_environment
+ ENV["RAILS_ENV"] ||= options[:environment]
+ end
</ruby>
-Here the only two gems we need are +rails+ and +sqlite3-ruby+, so it seems. This is until you run +bundle pack+. This command freezes all the gems required by your application into _vendor/cache_. The gems installed by default are:
+In fact, the +options+ method here does quite a lot. This method is defined in +Rack::Server+ like this:
-* abstract-1.0.0.gem
-* actionmailer-3.0.0.gem
-* actionpack-3.0.0.gem
-* activemodel-3.0.0.gem
-* activerecord-3.0.0.gem
-* activeresource-3.0.0.gem
-* activesupport-3.0.0.gem
-* arel-0.4.0.gem
-* builder-2.1.2.gem
-* bundler-1.0.3.gem
-* erubis-2.6.6.gem
-* i18n-0.4.1.gem
-* mail-2.2.5.gem
-* memcache-client-1.8.5.gem
-* mime-types-1.16.gem
-* nokogiri-1.4.3.1.gem
-* polyglot-0.3.1.gem
-* rack-1.2.1.gem
-* rack-mount-0.6.12.gem
-* rack-test-0.5.4.gem
-* rails-3.0.0.gem
-* railties-3.0.0.gem
-* rake-0.8.7.gem
-* sqlite3-ruby-1.3.1.gem
-* text-format-1.0.0.gem
-* text-hyphen-1.0.0.gem
-* thor-0.13.7.gem
-* treetop-1.4.8.gem
-* tzinfo-0.3.23.gem
+<ruby>
+ def options
+ @options ||= parse_options(ARGV)
+ end
+</ruby>
-TODO: Prettify when it becomes more stable.
+Then +parse_options+ is defined like this:
-I won't go into what each of these gems are, as that is really something that needs covering on a case-by-case basis. We will however just dig a little under the surface of Bundler.
+<ruby>
+ def parse_options(args)
+ options = default_options
-Back in _config/boot.rb_, we call +Bundler.setup+ which will load and parse the +Gemfile+ and add the _lib_ directory of the gems mentioned **and** their dependencies (**and** their dependencies' dependencies, and so on) to the +$LOAD_PATH+.
+ # Don't evaluate CGI ISINDEX parameters.
+ # http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
+ args.clear if ENV.include?("REQUEST_METHOD")
-h3. Requiring Rails
+ options.merge! opt_parser.parse! args
+ options[:config] = ::File.expand_path(options[:config])
+ ENV["RACK_ENV"] = options[:environment]
+ options
+ end
+</ruby>
-After _config/boot.rb_ is loaded, there's this +require+:
+With the +default_options+ set to this:
<ruby>
- require 'rails/commands'
+ def default_options
+ {
+ :environment => ENV['RACK_ENV'] || "development",
+ :pid => nil,
+ :Port => 9292,
+ :Host => "0.0.0.0",
+ :AccessLog => [],
+ :config => "config.ru"
+ }
+ end
</ruby>
-In this file, _railties/lib/rails/commands.rb_, there is a case statement for +ARGV.shift+:
+There is no +REQUEST_METHOD+ key in +ENV+ so we can skip over that line. The next line merges in the options from +opt_parser+ which is defined plainly in +Rack::Server+
<ruby>
- case ARGV.shift
- ...
- when 's', 'server'
- require 'rails/commands/server'
- # Initialize the server first, so environment options are set
- server = Rails::Server.new
- require APP_PATH
+ def opt_parser
+ Options.new
+ end
+</ruby>
+
+The class *is* defined in +Rack::Server+, but is overwritten in +Rails::Server+ to take different arguments. Its +parse!+ method begins like this:
+
+<ruby>
+ def parse!(args)
+ args, options = args.dup, {}
+
+ opt_parser = OptionParser.new do |opts|
+ opts.banner = "Usage: rails server [mongrel, thin, etc] [options]"
+ opts.on("-p", "--port=port", Integer,
+ "Runs Rails on the specified port.", "Default: 3000") { |v| options[:Port] = v }
...
+</ruby>
+
+This method will set up keys for the +options+ which Rails will then be able to use to determine how its server should run. After +initialize+ has finished, then the +start+ method will launch the server.
+
+h4. +Rails::Server#start+
+
+This method is defined like this:
+
+<ruby>
+ def start
+ puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
+ puts "=> Rails #{Rails.version} application starting in #{Rails.env} on http://#{options[:Host]}:#{options[:Port]}"
+ puts "=> Call with -d to detach" unless options[:daemonize]
+ trap(:INT) { exit }
+ puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
+
+ #Create required tmp directories if not found
+ %w(cache pids sessions sockets).each do |dir_to_make|
+ FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make))
+ end
+
+ super
+ ensure
+ # The '-h' option calls exit before @options is set.
+ # If we call 'options' with it unset, we get double help banners.
+ puts 'Exiting' unless @options && options[:daemonize]
end
</ruby>
-We're running +rails server+ and this means it will make a require out to _rails/commands/server_ (_railties/lib/rails/commands/server.rb_). Firstly, this file makes a couple of requires of its own:
+This is where the first output of the Rails initialization happens. This method creates a trap for +INT+ signals, so if you +CTRL+C+ the server, it will exit the process. As we can see from the code here, it will create the +tmp/cache+, +tmp/pids+, +tmp/sessions+ and +tmp/sockets+ directories if they don't already exist prior to calling +super+. The +super+ method will call +Rack::Server.start+ which begins its definition like this:
+
+<ruby>
+ def start
+ if options[:warn]
+ $-w = true
+ end
+
+ if includes = options[:include]
+ $LOAD_PATH.unshift(*includes)
+ end
+
+ if library = options[:require]
+ require library
+ end
+
+ if options[:debug]
+ $DEBUG = true
+ require 'pp'
+ p options[:server]
+ pp wrapped_app
+ pp app
+ end
+</ruby>
+
+In a Rails application, these options are not set at all and therefore aren't used at all. The first line of code that's executed in this method is a call to this method:
<ruby>
- require 'fileutils'
- require 'optparse'
- require 'action_dispatch'
+ wrapped_app
</ruby>
-The first two are Ruby core and this guide does not cover what they do, but _action_dispatch_ (_actionpack/lib/action_dispatch.rb_) is important. This file firstly make a require to _active_support_ (_activesupport/lib/active_support.rb_) which defines the +ActiveSupport+ module.
+This method calls another method:
-h4. +require 'active_support'+
+<ruby>
+ @wrapped_app ||= build_app app
+</ruby>
-_activesupport/lib/active_support.rb_ sets up +module ActiveSupport+:
+Then the +app+ method here is defined like so:
<ruby>
- module ActiveSupport
- class << self
- attr_accessor :load_all_hooks
- def on_load_all(&hook) load_all_hooks << hook end
- def load_all!; load_all_hooks.each { |hook| hook.call } end
+ def app
+ @app ||= begin
+ if !::File.exist? options[:config]
+ abort "configuration #{options[:config]} not found"
+ end
+
+ app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
+ self.options.merge! options
+ app
end
- self.load_all_hooks = []
+ end
+</ruby>
+
+The +options[:config]+ value defaults to +config.ru+ which contains this:
+
+<ruby>
+ # This file is used by Rack-based servers to start the application.
+
+ require ::File.expand_path('../config/environment', __FILE__)
+ run YourApp::Application
+</ruby>
+
+
+The +Rack::Builder.parse_file+ method here takes the content from this +config.ru+ file and parses it using this code:
+
+<ruby>
+ app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app",
+ TOPLEVEL_BINDING, config
+</ruby>
+
+The <ruby>initialize</ruby> method will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run:
+
+<ruby>
+ require ::File.expand_path('../config/environment', __FILE__)
+</ruby>
+
+h4. +config/environment.rb+
+
+This file is the common file required by +config.ru+ (+rails server+) and Passenger. This is where these two ways to run the server meet; everything before this point has been Rack and Rails setup.
+
+This file begins with requiring +config/application.rb+.
+
+h4. +config/application.rb+
+
+This file requires +config/boot.rb+, but only if it hasn't been required before, which would be the case in +rails server+ but *wouldn't* be the case with Passenger.
+
+Then the fun begins! The next line is:
- on_load_all do
- [Dependencies, Deprecation, Gzip, MessageVerifier, Multibyte, SecureRandom]
+<ruby>
+ require 'rails/all'
+</ruby>
+
+h4 +railties/lib/rails/all.rb+
+
+
+This file is responsible for requiring all the individual parts of Rails like so:
+
+<ruby>
+ require "rails"
+
+ %w(
+ active_record
+ action_controller
+ action_mailer
+ active_resource
+ rails/test_unit
+ ).each do |framework|
+ begin
+ require "#{framework}/railtie"
+ rescue LoadError
end
end
</ruby>
+First off the line is the +rails+ require itself.
+
+h4. +railties/lib/rails.rb+
+
+This file is responsible for the initial definition of the +Rails+ module and, rather than defining the autoloads like +ActiveSupport+, +ActionDispatch+ and so on, it actually defines other functionality. Such as the +root+, +env+ and +application+ methods which are extremely useful in Rails 3 applications.
+
+However, before all that takes place the +rails/ruby_version_check+ file is required first.
+
+
+
+
+**** REVIEW IS HERE ****
+
This defines two methods on the module itself by using the familiar +class << self+ syntax. This allows you to call them as if they were class methods: +ActiveSupport.on_load_all+ and +ActiveSupport.load_all!+ respectively. The first method simply adds loading hooks to save them up for loading later on when +load_all!+ is called. By +call+'ing the block, the classes will be loaded. (NOTE: kind of guessing, I feel 55% about this).
The +on_load_all+ method is called later with the +Dependencies+, +Deprecation+, +Gzip+, +MessageVerifier+, +Multibyte+ and +SecureRandom+. What each of these modules do will be covered later.
diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile
index 80a1fdd38d..4cdd4f2709 100644
--- a/railties/guides/source/layouts_and_rendering.textile
+++ b/railties/guides/source/layouts_and_rendering.textile
@@ -106,7 +106,7 @@ Perhaps the simplest thing you can do with +render+ is to render nothing at all:
render :nothing => true
</ruby>
-If you look at the response for this using Curl you will see the following:
+If you look at the response for this using cURL, you will see the following:
<shell>
$ curl -i 127.0.0.1:3000/books
@@ -123,7 +123,7 @@ Cache-Control: no-cache
$
</shell>
-We see there is an empty response (no data after the +Cache-Control+ line), but the request was successful because Rails has set the response to 200 OK. You can set the +:status+ options on render to change this response. Rendering nothing can be useful for AJAX requests where all you want to send back to the browser is an acknowledgement that the request was completed.
+We see there is an empty response (no data after the +Cache-Control+ line), but the request was successful because Rails has set the response to 200 OK. You can set the +:status+ option on render to change this response. Rendering nothing can be useful for AJAX requests where all you want to send back to the browser is an acknowledgement that the request was completed.
TIP: You should probably be using the +head+ method, discussed later in this guide, instead of +render :nothing+. This provides additional flexibility and makes it explicit that you're only generating HTTP headers.
@@ -346,7 +346,7 @@ render :status => 500
render :status => :forbidden
</ruby>
-Rails understands either numeric status codes or symbols for status codes. You can find its list of status codes in +actionpack/lib/action_controller/status_codes.rb+. You can also see there how Rails maps symbols to status codes.
+Rails understands both numeric status codes and symbols for status codes.
h6. The +:location+ Option
@@ -604,7 +604,7 @@ Which would detect that there are no books, populate the +@books+ instance varia
h4. Using +head+ To Build Header-Only Responses
-The +head+ method exists to let you send back responses to the browser that have only headers. It provides a more obvious alternative to calling +render :nothing+. The +head+ method takes one response, which is interpreted as a hash of header names and values. For example, you can return only an error header:
+The +head+ method can be used to send responses with only headers to the browser. It provides a more obvious alternative to calling +render :nothing+. The +head+ method takes one parameter, which is interpreted as a hash of header names and values. For example, you can return only an error header:
<ruby>
head :bad_request
@@ -651,11 +651,9 @@ When Rails renders a view as a response, it does so by combining the view with t
* +yield+ and +content_for+
* Partials
-I'll discuss each of these in turn.
-
h4. Asset Tags
-Asset tags provide methods for generating HTML that links views to assets like images, videos, audio, JavaScript, stylesheets, and feeds. There are six types of include tag:
+Asset tags provide methods for generating HTML that links views to feeds, JavaScript, stylesheets, images, videos and audios. These are the six asset tags available in Rails:
* +auto_discovery_link_tag+
* +javascript_include_tag+
@@ -680,7 +678,7 @@ The +auto_discovery_link_tag+ helper builds HTML that most browsers and newsread
There are three tag options available for +auto_discovery_link_tag+:
* +:rel+ specifies the +rel+ value in the link (defaults to "alternate")
-* +:type+ specifies an explicit MIME type. Rails will generate an appropriate MIME type automatically
+* +:type+ specifies an explicit MIME type. Rails will generate an appropriate MIME type automatically.
* +:title+ specifies the title of the link
h5. Linking to Javascript Files with +javascript_include_tag+
@@ -829,7 +827,7 @@ You can also supply an alternate image to show on mouseover:
<%= image_tag "home.gif", :onmouseover => "menu/home_highlight.gif" %>
</erb>
-Or alternate text if the user has rendering images turned off in their browser, if you do not specify an explicit alt tag, it defaults to the file name of the file, capitalized and with no extension, for example, these two image tags would return the same code:
+You can supply alternate text for the image which will be used if the user has images turned off in their browser. If you do not specify an alt text explicitly, it defaults to the file name of the file, capitalized and with no extension. For example, these two image tags would return the same code:
<erb>
<%= image_tag "home.gif" %>
@@ -939,7 +937,7 @@ The main body of the view will always render into the unnamed +yield+. To render
h4. Using +content_for+
-The +content_for+ method allows you to insert content into a +yield+ block in your layout. You only use +content_for+ to insert content in named yields. For example, this view would work with the layout that you just saw:
+The +content_for+ method allows you to insert content into a named +yield+ block in your layout. For example, this view would work with the layout that you just saw:
<erb>
<% content_for :head do %>
@@ -966,7 +964,7 @@ The +content_for+ method is very helpful when your layout contains distinct regi
h4. Using Partials
-Partial templates - usually just called "partials" - are another device for breaking apart the rendering process into more manageable chunks. With a partial, you can move the code for rendering a particular piece of a response to its own file.
+Partial templates - usually just called "partials" - are another device for breaking the rendering process into more manageable chunks. With a partial, you can move the code for rendering a particular piece of a response to its own file.
h5. Naming Partials
@@ -1086,15 +1084,13 @@ Partials are very useful in rendering collections. When you pass a collection to
When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is +_product+, and within the +_product+ partial, you can refer to +product+ to get the instance that is being rendered.
-In Rails 3.0, there is also a shorthand for this. Assuming +@products+ is a collection of +product+ instances, you can simply write this in the +index.html.erb+:
+In Rails 3.0, there is also a shorthand for this. Assuming +@products+ is a collection of +product+ instances, you can simply write this in the +index.html.erb+ to produce the same result:
<erb>
<h1>Products</h1>
<%= render @products %>
</erb>
-To produce the same result.
-
Rails determines the name of the partial to use by looking at the model name in the collection. In fact, you can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection:
* +index.html.erb+
diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile
index 41bdd27e9b..b9401f3559 100644
--- a/railties/guides/source/performance_testing.textile
+++ b/railties/guides/source/performance_testing.textile
@@ -398,7 +398,7 @@ $ rails benchmarker 'Item.first' 'Item.last'
h4. +profiler+
-+profiler+ is a wrapper around http://ruby-prof.rubyforge.org/[ruby-prof] gem.
++profiler+ is a wrapper around the "ruby-prof":http://ruby-prof.rubyforge.org gem.
Usage:
diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile
index 7af9779ac7..32346e8f2b 100644
--- a/railties/guides/source/routing.textile
+++ b/railties/guides/source/routing.textile
@@ -595,7 +595,7 @@ You can specify what Rails should route +"/"+ to with the +root+ method:
root :to => 'pages#main'
</ruby>
-You should put the +root+ route at the end of the file.
+You should put the +root+ route at the end of the file. You also need to delete the public/index.html.erb file for the root route to take effect.
h3. Customizing Resourceful Routes
diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile
index 528c8861d4..fbafc40d93 100644
--- a/railties/guides/source/security.textile
+++ b/railties/guides/source/security.textile
@@ -524,10 +524,10 @@ h4. Logging
-- _Tell Rails not to put passwords in the log files._
-By default, Rails logs all requests being made to the web application. But log files can be a huge security issue, as they may contain login credentials, credit card numbers et cetera. When designing a web application security concept, you should also think about what will happen if an attacker got (full) access to the web server. Encrypting secrets and passwords in the database will be quite useless, if the log files list them in clear text. You can _(highlight)filter certain request parameters from your log files_ by the filter_parameter_logging method in a controller. These parameters will be marked [FILTERED] in the log.
+By default, Rails logs all requests being made to the web application. But log files can be a huge security issue, as they may contain login credentials, credit card numbers et cetera. When designing a web application security concept, you should also think about what will happen if an attacker got (full) access to the web server. Encrypting secrets and passwords in the database will be quite useless, if the log files list them in clear text. You can _(highlight)filter certain request parameters from your log files_ by appending them to <tt>config.filter_parameters</tt> in the application configuration. These parameters will be marked [FILTERED] in the log.
<ruby>
-filter_parameter_logging :password
+config.filter_parameters << :password
</ruby>
h4. Good Passwords