aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/guides/rails_guides/generator.rb28
-rw-r--r--railties/guides/rails_guides/indexer.rb35
-rw-r--r--railties/guides/source/2_2_release_notes.textile2
-rw-r--r--railties/guides/source/3_0_release_notes.textile28
-rw-r--r--railties/guides/source/action_view_overview.textile4
-rw-r--r--railties/guides/source/active_record_querying.textile2
-rw-r--r--railties/guides/source/active_support_core_extensions.textile4
-rw-r--r--railties/guides/source/configuring.textile2
-rw-r--r--railties/guides/source/contributing_to_rails.textile7
-rw-r--r--railties/guides/source/credits.html.erb10
-rw-r--r--railties/guides/source/debugging_rails_applications.textile2
-rw-r--r--railties/guides/source/form_helpers.textile26
-rw-r--r--railties/guides/source/getting_started.textile12
-rw-r--r--railties/guides/source/index.html.erb4
-rw-r--r--railties/guides/source/initialization.textile774
-rw-r--r--railties/guides/source/layouts_and_rendering.textile2
-rw-r--r--railties/guides/source/plugins.textile2
-rw-r--r--railties/guides/source/rails_on_rack.textile2
-rw-r--r--railties/guides/source/routing.textile23
-rw-r--r--railties/guides/source/testing.textile2
20 files changed, 816 insertions, 155 deletions
diff --git a/railties/guides/rails_guides/generator.rb b/railties/guides/rails_guides/generator.rb
index f577182f5f..bb7cdb6756 100644
--- a/railties/guides/rails_guides/generator.rb
+++ b/railties/guides/rails_guides/generator.rb
@@ -48,6 +48,7 @@ require 'set'
require 'fileutils'
require 'active_support/core_ext/string/output_safety'
+require 'active_support/core_ext/object/blank'
require 'action_controller'
require 'action_view'
@@ -57,14 +58,14 @@ require 'rails_guides/levenshtein'
module RailsGuides
class Generator
- attr_reader :guides_dir, :source_dir, :output_dir, :edge
+ attr_reader :guides_dir, :source_dir, :output_dir, :edge, :warnings, :all
GUIDES_RE = /\.(?:textile|html\.erb)$/
def initialize(output=nil)
initialize_dirs(output)
create_output_dir_if_needed
- set_edge
+ set_flags_from_environment
end
def generate
@@ -83,8 +84,10 @@ module RailsGuides
FileUtils.mkdir_p(output_dir)
end
- def set_edge
- @edge = ENV['EDGE'] == '1'
+ def set_flags_from_environment
+ @edge = ENV['EDGE'] == '1'
+ @warnings = ENV['WARNINGS'] == '1'
+ @all = ENV['ALL'] == '1'
end
def generate_guides
@@ -117,7 +120,7 @@ module RailsGuides
def generate?(source_file, output_file)
fin = File.join(source_dir, source_file)
fout = File.join(output_dir, output_file)
- ENV['ALL'] == '1' || !File.exists?(fout) || File.mtime(fout) < File.mtime(fin)
+ all || !File.exists?(fout) || File.mtime(fout) < File.mtime(fin)
end
def generate_guide(guide, output_file)
@@ -136,7 +139,7 @@ module RailsGuides
result = view.render(:layout => 'layout', :text => textile(body))
- warn_about_broken_links(result) if ENV['WARNINGS'] == '1'
+ warn_about_broken_links(result) if @warnings
end
f.write result
@@ -148,7 +151,7 @@ module RailsGuides
header = $1
header =~ /h2\.(.*)/
- page_title = $1.strip
+ page_title = "Ruby on Rails Guides: #{$1.strip}"
header = textile(header)
@@ -164,16 +167,16 @@ module RailsGuides
<ol class="chapters">
INDEX
- i = Indexer.new(body)
+ i = Indexer.new(body, warnings)
i.index
# Set index for 2 levels
i.level_hash.each do |key, value|
- link = view.content_tag(:a, :href => key[:id]) { textile(key[:title]).html_safe }
+ link = view.content_tag(:a, :href => key[:id]) { textile(key[:title], true).html_safe }
children = value.keys.map do |k|
- l = view.content_tag(:a, :href => k[:id]) { textile(k[:title]).html_safe }
- view.content_tag(:li, l.html_safe)
+ view.content_tag(:li,
+ view.content_tag(:a, :href => k[:id]) { textile(k[:title], true).html_safe })
end
children_ul = children.empty? ? "" : view.content_tag(:ul, children.join(" ").html_safe)
@@ -189,11 +192,12 @@ module RailsGuides
i.result
end
- def textile(body)
+ def textile(body, lite_mode=false)
# If the issue with notextile is fixed just remove the wrapper.
with_workaround_for_notextile(body) do |body|
t = RedCloth.new(body)
t.hard_breaks = false
+ t.lite_mode = lite_mode
t.to_html(:notestuff, :plusplus, :code, :tip)
end
end
diff --git a/railties/guides/rails_guides/indexer.rb b/railties/guides/rails_guides/indexer.rb
index 939404c85f..bd817786ed 100644
--- a/railties/guides/rails_guides/indexer.rb
+++ b/railties/guides/rails_guides/indexer.rb
@@ -1,10 +1,14 @@
+require 'active_support/core_ext/object/blank'
+require 'active_support/ordered_hash'
+
module RailsGuides
class Indexer
- attr_reader :body, :result, :level_hash
+ attr_reader :body, :result, :warnings, :level_hash
- def initialize(body)
- @body = body
- @result = @body.dup
+ def initialize(body, warnings)
+ @body = body
+ @result = @body.dup
+ @warnings = warnings
end
def index
@@ -13,29 +17,30 @@ module RailsGuides
private
- def process(string, current_level= 3, counters = [1])
+ def process(string, current_level=3, counters=[1])
s = StringScanner.new(string)
level_hash = ActiveSupport::OrderedHash.new
while !s.eos?
- s.match?(/h[0-9]\..*$/)
+ re = %r{^h(\d)(?:\((#.*?)\))?\s*\.\s*(.*)$}
+ s.match?(re)
if matched = s.matched
- matched =~ /h([0-9])\.(.*)$/
- level, title = $1.to_i, $2
+ matched =~ re
+ level, idx, title = $1.to_i, $2, $3.strip
if level < current_level
# This is needed. Go figure.
return level_hash
elsif level == current_level
index = counters.join(".")
- bookmark = '#' + title.strip.downcase.gsub(/\s+|_/, '-').delete('^a-z0-9-')
+ idx ||= '#' + title_to_idx(title)
- raise "Parsing Fail" unless @result.sub!(matched, "h#{level}(#{bookmark}). #{index}#{title}")
+ raise "Parsing Fail" unless @result.sub!(matched, "h#{level}(#{idx}). #{index} #{title}")
key = {
:title => title,
- :id => bookmark
+ :id => idx
}
# Recurse
counters << 1
@@ -51,5 +56,13 @@ module RailsGuides
end
level_hash
end
+
+ def title_to_idx(title)
+ idx = title.strip.downcase.gsub(/\s+|_/, '-').delete('^a-z0-9-').sub(/^[^a-z]*/, '')
+ if warnings && idx.blank?
+ puts "BLANK ID: please put an explicit ID for section #{title}, as in h5(#my-id)"
+ end
+ idx
+ end
end
end
diff --git a/railties/guides/source/2_2_release_notes.textile b/railties/guides/source/2_2_release_notes.textile
index 117635bcee..5628d7e52f 100644
--- a/railties/guides/source/2_2_release_notes.textile
+++ b/railties/guides/source/2_2_release_notes.textile
@@ -385,7 +385,7 @@ You can unpack or install a single gem by specifying +GEM=_gem_name_+ on the com
h4. Other Railties Changes
* If you're a fan of the "Thin":http://code.macournoyer.com/thin/ web server, you'll be happy to know that +script/server+ now supports Thin directly.
-* +script/plugin install <plugin> -r <revision>+ now works with git-based as well as svn-based plugins.
+* +script/plugin install &lt;plugin&gt; -r &lt;revision&gt;+ now works with git-based as well as svn-based plugins.
* +script/console+ now supports a +--debugger+ option
* Instructions for setting up a continuous integration server to build Rails itself are included in the Rails source
* +rake notes:custom ANNOTATION=MYFLAG+ lets you list out custom annotations.
diff --git a/railties/guides/source/3_0_release_notes.textile b/railties/guides/source/3_0_release_notes.textile
index cc84129b35..86d72db125 100644
--- a/railties/guides/source/3_0_release_notes.textile
+++ b/railties/guides/source/3_0_release_notes.textile
@@ -302,9 +302,11 @@ More Information:
h4. Action View
+h5. Unobtrusive JavaScript
+
Major re-write was done in the Action View helpers, implementing Unobtrusive JavaScript (UJS) hooks and removing the old inline AJAX commands. This enables Rails to use any compliant UJS driver to implement the UJS hooks in the helpers.
-What this means is that all previous <tt>remote_<method></tt> helpers have been removed from Rails core and put into the "Prototype Legacy Helper":http://github.com/rails/prototype_legacy_helper. To get UJS hooks into your HTML, you now pass <tt>:remote => true</tt> instead. For example:
+What this means is that all previous <tt>remote_&lt;method&gt;</tt> helpers have been removed from Rails core and put into the "Prototype Legacy Helper":http://github.com/rails/prototype_legacy_helper. To get UJS hooks into your HTML, you now pass <tt>:remote => true</tt> instead. For example:
<ruby>
form_for @post, :remote => true
@@ -316,6 +318,22 @@ Produces:
<form action="http://host.com" id="create-post" method="post" data-remote="true">
</html>
+h5. Helpers with Blocks
+
+Helpers like +form_for+ or +div_for+ that insert content from a block use +&lt;%=+ now:
+
+<erb>
+<%= form_for @post do |f| %>
+ ...
+<% end %>
+</erb>
+
+Your own helpers of that kind are expected to return a string, rather than appending to the output buffer by hand.
+
+Helpers that do something else, like +cache+ or +content_for+, are not affected by this change, they need +&lt;%+ as before.
+
+h5. Other Changes
+
* You no longer need to call <tt>h(string)</tt> to escape HTML output, it is on by default in all view templates. If you want the unescaped string, call <tt>raw(string)</tt>.
* Helpers now output HTML 5 by default.
* Form label helper now pulls values from I18n with a single value, so <tt>f.label :name</tt> will pull the <tt>:name</tt> translation.
@@ -382,6 +400,13 @@ class Person < ActiveRecord::Base
end
</ruby>
+There's also support for introspection:
+
+<ruby>
+User.validators
+User.validators_on(:login)
+</ruby>
+
More Information:
* "Sexy Validation in Rails 3":http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/
* "Rails 3 Validations Explained":http://lindsaar.net/2010/1/31/validates_rails_3_awesome_is_true
@@ -512,6 +537,7 @@ These are the main changes in Active Support:
* <tt>MissingSourceFile</tt> exists as a constant but it is now just equals to <tt>LoadError</tt>.
* Added <tt>Class#class_attribute</tt>, to be able to declare a class-level attribute whose value is inheritable and overwritable by subclasses.
* Finally removed +DeprecatedCallbacks+ in <tt>ActiveRecord::Associations</tt>.
+* +Object#metaclass+ is now +Kernel#singleton_class+ to match Ruby.
The following methods have been removed because they are now available in Ruby 1.8.7 and 1.9.
diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile
index 842a8408ad..df8cf4dc29 100644
--- a/railties/guides/source/action_view_overview.textile
+++ b/railties/guides/source/action_view_overview.textile
@@ -1304,7 +1304,7 @@ h4. PrototypeHelper::JavaScriptGenerator::GeneratorMethods
JavaScriptGenerator generates blocks of JavaScript code that allow you to change the content and presentation of multiple DOM elements. Use this in your Ajax response bodies, either in a +script+ tag or as plain JavaScript sent with a Content-type of "text/javascript".
-h5. <<
+h5(#push). <<
Writes raw JavaScript to the page.
@@ -1312,7 +1312,7 @@ Writes raw JavaScript to the page.
page << "alert('JavaScript with Prototype.');"
</ruby>
-h5. []
+h5(#at). []
Returns a element reference by finding it through it's id in the DOM.
diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile
index 3a62ee567d..a993dad900 100644
--- a/railties/guides/source/active_record_querying.textile
+++ b/railties/guides/source/active_record_querying.textile
@@ -742,7 +742,7 @@ end
The above code will execute just <strong>2</strong> queries, as opposed to <strong>11</strong> queries in the previous case:
<sql>
-SELECT * FROM clients
+SELECT * FROM clients LIMIT 10
SELECT addresses.* FROM addresses
WHERE (addresses.client_id IN (1,2,3,4,5,6,7,8,9,10))
</sql>
diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index b41b16b728..398d2b2392 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/railties/guides/source/active_support_core_extensions.textile
@@ -212,7 +212,7 @@ String.new.singleton_class # => #<Class:#<String:0x17a1d1c>>
WARNING: Fixnums and symbols have no singleton classes, +singleton_class+
raises +TypeError+ on them. Moreover, the singleton classes of +nil+, +true+, and +false+, are +NilClass+, +TrueClass+, and +FalseClass+, respectively.
-NOTE: Defined in +active_support/core_ext/object/singleton_class.rb+.
+NOTE: Defined in +active_support/core_ext/kernel/singleton_class.rb+.
h4. +class_eval(*args, &block)+
@@ -233,7 +233,7 @@ class Proc
end
</ruby>
-NOTE: Defined in +active_support/core_ext/object/singleton_class.rb+.
+NOTE: Defined in +active_support/core_ext/kernel/singleton_class.rb+.
h4. +acts_like?(duck)+
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 55077bcd24..03d2519ee7 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -183,7 +183,7 @@ There are only a few configuration options for Action View, starting with four o
* +config.action_view.warn_cache_misses+ tells Rails to display a warning whenever an action results in a cache miss on your view paths. The default is +false+.
-* +config.action_view.field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is <tt>Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>" }</tt>
+* +config.action_view.field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is <tt>Proc.new{ |html_tag, instance| "&lt;div class=\"fieldWithErrors\"&gt;#{html_tag}&lt;/div&gt;" }</tt>
* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+.
diff --git a/railties/guides/source/contributing_to_rails.textile b/railties/guides/source/contributing_to_rails.textile
index 1b6823a39a..5590895508 100644
--- a/railties/guides/source/contributing_to_rails.textile
+++ b/railties/guides/source/contributing_to_rails.textile
@@ -208,7 +208,7 @@ h4. Follow the Coding Conventions
Rails follows a simple set of coding style conventions.
* Two spaces, no tabs
-* Prefer +&&+/+||+ over +and+/+or+
+* Prefer +&amp;&amp;+/+||+ over +and+/+or+
* +MyClass.my_method(my_arg)+ not +my_method( my_arg )+ or +my_method my_arg+
* Follow the conventions you see used in the source already
@@ -273,7 +273,6 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/64
+* April 6, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* August 1, 2009: Updates/amplifications by "Mike Gunderloy":credits.html#mgunderloy
-* March 2, 2009: Initial draft by "Mike Gunderloy":credits.html#mgunderloy
-
-
+* March 2, 2009: Initial draft by "Mike Gunderloy":credits.html#mgunderloy \ No newline at end of file
diff --git a/railties/guides/source/credits.html.erb b/railties/guides/source/credits.html.erb
index 9851702df9..4d0d1fe782 100644
--- a/railties/guides/source/credits.html.erb
+++ b/railties/guides/source/credits.html.erb
@@ -1,3 +1,7 @@
+<% content_for :page_title do %>
+Ruby on Rails Guides: Credits
+<% end %>
+
<% content_for :header_section do %>
<h2>Credits</h2>
@@ -58,9 +62,3 @@
<%= author('Mikel Lindsaar', 'raasdnil') do %>
Mikel Lindsaar has been working with Rails since 2006 and is the author of the Ruby Mail gem and core contributor (he helped re-write Action Mailer's API). Mikel has a <a href="http://lindsaar.net/">blog</a> and <a href="http://twitter.com/raasdnil">tweets</a>.
<% end %>
-
-<h3 class="section">Rails Guides Reviewers</h3>
-
-<%= author('Jaime Iniesta', 'jaimeiniesta', 'jaimeiniesta.jpg') do %>
- Jaime Iniesta works as a Ruby on Rails freelance developer since 2005. He's a member of <a href="http://www.prorubyteam.com">ProRuby</a>, co-founder of the <a href="http://srug.org">Spanish Ruby Users Group</a>, member of <a href="http://spainrb.org">Spain.rb</a>, and organizer of <a href="http://conferenciarails.org">Conferencia Rails</a> and <a href="http://euruko2009.org">EuRuKo 2009</a>. Jaime has a <a href="http://jaimeiniesta.com">blog</a> and <a href="http://twitter.com/jaimeiniesta">tweets</a>.
-<% end %>
diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile
index 3eddf1a2b1..8f502bac99 100644
--- a/railties/guides/source/debugging_rails_applications.textile
+++ b/railties/guides/source/debugging_rails_applications.textile
@@ -704,7 +704,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/5
-* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":credits.html#jaimeiniesta
+* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* November 3, 2008: Accepted for publication. Added RJS, memory leaks and plugins chapters by "Emilio Tagua":credits.html#miloops
* October 19, 2008: Copy editing pass by "Mike Gunderloy":credits.html#mgunderloy
* September 16, 2008: initial version by "Emilio Tagua":credits.html#miloops
diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile
index fe0f8f1ac9..050486a5a4 100644
--- a/railties/guides/source/form_helpers.textile
+++ b/railties/guides/source/form_helpers.textile
@@ -21,7 +21,7 @@ h3. Dealing with Basic Forms
The most basic form helper is +form_tag+.
<erb>
-<% form_tag do %>
+<%= form_tag do %>
Form contents
<% end %>
</erb>
@@ -59,14 +59,14 @@ To create this form you will use +form_tag+, +label_tag+, +text_field_tag+, and
A basic search form
<html>
-<% form_tag(search_path, :method => "get") do %>
+<%= form_tag(search_path, :method => "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
</html>
-TIP: +search_path+ can be a named route specified in "routes.rb": <pre>map.search "search", :controller => "search"</pre>
+TIP: +search_path+ can be a named route specified in "routes.rb": <br /><tt>map.search "search", :controller => "search"</tt>
The above view code will result in the following markup:
@@ -222,7 +222,7 @@ end
The corresponding view +app/views/articles/new.html.erb+ using +form_for+ looks like this:
<erb>
-<% form_for :article, @article, :url => { :action => "create" }, :html => {:class => "nifty_form"} do |f| %>
+<%= form_for :article, @article, :url => { :action => "create" }, :html => {:class => "nifty_form"} do |f| %>
<%= f.text_field :title %>
<%= f.text_area :body, :size => "60x12" %>
<%= submit_tag "Create" %>
@@ -253,7 +253,7 @@ The helper methods called on the form builder are identical to the model object
You can create a similar binding without actually creating +&lt;form&gt;+ tags with the +fields_for+ helper. This is useful for editing additional model objects with the same form. For example if you had a Person model with an associated ContactDetail model you could create a form for creating both like so:
<erb>
-<% form_for :person, @person, :url => { :action => "create" } do |person_form| %>
+<%= form_for :person, @person, :url => { :action => "create" } do |person_form| %>
<%= person_form.text_field :name %>
<% fields_for @person.contact_detail do |contact_details_form| %>
<%= contact_details_form.text_field :phone_number %>
@@ -429,7 +429,7 @@ As with other helpers, if you were to use the +select+ helper on a form builder
<%= f.select(:city_id, ...) %>
</erb>
-WARNING: If you are using +select+ (or similar helpers such as +collection_select+, +select_tag+) to set a +belongs_to+ association you must pass the name of the foreign key (in the example above +city_id+), not the name of association itself. If you specify +city+ instead of +city_id+ Active Record will raise an error along the lines of <pre> ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) </pre> when you pass the +params+ hash to +Person.new+ or +update_attributes+. Another way of looking at this is that form helpers only edit attributes. You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly. You may wish to consider the use of +attr_protected+ and +attr_accessible+. For further details on this, see the "Ruby On Rails Security Guide":security.html#_mass_assignment.
+WARNING: If you are using +select+ (or similar helpers such as +collection_select+, +select_tag+) to set a +belongs_to+ association you must pass the name of the foreign key (in the example above +city_id+), not the name of association itself. If you specify +city+ instead of +city_id+ Active Record will raise an error along the lines of <tt> ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) </tt> when you pass the +params+ hash to +Person.new+ or +update_attributes+. Another way of looking at this is that form helpers only edit attributes. You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly. You may wish to consider the use of +attr_protected+ and +attr_accessible+. For further details on this, see the "Ruby On Rails Security Guide":security.html#_mass_assignment.
h4. Option Tags from a Collection of Arbitrary Objects
@@ -554,11 +554,11 @@ A common task is uploading some sort of file, whether it's a picture of a person
The following two forms both upload a file.
<erb>
-<% form_tag({:action => :upload}, :multipart => true) do %>
+<%= form_tag({:action => :upload}, :multipart => true) do %>
<%= file_field_tag 'picture' %>
<% end %>
-<% form_for @person, :html => {:multipart => true} do |f| %>
+<%= form_for @person, :html => {:multipart => true} do |f| %>
<%= f.file_field :picture %>
<% end %>
</erb>
@@ -591,7 +591,7 @@ h3. Customizing Form Builders
As mentioned previously the object yielded by +form_for+ and +fields_for+ is an instance of FormBuilder (or a subclass thereof). Form builders encapsulate the notion of displaying form elements for a single object. While you can of course write helpers for your forms in the usual way you can also subclass FormBuilder and add the helpers there. For example
<erb>
-<% form_for @person do |f| %>
+<%= form_for @person do |f| %>
<%= text_field_with_label f, :first_name %>
<% end %>
</erb>
@@ -599,7 +599,7 @@ As mentioned previously the object yielded by +form_for+ and +fields_for+ is an
can be replaced with
<erb>
-<% form_for @person, :builder => LabellingFormBuilder do |f| %>
+<%= form_for @person, :builder => LabellingFormBuilder do |f| %>
<%= f.text_field :first_name %>
<% end %>
</erb>
@@ -631,7 +631,7 @@ action for a Person model, +params[:model]+ would usually be a hash of all the a
Fundamentally HTML forms don't know about any sort of structured data, all they generate is name–value pairs, where pairs are just plain strings. The arrays and hashes you see in your application are the result of some parameter naming conventions that Rails uses.
-TIP: You may find you can try out examples in this section faster by using the console to directly invoke Rails' parameter parser. For example <pre> ActionController::UrlEncodedPairParser.parse_query_parameters "name=fred&phone=0123456789" # => {"name"=>"fred", "phone"=>"0123456789"} </pre>
+TIP: You may find you can try out examples in this section faster by using the console to directly invoke Rails' parameter parser. For example <tt> ActionController::UrlEncodedPairParser.parse_query_parameters "name=fred&phone=0123456789" # => {"name"=>"fred", "phone"=>"0123456789"} </tt>
h4. Basic Structures
@@ -694,7 +694,7 @@ The previous sections did not use the Rails form helpers at all. While you can c
You might want to render a form with a set of edit fields for each of a person's addresses. For example:
<erb>
-<% form_for @person do |person_form| %>
+<%= form_for @person do |person_form| %>
<%= person_form.text_field :name %>
<% for address in @person.addresses %>
<% person_form.fields_for address, :index => address do |address_form|%>
@@ -762,6 +762,8 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/1
+* April 6, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
+
h3. Authors
* Mislav Marohnić <mislav.marohnic@gmail.com>
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile
index 9669f7f155..17279146a7 100644
--- a/railties/guides/source/getting_started.textile
+++ b/railties/guides/source/getting_started.textile
@@ -602,7 +602,7 @@ The +&lt;%= render 'form' %&gt;+ line is our first introduction to _partials_ in
If you take a look at +views/posts/_form.html.erb+ file, you will see the following:
<erb>
-<% form_for(@post) do |f| %>
+<%= form_for(@post) do |f| %>
<%= f.error_messages %>
<div class="field">
@@ -906,7 +906,7 @@ So first, we'll wire up the Post show template (+/app/views/posts/show.html.erb+
</p>
<h2>Add a comment:</h2>
-<% form_for([@post, @post.comments.build]) do |f| %>
+<%= form_for([@post, @post.comments.build]) do |f| %>
<%= f.error_messages %>
<div class="field">
@@ -1041,7 +1041,7 @@ Then in the +app/views/posts/show.html.erb+ you can change it to look like the f
:collection => @post.comments %>
<h2>Add a comment:</h2>
-<% form_for([@post, @post.comments.build]) do |f| %>
+<%= form_for([@post, @post.comments.build]) do |f| %>
<%= f.error_messages %>
<div class="field">
@@ -1070,7 +1070,7 @@ h4. Rendering a Partial Form
Lets also move that new comment section out to it's own partial, again, you create a file +app/views/comments/_form.html.erb+ and in it you put:
<erb>
-<% form_for([@post, @post.comments.build]) do |f| %>
+<%= form_for([@post, @post.comments.build]) do |f| %>
<%= f.error_messages %>
<div class="field">
@@ -1278,7 +1278,7 @@ We will modify +views/posts/_form.html.erb+ to render a partial to make a tag:
<erb>
<% @post.tags.build %>
-<% form_for(@post) do |post_form| %>
+<%= form_for(@post) do |post_form| %>
<%= post_form.error_messages %>
<div class="field">
@@ -1432,7 +1432,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/2
-* April 1, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":credits.html#jaimeiniesta
+* April 1, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* February 8, 2010: Full re-write for Rails 3.0-beta, added helpers and before_filters, refactored code by "Mikel Lindsaar":credits:html#raasdnil
* January 24, 2010: Re-write for Rails 3.0 by "Mikel Lindsaar":credits:html#raasdnil
* July 18, 2009: Minor cleanup in anticipation of Rails 2.3.3 by "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb
index 8864b52325..52da16d453 100644
--- a/railties/guides/source/index.html.erb
+++ b/railties/guides/source/index.html.erb
@@ -1,3 +1,7 @@
+<% content_for :page_title do %>
+Ruby on Rails Guides
+<% end %>
+
<% content_for :header_section do %>
<h2>Ruby on Rails Guides</h2>
diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile
index 590f9e1a81..2d64510c2f 100644
--- a/railties/guides/source/initialization.textile
+++ b/railties/guides/source/initialization.textile
@@ -252,9 +252,14 @@ This file goes on to define some classes that will be automatically loaded using
<ruby>
require "active_support/inflector/methods"
-
+ require "active_support/lazy_load_hooks"
+
module ActiveSupport
module Autoload
+ def self.extended(base)
+ base.extend(LazyLoadHooks)
+ end
+
@@autoloads = {}
@@under_path = nil
@@at_path = nil
@@ -275,7 +280,34 @@ This file goes on to define some classes that will be automatically loaded using
end
</ruby>
-Then it uses the method +eager_autoload+ also defined in _active_support/dependencies/autoload.rb_:
+h4. Lazy Hooks
+
+At the top if the +ActiveSupport::Autoload+ module is the +def self.extended+ method:
+
+<ruby>
+ def self.extended(base)
+ base.extend(LazyLoadHooks)
+ end
+</ruby>
+
+This is called when we extend this module into one of our classes or modules, such is the case later on when we call +extend ActiveSupport::LazyLoadHooks+ not only in the +ActiveSupport+ module, but in all of the Railtie modules (+ActiveRecord+ and so on), as well as in a couple of places.
+
++ActiveSupport::LazyLoadHooks+ is responsible for defining methods used for running hooks that are defined during the initialization process, such as the one defined inside the +active_record.initialize_timezone+ initializer:
+
+<ruby>
+ initializer "active_record.initialize_timezone" do
+ ActiveRecord.base_hook do
+ self.time_zone_aware_attributes = true
+ self.default_timezone = :utc
+ end
+ end
+</ruby>
+
+When the initializer is ran it defines a +base_hook+ for +ActiveRecord+ and will only run it when +run_base_hooks+ is called, which in the case of Active Record, is ran after the entirety of +activerecord/lib/active_record/base.rb+ has been evaluated.
+
+h4. +require 'active_support'+ cont'd.
+
+This file also uses the method +eager_autoload+ also defined in _active_support/dependencies/autoload.rb_:
<ruby>
def eager_autoload
@@ -286,7 +318,7 @@ Then it uses the method +eager_autoload+ also defined in _active_support/depende
end
</ruby>
-As you can see for the duration of the +eager_autoload+ block the class variable +@@eager_autoload+ is set to +true+, which has the consequence of when +autoload+ is called that the location of the file for that specific +autoload+'d constant is added to the +@@autoloads+ hash initialized at the beginning of this module declaration. So now that you have part of the context, here's the other, the code:
+As you can see for the duration of the +eager_autoload+ block the class variable +@@eager_autoload+ is set to +true+, which has the consequence of when +autoload+ is called that the location of the file for that specific +autoload+'d constant is added to the +@@autoloads+ hash initialized at the beginning of this module declaration. So now that you have part of the context, here's the other, the code from _activesupport/lib/active_support.rb_:
<ruby>
require "active_support/dependencies/autoload"
@@ -330,11 +362,11 @@ As you can see for the duration of the +eager_autoload+ block the class variable
autoload :I18n, "active_support/i18n"
</ruby>
-So we know the ones in +eager_autoload+ are eagerly loaded and it does this by storing them in an +@@autoloads+ hash object. This is then referenced by the +ActiveSupport::Autoload.eager_autoload!+ method which will go through and +require+ all the files specified. This method is called in the +preload_frameworks+ initializer and will be covered much later in this guide.
+So we know the ones in +eager_autoload+ are eagerly loaded and it does this by storing them in an +@@autoloads+ hash object and then loading them via +eager_autoload!+ which is called via the +preload_frameworks+ initializer defined in _railties/lib/rails/application/bootstrap.rb_.
-The ones that are not +eager_autoload+'d are automatically loaded as they are called.
+The classes and modules that are not +eager_autoload+'d are automatically loaded as they are references
-Note: What it means to be autoloaded. An example of this would be calling the +ActiveSupport::TestCase+ class which hasn't yet been initialized. Because it's been specified as an +autoload+ Ruby will require the file that it's told to. The file it requires is not defined in the +autoload+ call here but, as you may have seen, in the +ActiveSupport::Autoload.autoload+ definition. So once that file has been required Ruby will try again and then if it still can't find it it will throw the all-too-familiar +uninitialized constant+ error.
+Note: What does it means to be autoloaded? An example of this would be calling the +ActiveSupport::TestCase+ class which hasn't yet been initialized. Because it's been specified as an +autoload+ Ruby will require the file that it's told to. The file it requires is not defined in the +autoload+ call here but, as you may have seen, in the +ActiveSupport::Autoload.autoload+ definition. So once that file has been required Ruby will try again and then if it still can't find it it will throw the all-too-familiar +uninitialized constant+ error.
h4. +require 'action_dispatch'+
@@ -628,7 +660,7 @@ h4. +require 'rails/engine'+
This file requires _rails/railtie.rb_ which defines +Rails::Railtie+.
-+Rails::Engine+ defines a couple of initializers for your application:
++Rails::Engine+ defines a couple of further initializers for your application:
* set_load_path
* set_autoload_paths
@@ -655,29 +687,78 @@ This means when you call either the +middleware+, +paths+ or +root+ methods you
h4. +require 'rails/railtie'+
-+Rails::Railtie+ provides a method of classes to hook into Rails, providing them with methods to add generators, rake tasks and subscribers. Some of the more noticeable railties are ActionMailer, ActiveRecord and ActiveResource and as you've probably already figured out, the engines that you use are railties too. Plugins also can be railties, but they do not have to be.
++Rails::Railtie+ (_pronounced Rail-tie, as in a bowtie_), provides a method of classes to hook into Rails, providing them with methods to add generators, rake tasks and subscribers. All of the facets of Rails are their own Railtie. and as you've probably already figured out, the engines that you use are railties too. Plugins also can be railties, but they do not have to be.
Here there's requires to _rails/initializable.rb_ and and _rails/configurable.rb_.
h4. +require 'rails/initializable'+
-The +Rails::Initializable+ module includes methods helpful for the initialization process in rails, such as the method to define initializers: +initializer+. This is included into +Rails::Railtie+ so it's available in +Rails::Engine+, +Rails::Application+ and +YourApp::Application+. In here we also see the class definition for +Rails::Initializer+, the class for all initializer objects.
+The +Rails::Initializable+ module includes methods helpful for the initialization process in rails, such as the method to define initializers: +initializer+. This is included into +Rails::Railtie+ so it's available there as well as +Rails::Engine+, +Rails::Application+ and +YourApp::Application+. In here we also see the class definition for +Rails::Initializer+, the class for all initializer objects.
h4. +require 'rails/configuration'+
The +Rails::Configuration+ module sets up shared configuration for applications, engines and plugins alike.
-At the top of this file _rails/paths.rb_ and _rails/rack.rb_ are +require+'d.
+At the top of this file there are three +require+s:
+
+<ruby>
+ require 'active_support/ordered_options'
+ require 'rails/paths'
+ require 'rails/rack'
+</ruby>
+
+h4. +require 'active_support/ordered_options'+
-TODO: Expand on this section.
++ActiveSupport::OrderedOptions+ is a special-purpose +OrderedHash+, used for keeping track of the options specified in the configuration of your application.
+
+TODO: expand.
h4. +require 'rails/paths'+
-TODO: Figure out the usefulness of this code. Potentially used for specifying paths to applications/engines/plugins?
+This file is used to set up the +Rails::Paths+ module which is used to set up helpers for referencing paths to the folders of your Rails application, such as in _railties/lib/rails/engine/configuration.rb_ where it is used to firstly define them:
+
+<ruby>
+ def paths
+ @paths ||= begin
+ paths = Rails::Paths::Root.new(@root)
+ paths.app "app", :eager_load => true, :glob => "*"
+ paths.app.controllers "app/controllers", :eager_load => true
+ paths.app.helpers "app/helpers", :eager_load => true
+ paths.app.models "app/models", :eager_load => true
+ paths.app.mailers "app/mailers", :eager_load => true
+ paths.app.metals "app/metal", :eager_load => true
+ paths.app.views "app/views", :eager_load => true
+ paths.lib "lib", :load_path => true
+ paths.lib.tasks "lib/tasks", :glob => "**/*.rake"
+ paths.lib.templates "lib/templates"
+ paths.config "config"
+ paths.config.initializers "config/initializers", :glob => "**/*.rb"
+ paths.config.locales "config/locales", :glob => "*.{rb,yml}"
+ paths.config.routes "config/routes.rb"
+ paths.public "public"
+ paths.public.javascripts "public/javascripts"
+ paths.public.stylesheets "public/stylesheets"
+ paths
+ end
+ end
+</ruby>
+
+You can then get to these helper methods by calling +YourApp::Application.config.paths+.
h4. +require 'rails/rack'+
-This file sets up some +autoload+'d modules for Rails::Rack.
+This file sets up some +autoload+'d constants for +Rails::Rack+:
+
+<ruby>
+ module Rails
+ module Rack
+ autoload :Debugger, "rails/rack/debugger"
+ autoload :Logger, "rails/rack/logger"
+ autoload :LogTailer, "rails/rack/log_tailer"
+ autoload :Static, "rails/rack/static"
+ end
+ end
+</ruby>
h4. +require 'rails/version'+
@@ -691,7 +772,9 @@ The code in this file declares +Rails::VERSION+ so that the version number can e
h4. +require 'rails/deprecation'+
-This sets up a couple of familiar constants: +RAILS_ENV+, +RAILS_ROOT+ and +RAILS_DEFAULT_LOGGER+ to still be usable, but raise a deprecation warning when they are. Their alternatives (explained previously) are now +Rails.env+, +Rails.root+ and +Rails.logger+ respectively.
+This sets up a couple of familiar constants: +RAILS_ENV+, +RAILS_ROOT+ and +RAILS_DEFAULT_LOGGER+ to still be usable, but raise a deprecation warning when they are. Their alternatives are now +Rails.env+, +Rails.root+ and +Rails.logger+ respectively.
+
+If you wish to know more about how they're deprecated see the +require 'active_support/deprecation/proxy_wrappers'+ section. TODO: link to section.
h4. +require 'rails/log_subscriber'+
@@ -719,29 +802,9 @@ This file declares two Railties, one for ActiveSupport and the other for I18n. I
This Railtie also defines an an +after_initialize+ block, which will (as the name implies) be ran after the initialization process. More on this later. TODO: When you write the section you can link to it.
-
h4. +require 'action_dispatch/railtie'+
-This file first makes a require out to the _action_dispatch_ file which is explained in the ActionDispatch Railtie section, next it makes a require to _rails_ which is _railties/lib/rails.rb_ which is already required.
-
-This file then extends the +ActionDispatch+ module defined when we called +require "action_dispatch"+ like this:
-
-<ruby>
- module ActionDispatch
- class Railtie < Rails::Railtie
- railtie_name :action_dispatch
-
- # Prepare dispatcher callbacks and run 'prepare' callbacks
- initializer "action_dispatch.prepare_dispatcher" do |app|
- # TODO: This used to say unless defined?(Dispatcher). Find out why and fix.
- require 'rails/dispatcher'
- ActionDispatch::Callbacks.to_prepare { app.routes_reloader.reload_if_changed }
- end
- end
- end
-</ruby>
-
-This defines just the one initializer: +action_dispatch.prepare_dispatcher+. More on this later. TODO: link when written
+This file is explained in the ActionDispatch Railtie Section. TODO: link
h4. Return to _rails/all.rb_
@@ -762,6 +825,19 @@ Now that we've covered the extensive process of what the first line does in this
end
</ruby>
+As you may be able to tell from the code, this is going through and loading all the Railties for ActiveRecord, ActionController, ActionMailer, ActiveResource. Two other Railties, one for ActiveSupport and one for ActionDispatch were required earlier, but are still covered in this section for continuity reasons. TODO: link.
+
+h4. ActiveSupport Railtie
+
+From ActiveSupport's README:
+
+Active Support is a collection of various utility classes and standard library extensions that were found useful for Rails.
+
+TODO: Quotify.
+
+h5. +require 'active_support/railtie'+
+
+
h4. ActiveRecord Railtie
The ActiveRecord Railtie takes care of hooking ActiveRecord into Rails. This depends on ActiveSupport, ActiveModel and Arel. From ActiveRecord's readme:
@@ -1439,109 +1515,549 @@ Next, the Railtie itself is defined:
end
</ruby>
-TODO: Explain LogSubscriber.
+The +ActionView::LogSubscriber+ sets up a method called +render_template+ which is called when a template is rendered. TODO: Templates only or partials and layouts also? I would imagine these fall under the templates category, but there needs to research to ensure this is correct.
-The initializer defined here, _action_view.cache_asset_timestamps_ is responsible for caching the timestamps on the ends of your assets. If you've ever seen a link generated by +image_tag+ or +stylesheet_link_tag+ you would know that I mean that this timestamp is the number after the _?_ in this example: _/javascripts/prototype.js?1265442620_. This initializer will do nothing if +cache_classes+ is set to false in any of your application's configuration. TODO: Elaborate.
+The sole initializer defined here, _action_view.cache_asset_timestamps_ is responsible for caching the timestamps on the ends of your assets. If you've ever seen a link generated by +image_tag+ or +stylesheet_link_tag+ you would know that I mean that this timestamp is the number after the _?_ in this example: _/javascripts/prototype.js?1265442620_. This initializer will do nothing if +cache_classes+ is set to false in any of your application's configuration. TODO: Elaborate.
-WARNING: EVERYTHING AFTER THIS POINT HAS NOT BEEN UPDATED TO REFLECT THE RAILS 3 BETA RELEASE. HERE BE DRAGONS. DANGER, WILL ROBINSON, DANGER. CONTINUE AT YOUR OWN PERIL!!!
+h4. ActionMailer Railtie
+The ActionMailer Railtie is responsible for including all the emailing functionality into Rails by way of the ActionMailer gem itself. ActionMailer is:
+Action Mailer is a framework for designing email-service layers. These layers
+are used to consolidate code for sending out forgotten passwords, welcome
+wishes on signup, invoices for billing, and any other use case that requires
+a written notification to either a person or another system.
-h4. ActionMailer Railtie
+Action Mailer is in essence a wrapper around Action Controller and the
+Mail gem. It provides a way to make emails using templates in the same
+way that Action Controller renders views using templates.
+
+TODO: Quotify.
+
+h5. +require 'action_mailer/railtie'+
+
+This file first makes two requires:
+
+<ruby>
+ require "action_mailer"
+ require "rails"
+</ruby>
+
+The requires in +action_mailer+ are already loaded or are core extensions:
+
+<ruby>
+ require 'abstract_controller'
+ require 'action_view'
+
+ # Common ActiveSupport usage in ActionMailer
+ require 'active_support/core_ext/class'
+ require 'active_support/core_ext/object/blank'
+ require 'active_support/core_ext/array/uniq_by'
+ require 'active_support/core_ext/module/attr_internal'
+ require 'active_support/core_ext/module/delegation'
+ require 'active_support/core_ext/string/inflections'
+ require 'active_support/lazy_load_hooks'
+</ruby>
+
+_abstract_controller_ is covered in the "ActionController Railtie" section. TODO: Cover AbstractController there and link to it.
+_action_view_ was required by the ActionView Railtie and will not be required again.
+
+For the core extensions you may reference the "Core Extensions" guide. TODO: Link to guide.
+
+_active_support/lazy_load_hooks_ was covered earlier in the guide and since it has already been required at this point in the initialization process, it will not be required again.
+
+The +require "rails"+ is referencing the _railties/lib/rails.rb_ file which was included back in TODO: link to section.
+
+_actionmailer/lib/action_mailer.rb_ then goes on to define the +ActionMailer+ module:
+
+<ruby>
+ module ActionMailer
+ extend ::ActiveSupport::Autoload
+
+ autoload :AdvAttrAccessor
+ autoload :Collector
+ autoload :Base
+ autoload :DeliveryMethods
+ autoload :DeprecatedApi
+ autoload :MailHelper
+ autoload :OldApi
+ autoload :Quoting
+ autoload :TestCase
+ autoload :TestHelper
+ end
+</ruby>
+
+And a +Text+ module too:
+
+<ruby>
+ module Text
+ extend ActiveSupport::Autoload
+
+ autoload :Format, 'text/format'
+ end
+</ruby>
+
+which is used by the +ActionMailer::MailerHelper+ method +block_format+:
+
+<ruby>
+ def block_format(text)
+ formatted = text.split(/\n\r\n/).collect { |paragraph|
+ Text::Format.new(
+ :columns => 72, :first_indent => 2, :body_indent => 2, :text => paragraph
+ ).format
+ }.join("\n")
+
+ # Make list points stand on their own line
+ formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" }
+ formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" }
+
+ formatted
+ end
+</ruby>
+
+h5. ActionMailer Railtie
+
+The Railtie defines the +log_subscriber+ as +ActionMailer::Railties::LogSubscriber.new+, with this class having two logging methods: one for delivery called +deliver+ and one for receipt called +receive+.
+
+The initializers defined in this Railtie are:
+
+* action_mailer.url_for
+* action_mailer.logger
+* action_mailer.set_configs
+
+These are covered later on the Initialization section. TODO: first write then link to Initialization section.
h4. ActiveResource Railtie
+The ActiveResource Railtie is responsible for creating an interface into remote sites that offer a REST API. The ActiveResource Railtie depends on ActiveSupport and ActiveModel.
+
+h5. +require 'active_resource/railtie'+
+
+This file defines the ActiveResource Railtie:
+
+<ruby>
+ require "active_resource"
+ require "rails"
+
+ module ActiveResource
+ class Railtie < Rails::Railtie
+ railtie_name :active_resource
+
+ require "active_resource/railties/log_subscriber"
+ log_subscriber ActiveResource::Railties::LogSubscriber.new
+
+ initializer "active_resource.set_configs" do |app|
+ app.config.active_resource.each do |k,v|
+ ActiveResource::Base.send "#{k}=", v
+ end
+ end
+ end
+ end
+</ruby>
+
+The +require 'rails'+ has already been done back in TODO: link to section.
+
+h5. +require 'active_resource'+
+
+This file, _activeresource/lib/active_resource.rb_, defines the +ActiveResource+ module, first off this will add the path to ActiveSupport and ActiveModel to the load path if it's not already there, then require both +active_support+ (_activesupport/lib/active_support.rb_) and +active_model+ (_activemodel/lib/active_model.rb_)
+
+<ruby>
+ activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
+ $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
+
+ activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__)
+ $:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path)
+
+ require 'active_support'
+ require 'active_model'
+
+ module ActiveResource
+ extend ActiveSupport::Autoload
+
+ autoload :Base
+ autoload :Connection
+ autoload :CustomMethods
+ autoload :Formats
+ autoload :HttpMock
+ autoload :Observing
+ autoload :Schema
+ autoload :Validations
+ end
+</ruby>
+
+h5. ActiveResource Railtie
+
+The Railtie itself is fairly short as ActiveResource is the smallest component of Rails.
+
+<ruby>
+ module ActiveResource
+ class Railtie < Rails::Railtie
+ railtie_name :active_resource
+
+ require "active_resource/railties/log_subscriber"
+ log_subscriber ActiveResource::Railties::LogSubscriber.new
+
+ initializer "active_resource.set_configs" do |app|
+ app.config.active_resource.each do |k,v|
+ ActiveResource::Base.send "#{k}=", v
+ end
+ end
+ end
+ end
+</ruby>
+
+The Railtie defines the +log_subscriber+ as +ActiveResource::Railties::LogSubscriber.new+ which has one method defined: +request+. +request+ is used whenever a request is made to an external service.
+
+There is only one initializer defined here: +set_configs+. This is covered later in the Initialization section.
+
+
h4. ActionDispatch Railtie
+ActionDispatch handles all dispatch work for Rails. It interfaces with ActionController to determine what action to undertake when a request comes in. TODO: I would quote the README but it is strangely absent. Flyin' blind here!
+
+The ActionDispatch Railtie was previously required when we called +require 'rails'+, but we will cover the Railtie here too.
+
+ActionDispatch depends on ActiveSupport.
+
+h5. +require 'action_dispatch/railtie'+
+
+This file defines the ActionDispatch Railtie:
+
+<ruby>
+ require "action_dispatch"
+ require "rails"
+
+ module ActionDispatch
+ class Railtie < Rails::Railtie
+ railtie_name :action_dispatch
+
+ config.action_dispatch.x_sendfile_header = "X-Sendfile"
+ config.action_dispatch.ip_spoofing_check = true
+
+ # Prepare dispatcher callbacks and run 'prepare' callbacks
+ initializer "action_dispatch.prepare_dispatcher" do |app|
+ # TODO: This used to say unless defined?(Dispatcher). Find out why and fix.
+ require 'rails/dispatcher'
+ ActionDispatch::Callbacks.to_prepare { app.routes_reloader.reload_if_changed }
+ end
+ end
+ end
+</ruby>
+
+The +require 'rails'+ has already been done back in TODO: link to section.
+
+
+
+
h5. +require 'action_dispatch'+
-This file, _lib/actionpack/lib/action_dispatch.rb_ is initially required through the _railties/lib/rails.rb_ file earlier on in the initilization process. We will cover again what it does.
+This file was already loaded earlier in the initialization process. TODO: link to it.
- requires +ActionDispatch+ which is responsible for serving the requests and responses for your application. In it there are three initial requires:
+h5. ActionDispatch Railtie
+
+The ActionDispatch Railtie is almost as short as the ActiveResource Railtie:
<ruby>
- require 'active_support'
- require 'active_support/dependencies/autoload'
+ require "action_dispatch"
+ require "rails"
- require 'rack'
+ module ActionDispatch
+ class Railtie < Rails::Railtie
+ railtie_name :action_dispatch
+
+ config.action_dispatch.x_sendfile_header = "X-Sendfile"
+ config.action_dispatch.ip_spoofing_check = true
+
+ # Prepare dispatcher callbacks and run 'prepare' callbacks
+ initializer "action_dispatch.prepare_dispatcher" do |app|
+ # TODO: This used to say unless defined?(Dispatcher). Find out why and fix.
+ require 'rails/dispatcher'
+ ActionDispatch::Callbacks.to_prepare { app.routes_reloader.reload_if_changed }
+ end
+ end
+ end
</ruby>
-At this point in the application _active_support_ and _active_support/dependencies/autoload_ have already been loaded (TODO: link to sections) and so it's up the last require of _rack_.
+The +config+ method here is from +Rails::Railtie+ and pertains to your application's configuration. In this case, it is setting up some defaults which you can later override in _config/application.rb_.
-h3. Common Includes
+This Railtie does not define a +log_subscriber+ and only defines one initializer: +prepare_dispatcher+.
-This section is for all the common includes in the Railties.
+h3. Return to _config/application.rb_
-h4. +require 'active_support/inflector'+
+Now that Rails has finished loading all the Railties by way of +require 'rails/all'+ Rails can now move on to the next line:
-This file is _activesupport/lib/active_support/inflector.rb_ and makes a couple of requires out different files tasked with putting inflections in place:
+<ruby>
+ Bundler.require :default, Rails.env
+</ruby>
+
+Bundler was +require+'d back in _config/boot.rb_ and now we'll dive into the internals of Bundler to determine precisely what this line accomplishes.
+
+h4. +Bundler.require+
+
++Bundler.require+ is defined in _lib/bundler.rb_:
<ruby>
- require 'active_support/inflector/inflections'
- require 'active_support/inflector/transliterate'
- require 'active_support/inflector/methods'
+ def require(*groups)
+ gemfile = default_gemfile
+ load(gemfile).require(*groups)
+ end
+</ruby>
- require 'active_support/inflections'
- require 'active_support/core_ext/string/inflections'
+The +groups+ variable here would be a two-element array of the arguments passed to +Bundler.require+. In this case we're going to assume, +Rails.env+ is +"development"+.
+
+h4. Locating the Gemfile
+
++default_gemfile+ is defined in _lib/bundler.rb_ and makes a call out to the +SharedHelpers+ module:
+
+<ruby>
+ def default_gemfile
+ SharedHelpers.default_gemfile
+ end
</ruby>
-The files included here define methods for modifying strings, such as +transliterate+ which will convert a Unicode string to its ASCII version, +parameterize+ for making strings into url-safe versions, +camelize+ for camel-casing a string such as +string_other+ into +StringOther+ and +ordinalize+ converting a string such as +101+ into +101st+. More information about these methods can be found in the ActiveSupport Guide. TODO: Link to AS Guide.
++SharedHelpers+ defines +default_gemfile+ like this:
-h4. +require 'active_support/core_ext/module/delegation'+
+<ruby>
+ def default_gemfile
+ gemfile = find_gemfile
+ gemfile or raise GemfileNotFound, "The default Gemfile was not found"
+ Pathname.new(gemfile)
+ end
+</ruby>
-_activesupport/lib/active_support/core_ext/module/delegation.rb_ defines the +delegate+ method which can be used to delegate methods to other methods in your code. Take the following code example:
++find_gemfile+ is defined like this:
<ruby>
- class Client < ActiveRecord::Base
- has_one :address
-
- delegate :address_line_1, :to => :address
+ def find_gemfile
+ return ENV['BUNDLE_GEMFILE'] if ENV['BUNDLE_GEMFILE']
+
+ previous = nil
+ current = File.expand_path(Dir.pwd)
+
+ until !File.directory?(current) || current == previous
+ filename = File.join(current, 'Gemfile')
+ return filename if File.file?(filename)
+ current, previous = File.expand_path("..", current), current
+ end
end
</ruby>
-This defines an +address_line_1+ method which is defined as:
+The first line of course means if you define the environment variable +BUNDLE_GEMFILE+ this is the name of the file that will be used and returned. If not, then Bundler will look for a file called _Gemfile_ in the current directory and if it can find it then it will return the filename. If it cannot, it will recurse up the directory structure until it does. Once the file is found a +Pathname+ is made from the expanded path to _Gemfile_.
+
+If the file cannot be found at all then +GemfileNotFound+ will be raised back in +default_gemfile+.
+
+h4. Loading the Gemfile
+
+Now that Bundler has determined what the _Gemfile_ is, it goes about loading it:
<ruby>
- def address_line_1(*args, &block)
- address.__send__(:address_line_1, *args, &block)
- rescue NoMethodError
- if address.nil?
- raise "address_line_1 is delegated to address.address_line_1, but address is nil: #{client.inspect}"
- end
+ def require(*groups)
+ gemfile = default_gemfile
+ load(gemfile).require(*groups)
end
</ruby>
-h4. +require 'active_support/core_ext/class/attribute_accessors'+
++load+ is defined like this in _lib/bundler.rb_:
-The file, _activesupport/lib/active_support/core_ext/class/attribute_accessors.rb_, defines the class accessor methods +cattr_writer+, +cattr_reader+ and +cattr_accessor+. +cattr_accessor+ defines a +cattr_reader+ and +cattr_writer+ for the symbol passed in. These methods work by defining class variables when you call their dynamic methods.
+<ruby>
+ def load(gemfile = default_gemfile)
+ root = Pathname.new(gemfile).dirname
+ Runtime.new root, definition(gemfile)
+ end
+</ruby>
-Throughout the Railties there a couple of common includes. They are listed here for your convenience.
+The next method to be called here would be +definition+ and it is defined like this:
-h4. +require 'active_support/core_ext/module/attr_internal+
+<ruby>
+ def definition(gemfile = default_gemfile)
+ configure
+ root = Pathname.new(gemfile).dirname
+ lockfile = root.join("Gemfile.lock")
+ if lockfile.exist?
+ Definition.from_lock(lockfile)
+ else
+ Definition.from_gemfile(gemfile)
+ end
+ end
+</ruby>
-This file defines three methods +attr_internal_reader+, +attr_internal_writer+ and +attr_internal_accessor+. These work very similar to the +attr_reader+, +attr_writer+ and +attr_accessor+ methods, except the variables they define begin with +@_+. This was done to ensure that they do not clash with variables used people using Rails, as people are less-likely to define say, +@_request+ than they are to define +@request+. An example of where this method is used is for +params+ in the +ActionController::Metal+ class.
++configure+ is responsible for setting up the path to gem home and gem path:
-h4. +require 'active_support/ruby/shim'+
+<ruby>
+ def configure
+ @configured ||= begin
+ configure_gem_home_and_path
+ true
+ end
+ end
+</ruby>
-The _activesupport/lib/active_support/ruby/shim.rb_ file requires methods that have been implemented in Ruby versions greater than 1.9. This is done so you can use Rails 3 on versions earlier than 1.9, such as 1.8.7. These methods are:
++configure_gem_home_and_path+ defined like this:
+
+<ruby>
+ def configure_gem_home_and_path
+ if settings[:disable_shared_gems]
+ ENV['GEM_HOME'] = File.expand_path(bundle_path, root)
+ ENV['GEM_PATH'] = ''
+ else
+ gem_home, gem_path = Gem.dir, Gem.path
+ ENV["GEM_PATH"] = [gem_home, gem_path].flatten.compact.join(File::PATH_SEPARATOR)
+ ENV["GEM_HOME"] = bundle_path.to_s
+ end
+
+ Gem.clear_paths
+ end
+</ruby>
+
+We do not have +settings[:disabled_shared_gems]+ set to true so this will execute the code under the +else+. The +ENV["GEM_PATH"]+ will resemble +/usr/local/lib/ruby/gems/1.9.1:/home/you/.gem/ruby/1.9.1:/usr/local/lib/ruby/gems/1.9.1+
+
+TODO: Why the duplicates? Added an issue: http://github.com/carlhuda/bundler/issues#issue/249
+
+And +ENV["GEM_HOME"]+ will be the path to the gems installed into your home directory by Bundler, something resembling +/home/you/.bundle/ruby/1.9.1+.
+
+After +configure_gem_home_and_path+ is done the +definition+ method goes about creating a +Definition+ from either +Gemfile.lock+ if it exists, or the +gemfile+ previously located. +Gemfile.lock+ only exists if +bundle lock+ has been ran and so far it has not.
+
++Definition.from_lock+ is defined in _lib/definition.rb_:
+
+<ruby>
+ def self.from_gemfile(gemfile)
+ gemfile = Pathname.new(gemfile).expand_path
+
+ unless gemfile.file?
+ raise GemfileNotFound, "#{gemfile} not found"
+ end
+
+ Dsl.evaluate(gemfile)
+ end
+</ruby>
+
+Now that the +gemfile+ is located +Dsl.evaluate+ goes about loading it. The code for this can be found in _lib/dsl.rb_:
+
+<ruby>
+ def self.evaluate(gemfile)
+ builder = new
+ builder.instance_eval(File.read(gemfile.to_s), gemfile.to_s, 1)
+ builder.to_definition
+ end
+</ruby>
+
++new+ here will, of course, call +initialize+ which sets up a couple of variables:
+
+<ruby>
+ def initialize
+ @source = nil
+ @sources = []
+ @dependencies = []
+ @group = nil
+ end
+</ruby>
+
+When Bundler calls +instance_eval+ on the new +Bundler::Dsl+ object it evaluates the content of the +gemfile+ file within the context of this instance. The Gemfile for a default Rails 3 project with all the comments stripped out looks like this:
+
+<ruby>
+ source 'http://rubygems.org'
+
+ gem 'rails', '3.0.0.beta1'
+
+ # Bundle edge Rails instead:
+ # gem 'rails', :git => 'git://github.com/rails/rails.git'
+
+ gem 'sqlite3-ruby', :require => 'sqlite3'
+</ruby>
+
+When Bundler loads this file it firstly calls the +source+ method on the +Bundler::Dsl+ object:
+
+<ruby>
+ def source(source, options = {})
+ @source = case source
+ when :gemcutter, :rubygems, :rubyforge then Source::Rubygems.new("uri" => "http://gemcutter.org")
+ when String then Source::Rubygems.new("uri" => source)
+ else source
+ end
+
+ options[:prepend] ? @sources.unshift(@source) : @sources << @source
+
+ yield if block_given?
+ @source
+ ensure
+ @source = nil
+ end
+</ruby>
+
+TODO: Perhaps make this a side-note. However you do that.
+
+The interesting thing to note about this method is that it takes a block, so you may do:
+
+<ruby>
+ source 'http://someothergemhost.com' do
+ gem 'your_favourite_gem'
+ end
+</ruby>
+
+if you wish to install _your_favourite_gem_ from _http://someothergemhost.com_.
+
+In this instance however a block is not specified so this sets up the +@source+ instance variable to be +'http://rubygems.org'+.
+
+The next method that is called is +gem+:
+
+<ruby>
+ def gem(name, *args)
+ options = Hash === args.last ? args.pop : {}
+ version = args.last || ">= 0"
+ if options[:group]
+ options[:group] = options[:group].to_sym
+ end
+
+ _deprecated_options(options)
+ _normalize_options(name, version, options)
+
+ @dependencies << Dependency.new(name, version, options)
+ end
+</ruby>
+
+This sets up a couple of important things initially. If you specify a gem like the following:
+
+<ruby>
+ gem 'rails', "2.3.4"
+</ruby>
+
+This sets +options+ to be an empty hash, but +version+ to be +"2.3.4"+. TODO: How does one pass options and versions?
+
+In the Gemfile for a default Rails project, the first +gem+ line is:
+
+<ruby>
+ gem 'rails', '3.0.0.beta2'
+</ruby>
+
+TODO: change version number.
+
+This line will check that +options+ contains no deprecated options by using the +_deprecated_options+ method, but the +options+ hash is empty. This is of course until +_normalize_options+ has its way:
+
+<ruby>
+ def _normalize_options(name, version, opts)
+ _normalize_hash(opts)
+
+ group = opts.delete("group") || @group
+
+ # Normalize git and path options
+ ["git", "path"].each do |type|
+ if param = opts[type]
+ options = _version?(version) ? opts.merge("name" => name, "version" => version) : opts.dup
+ source = send(type, param, options, :prepend => true)
+ opts["source"] = source
+ end
+ end
+
+ opts["source"] ||= @source
+
+ opts["group"] = group
+ end
+</ruby>
+
++_normalize_hash+ will convert all the keys in the +opts+ hash to strings.
-* +Date#next_month+
-* +Date#next_year+
-* +DateTime#to_date+
-* +DateTime#to_datetime+
-* +DateTime#xmlschema+
-* +Enumerable#group_by+
-* +Enumerable#each_with_object+
-* +Enumerable#none?+
-* +Process#daemon+
-* +String#ord+
-* +Time#to_date+
-* +Time.to_time+
-* +Time.to_datetime+
-For more information see the ActiveSupport Extensions guide TODO: link to relevant sections for each method.
-And "the REXML security fix detailed here":[http://weblog.rubyonrails.org/2008/8/23/dos-vulnerabilities-in-rexml]
h3. Firing it up!
@@ -3332,3 +3848,81 @@ Here, +is_utf8?+ calls a +consumes+ method on the not-yet-loaded +ActiveSupport:
The +Chars+ class defines, along with +consumes?+, other methods such as the "spaceship" method +<=>+. This method is referenced by the methods defined in the included +Comparable+ module and will return either +-1+, +0+ or +1+ depending on if the word is before, identical or after the compared word. For example, +'é'.mb_chars <=> 'ü'.mb_chars+ returns +-1+ as e comes before u in the alphabet. Other methods are the commonly used +split+, +=~+, +insert+ and +include?+.
+
+
+h3. Common Includes
+
+TODO: I feel this section would be better at the end of the guide as it breaks the flow.
+
+This section is for all the common includes in the Railties.
+
+h4. +require 'active_support/inflector'+
+
+This file is _activesupport/lib/active_support/inflector.rb_ and makes a couple of requires out different files tasked with putting inflections in place:
+
+<ruby>
+ require 'active_support/inflector/inflections'
+ require 'active_support/inflector/transliterate'
+ require 'active_support/inflector/methods'
+
+ require 'active_support/inflections'
+ require 'active_support/core_ext/string/inflections'
+</ruby>
+
+The files included here define methods for modifying strings, such as +transliterate+ which will convert a Unicode string to its ASCII version, +parameterize+ for making strings into url-safe versions, +camelize+ for camel-casing a string such as +string_other+ into +StringOther+ and +ordinalize+ converting a string such as +101+ into +101st+. More information about these methods can be found in the ActiveSupport Guide. TODO: Link to AS Guide.
+
+h4. +require 'active_support/core_ext/module/delegation'+
+
+_activesupport/lib/active_support/core_ext/module/delegation.rb_ defines the +delegate+ method which can be used to delegate methods to other methods in your code. Take the following code example:
+
+<ruby>
+ class Client < ActiveRecord::Base
+ has_one :address
+
+ delegate :address_line_1, :to => :address
+ end
+</ruby>
+
+This defines an +address_line_1+ method which is defined as:
+
+<ruby>
+ def address_line_1(*args, &block)
+ address.__send__(:address_line_1, *args, &block)
+ rescue NoMethodError
+ if address.nil?
+ raise "address_line_1 is delegated to address.address_line_1, but address is nil: #{client.inspect}"
+ end
+ end
+</ruby>
+
+h4. +require 'active_support/core_ext/class/attribute_accessors'+
+
+The file, _activesupport/lib/active_support/core_ext/class/attribute_accessors.rb_, defines the class accessor methods +cattr_writer+, +cattr_reader+ and +cattr_accessor+. +cattr_accessor+ defines a +cattr_reader+ and +cattr_writer+ for the symbol passed in. These methods work by defining class variables when you call their dynamic methods.
+
+Throughout the Railties there a couple of common includes. They are listed here for your convenience.
+
+h4. +require 'active_support/core_ext/module/attr_internal+
+
+This file defines three methods +attr_internal_reader+, +attr_internal_writer+ and +attr_internal_accessor+. These work very similar to the +attr_reader+, +attr_writer+ and +attr_accessor+ methods, except the variables they define begin with +@_+. This was done to ensure that they do not clash with variables used people using Rails, as people are less-likely to define say, +@_request+ than they are to define +@request+. An example of where this method is used is for +params+ in the +ActionController::Metal+ class.
+
+h4. +require 'active_support/ruby/shim'+
+
+The _activesupport/lib/active_support/ruby/shim.rb_ file requires methods that have been implemented in Ruby versions greater than 1.9. This is done so you can use Rails 3 on versions earlier than 1.9, such as 1.8.7. These methods are:
+
+* +Date#next_month+
+* +Date#next_year+
+* +DateTime#to_date+
+* +DateTime#to_datetime+
+* +DateTime#xmlschema+
+* +Enumerable#group_by+
+* +Enumerable#each_with_object+
+* +Enumerable#none?+
+* +Process#daemon+
+* +String#ord+
+* +Time#to_date+
+* +Time.to_time+
+* +Time.to_datetime+
+
+For more information see the ActiveSupport Extensions guide TODO: link to relevant sections for each method.
+
+And "the REXML security fix detailed here":[http://weblog.rubyonrails.org/2008/8/23/dos-vulnerabilities-in-rexml] \ No newline at end of file
diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile
index d9781fc966..fad687466e 100644
--- a/railties/guides/source/layouts_and_rendering.textile
+++ b/railties/guides/source/layouts_and_rendering.textile
@@ -1197,7 +1197,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/15
-* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":credits.html#jaimeiniesta
+* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* January 25, 2010: Rails 3.0 Update by "Mikel Lindsaar":credits.html#raasdnil
* December 27, 2008: Merge patch from Rodrigo Rosenfeld Rosas covering subtemplates
* December 27, 2008: Information on new rendering defaults by "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/plugins.textile b/railties/guides/source/plugins.textile
index 74c8ee2df9..4af00a5ace 100644
--- a/railties/guides/source/plugins.textile
+++ b/railties/guides/source/plugins.textile
@@ -1511,5 +1511,5 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/32-update-plugins-guide
-* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":credits.html#jaimeiniesta
+* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* November 17, 2008: Major revision by Jeff Dean
diff --git a/railties/guides/source/rails_on_rack.textile b/railties/guides/source/rails_on_rack.textile
index eef44d9ec9..320ce137bb 100644
--- a/railties/guides/source/rails_on_rack.textile
+++ b/railties/guides/source/rails_on_rack.textile
@@ -28,7 +28,7 @@ h3. Rails on Rack
h4. Rails Application's Rack Object
-<tt>ActionController::Dispatcher.new</tt> is the primary Rack application object of a Rails application. Any Rack compliant web server should be using +ActionController::Dispatcher.new+ object to serve a Rails application.</p>
+<tt>ActionController::Dispatcher.new</tt> is the primary Rack application object of a Rails application. Any Rack compliant web server should be using +ActionController::Dispatcher.new+ object to serve a Rails application.
h4. +rails server+
diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile
index 0cf8c45761..cf71e700dc 100644
--- a/railties/guides/source/routing.textile
+++ b/railties/guides/source/routing.textile
@@ -364,6 +364,27 @@ In this case, all of the normal routes except the route for +destroy+ (a +DELETE
TIP: If your application has many RESTful routes, using +:only+ and +:except+ to generate only the routes that you actually need can cut down on memory use and speed up the routing process.
+h5. Changing Path Names for Resources
+
+Using +scope+, we can alter path names generated by resources:
+
+<ruby>
+scope(:resources_path_names => { :new => "neu", :edit => "bearbeiten" }) do
+ resources :categories, :path => "kategorien"
+end
+</ruby>
+
+With +scope+ defined, it now generates routes with customized path names.
+
+|_.HTTP verb|_.URL |_.controller |_.action |_:used for|
+|GET |/kategorien |Categories |index |display a list of all categories|
+|GET |/kategorien/neu |Categories |new |return an HTML form for creating a new category|
+|POST |/kategorien |Categories |create |create a new category|
+|GET |/kategorien/1 |Categories |show |display a specific category|
+|GET |/kategorien/:id/bearbeiten |Categories |edit |return an HTML form for editing a category|
+|PUT |/kategorien/1 |Categories |update |update a specific category|
+|DELETE |/kategorien/1 |Categories |destroy |delete a specific category|
+
h4. Nested Resources
It's common to have resources that are logically children of other resources. For example, suppose your application includes these models:
@@ -809,7 +830,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/3
-* April 2, 2010: Updated guide to match new Routing DSL in Rails 3, by Rizwan Reza
+* April 2, 2010: Updated guide to match new Routing DSL in Rails 3, by "Rizwan Reza":http://www.rizwanreza.com/
* Febuary 1, 2010: Modifies the routing documentation to match new routing DSL in Rails 3, by Prem Sichanugrist
* October 4, 2008: Added additional detail on specifying verbs for resource member/collection routes, by "Mike Gunderloy":credits.html#mgunderloy
* September 23, 2008: Added section on namespaced controllers and routing, by "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile
index b1eee0ccb9..b291b541ba 100644
--- a/railties/guides/source/testing.textile
+++ b/railties/guides/source/testing.textile
@@ -940,7 +940,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/8
-* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":credits.html#jaimeiniesta
+* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* November 13, 2008: Revised based on feedback from Pratik Naik by "Akshay Surve":credits.html#asurve (not yet approved for publication)
* October 14, 2008: Edit and formatting pass by "Mike Gunderloy":credits.html#mgunderloy (not yet approved for publication)
* October 12, 2008: First draft by "Akshay Surve":credits.html#asurve (not yet approved for publication)