Skip to content
This repository
Browse code

Merge docrails

  • Loading branch information...
commit 18eb80ccc7e932f9a6c00462ceaeea648631b120 1 parent 4185a4a
Pratik authored

Showing 48 changed files with 1,915 additions and 876 deletions. Show diff stats Hide diff stats

  1. 2  actionpack/lib/action_controller/integration.rb
  2. 4  actionpack/lib/action_view/helpers/date_helper.rb
  3. 2  actionpack/lib/action_view/helpers/number_helper.rb
  4. 2  activemodel/lib/active_model/validations/inclusion.rb
  5. 14  activerecord/lib/active_record/associations/association_collection.rb
  6. 4  activerecord/lib/active_record/base.rb
  7. 38  activerecord/lib/active_record/batches.rb
  8. 2  activerecord/lib/active_record/validations.rb
  9. 2  activesupport/lib/active_support/core_ext/date/calculations.rb
  10. 16  railties/guides/files/stylesheets/main.css
  11. BIN  railties/guides/images/error_messages.png
  12. BIN  railties/guides/images/fxn.jpg
  13. BIN  railties/guides/images/i18n/demo_localized_pirate.png
  14. BIN  railties/guides/images/i18n/demo_translated_en.png
  15. BIN  railties/guides/images/i18n/demo_translated_pirate.png
  16. BIN  railties/guides/images/i18n/demo_translation_missing.png
  17. BIN  railties/guides/images/i18n/demo_untranslated.png
  18. 1  railties/guides/rails_guides.rb
  19. 36  railties/guides/rails_guides/generator.rb
  20. 2  railties/guides/rails_guides/indexer.rb
  21. 112  railties/guides/rails_guides/levenshtein.rb
  22. 115  railties/guides/source/2_3_release_notes.textile
  23. 32  railties/guides/source/action_controller_overview.textile
  24. 60  railties/guides/source/action_mailer_basics.textile
  25. 8  railties/guides/source/active_record_basics.textile
  26. 170  railties/guides/source/active_record_querying.textile
  27. 543  railties/guides/source/activerecord_validations_callbacks.textile
  28. 80  railties/guides/source/association_basics.textile
  29. 150  railties/guides/source/caching_with_rails.textile
  30. 43  railties/guides/source/command_line.textile
  31. 22  railties/guides/source/contribute.textile
  32. 239  railties/guides/source/contributing_to_rails.textile
  33. 33  railties/guides/source/credits.erb.textile
  34. 12  railties/guides/source/debugging_rails_applications.textile
  35. 56  railties/guides/source/form_helpers.textile
  36. 13  railties/guides/source/getting_started.textile
  37. 294  railties/guides/source/i18n.textile
  38. 10  railties/guides/source/index.erb.textile
  39. 21  railties/guides/source/layout.html.erb
  40. 62  railties/guides/source/layouts_and_rendering.textile
  41. 46  railties/guides/source/migrations.textile
  42. 222  railties/guides/source/nested_model_forms.textile
  43. 60  railties/guides/source/performance_testing.textile
  44. 34  railties/guides/source/plugins.textile
  45. 67  railties/guides/source/rails_on_rack.textile
  46. 34  railties/guides/source/routing.textile
  47. 100  railties/guides/source/security.textile
  48. 28  railties/guides/source/testing.textile
2  actionpack/lib/action_controller/integration.rb
@@ -5,7 +5,7 @@
5 5
 module ActionController
6 6
   module Integration #:nodoc:
7 7
     # An integration Session instance represents a set of requests and responses
8  
-    # performed sequentially by some virtual user. Becase you can instantiate
  8
+    # performed sequentially by some virtual user. Because you can instantiate
9 9
     # multiple sessions and run them side-by-side, you can also mimic (to some
10 10
     # limited extent) multiple simultaneous users interacting with your system.
11 11
     #
4  actionpack/lib/action_view/helpers/date_helper.rb
@@ -876,8 +876,8 @@ def input_id_from_type(type)
876 876
           input_name_from_type(type).gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '')
877 877
         end
878 878
 
879  
-        # Given an ordering of datetime components, create the selection html
880  
-        # and join them with their appropriate seperators
  879
+        # Given an ordering of datetime components, create the selection HTML
  880
+        # and join them with their appropriate separators.
881 881
         def build_selects_from_types(order)
882 882
           select = ''
883 883
           order.reverse.each do |type|
2  actionpack/lib/action_view/helpers/number_helper.rb
@@ -140,7 +140,7 @@ def number_to_percentage(number, options = {})
140 140
       #  number_with_delimiter(12345678)                        # => 12,345,678
141 141
       #  number_with_delimiter(12345678.05)                     # => 12,345,678.05
142 142
       #  number_with_delimiter(12345678, :delimiter => ".")     # => 12.345.678
143  
-      #  number_with_delimiter(12345678, :seperator => ",")     # => 12,345,678
  143
+      #  number_with_delimiter(12345678, :separator => ",")     # => 12,345,678
144 144
       #  number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
145 145
       #  # => 98 765 432,98
146 146
       #
2  activemodel/lib/active_model/validations/inclusion.rb
@@ -4,7 +4,7 @@ module ClassMethods
4 4
       # Validates whether the value of the specified attribute is available in a particular enumerable object.
5 5
       #
6 6
       #   class Person < ActiveRecord::Base
7  
-      #     validates_inclusion_of :gender, :in => %w( m f ), :message => "woah! what are you then!??!!"
  7
+      #     validates_inclusion_of :gender, :in => %w( m f )
8 8
       #     validates_inclusion_of :age, :in => 0..99
9 9
       #     validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension %s is not included in the list"
10 10
       #   end
14  activerecord/lib/active_record/associations/association_collection.rb
@@ -143,6 +143,8 @@ def transaction(*args)
143 143
       end
144 144
 
145 145
       # Remove all records from this association
  146
+      #
  147
+      # See delete for more info.
146 148
       def delete_all
147 149
         load_target
148 150
         delete(@target)
@@ -200,11 +202,11 @@ def delete(*records)
200 202
         end
201 203
       end
202 204
 
203  
-      # Destroy +records+ and remove from this association calling +before_remove+
204  
-      # and +after_remove+ callbacks.
  205
+      # Destroy +records+ and remove them from this association calling
  206
+      # +before_remove+ and +after_remove+ callbacks.
205 207
       #
206  
-      # Note this method will always remove records from database ignoring the
207  
-      # +:dependent+ option.
  208
+      # Note that this method will _always_ remove records from the database
  209
+      # ignoring the +:dependent+ option.
208 210
       def destroy(*records)
209 211
         remove_records(records) do |records, old_records|
210 212
           old_records.each { |record| record.destroy }
@@ -226,7 +228,9 @@ def clear
226 228
         self
227 229
       end
228 230
 
229  
-      # Destory all the records from this association
  231
+      # Destory all the records from this association.
  232
+      #
  233
+      # See destroy for more info.
230 234
       def destroy_all
231 235
         load_target
232 236
         destroy(@target)
4  activerecord/lib/active_record/base.rb
@@ -736,12 +736,12 @@ def create(attributes = nil, &block)
736 736
       # ==== Parameters
737 737
       #
738 738
       # * +id+ - This should be the id or an array of ids to be updated.
739  
-      # * +attributes+ - This should be a Hash of attributes to be set on the object, or an array of Hashes.
  739
+      # * +attributes+ - This should be a hash of attributes to be set on the object, or an array of hashes.
740 740
       #
741 741
       # ==== Examples
742 742
       #
743 743
       #   # Updating one record:
744  
-      #   Person.update(15, { :user_name => 'Samuel', :group => 'expert' })
  744
+      #   Person.update(15, :user_name => 'Samuel', :group => 'expert')
745 745
       #
746 746
       #   # Updating multiple records:
747 747
       #   people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
38  activerecord/lib/active_record/batches.rb
@@ -4,10 +4,12 @@ def self.included(base)
4 4
       base.extend(ClassMethods)
5 5
     end
6 6
 
7  
-    # When processing large numbers of records, it's often a good idea to do so in batches to prevent memory ballooning.
  7
+    # When processing large numbers of records, it's often a good idea to do
  8
+    # so in batches to prevent memory ballooning.
8 9
     module ClassMethods
9  
-      # Yields each record that was found by the find +options+. The find is performed by find_in_batches
10  
-      # with a batch size of 1000 (or as specified by the +batch_size+ option).
  10
+      # Yields each record that was found by the find +options+. The find is
  11
+      # performed by find_in_batches with a batch size of 1000 (or as
  12
+      # specified by the <tt>:batch_size</tt> option).
11 13
       #
12 14
       # Example:
13 15
       #
@@ -15,9 +17,10 @@ module ClassMethods
15 17
       #     person.party_all_night!
16 18
       #   end
17 19
       #
18  
-      # Note: This method is only intended to use for batch processing of large amounts of records that wouldn't fit in
19  
-      # memory all at once. If you just need to loop over less than 1000 records, it's probably better just to use the
20  
-      # regular find methods.
  20
+      # Note: This method is only intended to use for batch processing of
  21
+      # large amounts of records that wouldn't fit in memory all at once. If
  22
+      # you just need to loop over less than 1000 records, it's probably
  23
+      # better just to use the regular find methods.
21 24
       def find_each(options = {})
22 25
         find_in_batches(options) do |records|
23 26
           records.each { |record| yield record }
@@ -26,17 +29,22 @@ def find_each(options = {})
26 29
         self
27 30
       end
28 31
 
29  
-      # Yields each batch of records that was found by the find +options+ as an array. The size of each batch is
30  
-      # set by the +batch_size+ option; the default is 1000.
  32
+      # Yields each batch of records that was found by the find +options+ as
  33
+      # an array. The size of each batch is set by the <tt>:batch_size</tt>
  34
+      # option; the default is 1000.
31 35
       #
32  
-      # You can control the starting point for the batch processing by supplying the +start+ option. This is especially
33  
-      # useful if you want multiple workers dealing with the same processing queue. You can make worker 1 handle all the
34  
-      # records between id 0 and 10,000 and worker 2 handle from 10,000 and beyond (by setting the +start+ option on that
35  
-      # worker).
  36
+      # You can control the starting point for the batch processing by
  37
+      # supplying the <tt>:start</tt> option. This is especially useful if you
  38
+      # want multiple workers dealing with the same processing queue. You can
  39
+      # make worker 1 handle all the records between id 0 and 10,000 and
  40
+      # worker 2 handle from 10,000 and beyond (by setting the <tt>:start</tt>
  41
+      # option on that worker).
36 42
       #
37  
-      # It's not possible to set the order. That is automatically set to ascending on the primary key ("id ASC") 
38  
-      # to make the batch ordering work. This also mean that this method only works with integer-based primary keys.
39  
-      # You can't set the limit either, that's used to control the the batch sizes.
  43
+      # It's not possible to set the order. That is automatically set to
  44
+      # ascending on the primary key ("id ASC") to make the batch ordering
  45
+      # work. This also mean that this method only works with integer-based
  46
+      # primary keys. You can't set the limit either, that's used to control
  47
+      # the the batch sizes.
40 48
       #
41 49
       # Example:
42 50
       #
2  activerecord/lib/active_record/validations.rb
@@ -802,7 +802,7 @@ def validates_format_of(*attr_names)
802 802
       # Validates whether the value of the specified attribute is available in a particular enumerable object.
803 803
       #
804 804
       #   class Person < ActiveRecord::Base
805  
-      #     validates_inclusion_of :gender, :in => %w( m f ), :message => "woah! what are you then!??!!"
  805
+      #     validates_inclusion_of :gender, :in => %w( m f )
806 806
       #     validates_inclusion_of :age, :in => 0..99
807 807
       #     validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension {{value}} is not included in the list"
808 808
       #   end
2  activesupport/lib/active_support/core_ext/date/calculations.rb
... ...
@@ -1,7 +1,7 @@
1 1
 module ActiveSupport #:nodoc:
2 2
   module CoreExtensions #:nodoc:
3 3
     module Date #:nodoc:
4  
-      # Enables the use of time calculations within Time itself
  4
+      # Enables the use of time calculations within Date itself
5 5
       module Calculations
6 6
         def self.included(base) #:nodoc:
7 7
           base.extend ClassMethods
16  railties/guides/files/stylesheets/main.css
@@ -337,7 +337,7 @@ h6 {
337 337
 	margin-top: 0.25em;
338 338
 }
339 339
 
340  
-#mainCol dd.warning, #subCol dd.warning {
  340
+#mainCol div.warning, #subCol dd.warning {
341 341
 	background: #f9d9d8 url(../../images/tab_red.gif) no-repeat left top;
342 342
 	border: none;
343 343
 	padding: 1.25em 1.25em 1.25em 48px;
@@ -426,4 +426,16 @@ code {
426 426
 .clearfix {display: inline-block;}
427 427
 * html .clearfix {height: 1%;}
428 428
 .clearfix {display: block;}
429  
-.clear { clear:both; }
  429
+.clear { clear:both; }
  430
+
  431
+/* Same bottom margin for special boxes than for regular paragraphs, this way
  432
+intermediate whitespace looks uniform. */
  433
+div.code_container, div.important, div.caution, div.warning, div.note, div.info {
  434
+    margin-bottom: 1.5em;
  435
+}
  436
+
  437
+/* Remove bottom margin of paragraphs in special boxes, otherwise they get a
  438
+spurious blank area below with the box background. */
  439
+div.important p, div.caution p, div.warning p, div.note p, div.info p {
  440
+    margin-bottom: 0px;
  441
+}
BIN  railties/guides/images/error_messages.png
BIN  railties/guides/images/fxn.jpg
BIN  railties/guides/images/i18n/demo_localized_pirate.png
BIN  railties/guides/images/i18n/demo_translated_en.png
BIN  railties/guides/images/i18n/demo_translated_pirate.png
BIN  railties/guides/images/i18n/demo_translation_missing.png
BIN  railties/guides/images/i18n/demo_untranslated.png
1  railties/guides/rails_guides.rb
@@ -22,6 +22,7 @@ module RailsGuides
22 22
   autoload :Indexer, "rails_guides/indexer"
23 23
   autoload :Helpers, "rails_guides/helpers"
24 24
   autoload :TextileExtensions, "rails_guides/textile_extensions"
  25
+  autoload :Levenshtein, "rails_guides/levenshtein"
25 26
 end
26 27
 
27 28
 RedCloth.send(:include, RailsGuides::TextileExtensions)
36  railties/guides/rails_guides/generator.rb
@@ -109,8 +109,8 @@ def set_index(body, view)
109 109
     end
110 110
 
111 111
     def textile(body)
112  
-      # If the issue with nontextile is fixed just remove the wrapper.
113  
-      with_workaround_for_nontextile(body) do |body|
  112
+      # If the issue with notextile is fixed just remove the wrapper.
  113
+      with_workaround_for_notextile(body) do |body|
114 114
         t = RedCloth.new(body)
115 115
         t.hard_breaks = false
116 116
         t.to_html(:notestuff, :plusplus, :code, :tip)
@@ -120,33 +120,51 @@ def textile(body)
120 120
     # For some reason the notextile tag does not always turn off textile. See
121 121
     # LH ticket of the security guide (#7). As a temporary workaround we deal
122 122
     # with code blocks by hand.
123  
-    def with_workaround_for_nontextile(body)
  123
+    def with_workaround_for_notextile(body)
124 124
       code_blocks = []
125 125
       body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain)>(.*?)</\1>}m) do |m|
126 126
         es = ERB::Util.h($2)
127 127
         css_class = ['erb', 'shell'].include?($1) ? 'html' : $1
128 128
         code_blocks << %{<div class="code_container"><code class="#{css_class}">#{es}</code></div>}
129  
-        "dirty_workaround_for_nontextile_#{code_blocks.size - 1}"
  129
+        "\ndirty_workaround_for_notextile_#{code_blocks.size - 1}\n"
130 130
       end
131 131
       
132 132
       body = yield body
133 133
       
134  
-      body.gsub(%r{<p>dirty_workaround_for_nontextile_(\d+)</p>}) do |_|
  134
+      body.gsub(%r{<p>dirty_workaround_for_notextile_(\d+)</p>}) do |_|
135 135
         code_blocks[$1.to_i]
136 136
       end
137 137
     end
138 138
 
139 139
     def warn_about_broken_links(html)
  140
+      anchors = extract_anchors(html)
  141
+      check_fragment_identifiers(html, anchors)
  142
+    end
  143
+    
  144
+    def extract_anchors(html)
140 145
       # Textile generates headers with IDs computed from titles.
141  
-      anchors  = Set.new(html.scan(/<h\d\s+id="([^"]+)/).flatten)
  146
+      anchors = Set.new
  147
+      html.scan(/<h\d\s+id="([^"]+)/).flatten.each do |anchor|
  148
+        if anchors.member?(anchor)
  149
+          puts "*** DUPLICATE HEADER ID: #{anchor}, please consider rewording"
  150
+        else
  151
+          anchors << anchor
  152
+        end
  153
+      end
  154
+
142 155
       # Also, footnotes are rendered as paragraphs this way.
143 156
       anchors += Set.new(html.scan(/<p\s+class="footnote"\s+id="([^"]+)/).flatten)
144  
-      
145  
-      # Check fragment identifiers.
  157
+      return anchors
  158
+    end
  159
+    
  160
+    def check_fragment_identifiers(html, anchors)
146 161
       html.scan(/<a\s+href="#([^"]+)/).flatten.each do |fragment_identifier|
147 162
         next if fragment_identifier == 'mainCol' # in layout, jumps to some DIV
148 163
         unless anchors.member?(fragment_identifier)
149  
-          puts "BROKEN LINK: ##{fragment_identifier}"
  164
+          guess = anchors.min { |a, b|
  165
+            Levenshtein.distance(fragment_identifier, a) <=> Levenshtein.distance(fragment_identifier, b)
  166
+          }
  167
+          puts "*** BROKEN LINK: ##{fragment_identifier}, perhaps you meant ##{guess}."
150 168
         end
151 169
       end
152 170
     end
2  railties/guides/rails_guides/indexer.rb
@@ -29,7 +29,7 @@ def process(string, current_level= 3, counters = [1])
29 29
             return level_hash
30 30
           elsif level == current_level
31 31
             index = counters.join(".")
32  
-            bookmark = '#' + title.gsub(/[^a-z0-9\-_]+/i, '').underscore.dasherize
  32
+            bookmark = '#' + title.strip.downcase.gsub(/\s+|_/, '-').delete('^a-z0-9-')
33 33
 
34 34
             raise "Parsing Fail" unless @result.sub!(matched, "h#{level}(#{bookmark}). #{index}#{title}")
35 35
 
112  railties/guides/rails_guides/levenshtein.rb
... ...
@@ -0,0 +1,112 @@
  1
+#
  2
+# Levenshtein distance algorithm implementation for Ruby, with UTF-8 support
  3
+#
  4
+# Author::  Paul BATTLEY (pbattley @ gmail.com)
  5
+# Version:: 1.3
  6
+# Date::    2005-04-19
  7
+#
  8
+# == About
  9
+#
  10
+# The Levenshtein distance is a measure of how similar two strings s and t are,
  11
+# calculated as the number of deletions/insertions/substitutions needed to
  12
+# transform s into t.  The greater the distance, the more the strings differ.
  13
+#
  14
+# The Levenshtein distance is also sometimes referred to as the
  15
+# easier-to-pronounce-and-spell 'edit distance'.
  16
+#
  17
+# == Revision history
  18
+#
  19
+# * 2005-05-19 1.3 Repairing an oversight, distance can now be called via
  20
+#   Levenshtein.distance(s, t)
  21
+# * 2005-05-04 1.2 Now uses just one 1-dimensional array.  I think this is as
  22
+#   far as optimisation can go.
  23
+# * 2005-05-04 1.1 Now storing only the current and previous rows of the matrix
  24
+#   instead of the whole lot.
  25
+#
  26
+# == Licence
  27
+#
  28
+# Copyright (c) 2005 Paul Battley
  29
+#
  30
+# Usage of the works is permitted provided that this instrument is retained
  31
+# with the works, so that any entity that uses the works is notified of this
  32
+# instrument.
  33
+#
  34
+# DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.  
  35
+#
  36
+
  37
+module Levenshtein
  38
+
  39
+    #
  40
+    # Calculate the Levenshtein distance between two strings +str1+ and +str2+.
  41
+    # +str1+ and +str2+ should be ASCII or UTF-8.
  42
+    #
  43
+    def distance(str1, str2)
  44
+        s = str1.unpack('U*')
  45
+        t = str2.unpack('U*')
  46
+        n = s.length
  47
+        m = t.length
  48
+        return m if (0 == n)
  49
+        return n if (0 == m)
  50
+        
  51
+        d = (0..m).to_a
  52
+        x = nil
  53
+
  54
+        (0...n).each do |i|
  55
+            e = i+1
  56
+            (0...m).each do |j|
  57
+                cost = (s[i] == t[j]) ? 0 : 1
  58
+                x = [
  59
+                    d[j+1] + 1, # insertion
  60
+                    e + 1,      # deletion
  61
+                    d[j] + cost # substitution
  62
+                ].min
  63
+                d[j] = e
  64
+                e = x
  65
+            end
  66
+            d[m] = x
  67
+        end
  68
+
  69
+        return x
  70
+    end
  71
+
  72
+    extend self
  73
+end
  74
+
  75
+if (__FILE__ == $0)
  76
+    require 'test/unit'
  77
+
  78
+    class LevenshteinTest < Test::Unit::TestCase
  79
+        include Levenshtein
  80
+
  81
+        EXPECTED = [
  82
+            # Easy ones
  83
+            ['test', 'test', 0],
  84
+            ['test', 'tent', 1],
  85
+            ['gumbo', 'gambol', 2],
  86
+            ['kitten', 'sitting', 3],
  87
+            # Empty strings
  88
+            ['foo', '', 3],
  89
+            ['', '', 0],
  90
+            ['a', '', 1],
  91
+            # UTF-8
  92
+            ["f\303\266o", 'foo', 1],
  93
+            ["fran\303\247ais", 'francais', 1],
  94
+            ["fran\303\247ais", "fran\303\246ais", 1],
  95
+            ["\347\247\201\343\201\256\345\220\215\345\211\215\343\201\257"<<
  96
+             "\343\203\235\343\203\274\343\203\253\343\201\247\343\201\231",
  97
+             "\343\201\274\343\201\217\343\201\256\345\220\215\345\211\215\343\201"<<
  98
+             "\257\343\203\235\343\203\274\343\203\253\343\201\247\343\201\231", 
  99
+             2], # Japanese
  100
+            # Edge cases
  101
+            ['a', 'a', 0],
  102
+            ['0123456789', 'abcdefghijklmnopqrstuvwxyz', 26]
  103
+        ]
  104
+
  105
+        def test_known_distances
  106
+            EXPECTED.each do |a,b,x|
  107
+                assert_equal(x, distance(a, b))
  108
+                assert_equal(x, distance(b, a))
  109
+            end
  110
+        end
  111
+    end
  112
+end
115  railties/guides/source/2_3_release_notes.textile
Source Rendered
... ...
@@ -1,7 +1,5 @@
1 1
 h2. Ruby on Rails 2.3 Release Notes
2 2
 
3  
-NOTE: These release notes refer to RC2 of Rails 2.3. This is a release candidate, and not the final version of Rails 2.3. It's intended to be a stable testing release, and we urge you to test your own applications and report any issues to the "Rails Lighthouse":http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/overview.
4  
-
5 3
 Rails 2.3 delivers a variety of new and improved features, including pervasive Rack integration, refreshed support for Rails Engines, nested transactions for Active Record, dynamic and default scopes, unified rendering, more efficient routing, application templates, and quiet backtraces. This list covers the major upgrades, but doesn't include every little bug fix and change. If you want to see everything, check out the "list of commits":http://github.com/rails/rails/commits/master in the main Rails repository on GitHub or review the +CHANGELOG+ files for the individual Rails components.
6 4
 
7 5
 endprologue.
@@ -22,24 +20,25 @@ Rails has now broken with its CGI past, and uses Rack everywhere. This required
22 20
 Here's a summary of the rack-related changes:
23 21
 
24 22
 * +script/server+ has been switched to use Rack, which means it supports any Rack compatible server. +script/server+ will also pick up a rackup configuration file if one exists. By default, it will look for a +config.ru+ file, but you can override this with the +-c+ switch.
25  
-* The FCGI handler goes through Rack
26  
-* +ActionController::Dispatcher+ maintains its own default middleware stack. Middlewares can be injected in, reordered, and removed. The stack is compiled into a chain on boot. You can configure the middleware stack in +environment.rb+
  23
+* The FCGI handler goes through Rack.
  24
+* +ActionController::Dispatcher+ maintains its own default middleware stack. Middlewares can be injected in, reordered, and removed. The stack is compiled into a chain on boot. You can configure the middleware stack in +environment.rb+.
27 25
 * The +rake middleware+ task has been added to inspect the middleware stack. This is useful for debugging the order of the middleware stack.
28 26
 * The integration test runner has been modified to execute the entire middleware and application stack. This makes integration tests perfect for testing Rack middleware.
29 27
 * +ActionController::CGIHandler+ is a backwards compatible CGI wrapper around Rack. The +CGIHandler+ is meant to take an old CGI object and convert its environment information into a Rack compatible form.
30  
-* +CgiRequest+ and +CgiResponse+ have been removed
  28
+* +CgiRequest+ and +CgiResponse+ have been removed.
31 29
 * Session stores are now lazy loaded. If you never access the session object during a request, it will never attempt to load the session data (parse the cookie, load the data from memcache, or lookup an Active Record object).
32  
-* +CGI::Session::CookieStore+ has been replaced by +ActionController::Session::CookieStore+
33  
-* +CGI::Session::MemCacheStore+ has been replaced by +ActionController::Session::MemCacheStore+
34  
-* +CGI::Session::ActiveRecordStore+ has been replaced by +ActiveRecord::SessionStore+
35  
-* You can still change your session store with +ActionController::Base.session_store = :active_record_store+
36  
-* Default sessions options are still set with +ActionController::Base.session = { :key => "..." }+
37  
-* The mutex that normally wraps your entire request has been moved into middleware, +ActionController::Lock+
  30
+* You no longer need to use +CGI::Cookie.new+ in your tests for setting a cookie value. Assigning a +String+ value to request.cookies["foo"] now sets the cookie as expected.
  31
+* +CGI::Session::CookieStore+ has been replaced by +ActionController::Session::CookieStore+.
  32
+* +CGI::Session::MemCacheStore+ has been replaced by +ActionController::Session::MemCacheStore+.
  33
+* +CGI::Session::ActiveRecordStore+ has been replaced by +ActiveRecord::SessionStore+.
  34
+* You can still change your session store with +ActionController::Base.session_store = :active_record_store+.
  35
+* Default sessions options are still set with +ActionController::Base.session = { :key => "..." }+.
  36
+* The mutex that normally wraps your entire request has been moved into middleware, +ActionController::Lock+.
38 37
 * +ActionController::AbstractRequest+ and +ActionController::Request+ have been unified. The new +ActionController::Request+ inherits from +Rack::Request+. This affects access to +response.headers['type']+ in test requests. Use +response.content_type+ instead.
39 38
 * +ActiveRecord::QueryCache+ middleware is automatically inserted onto the middleware stack if +ActiveRecord+ has been loaded. This middleware sets up and flushes the per-request Active Record query cache.
40 39
 * The Rails router and controller classes follow the Rack spec. You can call a controller directly with +SomeController.call(env)+. The router stores the routing parameters in +rack.routing_args+.
41  
-* +ActionController::Request+ inherits from +Rack::Request+
42  
-* Instead of +config.action_controller.session = { :session_key => 'foo', ...+ use  +config.action_controller.session = { :key => 'foo', ...+
  40
+* +ActionController::Request+ inherits from +Rack::Request+.
  41
+* Instead of +config.action_controller.session = { :session_key => 'foo', ...+ use  +config.action_controller.session = { :key => 'foo', ...+.
43 42
 * Using the +ParamsParser+ middleware preprocesses any XML, JSON, or YAML requests so they can be read normally with any +Rack::Request+ object after it.
44 43
 
45 44
 h4. Renewed Support for Rails Engines
@@ -50,7 +49,7 @@ h3. Documentation
50 49
 
51 50
 The "Ruby on Rails guides":http://guides.rubyonrails.org/ project has published several additional guides for Rails 2.3. In addition, a "separate site":http://guides.rails.info/ maintains updated copies of the Guides for Edge Rails. Other documentation efforts include a relaunch of the "Rails wiki":http://newwiki.rubyonrails.org/ and early planning for a Rails Book.
52 51
 
53  
-* More Information: "Rails Documentation Projects":http://weblog.rubyonrails.org/2009/1/15/rails-documentation-projects
  52
+* More Information: "Rails Documentation Projects":http://weblog.rubyonrails.org/2009/1/15/rails-documentation-projects.
54 53
 
55 54
 h3. Ruby 1.9.1 Support
56 55
 
@@ -140,19 +139,19 @@ end
140 139
 
141 140
 You can pass most of the +find+ options into +find_in_batches+. However, you cannot specify the order that records will be returned in (they will always be returned in ascending order of primary key, which must be an integer), or use the +:limit+ option. Instead, use the +:batch_size+ option, which defaults to 1000, to set the number of records that will be returned in each batch.
142 141
 
143  
-The new +each+ method provides a wrapper around +find_in_batches+ that returns individual records, with the find itself being done in batches (of 1000 by default):
  142
+The new +find_each+ method provides a wrapper around +find_in_batches+ that returns individual records, with the find itself being done in batches (of 1000 by default):
144 143
 
145 144
 <ruby>
146  
-Customer.each do |customer|
  145
+Customer.find_each do |customer|
147 146
   customer.update_account_balance!
148 147
 end
149 148
 </ruby>
150 149
 
151 150
 Note that you should only use this method for batch processing: for small numbers of records (less than 1000), you should just use the regular find methods with your own loop.
152 151
 
153  
-* More Information: 
154  
- - "Rails 2.3: Batch Finding":http://afreshcup.com/2009/02/23/rails-23-batch-finding/
155  
- - "What's New in Edge Rails: Batched Find":http://ryandaigle.com/articles/2009/2/23/what-s-new-in-edge-rails-batched-find
  152
+* More Information (at that point the convenience method was called just +each+): 
  153
+** "Rails 2.3: Batch Finding":http://afreshcup.com/2009/02/23/rails-23-batch-finding/
  154
+** "What's New in Edge Rails: Batched Find":http://ryandaigle.com/articles/2009/2/23/what-s-new-in-edge-rails-batched-find
156 155
 
157 156
 h4. Multiple Conditions for Callbacks
158 157
 
@@ -175,18 +174,6 @@ developers =  Developer.find(:all, :group => "salary",
175 174
 
176 175
 * Lead Contributor: "Emilio Tagua":http://github.com/miloops
177 176
 
178  
-h4. Hash Conditions for has_many relationships
179  
-
180  
-You can once again use a hash in conditions for a +has_many+ relationship:
181  
-
182  
-<ruby>
183  
-has_many :orders, :conditions => {:status => 'confirmed'}
184  
-</ruby>
185  
-
186  
-That worked in Rails 2.1, fails in Rails 2.2, and will now work again in Rails 2.3 (if you're dealing with this issue in Rails 2.2, you can use a string rather than a hash to specify conditions).
187  
-
188  
-* Lead Contributor: "Frederick Cheung":http://www.spacevatican.org/
189  
-
190 177
 h4. Reconnecting MySQL Connections
191 178
 
192 179
 MySQL supports a reconnect flag in its connections - if set to true, then the client will try reconnecting to the server before giving up in case of a lost connection. You can now set +reconnect = true+ for your MySQL connections in +database.yml+ to get this behavior from a Rails application. The default is +false+, so the behavior of existing applications doesn't change.
@@ -198,15 +185,17 @@ MySQL supports a reconnect flag in its connections - if set to true, then the cl
198 185
 
199 186
 h4. Other Active Record Changes
200 187
 
201  
-* An extra +AS+ was removed from the generated SQL for has_and_belongs_to_many preloading, making it work better for some databases.
  188
+* An extra +AS+ was removed from the generated SQL for +has_and_belongs_to_many+ preloading, making it work better for some databases.
202 189
 * +ActiveRecord::Base#new_record?+ now returns +false+ rather than +nil+ when confronted with an existing record.
203 190
 * A bug in quoting table names in some +has_many :through+ associations was fixed.
204 191
 * You can now specify a particular timestamp for +updated_at+ timestamps: +cust = Customer.create(:name => "ABC Industries", :updated_at => 1.day.ago)+
205 192
 * Better error messages on failed +find_by_attribute!+ calls.
206 193
 * Active Record's +to_xml+ support gets just a little bit more flexible with the addition of a +:camelize+ option.
207  
-* A bug in canceling callbacks from +before_update+ or +before_create_ was fixed.
  194
+* A bug in canceling callbacks from +before_update+ or +before_create+ was fixed.
208 195
 * Rake tasks for testing databases via JDBC have been added.
209  
-* +validates_length_of+ will use a custom error message with the +:in+ or +:within+ options (if one is supplied)
  196
+* +validates_length_of+ will use a custom error message with the +:in+ or +:within+ options (if one is supplied).
  197
+* Counts on scoped selects now work properly, so you can do things like +Account.scoped(:select => "DISTINCT credit_limit").count+.
  198
+* +ActiveRecord::Base#invalid?+ now works as the opposite of +ActiveRecord::Base#valid?+.
210 199
 
211 200
 h3. Action Controller
212 201
 
@@ -299,7 +288,7 @@ In some of the first fruits of the Rails-Merb team merger, Rails 2.3 includes so
299 288
 
300 289
 h4. Improved Caching Performance
301 290
 
302  
-Rails now keeps a per-request local cache of requests, cutting down on unnecessary reads and leading to better site performance. While this work was originally limited to +MemCacheStore+, it is available to any remote store than implements the required methods.
  291
+Rails now keeps a per-request local cache of read from the remote cache stores, cutting down on unnecessary reads and leading to better site performance. While this work was originally limited to +MemCacheStore+, it is available to any remote store than implements the required methods.
303 292
 
304 293
 * Lead Contributor: "Nahum Wild":http://www.motionstandingstill.com/
305 294
 
@@ -307,6 +296,8 @@ h4. Localized Views
307 296
 
308 297
 Rails can now provide localized views, depending on the locale that you have set. For example, suppose you have a +Posts+ controller with a +show+ action. By default, this will render +app/views/posts/show.html.erb+. But if you set +I18n.locale = :da+, it will render +app/views/posts/show.da.html.erb+. If the localized template isn't present, the undecorated version will be used. Rails also includes +I18n#available_locales+ and +I18n::SimpleBackend#available_locales+, which return an array of the translations that are available in the current Rails project.
309 298
 
  299
+In addition, you can use the same scheme to localize the rescue files in the +public+ directory: +public/500.da.html+ or +public/404.en.html+ work, for example.
  300
+
310 301
 h4. Partial Scoping for Translations
311 302
 
312 303
 A change to the translation API makes things easier and less repetitive to write key translations within partials. If you call +translate(".foo")+ from the +people/index.html.erb+ template, you'll actually be calling +I18n.translate("people.index.foo")+ If you don't prepend the key with a period, then the API doesn't scope, just as before.
@@ -321,6 +312,9 @@ h4. Other Action Controller Changes
321 312
 * The +:only+ and +:except+ options for +map.resources+ are no longer inherited by nested resources.
322 313
 * The bundled memcached client has been updated to version 1.6.4.99.
323 314
 * The +expires_in+, +stale?+, and +fresh_when+ methods now accept a +:public+ option to make them work well with proxy caching.
  315
+* The +:requirements+ option now works properly with additional RESTful member routes.
  316
+* Shallow routes now properly respect namespaces.
  317
+* +polymorphic_url+ does a better job of handling objects with irregular plural names.
324 318
 
325 319
 h3. Action View
326 320
 
@@ -439,6 +433,34 @@ returns
439 433
 </optgroup>
440 434
 </ruby>
441 435
 
  436
+h4. Disabled Option Tags for Form Select Helpers
  437
+
  438
+The form select helpers (such as +select+ and +options_for_select+) now support a +:disabled+ option, which can take a single value or an array of values to be disabled in the resulting tags:
  439
+
  440
+<ruby>
  441
+select(:post, :category, Post::CATEGORIES, :disabled => ‘private‘)
  442
+</ruby>
  443
+
  444
+returns
  445
+
  446
+<ruby>
  447
+<select name=“post[category]“>
  448
+<option>story</option>
  449
+<option>joke</option>
  450
+<option>poem</option>
  451
+<option disabled=“disabled“>private</option>
  452
+</select>	
  453
+</ruby>
  454
+
  455
+You can also use an anonymous function to determine at runtime which options from collections will be selected and/or disabled:
  456
+
  457
+<ruby>
  458
+options_from_collection_for_select(@product.sizes, :name, :id, :disabled => lambda{|size| size.out_of_stock?})
  459
+</ruby>
  460
+
  461
+* Lead Contributor: "Tekin Suleyman":http://tekin.co.uk/
  462
+* More Information: "New in rails 2.3 - disabled option tags and lambdas for selecting and disabling options from collections":http://tekin.co.uk/2009/03/new-in-rails-23-disabled-option-tags-and-lambdas-for-selecting-and-disabling-options-from-collections/
  463
+
442 464
 h4. A Note About Template Loading
443 465
 
444 466
 Rails 2.3 includes the ability to enable or disable cached templates for any particular environment. Cached templates give you a speed boost because they don't check for a new template file when they're rendered - but they also mean that you can't replace a template "on the fly" without restarting the server.
@@ -472,6 +494,17 @@ h4. Object#tap Backport
472 494
 
473 495
 +Object#tap+ is an addition to "Ruby 1.9":http://www.ruby-doc.org/core-1.9/classes/Object.html#M000309 and 1.8.7 that is similar to the +returning+ method that Rails has had for a while: it yields to a block, and then returns the object that was yielded. Rails now includes code to make this available under older versions of Ruby as well.
474 496
 
  497
+h4. Swappable Parsers for XMLmini
  498
+
  499
+The support for XML parsing in ActiveSupport has been made more flexible by allowing you to swap in different parsers. By default, it uses the standard REXML implementation, but you can easily specify the faster LibXML or Nokogiri implementations for your own applications, provided you have the appropriate gems installed:
  500
+
  501
+<ruby>
  502
+XmlMini.backend = 'LibXML'
  503
+</ruby>
  504
+
  505
+* Lead Contributor: "Bart ten Brinke":http://www.movesonrails.com/ 
  506
+* Lead Contributor: "Aaron Patterson":http://tenderlovemaking.com/
  507
+
475 508
 h4. Fractional seconds for TimeWithZone
476 509
 
477 510
 The +Time+ and +TimeWithZone+ classes include an +xmlschema+ method to return the time in an XML-friendly string. As of Rails 2.3, +TimeWithZone+ supports the same argument for specifying the number of digits in the fractional second part of the returned string that +Time+ does:
@@ -494,6 +527,10 @@ h4. Other Active Support Changes
494 527
 * +ActiveSupport::OrderedHash+: now implements +each_key+ and +each_value+.
495 528
 * +ActiveSupport::MessageEncryptor+ provides a simple way to encrypt information for storage in an untrusted location (like cookies).
496 529
 * Active Support's +from_xml+ no longer depends on XmlSimple. Instead, Rails now includes its own XmlMini implementation, with just the functionality that it requires. This lets Rails dispense with the bundled copy of XmlSimple that it's been carting around.
  530
+* If you memoize a private method, the result will now be private.
  531
+* +String#parameterize+ accepts an optional separator: +"Quick Brown Fox".parameterize('_') => "quick_brown_fox"+.
  532
+* +number_to_phone+ accepts 7-digit phone numbers now.
  533
+* +ActiveSupport::Json.decode+ now handles +\u0000+ style escape sequences.
497 534
 
498 535
 h3. Railties
499 536
 
@@ -532,6 +569,12 @@ Quite a bit of work was done to make sure that bits of Rails (and its dependenci
532 569
 
533 570
 You can also specify (by using the new +preload_frameworks+ option) whether the core libraries should be autoloaded at startup. This defaults to +false+ so that Rails autoloads itself piece-by-piece, but there are some circumstances where you still need to bring in everything at once - Passenger and JRuby both want to see all of Rails loaded together.
534 571
 
  572
+h4. rake gem Task Rewrite
  573
+
  574
+The internals of the various <code>rake gem</code> tasks have been substantially revised, to make the system work better for a variety of cases. The gem system now knows the difference between development and runtime dependencies, has a more robust unpacking system, gives better information when querying for the status of gems, and is less prone to "chicken and egg" dependency issues when you're bringing things up from scratch. There are also fixes for using gem commands under JRuby and for dependencies that try to bring in external copies of gems that are already vendored.
  575
+
  576
+* Lead Contributor: "David Dollar":http://www.workingwithrails.com/person/12240-david-dollar
  577
+
535 578
 h4. Other Railties Changes
536 579
 
537 580
 * The instructions for updating a CI server to build Rails have been updated and expanded.
@@ -543,6 +586,8 @@ h4. Other Railties Changes
543 586
 * Rails Guides have been converted from AsciiDoc to Textile markup.
544 587
 * Scaffolded views and controllers have been cleaned up a bit.
545 588
 * +script/server+ now accepts a <tt>--path</tt> argument to mount a Rails application from a specific path.
  589
+* If any configured gems are missing, the gem rake tasks will skip loading much of the environment. This should solve many of the "chicken-and-egg" problems where rake gems:install couldn't run because gems were missing.
  590
+* Gems are now unpacked exactly once. This fixes issues with gems (hoe, for instance) which are packed with read-only permissions on the files.
546 591
 
547 592
 h3. Deprecated
548 593
 
32  railties/guides/source/action_controller_overview.textile
Source Rendered
@@ -20,7 +20,7 @@ For most conventional RESTful applications, the controller will receive the requ
20 20
 
21 21
 A controller can thus be thought of as a middle man between models and views. It makes the model data available to the view so it can display that data to the user, and it saves or updates data from the user to the model.
22 22
 
23  
-NOTE: For more details on the routing process, see "Rails Routing from the Outside In":routing_outside_in.html.
  23
+NOTE: For more details on the routing process, see "Rails Routing from the Outside In":routing.html.
24 24
 
25 25
 h3. Methods and Actions
26 26
 
@@ -83,7 +83,7 @@ class ClientsController < ActionController::Base
83 83
 end
84 84
 </ruby>
85 85
 
86  
-h4. Hash and array parameters
  86
+h4. Hash and Array Parameters
87 87
 
88 88
 The +params+ hash is not limited to one-dimensional keys and values. It can contain arrays and (nested) hashes. To send an array of values, append an empty pair of square brackets "[]" to the key name:
89 89
 
@@ -123,7 +123,7 @@ map.connect "/clients/:status",
123 123
 
124 124
 In this case, when a user opens the URL +/clients/active+, +params[:status]+ will be set to "active". When this route is used, +params[:foo]+ will also be set to "bar" just like it was passed in the query string. In the same way +params[:action]+ will contain "index".
125 125
 
126  
-h4. default_url_options
  126
+h4. +default_url_options+
127 127
 
128 128
 You can set global default parameters that will be used when generating URLs with +default_url_options+. To do this, define a method with that name in your controller:
129 129
 
@@ -180,7 +180,7 @@ ActionController::Base.session = {
180 180
 
181 181
 NOTE: Changing the secret when using the CookieStore will invalidate all existing sessions.
182 182
 
183  
-h4. Accessing the session
  183
+h4. Accessing the Session
184 184
 
185 185
 In your controller you can access the session through the +session+ instance method.
186 186
 
@@ -235,7 +235,7 @@ end
235 235
 
236 236
 To reset the entire session, use +reset_session+.
237 237
 
238  
-h4. The flash
  238
+h4. The Flash
239 239
 
240 240
 The flash is a special part of the session which is cleared with each request. This means that values stored there will only be available in the next request, which is useful for storing error messages etc. It is accessed in much the same way as the session, like a hash. Let's use the act of logging out as an example. The controller can send a message which will be displayed to the user on the next request:
241 241
 
@@ -288,7 +288,7 @@ class MainController < ApplicationController
288 288
 end
289 289
 </ruby>
290 290
 
291  
-h5. flash.now
  291
+h5. +flash.now+
292 292
 
293 293
 By default, adding values to the flash will make them available to the next request, but sometimes you may want to access those values in the same request. For example, if the +create+ action fails to save a resource and you render the +new+ template directly, that's not going to result in a new request, but you may still want to display a message using the flash. To do this, you can use +flash.now+ in the same way you use the normal +flash+:
294 294
 
@@ -381,7 +381,7 @@ end
381 381
 
382 382
 Now, the +LoginsController+'s +new+ and +create+ actions will work as before without requiring the user to be logged in. The +:only+ option is used to only skip this filter for these actions, and there is also an +:except+ option which works the other way. These options can be used when adding filters too, so you can add a filter which only runs for selected actions in the first place.
383 383
 
384  
-h4. After filters and around filters
  384
+h4. After Filters and Around Filters
385 385
 
386 386
 In addition to before filters, you can run filters after an action has run or both before and after. The after filter is similar to the before filter, but because the action has already been run it has access to the response data that's about to be sent to the client. Obviously, after filters can not stop the action from running.
387 387
 
@@ -403,7 +403,7 @@ private
403 403
 end
404 404
 </ruby>
405 405
 
406  
-h4. Other ways to use filters
  406
+h4. Other Ways to Use Filters
407 407
 
408 408
 While the most common way to use filters is by creating private methods and using *_filter to add them, there are two other ways to do the same thing.
409 409
 
@@ -517,7 +517,7 @@ h3. The Request and Response Objects
517 517
 
518 518
 In every controller there are two accessor methods pointing to the request and the response objects associated with the request cycle that is currently in execution. The +request+ method contains an instance of +AbstractRequest+ and the +response+ method returns a response object representing what is going to be sent back to the client.
519 519
 
520  
-h4. The +request+ object
  520
+h4. The +request+ Object
521 521
 
522 522
 The request object contains a lot of useful information about the request coming in from the client. To get a full list of the available methods, refer to the "API documentation":http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html. Among the properties that you can access on this object are:
523 523
 
@@ -538,7 +538,7 @@ h5. +path_parameters+, +query_parameters+, and +request_parameters+
538 538
 
539 539
 Rails collects all of the parameters sent along with the request in the +params+ hash, whether they are sent as part of the query string or the post body. The request object has three accessors that give you access to these parameters depending on where they came from. The +query_parameters+ hash contains parameters that were sent as part of the query string while the +request_parameters+ hash contains parameters sent as part of the post body. The +path_parameters+ hash contains parameters that were recognized by the routing as being part of the path leading to this particular controller and action.
540 540
 
541  
-h4. The response object
  541
+h4. The +response+ Object
542 542
 
543 543
 The response object is not usually used directly, but is built up during the execution of the action and rendering of the data that is being sent back to the user, but sometimes - like in an after filter - it can be useful to access the response directly. Some of these accessor methods also have setters, allowing you to change their values.
544 544
 
@@ -550,7 +550,7 @@ The response object is not usually used directly, but is built up during the exe
550 550
 |charset|The character set being used for the response. Default is "utf-8".|
551 551
 |headers|Headers used for the response.|
552 552
 
553  
-h5. Setting custom headers
  553
+h5. Setting Custom Headers
554 554
 
555 555
 If you want to set custom headers for a response then +response.headers+ is the place to do it. The headers attribute is a hash which maps header names to their values, and Rails will set some of them automatically. If you want to add or change a header, just assign it to +response.headers+ this way:
556 556
 
@@ -565,7 +565,7 @@ Rails comes with two built-in HTTP authentication mechanisms:
565 565
 * Basic Authentication
566 566
 * Digest Authentication
567 567
 
568  
-h4. HTTP basic authentication
  568
+h4. HTTP Basic Authentication
569 569
 
570 570
 HTTP basic authentication is an authentication scheme that is supported by the majority of browsers and other HTTP clients. As an example, consider an administration section which will only be available by entering a username and a password into the browser's HTTP basic dialog window. Using the built-in authentication is quite easy and only requires you to use one method, +authenticate_or_request_with_http_basic+.
571 571
 
@@ -587,7 +587,7 @@ end
587 587
 
588 588
 With this in place, you can create namespaced controllers that inherit from +AdminController+. The before filter will thus be run for all actions in those controllers, protecting them with HTTP basic authentication.
589 589
 
590  
-h4. HTTP digest authentication
  590
+h4. HTTP Digest Authentication
591 591
 
592 592
 HTTP digest authentication is superior to the basic authentication as it does not require the client to send an unencrypted password over the network (though HTTP basic authentication is safe over HTTPS). Using digest authentication with Rails is quite easy and only requires using one method, +authenticate_or_request_with_http_digest+.
593 593
 
@@ -640,7 +640,7 @@ end
640 640
 
641 641
 The +download_pdf+ action in the example above will call a private method which actually generates the PDF document and returns it as a string. This string will then be streamed to the client as a file download and a filename will be suggested to the user. Sometimes when streaming files to the user, you may not want them to download the file. Take images, for example, which can be embedded into HTML pages. To tell the browser a file is not meant to be downloaded, you can set the +:disposition+ option to "inline". The opposite and default value for this option is "attachment".
642 642
 
643  
-h4. Sending files
  643
+h4. Sending Files
644 644
 
645 645
 If you want to send a file that already exists on disk, use the +send_file+ method.
646 646
 
@@ -662,7 +662,7 @@ WARNING: Be careful when using data coming from the client (params, cookies, etc
662 662
 
663 663
 TIP: It is not recommended that you stream static files through Rails if you can instead keep them in a public folder on your web server. It is much more efficient to let the user download the file directly using Apache or another web server, keeping the request from unnecessarily going through the whole Rails stack. Although if you do need the request to go through Rails for some reason, you can set the +:x_sendfile+ option to true, and Rails will let the web server handle sending the file to the user, freeing up the Rails process to do other things. Note that your web server needs to support the +X-Sendfile+ header for this to work.
664 664
 
665  
-h4. RESTful downloads
  665
+h4. RESTful Downloads
666 666
 
667 667
 While +send_data+ works just fine, if you are creating a RESTful application having separate actions for file downloads is usually not necessary. In REST terminology, the PDF file from the example above can be considered just another representation of the client resource. Rails provides an easy and quite sleek way of doing "RESTful downloads". Here's how you can rewrite the example so that the PDF download is a part of the +show+ action, without any streaming:
668 668
 
@@ -712,7 +712,7 @@ Most likely your application is going to contain bugs or otherwise throw an exce
712 712
 
713 713
 Rails' default exception handling displays a "500 Server Error" message for all exceptions. If the request was made locally, a nice traceback and some added information gets displayed so you can figure out what went wrong and deal with it. If the request was remote Rails will just display a simple "500 Server Error" message to the user, or a "404 Not Found" if there was a routing error or a record could not be found. Sometimes you might want to customize how these errors are caught and how they're displayed to the user. There are several levels of exception handling available in a Rails application:
714 714
 
715  
-h4. The default 500 and 404 templates
  715
+h4. The Default 500 and 404 Templates
716 716
 
717 717
 By default a production application will render either a 404 or a 500 error message. These messages are contained in static HTML files in the +public+ folder, in +404.html+ and +500.html+ respectively. You can customize these files to add some extra information and layout, but remember that they are static; i.e. you can't use RHTML or layouts in them, just plain HTML.
718 718
 
60  railties/guides/source/action_mailer_basics.textile
Source Rendered
@@ -12,9 +12,9 @@ h3. Sending Emails
12 12
 
13 13
 This section will provide a step-by-step guide to creating a mailer and its views.
14 14
 
15  
-h4. Walkthrough to generating a mailer
  15
+h4. Walkthrough to Generating a Mailer
16 16
 
17  
-h5. Create the mailer:
  17
+h5. Create the Mailer
18 18
 
19 19
 <shell>
20 20
 ./script/generate mailer UserMailer
@@ -28,7 +28,7 @@ create  test/unit/user_mailer_test.rb
28 28
 
29 29
 So we got the model, the fixtures, and the tests.
30 30
 
31  
-h5. Edit the model:
  31
+h5. Edit the Model
32 32
 
33 33
 +app/models/user_mailer.rb+ contains an empty mailer:
34 34
 
@@ -60,7 +60,7 @@ Here is a quick explanation of the options presented in the preceding method. Fo
60 60
 
61 61
 The keys of the hash passed to +body+ become instance variables in the view. Thus, in our example the mailer view will have a +@user+ and a +@url+ instance variables available.
62 62
 
63  
-h5. Create a mailer view
  63
+h5. Create a Mailer View
64 64
 
65 65
 Create a file called +welcome_email.text.html.erb+ in +app/views/user_mailer/+. This will be the template used for the email, formatted in HTML:
66 66
 
@@ -83,7 +83,7 @@ Create a file called +welcome_email.text.html.erb+ in +app/views/user_mailer/+.
83 83
 
84 84
 Had we wanted to send text-only emails, the file would have been called +welcome_email.text.plain.erb+. Rails sets the content type of the email to be the one in the filename.
85 85
 
86  
-h5. Wire it up so that the system sends the email when a user signs up
  86
+h5. Wire It Up So That the System Sends the Email When a User Signs Up
87 87
 
88 88
 There are three ways to achieve this. One is to send the email from the controller that sends the email, another is to put it in a +before_create+ callback in the user model, and the last one is to use an observer on the user model. Whether you use the second or third methods is up to you, but staying away from the first is recommended. Not because it's wrong, but because it keeps your controller clean, and keeps all logic related to the user model within the user model. This way, whichever way a user is created (from a web form, or from an API call, for example), we are guaranteed that the email will be sent.
89 89
 
@@ -112,7 +112,7 @@ end
112 112
 
113 113
 Notice how we call +deliver_welcome_email+? In Action Mailer we send emails by calling +deliver_&lt;method_name&gt;+. In UserMailer, we defined a method called +welcome_email+, and so we deliver the email by calling +deliver_welcome_email+. The next section will go through how Action Mailer achieves this.
114 114
 
115  
-h4. Action Mailer and dynamic deliver_&lt;method_name&gt; methods
  115
+h4. Action Mailer and Dynamic +deliver_&lt;method_name&gt;+ methods
116 116
 
117 117
 So how does Action Mailer understand this +deliver_welcome_email+ call? If you read the documentation (http://api.rubyonrails.org/files/vendor/rails/actionmailer/README.html), you will find this in the "Sending Emails" section:
118 118
 
@@ -135,7 +135,7 @@ end
135 135
 
136 136
 Hence, if the method name starts with +deliver_+ followed by any combination of lowercase letters or underscore, +method_missing+  calls +new+ on your mailer class (+UserMailer+ in our example above), sending the combination of lower case letters or underscore, along with the parameters. The resulting object is then sent the +deliver!+ method, which well... delivers it.
137 137
 
138  
-h4. Complete list of Action Mailer user-settable attributes
  138
+h4. Complete List of Action Mailer User-Settable Attributes
139 139
 
140 140
 |bcc| The BCC addresses of the email|
141 141
 |body| The body of the email. This is either a hash (in which case it specifies the variables to pass to the template when it is rendered), or a string, in which case it specifies the actual body of the message|
@@ -184,7 +184,7 @@ end
184 184
 
185 185
 Just like with controller views, use +yield+ to render the view inside the layout.
186 186
 
187  
-h4. Generating URLs in Action Mailer views
  187
+h4. Generating URLs in Action Mailer Views
188 188
 
189 189
 URLs can be generated in mailer views using +url_for+ or named routes.
190 190
 Unlike controllers, the mailer instance doesn't have any context about the incoming request so you'll need to provide the +:host+, +:controller+, and +:action+:
@@ -216,7 +216,7 @@ config.action_mailer.default_url_options = { :host => "example.com" }
216 216
 
217 217
 If you set a default +:host+ for your mailers you need to pass +:only_path => false+ to +url_for+. Otherwise it doesn't get included.
218 218
 
219  
-h4. Sending multipart emails
  219
+h4. Sending Multipart Emails
220 220
 
221 221
 Action Mailer will automatically send multipart emails if you have different templates for the same action. So, for our UserMailer example, if you have +welcome_email.text.plain.erb+ and +welcome_email.text.html.erb+ in +app/views/user_mailer+, Action Mailer will automatically send a multipart email with the HTML and text versions setup as different parts.
222 222
 
@@ -240,7 +240,7 @@ class UserMailer < ActionMailer::Base
240 240
 end
241 241
 </ruby>
242 242
 
243  
-h4. Sending emails with attachments
  243
+h4. Sending Emails with Attachments
244 244
 
245 245
 Attachments can be added by using the +attachment+ method:
246 246
 
@@ -262,6 +262,38 @@ class UserMailer < ActionMailer::Base
262 262
 end
263 263
 </ruby>
264 264
 
  265
+h4. Sending Multipart Emails with Attachments
  266
+
  267
+Once you use the +attachment+ method, ActionMailer will no longer automagically use the correct template based on the filename. You must declare which template you are using for each content type via the +part+ method.
  268
+
  269
+In the following example, there would be two template files, +welcome_email_html.erb+ and +welcome_email_plain.erb+ in the +app/views/user_mailer+ folder.
  270
+
  271
+<ruby>
  272
+class UserMailer < ActionMailer::Base
  273
+  def welcome_email(user)
  274
+    recipients      user.email_address
  275
+    subject         "New account information"
  276
+    from            "system@example.com"
  277
+    content_type    "multipart/alternative"
  278
+
  279
+    part "text/html" do |p|
  280
+      p.body = render_message("welcome_email_html", :message => "<h1>HTML content</h1>")
  281
+    end
  282
+
  283
+    part "text/plain" do |p|
  284
+      p.body = render_message("welcome_email_plain", :message => "text content")
  285
+    end
  286
+
  287
+    attachment :content_type => "image/jpeg",
  288
+      :body => File.read("an-image.jpg")
  289
+
  290
+    attachment "application/pdf" do |a|
  291
+      a.body = generate_your_pdf_here()
  292
+    end
  293
+  end
  294
+end
  295
+</ruby>
  296
+
265 297
 h3. Receiving Emails
266 298
 
267 299
 Receiving and parsing emails with Action Mailer can be a rather complex endeavour. Before your email reaches your Rails app, you would have had to configure your system to somehow forward emails to your app, which needs to be listening for that. So, to receive emails in your Rails app you'll need:
@@ -320,7 +352,7 @@ The following configuration options are best made in one of the environment file
320 352
 |default_implicit_parts_order|When a message is built implicitly (i.e. multiple parts are assembled from templates which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to ["text/html", "text/enriched", "text/plain"]. Items that appear first in the array have higher priority in the mail client and appear last in the mime encoded message. You can also pick a different order from inside a method with implicit_parts_order.|
321 353
 
322 354
 
323  
-h4. Example Action Mailer configuration
  355
+h4. Example Action Mailer Configuration
324 356
 
325 357
 An example would be:
326 358
 
@@ -352,7 +384,7 @@ ActionMailer::Base.smtp_settings = {
352 384
 }
353 385
 </ruby>
354 386
 
355  
-h4. Configure Action Mailer to recognize HAML templates
  387
+h4. Configure Action Mailer to Recognize HAML Templates
356 388
 
357 389
 In +config/environment.rb+, add the following line:
358 390
 
@@ -386,3 +418,7 @@ end
386 418
 </ruby>
387 419
 
388 420
 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.
  421
+
  422
+h3. Changelog
  423
+
  424
+"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/25
8  railties/guides/source/active_record_basics.textile
Source Rendered
@@ -29,7 +29,7 @@ h3. Object Relational Mapping
29 29
 
30 30
 The relation between databases and object-oriented software is called ORM, which is short for "Object Relational Mapping". The purpose of an ORM framework is to minimize the mismatch existent between relational databases and object-oriented software. In applications with a domain model, we have objects that represent both the state of the system and the behavior of the real world elements that were modeled through these objects. Since we need to store the system's state somehow, we can use relational databases, which are proven to be an excellent approach to data management. Usually this may become a very hard thing to do, since we need to create an object-oriented model of everything that lives in the database, from simple columns to complicated relations between different tables. Doing this kind of thing by hand is a tedious and error prone job. This is where an ORM framework comes in.
31 31
 
32  
-h3. ActiveRecord as an ORM framework
  32
+h3. ActiveRecord as an ORM Framework
33 33
 
34 34
 ActiveRecord gives us several mechanisms, being the most important ones the ability to:
35 35
 
@@ -41,7 +41,7 @@ ActiveRecord gives us several mechanisms, being the most important ones the abil
41 41
 
42 42
 It's easy to see that the Rails Active Record implementation goes way beyond the basic description of the Active Record Pattern.
43 43
 
44  
-h3. Active Record inside the MVC model
  44
+h3. Active Record Inside the MVC Model
45 45
 
46 46
 Active Record plays the role of model inside the MVC structure followed by Rails applications. Since model objects should encapsulate both state and logic of your applications, it's ActiveRecord responsibility to deliver you the easiest possible way to recover this data from the database.
47 47
 
@@ -81,7 +81,7 @@ There are also some optional column names that will create additional features t
81 81
 
82 82
 NOTE: While these column names are optional they are in fact reserved by ActiveRecord. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling.
83 83
 
84  
-h3. Creating ActiveRecord models
  84
+h3. Creating ActiveRecord Models
85 85
 
86 86
 It's very easy to create ActiveRecord models. All you have to do is to subclass the ActiveRecord::Base class and you're good to go:
87 87
 
@@ -107,7 +107,7 @@ p.name = "Some Book"
107 107
 puts p.name # "Some Book"
108 108
 </ruby>
109 109
 
110  
-h3. Overriding the naming conventions
  110
+h3. Overriding the Naming Conventions
111 111
 
112 112
 What if you need to follow a different naming convention or need to use your Rails application with a legacy database? No problem, you can easily override the default conventions.
113 113
 
170  railties/guides/source/active_record_querying.textile
Source Rendered
@@ -54,7 +54,7 @@ end
54 54
 
55 55
 Active Record will perform queries on the database for you and is compatible with most database systems (MySQL, PostgreSQL and SQLite to name a few). Regardless of which database system you're using, the Active Record method format will always be the same.
56 56