<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>db/migrate/20081015223630_add_settings_table.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/not_blank.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/not_nil.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/config/helpers.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/config/search.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/modifiers/lower.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/modifiers/ltrim.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/modifiers/rtrim.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/modifiers/trim.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/modifiers/upper.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/test/fixtures/cats.yml</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/test/fixtures/dogs.yml</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/test_libs/acts_as_tree.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/test_libs/ordered_hash.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/searchgasm/test_libs/rexml_fix.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/actionmailer/test/fixtures/test_mailer/body_ivar.erb</filename>
    </added>
    <added>
      <filename>vendor/rails/actionpack/test/fixtures/test/sub_template_raise.html.erb</filename>
    </added>
    <added>
      <filename>vendor/rails/activerecord/lib/active_record/i18n_interpolation_deprecation.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/activerecord/test/cases/reload_models_test.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/activesupport/bin/generate_tables</filename>
    </added>
    <added>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/float/time.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/integer/time.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/string/multibyte.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/activesupport/lib/active_support/multibyte/exceptions.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/activesupport/lib/active_support/multibyte/unicode_database.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/activesupport/lib/active_support/rescuable.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/activesupport/test/multibyte_test_helpers.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/activesupport/test/multibyte_unicode_database_test.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/activesupport/test/rescuable_test.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/configs/databases/ibm_db.yml</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/lib/rails/vendor_gem_source_index.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-a-0.4.0/.specification</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-a-0.4.0/lib/dummy-gem-a.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-b-0.4.0/.specification</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-b-0.4.0/lib/dummy-gem-b.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-b-0.6.0/.specification</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-b-0.6.0/lib/dummy-gem-b.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-c-0.4.0/.specification</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-c-0.4.0/lib/dummy-gem-c.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-c-0.6.0/.specification</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-c-0.6.0/lib/dummy-gem-c.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-d-1.0.0/lib/dummy-gem-d.rb</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-e-1.0.0/.specification</filename>
    </added>
    <added>
      <filename>vendor/rails/railties/test/vendor/gems/dummy-gem-e-1.0.0/lib/dummy-gem-e.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,4 +1,8 @@
 class User &lt; ActiveRecord::Base
   belongs_to :user_group
-  has_many :orders
+  has_many :orders, :dependent =&gt; :destroy
+  
+  def name(middle_name = &quot;&quot;)
+    &quot;#{first_name} #{middle_name} #{last_name}&quot;
+  end
 end</diff>
      <filename>app/models/user.rb</filename>
    </modified>
    <modified>
      <diff>@@ -46,7 +46,7 @@ Rails::Initializer.run do |config|
   config.time_zone = 'UTC'
   
   #if RAILS_ENV == &quot;development&quot; # putting this in environments/development.rb doesn't work, not sure why
-  #  config.plugin_paths = [&quot;#{RAILS_ROOT}/../../Libs&quot;]
+  #  config.plugin_paths += [&quot;#{RAILS_ROOT}/../../Libs&quot;]
   #  config.plugins = [:searchgasm]
   #  require &quot;ruby-debug&quot;
   #end</diff>
      <filename>config/environment.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 # Confugration
 Searchgasm::Config.configure do |config|
-  config.per_page = config.per_page_choices.first # 10
+  config.search.per_page = config.helpers.per_page_select_choices.first.last # 10
 end
 
 # Actual function for MySQL databases only</diff>
      <filename>config/initializers/searchgasm.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,36 @@
-== 1.3.4 released 2008-10-03
+== 1.5.1 released 2008-10-20
+
+* Fixed bug with per_page_links
+* Added &quot;ordering_by&quot; class for per_page_links
+
+== 1.5.0 released 2008-10-20
+
+* Merge array of conditions with or or and where it makes sense. Begins with condition does not make sense to join with and, so instead join with or.
+* Cleaned up html validity so it will pass W3C validators
+* Restructure configuration to be more organized and allow for more configuration options.
+* Added more configuration options, especially for class names.
+
+== 1.4.1 released 2008-10-15
+
+* Extracted english text into configuration to support alternate languages. I18n support.
+* Improved method detection in add_joins to use respond_to? with the private method option set to true
+
+== 1.4.0 released 2008-10-15
+
+* Fixed bug when duping or cloning to copy over instance vars instead of method values
+* Fixed bug with older versions of ActiveRecord and creating an alias method chain on find in AssociationCollection
+* Added modifiers: upper, lower, trim, ltrim, rtrim
+* Added not_nil and not_blank conditions
+* Modified conditions so that table name is a variable, this allows table name to be switched on the fly.
+* Modified auto joins to return symbols instead of SQL. This allows AR to properly merge the joins and ultimately result in proper SQL when performing multiple complex scopes.
+* Fixed conflicts between includes and joins, duplicate joins are not added. Includes are prioritized. This also makes ActiveRecord much more flexible. Now you can cherry pick included associations. And not have to worry about conflicting with joins.
+* Modified ActiveRecord's default behavior to use inner joins with the :joins option. Inner joins impose limitations. When providing this as a &quot;convenience&quot;, inner joins do not make sense. The don't allow OR conditions to be across associations, nor does it properly order when an ordering by an association attribute when that association is optional.
+
+== 1.3.5 released 2008-10-08
+
+* Since joins are now strings, AR doesn't know how to merge them properly. So searchgasm now checks which joins to skip over to avoid conflicts.
+
+== 1.3.4 released 2008-10-07
 
 * Fixed method names creation for conditions with modifiers
 * Create local column conditions, incase there are method conflicts. Such as &quot;id&quot;.</diff>
      <filename>vendor/plugins/searchgasm/CHANGELOG.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -22,14 +22,18 @@ lib/searchgasm/condition/less_than_or_equal_to.rb
 lib/searchgasm/condition/like.rb
 lib/searchgasm/condition/nil.rb
 lib/searchgasm/condition/not_begin_with.rb
+lib/searchgasm/condition/not_blank.rb
 lib/searchgasm/condition/not_end_with.rb
 lib/searchgasm/condition/not_equal.rb
 lib/searchgasm/condition/not_have_keywords.rb
 lib/searchgasm/condition/not_like.rb
+lib/searchgasm/condition/not_nil.rb
 lib/searchgasm/condition/sibling_of.rb
 lib/searchgasm/condition/tree.rb
 lib/searchgasm/conditions/base.rb
 lib/searchgasm/conditions/protection.rb
+lib/searchgasm/config/helpers.rb
+lib/searchgasm/config/search.rb
 lib/searchgasm/config.rb
 lib/searchgasm/core_ext/hash.rb
 lib/searchgasm/helpers/control_types/link.rb
@@ -60,6 +64,8 @@ lib/searchgasm/modifiers/hour.rb
 lib/searchgasm/modifiers/log.rb
 lib/searchgasm/modifiers/log10.rb
 lib/searchgasm/modifiers/log2.rb
+lib/searchgasm/modifiers/lower.rb
+lib/searchgasm/modifiers/ltrim.rb
 lib/searchgasm/modifiers/md5.rb
 lib/searchgasm/modifiers/microseconds.rb
 lib/searchgasm/modifiers/milliseconds.rb
@@ -68,11 +74,14 @@ lib/searchgasm/modifiers/month.rb
 lib/searchgasm/modifiers/octal.rb
 lib/searchgasm/modifiers/radians.rb
 lib/searchgasm/modifiers/round.rb
+lib/searchgasm/modifiers/rtrim.rb
 lib/searchgasm/modifiers/second.rb
 lib/searchgasm/modifiers/sign.rb
 lib/searchgasm/modifiers/sin.rb
 lib/searchgasm/modifiers/square_root.rb
 lib/searchgasm/modifiers/tan.rb
+lib/searchgasm/modifiers/trim.rb
+lib/searchgasm/modifiers/upper.rb
 lib/searchgasm/modifiers/week.rb
 lib/searchgasm/modifiers/year.rb
 lib/searchgasm/search/base.rb
@@ -90,12 +99,11 @@ MIT-LICENSE
 Rakefile
 README.rdoc
 test/fixtures/accounts.yml
+test/fixtures/cats.yml
+test/fixtures/dogs.yml
 test/fixtures/orders.yml
 test/fixtures/user_groups.yml
 test/fixtures/users.yml
-test/libs/acts_as_tree.rb
-test/libs/ordered_hash.rb
-test/libs/rexml_fix.rb
 test/test_active_record_associations.rb
 test/test_active_record_base.rb
 test/test_condition_base.rb
@@ -109,4 +117,7 @@ test/test_search_conditions.rb
 test/test_search_ordering.rb
 test/test_search_pagination.rb
 test/test_search_protection.rb
+test_libs/acts_as_tree.rb
+test_libs/ordered_hash.rb
+test_libs/rexml_fix.rb
 TODO.rdoc</diff>
      <filename>vendor/plugins/searchgasm/Manifest</filename>
    </modified>
    <modified>
      <diff>@@ -305,6 +305,11 @@ Here are all of the available modifiers:
   
   :md5                                                          Converts to a MD5
   :char_length      :length                                     The length of the string (integer)
+  :lower            :downcase, :lcase                           Converts the string to all lower case characters
+  :ltrin            :lstrip                                     Strips off spaces from the beginning of the string
+  :trim             :strip                                      Strips off spaces from the beginning and end of the string
+  :rtrim            :rstrip                                     Strips off spaces from the end of the string
+  :upper            :upcase, :ucase                             Converts the string to all upper case character
   
   :absolute         :abs                                        The absolute value (-1 =&gt; 1)
   :acos                                                         The arc cosine
@@ -344,6 +349,12 @@ Here's the cool part. Chaining modifiers:
   
 As long as the modifier chain makes sense the possibilities are endless.
 
+=== Modifiers are not indexed
+
+Depending on your database you can create complex indexes. But chances are you probably didn't or don't plan to. So keep in mind that once you use a modifier it will not be using an index, meaning the query will be slower. One of the ways to get the best of both worlds is to cache virtual attributes in the database. Checkout my tutorial:
+
+http://www.binarylogic.com/2008/10/5/tutorial-caching-virtual-attributes-in-the-database
+
 == Roll your own conditions &amp; modifiers
 
 For more information on this please see Searchgasm::Conditions::Base</diff>
      <filename>vendor/plugins/searchgasm/README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -10,6 +10,6 @@ Echoe.new 'searchgasm' do |p|
   p.project = 'searchgasm'
   p.summary = &quot;Object based ActiveRecord searching, ordering, pagination, and more!&quot;
   p.url = &quot;http://github.com/binarylogic/searchgasm&quot;
-  p.dependencies = %w(activerecord activesupport)
+  p.dependencies = %w(activerecord activesupport configatron)
   p.include_rakefile = true
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/searchgasm/Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,6 @@
 = To Do
 
-1. Perform &quot;more efficient&quot; checks: year_of_created_at = 2008 and month_of_created_at = 8. Should result in a &quot;BETWEEN&quot; statement utilizing the column indexes. Thanks Georg for letting me know about this.
\ No newline at end of file
+1. Perform &quot;more efficient&quot; checks: year_of_created_at = 2008 and month_of_created_at = 8. Should result in a &quot;BETWEEN&quot; statement utilizing the column indexes. Thanks Georg for letting me know about this.
+2. Solve conflicts between scope joins and joins in the search (for old versions of AR). Also solve conflicts between joins and includes.
+3. Add configuration to change the &quot;english&quot; words
+4. Re-add the distinct option
\ No newline at end of file</diff>
      <filename>vendor/plugins/searchgasm/TODO.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -21,6 +21,8 @@ require &quot;searchgasm/shared/virtual_classes&quot;
 
 # Base classes
 require &quot;searchgasm/version&quot;
+require &quot;searchgasm/config/helpers&quot;
+require &quot;searchgasm/config/search&quot;
 require &quot;searchgasm/config&quot;
 
 # ActiveRecord
@@ -42,12 +44,12 @@ require &quot;searchgasm/conditions/base&quot;
 # Condition
 require &quot;searchgasm/condition/base&quot;
 require &quot;searchgasm/condition/tree&quot;
-SEARCHGASM_CONDITIONS = [:begins_with, :blank, :child_of, :descendant_of, :ends_with, :equals, :greater_than, :greater_than_or_equal_to, :inclusive_descendant_of, :like, :nil, :not_begin_with, :not_end_with, :not_equal, :not_have_keywords, :keywords, :less_than, :less_than_or_equal_to, :sibling_of]
+SEARCHGASM_CONDITIONS = [:begins_with, :blank, :child_of, :descendant_of, :ends_with, :equals, :greater_than, :greater_than_or_equal_to, :inclusive_descendant_of, :like, :nil, :not_begin_with, :not_blank, :not_end_with, :not_equal, :not_have_keywords, :not_nil, :keywords, :less_than, :less_than_or_equal_to, :sibling_of]
 SEARCHGASM_CONDITIONS.each { |condition| require &quot;searchgasm/condition/#{condition}&quot; }
 
 # Modifiers
 require &quot;searchgasm/modifiers/base&quot;
-SEARCHGASM_MODIFIERS = [:day_of_month, :day_of_week, :day_of_year, :hour, :microseconds, :milliseconds, :minute, :month, :second, :week, :year]
+SEARCHGASM_MODIFIERS = [:absolute, :acos, :asin, :atan, :ceil, :char_length, :cos, :cot, :day_of_month, :day_of_week, :day_of_year, :degrees, :exp, :floor, :hex, :hour, :log, :log10, :log2, :lower, :ltrim, :md5, :microseconds, :milliseconds, :minute, :month, :octal, :radians, :round, :rtrim, :second, :sign, :sin, :square_root, :tan, :trim, :upper, :week, :year]
 SEARCHGASM_MODIFIERS.each { |modifier| require &quot;searchgasm/modifiers/#{modifier}&quot; }
 
 # Helpers</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,7 +13,7 @@ module Searchgasm
         end
       end
       
-      module Shared
+      module HasManyAssociation
         def count_with_searchgasm(*args)
           options = args.extract_options!
           args &lt;&lt; filter_options_with_searchgasm(options)
@@ -24,18 +24,29 @@ module Searchgasm
   end
 end
 
-module ActiveRecord
-  module Associations
-    class AssociationCollection
-      include Searchgasm::ActiveRecord::Associations::AssociationCollection
-      
-      alias_method_chain :find, :searchgasm
-    end
-    
-    class HasManyAssociation
-      include Searchgasm::ActiveRecord::Associations::Shared
-      
-      alias_method_chain :count, :searchgasm
-    end
+ActiveRecord::Associations::AssociationCollection.class_eval do
+  if respond_to?(:find)
+    include Searchgasm::ActiveRecord::Associations::AssociationCollection
+    alias_method_chain :find, :searchgasm
   end
+end
+
+ActiveRecord::Associations::HasManyAssociation.class_eval do
+  include Searchgasm::ActiveRecord::Associations::HasManyAssociation
+  alias_method_chain :count, :searchgasm
+  
+  # Older versions of AR have find in here, not in AssociationCollection
+  include Searchgasm::ActiveRecord::Associations::AssociationCollection
+  alias_method_chain :find, :searchgasm
+end
+
+ActiveRecord::Associations::ClassMethods::InnerJoinDependency::InnerJoinAssociation.class_eval do
+  private
+    # Inner joins impose limitations on queries. They can be quicker but you can't do OR conditions when conditions
+    # overlap from the base model to any of its associations. Also, inner joins won't allow you to order by an association
+    # attribute. What if the association is optional? All of those records are ommitted. It just doesn't make sense to default
+    # to inner joins when providing this as a &quot;convenience&quot; when searching. So let's change it.
+    def join_type
+      &quot;LEFT OUTER JOIN&quot;
+    end
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/active_record/associations.rb</filename>
    </modified>
    <modified>
      <diff>@@ -108,6 +108,7 @@ module Searchgasm
           return options unless Searchgasm::Search::Base.needed?(self, options)
           search = Searchgasm::Search::Base.create_virtual_class(self).new # call explicitly to avoid merging the scopes into the search
           search.acting_as_filter = true
+          search.scope = scope(:find)
           conditions = options.delete(:conditions) || options.delete(&quot;conditions&quot;) || {}
           if conditions
             case conditions
@@ -120,7 +121,7 @@ module Searchgasm
           search.options = options
           search.sanitize(searching)
         end
-      
+        
         def searchgasm_search(options = {})
           scope = {}
           current_scope = scope(:find) &amp;&amp; scope(:find).deep_dup
@@ -164,6 +165,54 @@ module ActiveRecord #:nodoc: all
       def valid_calculations_options
         Calculations::CALCULATIONS_OPTIONS
       end
+      
+      private
+        # This is copied over from 2 different versions of ActiveRecord. I have to do this in order to preserve the &quot;auto joins&quot;
+        # as symbols. Keeping them as symbols allows ActiveRecord to merge them properly. The problem is when they conflict with includes.
+        # Includes add joins also, and they add them before joins do. So if they already added them skip them. Now you can do queries like:
+        #
+        # User.all(:joins =&gt; {:orders =&gt; :line_items}, :include =&gt; :orders)
+        #
+        # Where as before, the only way to get the above query to work would be to include line_items also, which is not neccessarily what you want.
+        def add_joins!(sql, options_or_joins, scope = :auto) # :nodoc:
+          code_type = (respond_to?(:array_of_strings?, true) &amp;&amp; :array_of_strings) || (respond_to?(:merge_joins, true) &amp;&amp; :merge_joins)
+
+          case code_type
+          when :array_of_strings, :merge_joins
+            joins = options_or_joins
+            scope = scope(:find) if :auto == scope
+            merged_joins = scope &amp;&amp; scope[:joins] &amp;&amp; joins ? merge_joins(scope[:joins], joins) : (joins || scope &amp;&amp; scope[:joins])
+            case merged_joins
+            when Symbol, Hash, Array
+              if code_type == :array_of_strings &amp;&amp; array_of_strings?(merged_joins)
+                merged_joins.each { |merged_join| sql &lt;&lt; &quot; #{merged_join} &quot; unless sql.include?(merged_join) }
+              else
+                join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, merged_joins, nil)
+                join_dependency.join_associations.each do |assoc|
+                  join_sql = assoc.association_join
+                  sql &lt;&lt; &quot; #{join_sql} &quot; unless sql.include?(join_sql)
+                end
+              end
+            when String
+              sql &lt;&lt; &quot; #{merged_joins} &quot; if merged_joins &amp;&amp; !sql.include?(merged_joins)
+            end
+          else
+            options = options_or_joins
+            scope = scope(:find) if :auto == scope
+            [(scope &amp;&amp; scope[:joins]), options[:joins]].each do |join|
+              case join
+              when Symbol, Hash, Array
+                join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, join, nil)
+                join_dependency.join_associations.each do |assoc|
+                  join_sql = assoc.association_join
+                  sql &lt;&lt; &quot; #{join_sql} &quot; unless sql.include?(join_sql)
+                end
+              else
+                sql &lt;&lt; &quot; #{join} &quot; if join &amp;&amp; !sql.include?(join)
+              end
+            end
+          end
+        end
     end
   end
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/active_record/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -52,10 +52,30 @@ module Searchgasm
           &quot;CHAR_LENGTH(#{column_name})&quot;
         end
         
+        def lower_sql(column_name)
+          &quot;LOWER(#{column_name})&quot;
+        end
+        
+        def ltrim_sql(column_name)
+          &quot;LTRIM(#{column_name})&quot;
+        end
+        
         def md5_sql(column_name)
           &quot;MD5(#{column_name})&quot;
         end
         
+        def rtrim_sql(column_name)
+          &quot;RTRIM(#{column_name})&quot;
+        end
+        
+        def trim_sql(column_name)
+          &quot;TRIM(#{column_name})&quot;
+        end
+        
+        def upper_sql(column_name)
+          &quot;UPPER(#{column_name})&quot;
+        end
+        
         # Number functions
         def absolute_sql(column_name)
           &quot;ABS(#{column_name})&quot;</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/active_record/connection_adapters/mysql_adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -52,10 +52,30 @@ module Searchgasm
           &quot;length(#{column_name})&quot;
         end
         
+        def lower_sql(column_name)
+          &quot;lower(#{column_name})&quot;
+        end
+        
+        def ltrim_sql(column_name)
+          &quot;ltrim(#{column_name})&quot;
+        end
+        
         def md5_sql(column_name)
           &quot;md5(#{column_name})&quot;
         end
         
+        def rtrim_sql(column_name)
+          &quot;rtrim(#{column_name})&quot;
+        end
+        
+        def trim_sql(column_name)
+          &quot;trim(#{column_name})&quot;
+        end
+        
+        def upper_sql(column_name)
+          &quot;upper(#{column_name})&quot;
+        end
+        
         # Number functions
         def absolute_sql(column_name)
           &quot;abs(#{column_name})&quot;</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/active_record/connection_adapters/postgresql_adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -46,6 +46,27 @@ module Searchgasm
         def year_sql(column_name)
           &quot;strftime('%Y', #{column_name})&quot;
         end
+        
+        # String functions
+        def lower_sql(column_name)
+          &quot;lower(#{column_name})&quot;
+        end
+        
+        def ltrim_sql(column_name)
+          &quot;ltrim(#{column_name})&quot;
+        end
+        
+        def rtrim_sql(column_name)
+          &quot;rtrim(#{column_name})&quot;
+        end
+        
+        def trim_sql(column_name)
+          &quot;trim(#{column_name})&quot;
+        end
+        
+        def upper_sql(column_name)
+          &quot;upper(#{column_name})&quot;
+        end
       end
     end
   end</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/active_record/connection_adapters/sqlite_adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,8 +7,8 @@ module Searchgasm
     class Base
       include Shared::Utilities
       
-      attr_accessor :column, :column_for_type_cast, :column_sql, :klass
-      class_inheritable_accessor :handle_array_value, :ignore_meaningless_value, :value_type
+      attr_accessor :column, :column_for_type_cast, :column_sql, :column_sql_format, :klass, :table_name
+      class_inheritable_accessor :handle_array_value, :ignore_meaningless_value, :join_arrays_with_or, :value_type
       self.ignore_meaningless_value = true
     
       class &lt;&lt; self
@@ -16,7 +16,7 @@ module Searchgasm
         def condition_type_name
           name.split(&quot;::&quot;).last.underscore
         end
-        
+                
         def handle_array_value?
           handle_array_value == true
         end
@@ -25,6 +25,10 @@ module Searchgasm
           ignore_meaningless_value == true
         end
         
+        def join_arrays_with_or?
+          join_arrays_with_or == true
+        end
+        
         # Determines what to call the condition for the model
         #
         # Searchgasm tries to create conditions on each model. Before it does this it passes the model to this method to see what to call the condition. If the condition type doesnt want to create a condition on
@@ -39,16 +43,29 @@ module Searchgasm
         end
       end
     
-      def initialize(klass, column_obj = nil, column_type = nil, column_sql = nil)
+      def initialize(klass, options = {})
         self.klass = klass
-
-        if column_obj
-          self.column = column_obj.class &lt; ::ActiveRecord::ConnectionAdapters::Column ? column_obj : klass.columns_hash[column_obj.to_s]
-          type = (!self.class.value_type.blank? &amp;&amp; self.class.value_type.to_s) || (!column_type.blank? &amp;&amp; column_type.to_s) || column.sql_type
-          self.column_for_type_cast = column.class.new(column.name, column.default.to_s, type, column.null)
-          self.column_sql = column_sql || &quot;#{klass.connection.quote_table_name(klass.table_name)}.#{klass.connection.quote_column_name(column.name)}&quot;
+        self.table_name = options[:table_name] || klass.table_name
+        
+        if options[:column]
+          self.column = options[:column].class &lt; ::ActiveRecord::ConnectionAdapters::Column ? options[:column] : klass.columns_hash[options[:column].to_s]
+          
+          if options[:column_for_type_cast]
+            self.column_for_type_cast = options[:column_for_type_cast]
+          else
+            type = (!self.class.value_type.blank? &amp;&amp; self.class.value_type.to_s) || (!options[:column_type].blank? &amp;&amp; options[:column_type].to_s) || column.sql_type
+            self.column_for_type_cast = column.class.new(column.name, column.default.to_s, type, column.null)
+          end
+          
+          self.column_sql_format = options[:column_sql_format] || &quot;{table}.{column}&quot;
         end
       end
+      
+      # Substitutes string vars with table and column name. Allows us to switch the column and table on the fly and have the condition update appropriately.
+      # The table name could be variable depending on the condition. Take STI and more than one child model is used in the condition, the first gets the parent table name, the rest get aliases.
+      def column_sql
+        column_sql_format.gsub(&quot;{table}&quot;, quoted_table_name).gsub(&quot;{column}&quot;, quoted_column_name)
+      end
     
       # Allows nils to be meaninful values
       def explicitly_set_value=(value)
@@ -60,12 +77,16 @@ module Searchgasm
         @explicitly_set_value == true
       end
       
+      def options
+        {:table_name =&gt; table_name, :column =&gt; column, :column_for_type_cast =&gt; column_for_type_cast, :column_sql_format =&gt; column_sql_format}
+      end
+      
       # You should refrain from overwriting this method, it performs various tasks before callign your to_conditions method, allowing you to keep to_conditions simple.
       def sanitize(alt_value = nil) # :nodoc:
         return if value_is_meaningless?
         v = alt_value || value
         if v.is_a?(Array) &amp;&amp; !self.class.handle_array_value?
-          merge_conditions(*v.collect { |i| sanitize(i) })
+          merge_conditions(*v.collect { |i| sanitize(i) } &lt;&lt; {:any =&gt; self.class.join_arrays_with_or?})
         else
           v = v.utc if column &amp;&amp; v.respond_to?(:utc) &amp;&amp; [:time, :timestamp, :datetime].include?(column.type) &amp;&amp; klass.time_zone_aware_attributes &amp;&amp; !klass.skip_time_zone_conversion_for_attributes.include?(column.name.to_sym)
           to_conditions(v)
@@ -107,12 +128,16 @@ module Searchgasm
           klass.connection.quote_column_name(column_name)
         end
         
+        def quoted_column_name
+          quote_column_name(column.name)
+        end
+        
         def quote_table_name(table_name)
           klass.connection.quote_table_name(table_name)
         end
         
         def quoted_table_name
-          quote_table_name(klass.table_name)
+          quote_table_name(table_name)
         end
         
         def type_cast_value(v)</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,8 @@
 module Searchgasm
   module Condition
     class BeginsWith &lt; Base
+      self.join_arrays_with_or = true
+      
       class &lt;&lt; self
         def condition_names_for_column
           super + [&quot;bw&quot;, &quot;sw&quot;, &quot;starts_with&quot;, &quot;start&quot;]</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/begins_with.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 module Searchgasm
   module Condition
-    class ChildOf &lt; Tree
+    class ChildOf &lt; Tree      
       def to_conditions(value)
         parent_association = klass.reflect_on_association(:parent)
         foreign_key_name = (parent_association &amp;&amp; parent_association.options[:foreign_key]) || &quot;parent_id&quot;</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/child_of.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 module Searchgasm
   module Condition
-    class DescendantOf &lt; Tree
+    class DescendantOf &lt; Tree      
       def to_conditions(value)
         # Wish I knew how to do this in SQL
         root = (value.is_a?(klass) ? value : klass.find(value)) rescue return</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/descendant_of.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,8 @@
 module Searchgasm
   module Condition
     class EndsWith &lt; Base
+      self.join_arrays_with_or = true
+      
       class &lt;&lt; self
         def condition_names_for_column
           super + [&quot;ew&quot;, &quot;ends&quot;, &quot;end&quot;]</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/ends_with.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,8 +1,8 @@
 module Searchgasm
   module Condition
-    class InclusiveDescendantOf &lt; Tree
+    class InclusiveDescendantOf &lt; Tree      
       def to_conditions(value)
-        condition = DescendantOf.new(klass, column)
+        condition = DescendantOf.new(klass, options)
         condition.value = value
         merge_conditions([&quot;#{quoted_table_name}.#{quote_column_name(klass.primary_key)} = ?&quot;, (value.is_a?(klass) ? value.send(klass.primary_key) : value)], condition.sanitize, :any =&gt; true)
       end</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/inclusive_descendant_of.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,9 @@
 module Searchgasm
   module Condition
     class Keywords &lt; Base
+      # Because be default it joins with AND, so padding an array just gives you more options. Joining with and is no different than combining all of the words.
+      self.join_arrays_with_or = true
+      
       BLACKLISTED_WORDS = ('a'..'z').to_a + [&quot;about&quot;, &quot;an&quot;, &quot;are&quot;, &quot;as&quot;, &quot;at&quot;, &quot;be&quot;, &quot;by&quot;, &quot;com&quot;, &quot;de&quot;, &quot;en&quot;, &quot;for&quot;, &quot;from&quot;, &quot;how&quot;, &quot;in&quot;, &quot;is&quot;, &quot;it&quot;, &quot;la&quot;, &quot;of&quot;, &quot;on&quot;, &quot;or&quot;, &quot;that&quot;, &quot;the&quot;, &quot;the&quot;, &quot;this&quot;, &quot;to&quot;, &quot;und&quot;, &quot;was&quot;, &quot;what&quot;, &quot;when&quot;, &quot;where&quot;, &quot;who&quot;, &quot;will&quot;, &quot;with&quot;, &quot;www&quot;] # from ranks.nl        
       
       class &lt;&lt; self</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/keywords.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ module Searchgasm
       end
       
       def to_conditions(value)
-        begin_with = BeginWith.new
+        begin_with = BeginWith.new(klass, options)
         begin_with.value = value
         conditions = being_with.to_conditions
         return conditions if conditions.blank?</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/not_begin_with.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ module Searchgasm
       end
       
       def to_conditions(value)
-        ends_with = EndsWith.new
+        ends_with = EndsWith.new(klass, options)
         ends_with.value = value
         conditions = ends_with.to_conditions
         return conditions if conditions.blank?</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/not_end_with.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,7 +12,7 @@ module Searchgasm
       
       def to_conditions(value)
         # Delegate to equals and then change
-        condition = Equals.new(klass, column)
+        condition = Equals.new(klass, options)
         condition.value = value
         
         conditions_array = condition.sanitize</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/not_equal.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ module Searchgasm
       end
       
       def to_conditions(value)
-        keywords = Keywords.new
+        keywords = Keywords.new(klass, options)
         keywords.value = value
         conditions = keywords.to_conditions
         return conditions if conditions.blank?</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/not_have_keywords.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ module Searchgasm
       end
       
       def to_conditions(value)
-        like = Like.new
+        like = Like.new(klass, options)
         like.value = value
         conditions = like.to_conditions
         return conditions if conditions.blank?</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/not_like.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@ module Searchgasm
         parent_association = klass.reflect_on_association(:parent)
         foreign_key_name = (parent_association &amp;&amp; parent_association.options[:foreign_key]) || &quot;parent_id&quot;
         parent_id = (value.is_a?(klass) ? value : klass.find(value)).send(foreign_key_name)
-        condition = ChildOf.new(klass, column)
+        condition = ChildOf.new(klass, options)
         condition.value = parent_id
         merge_conditions([&quot;#{quoted_table_name}.#{quote_column_name(klass.primary_key)} != ?&quot;, (value.is_a?(klass) ? value.send(klass.primary_key) : value)], condition.sanitize)
       end</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/sibling_of.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,8 @@
 module Searchgasm
   module Condition
     class Tree &lt; Base # :nodoc:
+      self.join_arrays_with_or = true
+      
       class &lt;&lt; self
         def condition_names_for_column
           []</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/condition/tree.rb</filename>
    </modified>
    <modified>
      <diff>@@ -179,7 +179,7 @@ module Searchgasm
         associations.each do |name, association|
           next if association.conditions.blank?
           association_joins = association.auto_joins
-          j &lt;&lt; (association_joins.blank? ? association.relationship_name.to_sym : {association.relationship_name.to_sym =&gt; association_joins})
+          j &lt;&lt; (association_joins.blank? ? name : {name =&gt; association_joins})
         end
         j.blank? ? nil : (j.size == 1 ? j.first : j)
       end
@@ -233,7 +233,7 @@ module Searchgasm
           if object.class &lt; Searchgasm::Conditions::Base
             relationship_conditions = object.conditions
             next if relationship_conditions.blank?
-            conditions_hash[object.relationship_name.to_sym] = relationship_conditions
+            conditions_hash[name] = relationship_conditions
           else
             next if object.value_is_meaningless?
             conditions_hash[name] = object.value
@@ -367,14 +367,14 @@ module Searchgasm
                 column_type = modifier_klasses.first.return_type
               
                 # Build the column sql
-                column_sql = &quot;#{klass.connection.quote_table_name(klass.table_name)}.#{klass.connection.quote_column_name(column_detail[:column].name)}&quot;
+                column_sql = &quot;{table}.{column}&quot;
                 modifier_klasses.each do |modifier_klass|
                   next unless klass.connection.respond_to?(modifier_klass.adapter_method_name)
                   column_sql = klass.connection.send(modifier_klass.adapter_method_name, column_sql)
                 end
               end
             
-              add_condition!(condition_klass, method_name, column_detail[:column], column_type, column_sql)
+              add_condition!(condition_klass, method_name, :column =&gt; column_detail[:column], :column_type =&gt; column_type, :column_sql_format =&gt; column_sql)
             
               ([column_detail[:column].name] + column_detail[:aliases]).each do |column_name|
                 condition_klass.condition_names_for_column.each do |condition_name|
@@ -393,13 +393,15 @@ module Searchgasm
           false
         end
         
-        def add_condition!(condition, name, column = nil, column_type = nil, column_sql = nil)
+        def add_condition!(condition, name, options = {})
           self.class.condition_names &lt;&lt; name
+          options[:column] = options[:column].name if options[:column].class &lt; ::ActiveRecord::ConnectionAdapters::Column
           
           self.class.class_eval &lt;&lt;-&quot;end_eval&quot;, __FILE__, __LINE__
             def #{name}_object
               if objects[:#{name}].nil?
-                objects[:#{name}] = #{condition.name}.new(klass, #{column.blank? ? &quot;nil&quot; : &quot;klass.columns_hash['#{column.name}']&quot;}, #{column_type.blank? ? &quot;nil&quot; : &quot;\&quot;#{column_type}\&quot;&quot;}, #{column_sql.blank? ? &quot;nil&quot; : &quot;\&quot;#{column_sql.gsub('&quot;', '\&quot;')}\&quot;&quot;})
+                options = {}
+                objects[:#{name}] = #{condition.name}.new(klass, #{options.inspect})
               end
               objects[:#{name}]
             end
@@ -465,7 +467,7 @@ module Searchgasm
         end
         
         def reset_objects!
-          objects.each { |name, object| object.class &lt; ::Searchgasm::Conditions::Base ? eval(&quot;@#{object.relationship_name} = nil&quot;) : eval(&quot;@#{name} = nil&quot;) }
+          objects.each { |name, object| eval(&quot;@#{name} = nil&quot;) }
           objects.clear
         end
         </diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/conditions/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -23,7 +23,7 @@ module Searchgasm
       end
       
       def protect=(value)
-        associations.each { |association| association.protect = value }
+        associations.each { |name, obj| obj.protect = value }
         @protect = value
       end
       </diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/conditions/protection.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,16 @@
 module Searchgasm
   # = Config
-  # Adds default configuration for all of searchgasm. Just make sure you set your config before you use Searchgasm.
-  # For rails the best place to do this is in config/initializers. Create a file in there called searchgasm.rb with the following content:
+  # Adds default configuration for all of searchgasm. For rails the best place to do this is in config/initializers. Create a file in there called searchgasm.rb with the following content:
   #
   # === Example
   #
   #   # config/iniitializers/searchgasm.rb
   #   Searchgasm::Config.configure do |config|
-  #     config.you_option_here = your_value # see methods below
+  #     config.search.per_page = 25
+  #     config.helpers.order_by_link_asc_indicator = &quot;My indicator&quot;
   #   end
+  #
+  # For a list of all configuration options see Searchgasm::Config::Search and Searchgasm::Config::Helpers
   class Config
     class &lt;&lt; self
       # Convenience method for setting configuration
@@ -17,163 +19,12 @@ module Searchgasm
         yield self
       end
       
-      def asc_indicator # :nodoc:
-        @asc_indicator ||= &quot;&amp;nbsp;&amp;#9650;&quot;
-      end
-      
-      # The indicator that is used when the sort of a column is ascending
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; &amp;nbsp;&amp;#9650;
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; String or a Proc.
-      #
-      # === Examples
-      #
-      #   config.asc_indicator = &quot;(ASC)&quot;
-      #   config.asc_indicator = Proc.new { |template| template.image_tag(&quot;asc.jpg&quot;) }
-      def asc_indicator=(value)
-        @asc_indicator = value
-      end
-      
-      def desc_indicator # :nodoc:
-        @desc_indicator ||= &quot;&amp;nbsp;&amp;#9660;&quot;
-      end
-      
-      # See asc_indicator=
-      def desc_indicator=(value)
-        @desc_indicator = value
-      end
-      
-      def hidden_fields # :nodoc:
-        @hidden_fields ||= (Search::Base::SPECIAL_FIND_OPTIONS - [:page, :priority_order])
-      end
-      
-      # Which hidden fields to automatically include when creating a form with a Searchgasm object. See Searchgasm::Helpers::Form for more info.
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; [:order_by, :order_as, :per_page]
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; Array, nil, false
-      def hidden_fields=(value)
-        @hidden_fields = value
-      end
-      
-      def page_links_first # :nodoc:
-        @page_links_first
-      end
-      
-      # The default for the :first option for the page_links helper.
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; nil
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; Anything you want, text, html, etc. nil to disable
-      def page_links_first=(value)
-        @page_links_first = value
-      end
-      
-      def page_links_last # :nodoc:
-        @page_links_last
-      end
-      
-      # The default for the :last option for the page_links helper.
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; nil
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; Anything you want, text, html, etc. nil to disable
-      def page_links_last=(value)
-        @page_links_last = value
-      end
-      
-      def page_links_inner_spread # :nodoc:
-        @page_links_inner_spread ||= 3
-      end
-      
-      # The default for the :inner_spread option for the page_links helper.
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; 3
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; Any integer &gt;= 1, set to nil to show all pages
-      def page_links_inner_spread=(value)
-        @page_links_inner_spread = value
-      end
-      
-      def page_links_outer_spread # :nodoc:
-        @page_links_outer_spread ||= 1
-      end
-      
-      # The default for the :outer_spread option for the page_links helper.
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; 2
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; Any integer &gt;= 1, set to nil to display, 0 to only show the &quot;...&quot; separator
-      def page_links_outer_spread=(value)
-        @page_links_outer_spread = value
-      end
-      
-      def page_links_next # :nodoc:
-        @page_links_next ||= &quot;Next &gt;&quot;
-      end
-      
-      # The default for the :next option for the page_links helper.
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; &quot;Next &gt;&quot;
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; Anything you want, text, html, etc. nil to disable
-      def page_links_next=(value)
-        @page_links_next = value
-      end
-      
-      def page_links_prev # :nodoc:
-        @page_links_prev ||= &quot;&lt; Prev&quot;
-      end
-      
-      # The default for the :prev option for the page_links helper.
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; &quot;&lt; Prev&quot;
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; Anything you want, text, html, etc. nil to disable
-      def page_links_prev=(value)
-        @page_links_prev = value
-      end
-      
-      def per_page # :nodoc:
-        @per_page ||= per_page_choices[1]
-      end
-      
-      # The default for per page. This is only applicaple for protected searches. Meaning you start the search with new_search or new_conditions.
-      # The reason for this not to disturb regular queries such as Whatever.find(:all). You would not expect that to be limited.
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; The 3rd option in your per_page_choices, default of 50
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; Any value in your per_page choices, nil or a blank string means &quot;show all&quot;
-      def per_page=(value)
-        @per_page = value
-      end
-      
-      def per_page_choices # :nodoc:
-        @per_page_choices ||= [10, 25, 50, 100, 150, 200, nil]
-      end
-      
-      # The choices used in the per_page helper
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; [10, 25, 50, 100, 150, 200, nil]
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; Array
-      #
-      # nil means &quot;Show all&quot;
-      def per_page_choices=(value)
-        @per_page_choices = value
-      end
-      
-      def remove_duplicates # :nodoc:
-        return @remove_duplicates if @set_remove_duplicates
-        @remove_duplicates ||= true
-      end
-      
-      def remove_duplicates? # :nodoc:
-        remove_duplicates == true
+      def search # :nodoc:
+        Search
       end
       
-      # If you are using ActiveRecord &lt; 2.2.0 then ActiveRecord does not remove duplicates when using the :joins option, when it should. To fix this problem searchgasm does this for you. Searchgasm tries to act
-      # just like ActiveRecord, but in this instance it doesn't make sense.
-      #
-      # As a result, Searchgasm removes all duplicates results in *ALL* search / calculation queries. It does this by forcing the DISTINCT or GROUP BY operation in your SQL. Which might come as a surprise to you
-      # since it is not the &quot;norm&quot;. If you don't want searchgasm to do this, set this to false.
-      #
-      # * &lt;tt&gt;Default:&lt;/tt&gt; true
-      # * &lt;tt&gt;Accepts:&lt;/tt&gt; Boolean
-      def remove_duplicates=(value)
-        @set_remove_duplicates = true
-        @remove_duplicates = value
+      def helpers # :nodoc:
+        Helpers
       end
     end
   end</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/config.rb</filename>
    </modified>
    <modified>
      <diff>@@ -78,10 +78,10 @@ module Searchgasm
         # * &lt;tt&gt;:html&lt;/tt&gt; -- html arrtributes for the &lt;a&gt; tag.
         #
         # === Advanced Options
-        # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base leve in params such as params[:page], params[:per_page], etc, then set this to nil.
+        # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base level in params such as params[:page], params[:per_page], etc, then set this to nil.
         # * &lt;tt&gt;:search_obj&lt;/tt&gt; -- default: @#{params_scope}, this is your search object, everything revolves around this. It will try to infer the name from your params_scope. If your params_scope is :search it will try to get @search, etc. If it can not be inferred by this, you need to pass the object itself.
         # * &lt;tt&gt;:params&lt;/tt&gt; -- default: nil, Additional params to add to the url, must be a hash
-        # * &lt;tt&gt;:exclude_params&lt;/tt&gt; -- default: nil, params you want to exclude. This is nifty because it does a &quot;deep delete&quot;. So you can pass {:param1 =&gt; {:param2 =&gt; :param3}} and it will make sure param3 does not get include. param1 and param2 will not be touched. This also accepts an array or just a symbol or string.
+        # * &lt;tt&gt;:exclude_params&lt;/tt&gt; -- default: nil, params you want to exclude. This is nifty because it does a &quot;deep delete&quot;. So you can pass {:param1 =&gt; {:param2 =&gt; :param3}} and it will make sure param3 does not get included. param1 and param2 will not be touched. This also accepts an array or just a symbol or string.
         # * &lt;tt&gt;:search_params&lt;/tt&gt; -- default: nil, Additional search params to add to the url, must be a hash. Adds the options into the :params_scope.
         # * &lt;tt&gt;:exclude_search_params&lt;/tt&gt; -- default: nil, Same as :exclude_params but for the :search_params.
         def order_by_link(order_by, options = {})
@@ -97,7 +97,7 @@ module Searchgasm
           html
         end
         
-        # Creates a link for ascending or descending data, pretty self e
+        # Creates a link for ascending or descending data.
         #
         # === Example uses
         #
@@ -110,10 +110,10 @@ module Searchgasm
         # * &lt;tt&gt;:html&lt;/tt&gt; -- html arrtributes for the &lt;a&gt; tag.
         #
         # === Advanced Options
-        # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base leve in params such as params[:page], params[:per_page], etc, then set this to nil.
+        # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base level in params such as params[:page], params[:per_page], etc, then set this to nil.
         # * &lt;tt&gt;:search_obj&lt;/tt&gt; -- default: @#{params_scope}, this is your search object, everything revolves around this. It will try to infer the name from your params_scope. If your params_scope is :search it will try to get @search, etc. If it can not be inferred by this, you need to pass the object itself.
         # * &lt;tt&gt;:params&lt;/tt&gt; -- default: nil, Additional params to add to the url, must be a hash
-        # * &lt;tt&gt;:exclude_params&lt;/tt&gt; -- default: nil, params you want to exclude. This is nifty because it does a &quot;deep delete&quot;. So you can pass {:param1 =&gt; {:param2 =&gt; :param3}} and it will make sure param3 does not get include. param1 and param2 will not be touched. This also accepts an array or just a symbol or string.
+        # * &lt;tt&gt;:exclude_params&lt;/tt&gt; -- default: nil, params you want to exclude. This is nifty because it does a &quot;deep delete&quot;. So you can pass {:param1 =&gt; {:param2 =&gt; :param3}} and it will make sure param3 does not get included. param1 and param2 will not be touched. This also accepts an array or just a symbol or string.
         # * &lt;tt&gt;:search_params&lt;/tt&gt; -- default: nil, Additional search params to add to the url, must be a hash. Adds the options into the :params_scope.
         # * &lt;tt&gt;:exclude_search_params&lt;/tt&gt; -- default: nil, Same as :exclude_params but for the :search_params.
         def order_as_link(order_as, options = {})
@@ -151,10 +151,10 @@ module Searchgasm
         # * &lt;tt&gt;:html&lt;/tt&gt; -- html arrtributes for the &lt;a&gt; tag.
         #
         # === Advanced Options
-        # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base leve in params such as params[:page], params[:per_page], etc, then set this to nil.
+        # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base level in params such as params[:page], params[:per_page], etc, then set this to nil.
         # * &lt;tt&gt;:search_obj&lt;/tt&gt; -- default: @#{params_scope}, this is your search object, everything revolves around this. It will try to infer the name from your params_scope. If your params_scope is :search it will try to get @search, etc. If it can not be inferred by this, you need to pass the object itself.
         # * &lt;tt&gt;:params&lt;/tt&gt; -- default: nil, Additional params to add to the url, must be a hash
-        # * &lt;tt&gt;:exclude_params&lt;/tt&gt; -- default: nil, params you want to exclude. This is nifty because it does a &quot;deep delete&quot;. So you can pass {:param1 =&gt; {:param2 =&gt; :param3}} and it will make sure param3 does not get include. param1 and param2 will not be touched. This also accepts an array or just a symbol or string.
+        # * &lt;tt&gt;:exclude_params&lt;/tt&gt; -- default: nil, params you want to exclude. This is nifty because it does a &quot;deep delete&quot;. So you can pass {:param1 =&gt; {:param2 =&gt; :param3}} and it will make sure param3 does not get included. param1 and param2 will not be touched. This also accepts an array or just a symbol or string.
         # * &lt;tt&gt;:search_params&lt;/tt&gt; -- default: nil, Additional search params to add to the url, must be a hash. Adds the options into the :params_scope.
         # * &lt;tt&gt;:exclude_search_params&lt;/tt&gt; -- default: nil, Same as :exclude_params but for the :search_params.
         def priority_order_by_link(priority_order_by, priority_order_as, options = {})
@@ -181,14 +181,13 @@ module Searchgasm
         # As you can see above, passing nil means &quot;show all&quot; and the text will automatically revert to &quot;show all&quot;
         #
         # === Options
-        # * &lt;tt&gt;:text&lt;/tt&gt; -- default: column_name.to_s.humanize, text for the link
         # * &lt;tt&gt;:html&lt;/tt&gt; -- html arrtributes for the &lt;a&gt; tag.
         #
         # === Advanced Options
-        # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base leve in params such as params[:page], params[:per_page], etc, then set this to nil.
+        # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base level in params such as params[:page], params[:per_page], etc, then set this to nil.
         # * &lt;tt&gt;:search_obj&lt;/tt&gt; -- default: @#{params_scope}, this is your search object, everything revolves around this. It will try to infer the name from your params_scope. If your params_scope is :search it will try to get @search, etc. If it can not be inferred by this, you need to pass the object itself.
         # * &lt;tt&gt;:params&lt;/tt&gt; -- default: nil, Additional params to add to the url, must be a hash
-        # * &lt;tt&gt;:exclude_params&lt;/tt&gt; -- default: nil, params you want to exclude. This is nifty because it does a &quot;deep delete&quot;. So you can pass {:param1 =&gt; {:param2 =&gt; :param3}} and it will make sure param3 does not get include. param1 and param2 will not be touched. This also accepts an array or just a symbol or string.
+        # * &lt;tt&gt;:exclude_params&lt;/tt&gt; -- default: nil, params you want to exclude. This is nifty because it does a &quot;deep delete&quot;. So you can pass {:param1 =&gt; {:param2 =&gt; :param3}} and it will make sure param3 does not get included. param1 and param2 will not be touched. This also accepts an array or just a symbol or string.
         # * &lt;tt&gt;:search_params&lt;/tt&gt; -- default: nil, Additional search params to add to the url, must be a hash. Adds the options into the :params_scope.
         # * &lt;tt&gt;:exclude_search_params&lt;/tt&gt; -- default: nil, Same as :exclude_params but for the :search_params.
         def per_page_link(per_page, options = {})
@@ -217,10 +216,10 @@ module Searchgasm
         # * &lt;tt&gt;:html&lt;/tt&gt; -- html arrtributes for the &lt;a&gt; tag.
         #
         # === Advanced Options
-        # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base leve in params such as params[:page], params[:per_page], etc, then set this to nil.
+        # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base level in params such as params[:page], params[:per_page], etc, then set this to nil.
         # * &lt;tt&gt;:search_obj&lt;/tt&gt; -- default: @#{params_scope}, this is your search object, everything revolves around this. It will try to infer the name from your params_scope. If your params_scope is :search it will try to get @search, etc. If it can not be inferred by this, you need to pass the object itself.
         # * &lt;tt&gt;:params&lt;/tt&gt; -- default: nil, Additional params to add to the url, must be a hash
-        # * &lt;tt&gt;:exclude_params&lt;/tt&gt; -- default: nil, params you want to exclude. This is nifty because it does a &quot;deep delete&quot;. So you can pass {:param1 =&gt; {:param2 =&gt; :param3}} and it will make sure param3 does not get include. param1 and param2 will not be touched. This also accepts an array or just a symbol or string.
+        # * &lt;tt&gt;:exclude_params&lt;/tt&gt; -- default: nil, params you want to exclude. This is nifty because it does a &quot;deep delete&quot;. So you can pass {:param1 =&gt; {:param2 =&gt; :param3}} and it will make sure param3 does not get included. param1 and param2 will not be touched. This also accepts an array or just a symbol or string.
         # * &lt;tt&gt;:search_params&lt;/tt&gt; -- default: nil, Additional search params to add to the url, must be a hash. Adds the options into the :params_scope.
         # * &lt;tt&gt;:exclude_search_params&lt;/tt&gt; -- default: nil, Same as :exclude_params but for the :search_params.
         def page_link(page, options = {})
@@ -238,29 +237,32 @@ module Searchgasm
         
         private
           def add_order_by_link_defaults!(order_by, options = {})
-            add_searchgasm_control_defaults!(:order_by, options)
+            add_searchgasm_control_defaults!(options)
+            searchgasm_add_class!(options[:html], Config.helpers.order_by_link_class_name)
             ordering_by_this = searchgasm_ordering_by?(order_by, options)
             searchgasm_add_class!(options[:html], &quot;ordering&quot;) if ordering_by_this
             options[:text] ||= determine_order_by_text(order_by)
-            options[:asc_indicator] ||= Config.asc_indicator
-            options[:desc_indicator] ||= Config.desc_indicator
+            options[:asc_indicator] ||= Config.helpers.order_by_link_asc_indicator
+            options[:desc_indicator] ||= Config.helpers.order_by_link_desc_indicator
             options[:text] += options[:search_obj].desc? ? options[:desc_indicator] : options[:asc_indicator] if ordering_by_this
             options[:url] = searchgasm_params(options.merge(:search_params =&gt; {:order_by =&gt; order_by}))
             options
           end
           
           def add_order_as_link_defaults!(order_as, options = {})
-            add_searchgasm_control_defaults!(:order_as, options)
+            add_searchgasm_control_defaults!(options)
+            searchgasm_add_class!(options[:html], Config.helpers.order_as_link_class_name)
             options[:text] ||= order_as.to_s
             options[:url] = searchgasm_params(options.merge(:search_params =&gt; {:order_as =&gt; order_as}))
             options
           end
           
           def add_priority_order_by_link_defaults!(priority_order_by, priority_order_as, options = {})
-            add_searchgasm_control_defaults!(:priority_order_by, options)
+            add_searchgasm_control_defaults!(options)
+            searchgasm_add_class!(options[:html], Config.helpers.priority_order_by_link_class_name)
             options[:column_name] ||= determine_order_by_text(priority_order_by).downcase 
-            options[:activate_text] ||= &quot;Show #{options[:column_name]} first&quot;
-            options[:deactivate_text] ||= &quot;Don't show #{options[:column_name]} first&quot;
+            options[:activate_text] ||= Config.helpers.priority_order_by_link_activate_text % options[:column_name]
+            options[:deactivate_text] ||= Config.helpers.priority_order_by_link_deactivate_text % options[:column_name]
             active = deep_stringify(options[:search_obj].priority_order_by) == deep_stringify(priority_order_by) &amp;&amp; options[:search_obj].priority_order_as == priority_order_as
             options[:text] ||= active ? options[:deactivate_text] : options[:activate_text]
             if active
@@ -273,14 +275,16 @@ module Searchgasm
           end
           
           def add_per_page_link_defaults!(per_page, options = {})
-            add_searchgasm_control_defaults!(:per_page, options)
-            options[:text] ||= per_page.blank? ? &quot;Show all&quot; : &quot;#{per_page} per page&quot;
+            add_searchgasm_control_defaults!(options)
+            searchgasm_add_class!(options[:html], Config.helpers.per_page_link_class_name)
+            options[:text] ||= per_page.to_s
             options[:url] = searchgasm_params(options.merge(:search_params =&gt; {:per_page =&gt; per_page}))
             options
           end
           
           def add_page_link_defaults!(page, options = {})
-            add_searchgasm_control_defaults!(:page, options)
+            add_searchgasm_control_defaults!(options)
+            searchgasm_add_class!(options[:html], Config.helpers.page_link_class_name)
             options[:text] ||= page.to_s
             options[:url] = searchgasm_params(options.merge(:search_params =&gt; {:page =&gt; page}))
             options</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/helpers/control_types/link.rb</filename>
    </modified>
    <modified>
      <diff>@@ -16,10 +16,15 @@ module Searchgasm
         # * &lt;tt&gt;:choices&lt;/tt&gt; -- default: the models column names, the choices to loop through when calling order_by_link
         def order_by_links(options = {})
           add_order_by_links_defaults!(options)
-          link_options = options.deep_dup
-          link_options.delete(:choices)
+          links_options = options.deep_dup
+          links_options.delete(:choices)
           html = &quot;&quot;
-          options[:choices].each { |choice| html += order_by_link(choice, link_options.deep_dup) }
+          options[:choices].each do |choice|
+            link_options = links_option.deep_dup
+            text, value = option_text_and_value(choice)
+            link_options[:text] ||= text
+            html += order_by_link(value, link_options)
+          end
           html
         end
         
@@ -37,10 +42,15 @@ module Searchgasm
         # * &lt;tt&gt;:choices&lt;/tt&gt; -- default: [&quot;asc&quot;, &quot;desc&quot;], the choices to loop through when calling order_as_link
         def order_as_links(options = {})
           add_order_as_links_defaults!(options)
-          link_options = options.deep_dup
-          link_options.delete(:choices)
+          links_options = options.deep_dup
+          links_options.delete(:choices)
           html = &quot;&quot;
-          options[:choices].each { |choice| html += order_as_link(choice, link_options.deep_dup) }
+          options[:choices].each do |choice|
+            link_options = links_option.deep_dup
+            text, value = option_text_and_value(choice)
+            link_options[:text] ||= text
+            html += order_as_link(value, link_options)
+          end
           html
         end
         
@@ -55,13 +65,19 @@ module Searchgasm
         #
         # Please look at per_page_link. All options there are applicable here and are passed onto each option.
         #
-        # * &lt;tt&gt;:choices&lt;/tt&gt; -- default: [10, 25, 50, 100, 150, 200, nil], the choices to loop through when calling per_page_link.
+        # * &lt;tt&gt;:choices&lt;/tt&gt; -- default: [[&quot;10 per page&quot;, 10], [&quot;25 per page&quot;, 25], [&quot;50 per page&quot;, 50], [&quot;100 per page&quot;, 100], [&quot;150 per page&quot;, 150], [&quot;200 per page&quot;, 200], [&quot;Show all&quot;, nil]]
         def per_page_links(options = {})
           add_per_page_links_defaults!(options)
-          link_options = options.deep_dup
-          link_options.delete(:choices)
+          links_options = options.deep_dup
+          links_options.delete(:choices)
           html = &quot;&quot;
-          options[:choices].each { |choice| html += per_page_link(choice, link_options.deep_dup) }
+          options[:choices].each do |choice|
+            link_options = links_options.deep_dup
+            text, value = option_text_and_value(choice)
+            link_options[:text] ||= text
+            searchgasm_add_class!(link_options[:html], Config.helpers.order_by_links_ordering_by_class_name) if link_options[:search_obj].per_page == value
+            html += per_page_link(value, link_options)
+          end
           html
         end
         
@@ -148,41 +164,51 @@ module Searchgasm
         
         private
           def add_order_by_links_defaults!(options)
-            add_searchgasm_control_defaults!(:order_by, options)
+            add_searchgasm_control_defaults!(options)
             options[:choices] ||= options[:search_obj].klass.column_names.map(&amp;:humanize)
             options
           end
           
           def add_order_as_links_defaults!(options)
-            add_searchgasm_control_defaults!(:order_as, options)
+            add_searchgasm_control_defaults!(options)
             options[:choices] = [:asc, :desc]
             options
           end
           
           def add_per_page_links_defaults!(options)
-            add_searchgasm_control_defaults!(:per_page, options)
-            options[:choices] ||= Config.per_page_choices.dup
-            if !options[:search_obj].per_page.blank? &amp;&amp; !options[:choices].include?(options[:search_obj].per_page)
-              options[:choices] &lt;&lt; options[:search_obj].per_page
-              has_nil = options[:choices].include?(nil)
-              options[:choices].compact!
-              options[:choices].sort!
-              options[:choices] &lt;&lt; nil if has_nil
+            add_searchgasm_control_defaults!(options)
+            options[:choices] ||= Config.helpers.per_page_links_choices.dup
+            if !options[:search_obj].per_page.blank? &amp;&amp; !choices_include?(options[:choices], options[:search_obj].per_page)
+              options[:choices] &lt;&lt; [&quot;#{options[:search_obj].per_page} per page&quot;, options[:search_obj].per_page]
+              options[:choices].sort! do |a, b|
+                a_value = (a.is_a?(Array) ? a.last : a).to_i
+                return -1 if a_value == 0
+                b_value = (b.is_a?(Array) ? b.last : b).to_i
+                a_value &lt;=&gt; b_value
+              end
             end
             options
           end
           
+          def choices_include?(choices, includes)
+            choices.each do |choice|
+              value = choice.is_a?(Array) ? choice.last : choice
+              return true if value == includes
+            end
+            false
+          end
+          
           def add_page_links_defaults!(options)
-            add_searchgasm_control_defaults!(:page, options)
+            add_searchgasm_control_defaults!(options)
             options[:first_page] ||= 1
             options[:last_page] ||= options[:search_obj].page_count
             options[:current_page] ||= options[:search_obj].page
-            options[:inner_spread] = Config.page_links_inner_spread unless options.has_key?(:inner_spread)
-            options[:outer_spread] = Config.page_links_outer_spread unless options.has_key?(:outer_spread)
-            options[:prev] = Config.page_links_prev unless options.has_key?(:prev)
-            options[:next] = Config.page_links_next unless options.has_key?(:next)
-            options[:first] = Config.page_links_first unless options.has_key?(:first)
-            options[:last] = Config.page_links_last unless options.has_key?(:last)
+            options[:inner_spread] = Config.helpers.page_links_inner_spread unless options.has_key?(:inner_spread)
+            options[:outer_spread] = Config.helpers.page_links_outer_spread unless options.has_key?(:outer_spread)
+            options[:prev] = Config.helpers.page_links_prev unless options.has_key?(:prev)
+            options[:next] = Config.helpers.page_links_next unless options.has_key?(:next)
+            options[:first] = Config.helpers.page_links_first unless options.has_key?(:first)
+            options[:last] = Config.helpers.page_links_last unless options.has_key?(:last)
             options
           end
           
@@ -193,14 +219,17 @@ module Searchgasm
             when Fixnum
               text = name
               page = name
-              searchgasm_add_class!(options[:html], &quot;current_page&quot;) if span
+              searchgasm_add_class!(options[:html], Config.helpers.page_links_current_page_class_name) if span
             else
               text = options[name]
               page = options[:search_obj].send(&quot;#{name}_page&quot;)
-              searchgasm_add_class!(options[:html], &quot;#{name}_page&quot;)
+              searchgasm_add_class!(options[:html], Config.helpers.send(&quot;page_links_#{name}_page_class_name&quot;))
             end
             
-            searchgasm_add_class!(options[:html], &quot;disabled_page&quot;) if span
+            if span
+              searchgasm_add_class!(options[:html], Config.helpers.page_links_disabled_class_name)
+              searchgasm_add_class!(options[:html], &quot;page&quot;)
+            end
             options[:text] = text
             span ? content_tag(:span, text, options[:html]) : page_link(page, options)
           end</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/helpers/control_types/links.rb</filename>
    </modified>
    <modified>
      <diff>@@ -32,25 +32,28 @@ module Searchgasm
         private
           def add_order_by_select_defaults!(options)
             add_order_by_links_defaults!(options)
+            searchgasm_add_class!(options[:html], Config.helpers.order_by_select_class_name)
             add_searchgasm_select_defaults!(:order_by, options)
             options
           end
           
           def add_order_as_select_defaults!(options)
             add_order_as_links_defaults!(options)
+            searchgasm_add_class!(options[:html], Config.helpers.order_as_select_class_name)
             add_searchgasm_select_defaults!(:order_as, options)
             options
           end
           
           def add_per_page_select_defaults!(options)
             add_per_page_links_defaults!(options)
-            options[:choices] = options[:choices].collect { |choice| choice.nil? ? [&quot;Show all&quot;, choice] : [&quot;#{choice} per page&quot;, choice]}
+            searchgasm_add_class!(options[:html], Config.helpers.per_page_select_class_name)
             add_searchgasm_select_defaults!(:per_page, options)
             options
           end
           
           def add_page_select_defaults!(options)
             add_page_links_defaults!(options)
+            searchgasm_add_class!(options[:html], Config.helpers.page_select_class_name)
             add_searchgasm_select_defaults!(:page, options)
             options
           end
@@ -68,7 +71,7 @@ module Searchgasm
             else
               options[:html][:onchange] += remote_function(:url =&gt; url, :method =&gt; :get).gsub(/\\'\+this.value\+\\'/, &quot;'+this.value+'&quot;)
             end
-            options[:html][:id] ||= &quot;&quot;
+            options[:html][:id] ||= &quot;#{option}_select&quot;
             options
           end
       end</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/helpers/control_types/select.rb</filename>
    </modified>
    <modified>
      <diff>@@ -55,12 +55,12 @@ module Searchgasm
           def extract_searchgasm_options!(args)
             options = args.extract_options!
             searchgasm_options = {}
-            [:hidden_fields].each { |option| searchgasm_options[option] = options.has_key?(option) ? options.delete(option) : Config.send(option) }
+            [:hidden_fields].each { |option| searchgasm_options[option] = options.has_key?(option) ? options.delete(option) : Config.helpers.send(option) }
             searchgasm_options[:hidden_fields] = [searchgasm_options[:hidden_fields]].flatten.compact
             args &lt;&lt; options
             searchgasm_options
           end
-        
+          
           def searchgasm_args(args, search_object, search_options, for_helper = nil)
             args = args.dup
             first = args.shift
@@ -93,7 +93,7 @@ module Searchgasm
               
                 javascript = &quot;if(typeof(Prototype) != 'undefined') {&quot;
                 search_options[:hidden_fields].each { |field| javascript += &quot;field = $('#{name}_#{field}'); if(field) { $('#{name}_#{field}_hidden').value = field.value; }&quot; }
-                javascript += &quot;} else if(jQuery) {&quot;
+                javascript += &quot;} else if(typeof(jQuery) != 'undefined') {&quot;
                 search_options[:hidden_fields].each { |field| javascript += &quot;field = $('##{name}_#{field}'); if(field) { $('##{name}_#{field}_hidden').val(field.val()); }&quot; }
                 javascript += &quot;}&quot;
               </diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/helpers/form.rb</filename>
    </modified>
    <modified>
      <diff>@@ -105,7 +105,7 @@ module Searchgasm
       # === Options
       # * &lt;tt&gt;:params_scope&lt;/tt&gt; -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base leve in params such as params[:page], params[:per_page], etc, then set this to nil.
       # * &lt;tt&gt;:search_obj&lt;/tt&gt; -- default: @#{params_scope}, this is your search object, everything revolves around this. It will try to infer the name from your params_scope. If your params_scope is :search it will try to get @search, etc. If it can not be inferred by this, you need to pass the object itself.
-      def searchgasm_state(options)
+      def searchgasm_state(options = {})
         return &quot;&quot; if @added_searchgasm_state
         add_searchgasm_defaults!(options)
         html = &quot;&quot;
@@ -127,16 +127,15 @@ module Searchgasm
         end
         
         # Adds default options for all control type helper methods.
-        def add_searchgasm_control_defaults!(option, options)
+        def add_searchgasm_control_defaults!(options)
           add_searchgasm_defaults!(options)
           options[:html] ||= {}
-          options[:html][:class] ||= &quot;&quot;
-          searchgasm_add_class!(options[:html], option)
           options
         end
         
         def searchgasm_add_class!(html_options, new_class)
           new_class = new_class.to_s
+          html_options[:class] ||= &quot;&quot;
           classes = html_options[:class].split(&quot; &quot;)
           classes &lt;&lt; new_class unless classes.include?(new_class)
           html_options[:class] = classes.join(&quot; &quot;)</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/helpers/utilities.rb</filename>
    </modified>
    <modified>
      <diff>@@ -22,7 +22,7 @@ module Searchgasm #:nodoc:
       OPTIONS = SPECIAL_FIND_OPTIONS + AR_OPTIONS # the order is very important, these options get set in this order
       
       attr_accessor *AR_OPTIONS
-      attr_reader :auto_joins
+      attr_writer :scope
       
       class &lt;&lt; self
         # Used in the ActiveRecord methods to determine if Searchgasm should get involved or not.
@@ -43,7 +43,7 @@ module Searchgasm #:nodoc:
       end
       
       # Flag to determine if searchgasm is acting as a filter for the ActiveRecord search methods.
-      # The purpose of this is to determine if Config.per_page should be implemented.
+      # By filter it means that searchgasm is being used on the default ActiveRecord search methods, like all, count, find(:all), first, etc.
       def acting_as_filter=(value)
         @acting_as_filter = value
       end
@@ -56,8 +56,9 @@ module Searchgasm #:nodoc:
       # Specific implementation of cloning
       def clone
         options = {}
-        (OPTIONS - [:conditions]).each { |option| options[option] = send(option) }
+        (AR_OPTIONS - [:conditions]).each { |option| options[option] = instance_variable_get(&quot;@#{option}&quot;) }
         options[:conditions] = conditions.conditions
+        SPECIAL_FIND_OPTIONS.each { |option| options[option] = send(option) }
         obj = self.class.new(options)
         obj.protect = protected?
         obj.scope = scope
@@ -79,27 +80,10 @@ module Searchgasm #:nodoc:
         &quot;#&lt;#{klass}Search #{current_find_options.inspect}&gt;&quot;
       end
       
-      # Searchgasm requires that all joins be left outer joins for conditions and ordering to work properly
+      # Merges all joins together, including the scopes joins for
       def joins
-        joins_sql = &quot;&quot;
-        all_joins = auto_joins
-        
-        case @joins
-        when String
-          joins_sql += @joins
-        else
-          all_joins = merge_joins(@joins, all_joins)
-        end
-        
-        return if joins_sql.blank? &amp;&amp; all_joins.blank?
-        
-        unless all_joins.blank?
-          join_dependency = ::ActiveRecord::Associations::ClassMethods::JoinDependency.new(klass, all_joins, nil)
-          joins_sql += &quot; &quot; unless joins_sql.blank?
-          joins_sql += join_dependency.join_associations.collect { |assoc| assoc.association_join }.join
-        end
-        
-        joins_sql
+        all_joins = (safe_to_array(conditions.auto_joins) + safe_to_array(order_by_auto_joins) + safe_to_array(priority_order_by_auto_joins) + safe_to_array(@joins)).uniq
+        all_joins.size &lt;= 1 ? all_joins.first : all_joins
       end
       
       def limit=(value)
@@ -108,7 +92,7 @@ module Searchgasm #:nodoc:
       end
       
       def limit
-        @limit ||= Config.per_page if !acting_as_filter? &amp;&amp; !@set_limit
+        @limit ||= Config.search.per_page if !acting_as_filter? &amp;&amp; !@set_limit
         @limit
       end
       
@@ -123,7 +107,7 @@ module Searchgasm #:nodoc:
       end
       
       # Sanitizes everything down into options ActiveRecord::Base.find can understand
-      def sanitize(searching = true)
+      def sanitize(searching = true)  
         find_options = {}
         
         (searching ? AR_FIND_OPTIONS : AR_CALCULATIONS_OPTIONS).each do |find_option|
@@ -135,9 +119,30 @@ module Searchgasm #:nodoc:
         find_options
       end
       
+      def select
+        @select ||= &quot;DISTINCT #{klass.connection.quote_table_name(klass.table_name)}.*&quot; if !joins.blank? &amp;&amp; Config.search.remove_duplicates?
+        @select
+      end
+      
       def scope
         @scope ||= {}
       end
+      
+      private
+        def safe_to_array(o)
+          case o
+          when NilClass
+            []
+          when Array
+            o
+          else
+            [o]
+          end
+        end
+        
+        def array_of_strings?(o)
+          o.is_a?(Array) &amp;&amp; o.all?{|obj| obj.is_a?(String)}
+        end
     end
   end
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/search/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,8 +9,6 @@ module Searchgasm
         klass.class_eval do
           alias_method_chain :initialize, :conditions
           alias_method_chain :conditions=, :conditions
-          alias_method_chain :conditions, :conditions
-          alias_method_chain :auto_joins, :conditions
           alias_method_chain :sanitize, :conditions
         end
       end
@@ -34,7 +32,6 @@ module Searchgasm
       # now you can create the rest of your search and your &quot;scope&quot; will get merged into your final SQL.
       # What this does is determine if the value a hash or a conditions object, if not it sets it up as a scope.
       def conditions_with_conditions=(values)
-        @memoized_auto_joins = nil
         case values
         when Searchgasm::Conditions::Base
           @conditions = values
@@ -43,19 +40,6 @@ module Searchgasm
         end
       end
       
-      def conditions_with_conditions
-        @memoized_auto_joins = nil # have to assume they are calling a condition on a relationship
-        conditions_without_conditions
-      end
-      
-      # Tells searchgasm what relationships to join during the search. This is based on what conditions you set.
-      #
-      # &lt;b&gt;Be careful!&lt;/b&gt;
-      # ActiveRecord associations can be an SQL train wreck. Make sure you think about what you are searching and that you aren't joining a table with a million records.
-      def auto_joins_with_conditions
-        @memoized_auto_joins ||= merge_joins(auto_joins_without_conditions, conditions.auto_joins)
-      end
-      
       def sanitize_with_conditions(searching = true) # :nodoc:
         find_options = sanitize_without_conditions(searching)
         if conditions_obj = find_options.delete(:conditions)</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/search/conditions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,22 +18,16 @@ module Searchgasm
     module Ordering
       def self.included(klass)
         klass.class_eval do
-          alias_method_chain :auto_joins, :ordering
           alias_method_chain :order=, :ordering
           alias_method_chain :sanitize, :ordering
           attr_reader :priority_order
         end
       end
       
-      def auto_joins_with_ordering # :nodoc:
-        @memoized_auto_joins ||= merge_joins(auto_joins_without_ordering, order_by_auto_joins, priority_order_by_auto_joins)
-      end
-      
       def order_with_ordering=(value) # :nodoc
         @order_by = nil
         @order_as = nil
         @order_by_auto_joins = nil
-        @memoized_auto_joins = nil
         self.order_without_ordering = value
       end
       
@@ -93,7 +87,6 @@ module Searchgasm
       #   order_by = [:id, {:user_group =&gt; :name}] # =&gt; users.id ASC, user_groups.name ASC
       def order_by=(value)  
         @order_by_auto_joins = nil
-        @memoized_auto_joins = nil
         @order_by = get_order_by_value(value)
         @order = order_by_to_order(@order_by, @order_as)
         @order_by
@@ -122,7 +115,6 @@ module Searchgasm
       # Same as order_by= but for your priority order. See priority_order= for more informaton on priority_order.
       def priority_order_by=(value)
         @priority_order_by_auto_joins = nil
-        @memoized_auto_joins = nil
         @priority_order_by = get_order_by_value(value)
         @priority_order = order_by_to_order(@priority_order_by, @priority_order_as)
         @priority_order_by
@@ -178,7 +170,7 @@ module Searchgasm
           
           case order_by
           when Array
-            order_by.each { |part| sql_parts &lt;&lt; order_by_to_order(part, order_as) }
+            order_by.each { |part| sql_parts &lt;&lt; order_by_to_order(part, order_as, alt_klass) }
           when Hash
             raise(ArgumentError, &quot;when passing a hash to order_by you must only have 1 key: {:user_group =&gt; :name} not {:user_group =&gt; :name, :user_group =&gt; :id}. The latter should be [{:user_group =&gt; :name}, {:user_group =&gt; :id}]&quot;) if order_by.keys.size != 1
             key = order_by.keys.first</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/search/ordering.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,27 +9,19 @@ module Searchgasm
       SEARCH_METHODS = [:all, :find, :first]
       CALCULATION_METHODS = [:average, :calculate, :count, :maximum, :minimum, :sum]
       
-      def self.included(klass)
-        klass.class_eval do
-          attr_accessor :scope
-        end
-      end
-      
       (SEARCH_METHODS + CALCULATION_METHODS).each do |method|
         class_eval &lt;&lt;-&quot;end_eval&quot;, __FILE__, __LINE__
           def #{method}(*args)
             find_options = {}
             options = args.extract_options! # can't pass options, your options are in the search
-            klass.send(:with_scope, :find =&gt; scope) do
+            klass.send(:with_scope, :find =&gt; acting_as_filter? ? {} : scope) do
               options = sanitize(#{SEARCH_METHODS.include?(method)})
               if #{CALCULATION_METHODS.include?(method)}
                 options[:distinct] = true
                 args[0] = klass.primary_key if [nil, :all].include?(args[0])
               end
               args &lt;&lt; options
-              result = klass.#{method}(*args)
-              result.uniq! if result.is_a?(Array) &amp;&amp; Config.remove_duplicates?
-              result
+              klass.#{method}(*args)
             end
           end
         end_eval</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/search/searching.rb</filename>
    </modified>
    <modified>
      <diff>@@ -66,8 +66,8 @@ module Searchgasm
     end
 
     MAJOR = 1
-    MINOR = 3
-    TINY  = 4
+    MINOR = 5
+    TINY  = 1
 
     # The current version as a Version instance
     CURRENT = new(MAJOR, MINOR, TINY)</diff>
      <filename>vendor/plugins/searchgasm/lib/searchgasm/version.rb</filename>
    </modified>
    <modified>
      <diff>@@ -45,12 +45,15 @@ class TestActiveRecordBase &lt; Test::Unit::TestCase
     assert_equal Account.find(1, 3), Account.all(:conditions =&gt; {:name_contains =&gt; &quot;Binary&quot;})
     assert_equal [Account.find(1)], Account.all(:conditions =&gt; {:name_contains =&gt; &quot;Binary&quot;, :users =&gt; {:first_name_starts_with =&gt; &quot;Ben&quot;}})
     assert_equal [], Account.all(:conditions =&gt; {:name_contains =&gt; &quot;Binary&quot;, :users =&gt; {:first_name_starts_with =&gt; &quot;Ben&quot;, :last_name =&gt; &quot;Mills&quot;}})
+    assert_equal Account.find(1, 2), Account.all(:conditions =&gt; {:users =&gt; {:id_gt =&gt; 0}}, :include =&gt; :users)
     
     read_only_accounts = Account.all(:conditions =&gt; {:name_contains =&gt; &quot;Binary&quot;}, :readonly =&gt; true)
     assert read_only_accounts.first.readonly?
     
     assert_equal Account.find(1, 3), Account.all(:conditions =&gt; {:name_contains =&gt; &quot;Binary&quot;}, :page =&gt; 2)
     assert_equal [], Account.all(:conditions =&gt; {:name_contains =&gt; &quot;Binary&quot;}, :page =&gt; 2, :per_page =&gt; 20)
+    
+    assert_equal [Account.find(1)], Account.scope1.all(:conditions =&gt; {:users =&gt; {:first_name_starts_with =&gt; &quot;Ben&quot;}})
   end
   
   def test_searchgasm_counting
@@ -83,4 +86,8 @@ class TestActiveRecordBase &lt; Test::Unit::TestCase
     assert_equal Set.new([&quot;id_gt&quot;, &quot;name_contains&quot;]), Account.protected_conditions
     Account.send(:write_inheritable_attribute, :conditions_protected, nil)
   end
+  
+  def test_includes
+    assert_nothing_raised { Account.all(:conditions =&gt; {:users =&gt; {:first_name_like =&gt; &quot;Ben&quot;}}, :include =&gt; :users) }
+  end
 end</diff>
      <filename>vendor/plugins/searchgasm/test/test_active_record_base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -22,21 +22,21 @@ class TestConditionBase &lt; Test::Unit::TestCase
   end
   
   def test_initialize
-    condition = Searchgasm::Condition::Keywords.new(Account, Account.columns_hash[&quot;name&quot;])
+    condition = Searchgasm::Condition::Keywords.new(Account, :column =&gt; Account.columns_hash[&quot;name&quot;])
     assert_equal condition.klass, Account
     assert_equal Account.columns_hash[&quot;name&quot;], condition.column
     
-    condition = Searchgasm::Condition::GreaterThan.new(Account, &quot;id&quot;)
+    condition = Searchgasm::Condition::GreaterThan.new(Account, :column =&gt; &quot;id&quot;)
     assert_equal Account.columns_hash[&quot;id&quot;], condition.column
     
-    condition = Searchgasm::Condition::GreaterThan.new(Account, &quot;id&quot;, :string, &quot;some sql&quot;)
+    condition = Searchgasm::Condition::GreaterThan.new(Account, :column =&gt; &quot;id&quot;, :column_type =&gt; :string, :column_sql_format =&gt; &quot;some sql&quot;)
     assert_equal Account.columns_hash[&quot;id&quot;], condition.column
     condition.value = &quot;awesome&quot;
     assert_equal [&quot;some sql &gt; ?&quot;, &quot;awesome&quot;], condition.sanitize
   end
   
   def test_explicitly_set_value
-    condition = Searchgasm::Condition::Keywords.new(Account, Account.columns_hash[&quot;name&quot;])
+    condition = Searchgasm::Condition::Keywords.new(Account, :column =&gt; Account.columns_hash[&quot;name&quot;])
     assert !condition.explicitly_set_value?
     condition.value = &quot;test&quot;
     assert condition.explicitly_set_value?</diff>
      <filename>vendor/plugins/searchgasm/test/test_condition_base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,31 +2,31 @@ require File.dirname(__FILE__) + '/test_helper.rb'
 
 class TestConditionTypes &lt; Test::Unit::TestCase
   def test_sanitize
-    condition = Searchgasm::Condition::BeginsWith.new(Account, Account.columns_hash[&quot;name&quot;])
+    condition = Searchgasm::Condition::BeginsWith.new(Account, :column =&gt; Account.columns_hash[&quot;name&quot;])
     condition.value = &quot;Binary&quot;
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;name\&quot; LIKE ?&quot;, &quot;Binary%&quot;], condition.sanitize
     
-    condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Blank.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = &quot;true&quot;
     assert_equal &quot;\&quot;accounts\&quot;.\&quot;id\&quot; is NULL or \&quot;accounts\&quot;.\&quot;id\&quot; = '' or \&quot;accounts\&quot;.\&quot;id\&quot; = false&quot;, condition.sanitize
     
-    condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Blank.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = &quot;false&quot;
     assert_equal &quot;\&quot;accounts\&quot;.\&quot;id\&quot; is NOT NULL and \&quot;accounts\&quot;.\&quot;id\&quot; != '' and \&quot;accounts\&quot;.\&quot;id\&quot; != false&quot;, condition.sanitize
     
-    condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Blank.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = true
     assert_equal &quot;\&quot;accounts\&quot;.\&quot;id\&quot; is NULL or \&quot;accounts\&quot;.\&quot;id\&quot; = '' or \&quot;accounts\&quot;.\&quot;id\&quot; = false&quot;, condition.sanitize
     
-    condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Blank.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = false
     assert_equal &quot;\&quot;accounts\&quot;.\&quot;id\&quot; is NOT NULL and \&quot;accounts\&quot;.\&quot;id\&quot; != '' and \&quot;accounts\&quot;.\&quot;id\&quot; != false&quot;, condition.sanitize
     
-    condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Blank.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = nil
     assert_equal nil, condition.sanitize
     
-    condition = Searchgasm::Condition::Blank.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Blank.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = &quot;&quot;
     assert_equal nil, condition.sanitize
     
@@ -42,27 +42,27 @@ class TestConditionTypes &lt; Test::Unit::TestCase
     condition.value = User.find(1)
     assert_equal [&quot;\&quot;users\&quot;.\&quot;id\&quot; = ? OR \&quot;users\&quot;.\&quot;id\&quot; = ?&quot;, 2, 3], condition.sanitize
     
-    condition = Searchgasm::Condition::EndsWith.new(Account, Account.columns_hash[&quot;name&quot;])
+    condition = Searchgasm::Condition::EndsWith.new(Account, :column =&gt; Account.columns_hash[&quot;name&quot;])
     condition.value = &quot;Binary&quot;
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;name\&quot; LIKE ?&quot;, &quot;%Binary&quot;], condition.sanitize
     
-    condition = Searchgasm::Condition::Equals.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Equals.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = 12
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;id\&quot; = ?&quot;, 12], condition.sanitize
     
-    condition = Searchgasm::Condition::Equals.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Equals.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = [1,2,3,4]
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;id\&quot; IN (?)&quot;, [1, 2, 3, 4]], condition.sanitize
     
-    condition = Searchgasm::Condition::Equals.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Equals.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = (1..10)
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;id\&quot; BETWEEN ? AND ?&quot;, 1, 10], condition.sanitize
     
-    condition = Searchgasm::Condition::GreaterThan.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::GreaterThan.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = 2
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;id\&quot; &gt; ?&quot;, 2], condition.sanitize
     
-    condition = Searchgasm::Condition::GreaterThanOrEqualTo.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::GreaterThanOrEqualTo.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = 2
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;id\&quot; &gt;= ?&quot;, 2], condition.sanitize
     
@@ -70,59 +70,59 @@ class TestConditionTypes &lt; Test::Unit::TestCase
     condition.value = User.find(1)
     assert_equal [&quot;(\&quot;users\&quot;.\&quot;id\&quot; = ?) OR (\&quot;users\&quot;.\&quot;id\&quot; = ? OR \&quot;users\&quot;.\&quot;id\&quot; = ?)&quot;, 1, 2, 3], condition.sanitize
     
-    condition = Searchgasm::Condition::Like.new(Account, Account.columns_hash[&quot;name&quot;])
+    condition = Searchgasm::Condition::Like.new(Account, :column =&gt; Account.columns_hash[&quot;name&quot;])
     condition.value = &quot;Binary and blah&quot;
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;name\&quot; LIKE ?&quot;, &quot;%Binary and blah%&quot;], condition.sanitize
     
-    condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Nil.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = true
     assert_equal &quot;\&quot;accounts\&quot;.\&quot;id\&quot; is NULL&quot;, condition.sanitize
     
-    condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Nil.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = false
     assert_equal &quot;\&quot;accounts\&quot;.\&quot;id\&quot; is NOT NULL&quot;, condition.sanitize
     
-    condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Nil.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = &quot;true&quot;
     assert_equal &quot;\&quot;accounts\&quot;.\&quot;id\&quot; is NULL&quot;, condition.sanitize
     
-    condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Nil.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = &quot;false&quot;
     assert_equal &quot;\&quot;accounts\&quot;.\&quot;id\&quot; is NOT NULL&quot;, condition.sanitize
     
-    condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Nil.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = nil
     assert_equal nil, condition.sanitize
     
-    condition = Searchgasm::Condition::Nil.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::Nil.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = &quot;&quot;
     assert_equal nil, condition.sanitize
     
-    condition = Searchgasm::Condition::NotEqual.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::NotEqual.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = 12
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;id\&quot; != ?&quot;, 12], condition.sanitize
     
-    condition = Searchgasm::Condition::NotEqual.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::NotEqual.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = [1,2,3,4]
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;id\&quot; NOT IN (?)&quot;, [1, 2, 3, 4]], condition.sanitize
     
-    condition = Searchgasm::Condition::NotEqual.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::NotEqual.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = (1..10)
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;id\&quot; NOT BETWEEN ? AND ?&quot;, 1, 10], condition.sanitize
     
-    condition = Searchgasm::Condition::Keywords.new(Account, Account.columns_hash[&quot;name&quot;])
+    condition = Searchgasm::Condition::Keywords.new(Account, :column =&gt; Account.columns_hash[&quot;name&quot;])
     condition.value = &quot;freedom yeah, freedom YEAH right&quot;
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;name\&quot; LIKE ? AND \&quot;accounts\&quot;.\&quot;name\&quot; LIKE ? AND \&quot;accounts\&quot;.\&quot;name\&quot; LIKE ?&quot;, &quot;%freedom%&quot;, &quot;%yeah%&quot;, &quot;%right%&quot;], condition.sanitize
     
-    condition = Searchgasm::Condition::Keywords.new(Account, Account.columns_hash[&quot;name&quot;])
+    condition = Searchgasm::Condition::Keywords.new(Account, :column =&gt; Account.columns_hash[&quot;name&quot;])
     condition.value = &quot;%^$*(^$)&quot;
     assert_equal nil, condition.sanitize
     
-    condition = Searchgasm::Condition::LessThan.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::LessThan.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = 2
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;id\&quot; &lt; ?&quot;, 2], condition.sanitize
     
-    condition = Searchgasm::Condition::LessThanOrEqualTo.new(Account, Account.columns_hash[&quot;id&quot;])
+    condition = Searchgasm::Condition::LessThanOrEqualTo.new(Account, :column =&gt; Account.columns_hash[&quot;id&quot;])
     condition.value = 2
     assert_equal [&quot;\&quot;accounts\&quot;.\&quot;id\&quot; &lt;= ?&quot;, 2], condition.sanitize
     </diff>
      <filename>vendor/plugins/searchgasm/test/test_condition_types.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,7 @@ class TestConditionsBase &lt; Test::Unit::TestCase
   end
   
   def test_association_names
-    assert_equal [&quot;account&quot;, &quot;parent&quot;, &quot;orders&quot;, &quot;user_groups&quot;, &quot;children&quot;], Searchgasm::Cache::UserConditions.association_names
+    assert_equal [&quot;dogs&quot;, &quot;children&quot;, &quot;user_groups&quot;, &quot;orders&quot;, &quot;account&quot;, &quot;parent&quot;, &quot;cats&quot;], Searchgasm::Cache::UserConditions.association_names
     assert_equal [&quot;admin&quot;, &quot;orders&quot;, &quot;users&quot;], Searchgasm::Cache::AccountConditions.association_names
   end
   
@@ -218,4 +218,25 @@ class TestConditionsBase &lt; Test::Unit::TestCase
     conditions = Searchgasm::Cache::AccountConditions.new
     assert_equal nil, conditions.id
   end
+  
+  def test_sti
+    #s = User.new_search
+    #s.conditions.dogs.description_like = &quot;awesome&quot;
+    #s.conditions.cats.description_like = &quot;awesome&quot;
+    #s.select = &quot;ass&quot;
+    #s.all
+    
+    joins = []
+    join_dependency = ::ActiveRecord::Associations::ClassMethods::JoinDependency.new(User, [:dogs, :cats], nil)
+    join_dependency.join_associations.each_with_index do |assoc, index|
+      #raise assoc.aliased_table_name.inspect if index == 1
+      joins &lt;&lt; assoc.association_join
+    end
+    #raise joins.inspect
+    
+    conditions = Searchgasm::Cache::UserConditions.new
+    conditions.dogs.description_like = &quot;Harry&quot;
+    r = User.reflect_on_association(:dogs)
+    #raise r.inspect
+  end
 end</diff>
      <filename>vendor/plugins/searchgasm/test/test_conditions_base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/test_helper.rb'
 
 class TestConfig &lt; Test::Unit::TestCase
   def test_per_page
-    Searchgasm::Config.per_page = 1
+    Searchgasm::Config.search.per_page = 1
     
     assert Account.count &gt; 1
     assert Account.all.size &gt; 1
@@ -11,7 +11,7 @@ class TestConfig &lt; Test::Unit::TestCase
     assert User.new_search.all.size == 1
     assert User.new_search(:per_page =&gt; nil).all.size &gt; 1
     
-    Searchgasm::Config.per_page = nil
+    Searchgasm::Config.search.per_page = nil
     
     assert Account.count &gt; 1
     assert Account.all.size &gt; 1
@@ -20,6 +20,4 @@ class TestConfig &lt; Test::Unit::TestCase
     assert User.new_search.all.size &gt; 1
     assert User.new_search(:per_page =&gt; 1).all.size == 1
   end
-  
-  # test that config options do not mess up regular AR searches
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/searchgasm/test/test_config.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,10 @@
 require &quot;test/unit&quot;
 require &quot;rubygems&quot;
 require &quot;ruby-debug&quot;
-require &quot;activerecord&quot;
-require File.dirname(__FILE__) + '/libs/acts_as_tree'
-require File.dirname(__FILE__) + '/libs/ordered_hash'
-require File.dirname(__FILE__) + '/libs/rexml_fix'
+require &quot;active_record&quot;
+require File.dirname(__FILE__) + '/../test_libs/acts_as_tree'
+require File.dirname(__FILE__) + '/../test_libs/ordered_hash'
+require File.dirname(__FILE__) + '/../test_libs/rexml_fix'
 require File.dirname(__FILE__) + '/../lib/searchgasm'
 
 ActiveRecord::Base.establish_connection(:adapter =&gt; &quot;sqlite3&quot;, :dbfile =&gt; &quot;:memory:&quot;)
@@ -13,6 +13,8 @@ class Account &lt; ActiveRecord::Base
   has_one :admin, :class_name =&gt; &quot;User&quot;, :conditions =&gt; {:first_name =&gt; &quot;Ben&quot;}
   has_many :users, :dependent =&gt; :destroy
   has_many :orders, :through =&gt; :users
+  
+  named_scope :scope1, :conditions =&gt; {:users =&gt; {:first_name_contains =&gt; &quot;Ben&quot;}}
 end
 
 class UserGroup &lt; ActiveRecord::Base
@@ -23,6 +25,8 @@ class User &lt; ActiveRecord::Base
   acts_as_tree
   belongs_to :account
   has_many :orders, :dependent =&gt; :destroy
+  has_many :cats, :dependent =&gt; :destroy
+  has_many :dogs, :dependent =&gt; :destroy
   has_and_belongs_to_many :user_groups
 end
 
@@ -30,6 +34,16 @@ class Order &lt; ActiveRecord::Base
   belongs_to :user
 end
 
+# STI
+class Animal &lt; ActiveRecord::Base
+end
+
+class Dog &lt; Animal
+end
+
+class Cat &lt; Animal
+end
+
 class Test::Unit::TestCase
   def setup_db
     ActiveRecord::Schema.define(:version =&gt; 1) do
@@ -70,11 +84,18 @@ class Test::Unit::TestCase
         t.text      :description
         t.binary    :receipt
       end
+      
+      create_table :animals do |t|
+        t.datetime  :created_at      
+        t.datetime  :updated_at
+        t.string   :type
+        t.text     :description
+      end
     end
   end
   
   def load_fixtures
-    fixtures = [:accounts, :orders, :users, :user_groups]
+    fixtures = [:accounts, :orders, :users, :user_groups, :dogs, :cats]
     fixtures.each do |fixture|
       records = YAML.load(File.read(File.dirname(__FILE__) + &quot;/fixtures/#{fixture.to_s}.yml&quot;))
       records.each do |name, attributes|</diff>
      <filename>vendor/plugins/searchgasm/test/test_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -30,7 +30,7 @@ class TestSearchBase &lt; Test::Unit::TestCase
   def test_setting_first_level_options
     search = Account.new_search!(:include =&gt; :users, :joins =&gt; :users, :offset =&gt; 5, :limit =&gt; 20, :order =&gt; &quot;name ASC&quot;, :select =&gt; &quot;name&quot;, :readonly =&gt; true, :group =&gt; &quot;name&quot;, :from =&gt; &quot;accounts&quot;, :lock =&gt; true)
     assert_equal :users, search.include
-    assert_equal &quot; LEFT OUTER JOIN \&quot;users\&quot; ON users.account_id = accounts.id &quot;, search.joins
+    assert_equal :users, search.joins
     assert_equal 5, search.offset
     assert_equal 20, search.limit
     assert_equal &quot;name ASC&quot;, search.order
@@ -99,20 +99,20 @@ class TestSearchBase &lt; Test::Unit::TestCase
     assert_equal search.lock, true
   end
 
-  def test_auto_joins
+  def test_joins
     search = Account.new_search
-    assert_equal nil, search.auto_joins
+    assert_equal nil, search.joins
     search.conditions.name_contains = &quot;Binary&quot;
-    assert_equal nil, search.auto_joins
+    assert_equal nil, search.joins
     search.conditions.users.first_name_contains = &quot;Ben&quot;
-    assert_equal(:users, search.auto_joins)
+    assert_equal(:users, search.joins)
     search.conditions.users.orders.id_gt = 2
-    assert_equal({:users =&gt; :orders}, search.auto_joins)
+    assert_equal({:users =&gt; :orders}, search.joins)
     search.conditions.users.reset_orders!
-    assert_equal(:users, search.auto_joins)
+    assert_equal(:users, search.joins)
     search.conditions.users.orders.id_gt = 2
     search.conditions.reset_users!
-    assert_equal nil, search.auto_joins
+    assert_equal nil, search.joins
   end
 
   def test_limit
@@ -141,7 +141,7 @@ class TestSearchBase &lt; Test::Unit::TestCase
     search.conditions.users.id_greater_than = 2
     search.page = 3
     search.readonly = true
-    assert_equal({:joins =&gt; &quot; LEFT OUTER JOIN \&quot;users\&quot; ON users.account_id = accounts.id &quot;, :offset =&gt; 4, :readonly =&gt; true, :conditions =&gt; [&quot;(\&quot;accounts\&quot;.\&quot;name\&quot; LIKE ?) AND (\&quot;users\&quot;.\&quot;id\&quot; &gt; ?)&quot;, &quot;%Binary%&quot;, 2], :limit =&gt; 2 }, search.sanitize)
+    assert_equal({:joins =&gt; :users, :offset =&gt; 4, :select =&gt; &quot;DISTINCT \&quot;accounts\&quot;.*&quot;, :readonly =&gt; true, :conditions =&gt; [&quot;(\&quot;accounts\&quot;.\&quot;name\&quot; LIKE ?) AND (\&quot;users\&quot;.\&quot;id\&quot; &gt; ?)&quot;, &quot;%Binary%&quot;, 2], :limit =&gt; 2 }, search.sanitize)
   end
 
   def test_scope
@@ -185,6 +185,11 @@ class TestSearchBase &lt; Test::Unit::TestCase
     search = Account.new_search
     search.select = &quot;id, name&quot;
     assert_equal Account.all, search.all
+    
+    search = Account.scope1.new_search!(:conditions =&gt; {:users =&gt; {:first_name_starts_with =&gt; &quot;Ben&quot;}})
+    assert_equal [Account.find(1)], search.all
+    search2 = search.dup
+    assert_equal [Account.find(1)], search2.all
   end
 
   def test_calculations
@@ -211,22 +216,12 @@ class TestSearchBase &lt; Test::Unit::TestCase
     assert_equal 1, search.count
   end
   
-  def test_method_creation_in_scope
-    # test ot make sure methods are not created across the board for all models
-  end
-  
-=begin
-  # AR desont handle this problem either
-  def test_specifying_includes
-    search = Account.new_search
-    search.include = :users
-    search.conditions.users.first_name_like = &quot;Ben&quot;
-    assert_nothing_raised { search.all }
-  end
-=end
-  
   def test_inspect
     search = Account.new_search
     assert_nothing_raised { search.inspect }
   end
+  
+  def test_sti
+    
+  end
 end
\ No newline at end of file</diff>
      <filename>vendor/plugins/searchgasm/test/test_search_base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,17 +12,7 @@ class TestSearchConditions &lt; Test::Unit::TestCase
     search = Account.new_search(:conditions =&gt; {:name_like =&gt; &quot;Ben&quot;})
     assert_equal({:name_like =&gt; &quot;Ben&quot;}, search.conditions.conditions)
   end
-  
-  def test_auto_joins
-    search = Account.new_search
-    search.conditions = {:name_like =&gt; &quot;Binary&quot;}
-    assert_equal nil, search.auto_joins
-    search.conditions.users.first_name_like = &quot;Ben&quot;
-    assert_equal :users, search.auto_joins
-    search.conditions.reset_users!
-    assert_equal nil, search.auto_joins
-  end
-  
+
   def test_sanitize
     # This is tested in test_search_base
   end</diff>
      <filename>vendor/plugins/searchgasm/test/test_search_conditions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -99,7 +99,7 @@ class TestSearchOrdering &lt; Test::Unit::TestCase
     
     assert_raise(ArgumentError) { search.order_as = &quot;awesome&quot; }
   end
-  
+
   def test_order_by_auto_joins
     search = Account.new_search
     assert_equal nil, search.order_by_auto_joins
@@ -113,9 +113,8 @@ class TestSearchOrdering &lt; Test::Unit::TestCase
     assert_equal [:users, :orders, {:users =&gt; :user_groups}], search.order_by_auto_joins
     search.priority_order_by = {:users =&gt; {:orders =&gt; :total}}
     assert_equal({:users =&gt; :orders}, search.priority_order_by_auto_joins)
-    assert_equal [:users, :orders, {:users =&gt; :user_groups}, {:users =&gt; :orders}], search.auto_joins
   end
-  
+
   def test_priority_order_by
     search = Account.new_search
     assert_equal nil, search.priority_order
@@ -159,7 +158,7 @@ class TestSearchOrdering &lt; Test::Unit::TestCase
   end
   
   def test_ordering_includes_blank
-    search = User.new_search
+    search = User.new_search!
     search.order_by = {:account =&gt; :name}
     assert_equal 4, search.count
   end</diff>
      <filename>vendor/plugins/searchgasm/test/test_search_ordering.rb</filename>
    </modified>
    <modified>
      <diff>@@ -63,7 +63,7 @@ class TestSearchPagination &lt; Test::Unit::TestCase
     search.per_page = 100
     assert_equal 1, search.page_count
     
-    Searchgasm::Config.per_page = 1
+    Searchgasm::Config.search.per_page = 1
     search = Account.new_search
     assert_equal 3, search.page_count    
     search.conditions.users.first_name_contains</diff>
      <filename>vendor/plugins/searchgasm/test/test_search_pagination.rb</filename>
    </modified>
    <modified>
      <diff>@@ -296,6 +296,9 @@ module ActionMailer #:nodoc:
     @@default_implicit_parts_order = [ &quot;text/html&quot;, &quot;text/enriched&quot;, &quot;text/plain&quot; ]
     cattr_accessor :default_implicit_parts_order
 
+    cattr_reader :protected_instance_variables
+    @@protected_instance_variables = %w(@body)
+
     # Specify the BCC addresses for the message
     adv_attr_accessor :bcc
 </diff>
      <filename>vendor/rails/actionmailer/lib/action_mailer/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 module ActionMailer
   module VERSION #:nodoc:
     MAJOR = 2
-    MINOR = 1
+    MINOR = 2
     TINY  = 0
 
     STRING = [MAJOR, MINOR, TINY].join('.')</diff>
      <filename>vendor/rails/actionmailer/lib/action_mailer/version.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,8 @@
 require 'test/unit'
 
 $:.unshift &quot;#{File.dirname(__FILE__)}/../lib&quot;
+$:.unshift &quot;#{File.dirname(__FILE__)}/../../activesupport/lib&quot;
+$:.unshift &quot;#{File.dirname(__FILE__)}/../../actionpack/lib&quot;
 require 'action_mailer'
 require 'action_mailer/test_case'
 </diff>
      <filename>vendor/rails/actionmailer/test/abstract_unit.rb</filename>
    </modified>
    <modified>
      <diff>@@ -273,6 +273,13 @@ class TestMailer &lt; ActionMailer::Base
     headers      &quot;return-path&quot; =&gt; &quot;another@somewhere.test&quot;
   end
 
+  def body_ivar(recipient)
+    recipients   recipient
+    subject      &quot;Body as a local variable&quot;
+    from         &quot;test@example.com&quot;
+    body         :body =&gt; &quot;foo&quot;, :bar =&gt; &quot;baz&quot;
+  end
+
   class &lt;&lt;self
     attr_accessor :received_body
   end
@@ -926,6 +933,11 @@ EOF
     TestMailer.deliver_return_path
     assert_match %r{^Return-Path: &lt;another@somewhere.test&gt;}, MockSMTP.deliveries[0][0]
   end
+
+  def test_body_is_stored_as_an_ivar
+    mail = TestMailer.create_body_ivar(@recipient)
+    assert_equal &quot;body: foo\nbar: baz&quot;, mail.body
+  end
 end
 
 end # uses_mocha</diff>
      <filename>vendor/rails/actionmailer/test/mail_service_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,15 @@
 *Edge*
 
+* Added inline builder yield to atom_feed_helper tags where appropriate [Sam Ruby]. Example:
+
+    entry.summary :type =&gt; 'xhtml' do |xhtml|
+      xhtml.p pluralize(order.line_items.count, &quot;line item&quot;)
+      xhtml.p &quot;Shipped to #{order.address}&quot;
+      xhtml.p &quot;Paid by #{order.pay_type}&quot;
+    end
+
+* Make PrototypeHelper#submit_to_remote a wrapper around PrototypeHelper#button_to_remote. [Tarmo T&#228;nav]
+
 * Set HttpOnly for the cookie session store's cookie.  #1046 
 
 * Added FormTagHelper#image_submit_tag confirm option #784 [Alastair Brunton]</diff>
      <filename>vendor/rails/actionpack/CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -252,7 +252,7 @@ module ActionController #:nodoc:
   #
   #   def do_something
   #     redirect_to(:action =&gt; &quot;elsewhere&quot;) and return if monkeys.nil?
-  #     render :action =&gt; &quot;overthere&quot; # won't be called unless monkeys is nil
+  #     render :action =&gt; &quot;overthere&quot; # won't be called if monkeys is nil
   #   end
   #
   class Base
@@ -290,8 +290,6 @@ module ActionController #:nodoc:
     @@allow_concurrency = false
     cattr_accessor :allow_concurrency
 
-    @@guard = Monitor.new
-
     # Modern REST web services often need to submit complex data to the web application.
     # The &lt;tt&gt;@@param_parsers&lt;/tt&gt; hash lets you register handlers which will process the HTTP body and add parameters to the
     # &lt;tt&gt;params&lt;/tt&gt; hash. These handlers are invoked for POST and PUT requests.
@@ -532,12 +530,7 @@ module ActionController #:nodoc:
         assign_names
 
         log_processing
-
-        if @@allow_concurrency
-          send(method, *arguments)
-        else
-          @@guard.synchronize { send(method, *arguments) }
-        end
+        send(method, *arguments)
 
         send_response
       ensure
@@ -549,8 +542,8 @@ module ActionController #:nodoc:
         response
       end
 
-      # Returns a URL that has been rewritten according to the options hash and the defined Routes.
-      # (For doing a complete redirect, use redirect_to).
+      # Returns a URL that has been rewritten according to the options hash and the defined routes.
+      # (For doing a complete redirect, use +redirect_to+).
       #
       # &lt;tt&gt;url_for&lt;/tt&gt; is used to:
       #
@@ -590,7 +583,15 @@ module ActionController #:nodoc:
       # missing values in the current request's parameters. Routes attempts to guess when a value should and should not be
       # taken from the defaults. There are a few simple rules on how this is performed:
       #
-      # * If the controller name begins with a slash, no defaults are used: &lt;tt&gt;url_for :controller =&gt; '/home'&lt;/tt&gt;
+      # * If the controller name begins with a slash no defaults are used:
+      #
+      #     url_for :controller =&gt; '/home'
+      #
+      #   In particular, a leading slash ensures no namespace is assumed. Thus,
+      #   while &lt;tt&gt;url_for :controller =&gt; 'users'&lt;/tt&gt; may resolve to
+      #   &lt;tt&gt;Admin::UsersController&lt;/tt&gt; if the current controller lives under
+      #   that module, &lt;tt&gt;url_for :controller =&gt; '/users'&lt;/tt&gt; ensures you link
+      #   to &lt;tt&gt;::UsersController&lt;/tt&gt; no matter what.
       # * If the controller changes, the action will default to index unless provided
       #
       # The final rule is applied while the URL is being generated and is best illustrated by an example. Let us consider the
@@ -967,13 +968,17 @@ module ActionController #:nodoc:
       # Sets the Last-Modified response header. Returns 304 Not Modified if the
       # If-Modified-Since request header is &lt;= last modified.
       def last_modified!(utc_time)
-        head(:not_modified) if response.last_modified!(utc_time)
+        response.last_modified= utc_time
+        if request.if_modified_since &amp;&amp; request.if_modified_since &lt;= utc_time
+          head(:not_modified)
+        end
       end
 
       # Sets the ETag response header. Returns 304 Not Modified if the
       # If-None-Match request header matches.
       def etag!(etag)
-        head(:not_modified) if response.etag!(etag)
+        response.etag = etag
+        head(:not_modified) if response.etag == request.if_none_match
       end
 
       # Clears the rendered results, allowing for another render to be performed.
@@ -1248,7 +1253,7 @@ module ActionController #:nodoc:
             action_name = strip_out_controller(action_name)
           end
         end
-        &quot;#{self.class.controller_path}/#{action_name}&quot;
+        &quot;#{self.controller_path}/#{action_name}&quot;
       end
 
       def strip_out_controller(path)
@@ -1256,7 +1261,7 @@ module ActionController #:nodoc:
       end
 
       def template_path_includes_controller?(path)
-        self.class.controller_path.split('/')[-1] == path.split('/')[0]
+        self.controller_path.split('/')[-1] == path.split('/')[0]
       end
 
       def process_cleanup</diff>
      <filename>vendor/rails/actionpack/lib/action_controller/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,28 +6,8 @@ class CGI #:nodoc:
   # * Expose the CGI instance to session stores.
   # * Don't require 'digest/md5' whenever a new session id is generated.
   class Session #:nodoc:
-    begin
-      require 'securerandom'
-
-      # Generate a 32-character unique id using SecureRandom.
-      # This is used to generate session ids but may be reused elsewhere.
-      def self.generate_unique_id(constant = nil)
-        SecureRandom.hex(16)
-      end
-    rescue LoadError
-      # Generate an 32-character unique id based on a hash of the current time,
-      # a random number, the process id, and a constant string. This is used
-      # to generate session ids but may be reused elsewhere.
-      def self.generate_unique_id(constant = 'foobar')
-        md5 = Digest::MD5.new
-        now = Time.now
-        md5 &lt;&lt; now.to_s
-        md5 &lt;&lt; String(now.usec)
-        md5 &lt;&lt; String(rand(0))
-        md5 &lt;&lt; String($$)
-        md5 &lt;&lt; constant
-        md5.hexdigest
-      end
+    def self.generate_unique_id(constant = nil)
+      ActiveSupport::SecureRandom.hex(16)
     end
 
     # Make the CGI instance available to session stores.</diff>
      <filename>vendor/rails/actionpack/lib/action_controller/cgi_ext/session.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,8 @@ module ActionController
   # Dispatches requests to the appropriate controller and takes care of
   # reloading the app after each request when Dependencies.load? is true.
   class Dispatcher
+    @@guard = Mutex.new
+
     class &lt;&lt; self
       def define_dispatcher_callbacks(cache_classes)
         unless cache_classes
@@ -20,6 +22,7 @@ module ActionController
         end
 
         if defined?(ActiveRecord)
+          after_dispatch :checkin_connections
           before_dispatch { ActiveRecord::Base.verify_active_connections! }
           to_prepare(:activerecord_instantiate_observers) { ActiveRecord::Base.instantiate_observers }
         end
@@ -98,7 +101,7 @@ module ActionController
       @output, @request, @response = output, request, response
     end
 
-    def dispatch
+    def dispatch_unlocked
       begin
         run_callbacks :before_dispatch
         handle_request
@@ -109,6 +112,16 @@ module ActionController
       end
     end
 
+    def dispatch
+      if ActionController::Base.allow_concurrency
+        dispatch_unlocked
+      else
+        @@guard.synchronize do
+          dispatch_unlocked
+        end
+      end
+    end
+
     def dispatch_cgi(cgi, session_options)
       if cgi ||= self.class.failsafe_response(@output, '400 Bad Request') { CGI.new }
         @request = CgiRequest.new(cgi, session_options)
@@ -145,6 +158,21 @@ module ActionController
       Base.logger.flush
     end
 
+    def mark_as_test_request!
+      @test_request = true
+      self
+    end
+
+    def test_request?
+      @test_request
+    end
+
+    def checkin_connections
+      # Don't return connection (and peform implicit rollback) if this request is a part of integration test
+      return if test_request?
+      ActiveRecord::Base.clear_active_connections!
+    end
+
     protected
       def handle_request
         @controller = Routing::Routes.recognize(@request)</diff>
      <filename>vendor/rails/actionpack/lib/action_controller/dispatcher.rb</filename>
    </modified>
    <modified>
      <diff>@@ -276,7 +276,7 @@ module ActionController
           ActionController::Base.clear_last_instantiation!
 
           env['rack.input'] = data.is_a?(IO) ? data : StringIO.new(data || '')
-          @status, @headers, result_body = ActionController::Dispatcher.new.call(env)
+          @status, @headers, result_body = ActionController::Dispatcher.new.mark_as_test_request!.call(env)
           @request_count += 1
 
           @controller = ActionController::Base.last_instantiation</diff>
      <filename>vendor/rails/actionpack/lib/action_controller/integration.rb</filename>
    </modified>
    <modified>
      <diff>@@ -167,7 +167,7 @@ module ActionController
       parameter_format = parameters[:format]
 
       if parameter_format
-        parameter_format.to_sym
+        parameter_format
       elsif xhr?
         :js
       else
@@ -176,8 +176,7 @@ module ActionController
     end
 
     def cache_format
-      parameter_format = parameters[:format]
-      parameter_format &amp;&amp; parameter_format.to_sym
+      parameters[:format]
     end
 
     # Returns true if the request's &quot;X-Requested-With&quot; header contains</diff>
      <filename>vendor/rails/actionpack/lib/action_controller/request.rb</filename>
    </modified>
    <modified>
      <diff>@@ -41,10 +41,9 @@ module ActionController #:nodoc:
       base.rescue_templates = Hash.new(DEFAULT_RESCUE_TEMPLATE)
       base.rescue_templates.update DEFAULT_RESCUE_TEMPLATES
 
-      base.class_inheritable_array :rescue_handlers
-      base.rescue_handlers = []
-
       base.extend(ClassMethods)
+      base.send :include, ActiveSupport::Rescuable
+
       base.class_eval do
         alias_method_chain :perform_action, :rescue
       end
@@ -54,82 +53,12 @@ module ActionController #:nodoc:
       def process_with_exception(request, response, exception) #:nodoc:
         new.process(request, response, :rescue_action, exception)
       end
-
-      # Rescue exceptions raised in controller actions.
-      #
-      # &lt;tt&gt;rescue_from&lt;/tt&gt; receives a series of exception classes or class
-      # names, and a trailing &lt;tt&gt;:with&lt;/tt&gt; option with the name of a method
-      # or a Proc object to be called to handle them. Alternatively a block can
-      # be given.
-      #
-      # Handlers that take one argument will be called with the exception, so
-      # that the exception can be inspected when dealing with it.
-      #
-      # Handlers are inherited. They are searched from right to left, from
-      # bottom to top, and up the hierarchy. The handler of the first class for
-      # which &lt;tt&gt;exception.is_a?(klass)&lt;/tt&gt; holds true is the one invoked, if
-      # any.
-      #
-      #   class ApplicationController &lt; ActionController::Base
-      #     rescue_from User::NotAuthorized, :with =&gt; :deny_access # self defined exception
-      #     rescue_from ActiveRecord::RecordInvalid, :with =&gt; :show_errors
-      #
-      #     rescue_from 'MyAppError::Base' do |exception|
-      #       render :xml =&gt; exception, :status =&gt; 500
-      #     end
-      #
-      #     protected
-      #       def deny_access
-      #         ...
-      #       end
-      #
-      #       def show_errors(exception)
-      #         exception.record.new_record? ? ...
-      #       end
-      #   end
-      def rescue_from(*klasses, &amp;block)
-        options = klasses.extract_options!
-        unless options.has_key?(:with)
-          block_given? ? options[:with] = block : raise(ArgumentError, &quot;Need a handler. Supply an options hash that has a :with key as the last argument.&quot;)
-        end
-
-        klasses.each do |klass|
-          key = if klass.is_a?(Class) &amp;&amp; klass &lt;= Exception
-            klass.name
-          elsif klass.is_a?(String)
-            klass
-          else
-            raise(ArgumentError, &quot;#{klass} is neither an Exception nor a String&quot;)
-          end
-
-          # Order is important, we put the pair at the end. When dealing with an
-          # exception we will follow the documented order going from right to left.
-          rescue_handlers &lt;&lt; [key, options[:with]]
-        end
-      end
     end
 
     protected
       # Exception handler called when the performance of an action raises an exception.
       def rescue_action(exception)
-        if handler_for_rescue(exception)
-          rescue_action_with_handler(exception)
-        else
-          log_error(exception) if logger
-          erase_results if performed?
-
-          # Let the exception alter the response if it wants.
-          # For example, MethodNotAllowed sets the Allow header.
-          if exception.respond_to?(:handle_response!)
-            exception.handle_response!(response)
-          end
-
-          if consider_all_requests_local || local_request?
-            rescue_action_locally(exception)
-          else
-            rescue_action_in_public(exception)
-          end
-        end
+        rescue_with_handler(exception) || rescue_action_without_handler(exception)
       end
 
       # Overwrite to implement custom logging of errors. By default logs as fatal.
@@ -185,15 +114,20 @@ module ActionController #:nodoc:
         render_for_file(rescues_path(&quot;layout&quot;), response_code_for_rescue(exception))
       end
 
-      # Tries to rescue the exception by looking up and calling a registered handler.
-      def rescue_action_with_handler(exception)
-        if handler = handler_for_rescue(exception)
-          if handler.arity != 0
-            handler.call(exception)
-          else
-            handler.call
-          end
-          true # don't rely on the return value of the handler
+      def rescue_action_without_handler(exception)
+        log_error(exception) if logger
+        erase_results if performed?
+
+        # Let the exception alter the response if it wants.
+        # For example, MethodNotAllowed sets the Allow header.
+        if exception.respond_to?(:handle_response!)
+          exception.handle_response!(response)
+        end
+
+        if consider_all_requests_local || local_request?
+          rescue_action_locally(exception)
+        else
+          rescue_action_in_public(exception)
         end
       end
 
@@ -216,36 +150,6 @@ module ActionController #:nodoc:
         rescue_responses[exception.class.name]
       end
 
-      def handler_for_rescue(exception)
-        # We go from right to left because pairs are pushed onto rescue_handlers
-        # as rescue_from declarations are found.
-        _, handler = *rescue_handlers.reverse.detect do |klass_name, handler|
-          # The purpose of allowing strings in rescue_from is to support the
-          # declaration of handler associations for exception classes whose
-          # definition is yet unknown.
-          #
-          # Since this loop needs the constants it would be inconsistent to
-          # assume they should exist at this point. An early raised exception
-          # could trigger some other handler and the array could include
-          # precisely a string whose corresponding constant has not yet been
-          # seen. This is why we are tolerant to unknown constants.
-          #
-          # Note that this tolerance only matters if the exception was given as
-          # a string, otherwise a NameError will be raised by the interpreter
-          # itself when rescue_from CONSTANT is executed.
-          klass = self.class.const_get(klass_name) rescue nil
-          klass ||= klass_name.constantize rescue nil
-          exception.is_a?(klass) if klass
-        end
-
-        case handler
-        when Symbol
-          method(handler)
-        when Proc
-          handler.bind(self)
-        end
-      end
-
       def clean_backtrace(exception)
         if backtrace = exception.backtrace
           if defined?(RAILS_ROOT)</diff>
      <filename>vendor/rails/actionpack/lib/action_controller/rescue.rb</filename>
    </modified>
    <modified>
      <diff>@@ -60,12 +60,10 @@ module ActionController
       # segments are passed alongside in order to distinguish between default values
       # and requirements.
       def divide_route_options(segments, options)
-        options = options.dup
+        options = options.except(:path_prefix, :name_prefix)
 
         if options[:namespace]
           options[:controller] = &quot;#{options.delete(:namespace).sub(/\/$/, '')}/#{options[:controller]}&quot;
-          options.delete(:path_prefix)
-          options.delete(:name_prefix)
         end
 
         requirements = (options.delete(:requirements) || {}).dup</diff>
      <filename>vendor/rails/actionpack/lib/action_controller/routing/builder.rb</filename>
    </modified>
    <modified>
      <diff>@@ -84,7 +84,7 @@ module ActionController
     module RaiseActionExceptions
       attr_accessor :exception
 
-      def rescue_action(e)
+      def rescue_action_without_handler(e)
         self.exception = e
         
         if request.remote_addr == &quot;0.0.0.0&quot;
@@ -134,6 +134,9 @@ module ActionController
       @controller = self.class.controller_class.new
       @controller.request = @request = TestRequest.new
       @response = TestResponse.new
+
+      @controller.params = {}
+      @controller.send(:initialize_current_url)
     end
     
     # Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local</diff>
      <filename>vendor/rails/actionpack/lib/action_controller/test_case.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 module ActionPack #:nodoc:
   module VERSION #:nodoc:
     MAJOR = 2
-    MINOR = 1
+    MINOR = 2
     TINY  = 0
 
     STRING = [MAJOR, MINOR, TINY].join('.')</diff>
      <filename>vendor/rails/actionpack/lib/action_pack/version.rb</filename>
    </modified>
    <modified>
      <diff>@@ -43,7 +43,7 @@ require 'action_view/base'
 require 'action_view/partials'
 require 'action_view/template_error'
 
-I18n.load_translations &quot;#{File.dirname(__FILE__)}/action_view/locale/en-US.yml&quot;
+I18n.load_path &lt;&lt; &quot;#{File.dirname(__FILE__)}/action_view/locale/en-US.yml&quot;
 
 require 'action_view/helpers'
 </diff>
      <filename>vendor/rails/actionpack/lib/action_view.rb</filename>
    </modified>
    <modified>
      <diff>@@ -290,21 +290,23 @@ module ActionView #:nodoc:
     private
       attr_accessor :_first_render, :_last_render
 
-      # Evaluate the local assigns and pushes them to the view.
+      # Evaluates the local assigns and controller ivars, pushes them to the view.
       def _evaluate_assigns_and_ivars #:nodoc:
         unless @assigns_added
           @assigns.each { |key, value| instance_variable_set(&quot;@#{key}&quot;, value) }
-
-          if @controller
-            variables = @controller.instance_variables
-            variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables)
-            variables.each {|name| instance_variable_set(name, @controller.instance_variable_get(name)) }
-          end
-
+          _copy_ivars_from_controller
           @assigns_added = true
         end
       end
 
+      def _copy_ivars_from_controller #:nodoc:
+        if @controller
+          variables = @controller.instance_variable_names
+          variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables)
+          variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) }
+        end
+      end
+
       def _set_controller_content_type(content_type) #:nodoc:
         if controller.respond_to?(:response)
           controller.response.content_type ||= content_type</diff>
      <filename>vendor/rails/actionpack/lib/action_view/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,7 +21,6 @@ module ActionView #:nodoc:
     include CaptureHelper
     include DateHelper
     include DebugHelper
-    include FormCountryHelper
     include FormHelper
     include FormOptionsHelper
     include FormTagHelper</diff>
      <filename>vendor/rails/actionpack/lib/action_view/helpers.rb</filename>
    </modified>
    <modified>
      <diff>@@ -151,7 +151,7 @@ module ActionView
       #   javascript_path &quot;http://www.railsapplication.com/js/xmlhr&quot; # =&gt; http://www.railsapplication.com/js/xmlhr.js
       #   javascript_path &quot;http://www.railsapplication.com/js/xmlhr.js&quot; # =&gt; http://www.railsapplication.com/js/xmlhr.js
       def javascript_path(source)
-        compute_public_path(source, 'javascripts', 'js')
+        JavaScriptTag.create(self, @controller, source).public_path
       end
       alias_method :path_to_javascript, :javascript_path # aliased to avoid conflicts with a javascript_path named route
 
@@ -249,15 +249,17 @@ module ActionView
           joined_javascript_name = (cache == true ? &quot;all&quot; : cache) + &quot;.js&quot;
           joined_javascript_path = File.join(JAVASCRIPTS_DIR, joined_javascript_name)
 
-          write_asset_file_contents(joined_javascript_path, compute_javascript_paths(sources, recursive)) unless File.exists?(joined_javascript_path)
+          unless File.exists?(joined_javascript_path)
+            JavaScriptSources.create(self, @controller, sources, recursive).write_asset_file_contents(joined_javascript_path)
+          end
           javascript_src_tag(joined_javascript_name, options)
         else
-          expand_javascript_sources(sources, recursive).collect { |source| javascript_src_tag(source, options) }.join(&quot;\n&quot;)
+          JavaScriptSources.create(self, @controller, sources, recursive).expand_sources.collect { |source|
+            javascript_src_tag(source, options)
+          }.join(&quot;\n&quot;)
         end
       end
 
-      @@javascript_expansions = { :defaults =&gt; JAVASCRIPT_DEFAULT_SOURCES.dup }
-
       # Register one or more javascript files to be included when &lt;tt&gt;symbol&lt;/tt&gt;
       # is passed to &lt;tt&gt;javascript_include_tag&lt;/tt&gt;. This method is typically intended
       # to be called from plugin initialization to register javascript files
@@ -270,11 +272,9 @@ module ActionView
       #     &lt;script type=&quot;text/javascript&quot; src=&quot;/javascripts/body.js&quot;&gt;&lt;/script&gt;
       #     &lt;script type=&quot;text/javascript&quot; src=&quot;/javascripts/tail.js&quot;&gt;&lt;/script&gt;
       def self.register_javascript_expansion(expansions)
-        @@javascript_expansions.merge!(expansions)
+        JavaScriptSources.expansions.merge!(expansions)
       end
 
-      @@stylesheet_expansions = {}
-
       # Register one or more stylesheet files to be included when &lt;tt&gt;symbol&lt;/tt&gt;
       # is passed to &lt;tt&gt;stylesheet_link_tag&lt;/tt&gt;. This method is typically intended
       # to be called from plugin initialization to register stylesheet files
@@ -287,7 +287,7 @@ module ActionView
       #     &lt;link href=&quot;/stylesheets/body.css&quot;  media=&quot;screen&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
       #     &lt;link href=&quot;/stylesheets/tail.css&quot;  media=&quot;screen&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
       def self.register_stylesheet_expansion(expansions)
-        @@stylesheet_expansions.merge!(expansions)
+        StylesheetSources.expansions.merge!(expansions)
       end
 
       # Register one or more additional JavaScript files to be included when
@@ -295,11 +295,11 @@ module ActionView
       # typically intended to be called from plugin initialization to register additional
       # .js files that the plugin installed in &lt;tt&gt;public/javascripts&lt;/tt&gt;.
       def self.register_javascript_include_default(*sources)
-        @@javascript_expansions[:defaults].concat(sources)
+        JavaScriptSources.expansions[:defaults].concat(sources)
       end
 
       def self.reset_javascript_include_default #:nodoc:
-        @@javascript_expansions[:defaults] = JAVASCRIPT_DEFAULT_SOURCES.dup
+        JavaScriptSources.expansions[:defaults] = JAVASCRIPT_DEFAULT_SOURCES.dup
       end
 
       # Computes the path to a stylesheet asset in the public stylesheets directory.
@@ -314,7 +314,7 @@ module ActionView
       #   stylesheet_path &quot;http://www.railsapplication.com/css/style&quot; # =&gt; http://www.railsapplication.com/css/style.css
       #   stylesheet_path &quot;http://www.railsapplication.com/css/style.js&quot; # =&gt; http://www.railsapplication.com/css/style.css
       def stylesheet_path(source)
-        compute_public_path(source, 'stylesheets', 'css')
+        StylesheetTag.create(self, @controller, source).public_path
       end
       alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route
 
@@ -389,10 +389,14 @@ module ActionView
           joined_stylesheet_name = (cache == true ? &quot;all&quot; : cache) + &quot;.css&quot;
           joined_stylesheet_path = File.join(STYLESHEETS_DIR, joined_stylesheet_name)
 
-          write_asset_file_contents(joined_stylesheet_path, compute_stylesheet_paths(sources, recursive)) unless File.exists?(joined_stylesheet_path)
+          unless File.exists?(joined_stylesheet_path)
+            StylesheetSources.create(self, @controller, sources, recursive).write_asset_file_contents(joined_stylesheet_path)
+          end
           stylesheet_tag(joined_stylesheet_name, options)
         else
-          expand_stylesheet_sources(sources, recursive).collect { |source| stylesheet_tag(source, options) }.join(&quot;\n&quot;)
+          StylesheetSources.create(self, @controller, sources, recursive).expand_sources.collect { |source|
+            stylesheet_tag(source, options)
+          }.join(&quot;\n&quot;)
         end
       end
 
@@ -407,7 +411,7 @@ module ActionView
       #   image_path(&quot;/icons/edit.png&quot;)                              # =&gt; /icons/edit.png
       #   image_path(&quot;http://www.railsapplication.com/img/edit.png&quot;) # =&gt; http://www.railsapplication.com/img/edit.png
       def image_path(source)
-        compute_public_path(source, 'images')
+        ImageTag.create(self, @controller, source).public_path
       end
       alias_method :path_to_image, :image_path # aliased to avoid conflicts with an image_path named route
 
@@ -463,180 +467,344 @@ module ActionView
       end
 
       private
-        COMPUTED_PUBLIC_PATHS = {}
-        COMPUTED_PUBLIC_PATHS_GUARD = Mutex.new
-
-        # Add the the extension +ext+ if not present. Return full URLs otherwise untouched.
-        # Prefix with &lt;tt&gt;/dir/&lt;/tt&gt; if lacking a leading +/+. Account for relative URL
-        # roots. Rewrite the asset path for cache-busting asset ids. Include
-        # asset host, if configured, with the correct request protocol.
-        def compute_public_path(source, dir, ext = nil, include_host = true)
-          has_request = @controller.respond_to?(:request)
-
-          cache_key =
-            if has_request
-              [ @controller.request.protocol,
-                ActionController::Base.asset_host.to_s,
-                ActionController::Base.relative_url_root,
-                dir, source, ext, include_host ].join
-            else
-              [ ActionController::Base.asset_host.to_s,
-                dir, source, ext, include_host ].join
-            end
+        def javascript_src_tag(source, options)
+          content_tag(&quot;script&quot;, &quot;&quot;, { &quot;type&quot; =&gt; Mime::JS, &quot;src&quot; =&gt; path_to_javascript(source) }.merge(options))
+        end
 
-          COMPUTED_PUBLIC_PATHS_GUARD.synchronize do
-            source = COMPUTED_PUBLIC_PATHS[cache_key] ||=
-              begin
-                source += &quot;.#{ext}&quot; if ext &amp;&amp; File.extname(source).blank? || File.exist?(File.join(ASSETS_DIR, dir, &quot;#{source}.#{ext}&quot;))
+        def stylesheet_tag(source, options)
+          tag(&quot;link&quot;, { &quot;rel&quot; =&gt; &quot;stylesheet&quot;, &quot;type&quot; =&gt; Mime::CSS, &quot;media&quot; =&gt; &quot;screen&quot;, &quot;href&quot; =&gt; html_escape(path_to_stylesheet(source)) }.merge(options), false, false)
+        end
 
-                if source =~ %r{^[-a-z]+://}
-                  source
-                else
-                  source = &quot;/#{dir}/#{source}&quot; unless source[0] == ?/
-                  if has_request
-                    unless source =~ %r{^#{ActionController::Base.relative_url_root}/}
-                      source = &quot;#{ActionController::Base.relative_url_root}#{source}&quot;
-                    end
-                  end
+        module ImageAsset
+          DIRECTORY = 'images'.freeze
 
-                  rewrite_asset_path(source)
-                end
-              end
+          def directory
+            DIRECTORY
           end
 
-          if include_host &amp;&amp; source !~ %r{^[-a-z]+://}
-            host = compute_asset_host(source)
+          def extension
+            nil
+          end
+        end
 
-            if has_request &amp;&amp; !host.blank? &amp;&amp; host !~ %r{^[-a-z]+://}
-              host = &quot;#{@controller.request.protocol}#{host}&quot;
-            end
+        module JavaScriptAsset
+          DIRECTORY = 'javascripts'.freeze
+          EXTENSION = 'js'.freeze
+
+          def public_directory
+            JAVASCRIPTS_DIR
+          end
+
+          def directory
+            DIRECTORY
+          end
+
+          def extension
+            EXTENSION
+          end
+        end
+
+        module StylesheetAsset
+          DIRECTORY = 'stylesheets'.freeze
+          EXTENSION = 'css'.freeze
+
+          def public_directory
+            STYLESHEETS_DIR
+          end
+
+          def directory
+            DIRECTORY
+          end
 
-            &quot;#{host}#{source}&quot;
-          else
-            source
+          def extension
+            EXTENSION
           end
         end
 
-        # Pick an asset host for this source. Returns +nil+ if no host is set,
-        # the host if no wildcard is set, the host interpolated with the
-        # numbers 0-3 if it contains &lt;tt&gt;%d&lt;/tt&gt; (the number is the source hash mod 4),
-        # or the value returned from invoking the proc if it's a proc.
-        def compute_asset_host(source)
-          if host = ActionController::Base.asset_host
-            if host.is_a?(Proc)
-              case host.arity
-              when 2
-                host.call(source, @controller.request)
+        class AssetTag
+          extend ActiveSupport::Memoizable
+
+          Cache = {}
+          CacheGuard = Mutex.new
+
+          def self.create(template, controller, source, include_host = true)
+            CacheGuard.synchronize do
+              key = if controller.respond_to?(:request)
+                [self, controller.request.protocol,
+                 ActionController::Base.asset_host,
+                 ActionController::Base.relative_url_root,
+                 source, include_host]
               else
-                host.call(source)
+                [self, ActionController::Base.asset_host, source, include_host]
               end
-            else
-              (host =~ /%d/) ? host % (source.hash % 4) : host
+              Cache[key] ||= new(template, controller, source, include_host).freeze
             end
           end
-        end
 
-        # Use the RAILS_ASSET_ID environment variable or the source's
-        # modification time as its cache-busting asset id.
-        def rails_asset_id(source)
-          if asset_id = ENV[&quot;RAILS_ASSET_ID&quot;]
-            asset_id
-          else
-            path = File.join(ASSETS_DIR, source)
+          ProtocolRegexp = %r{^[-a-z]+://}.freeze
 
-            if File.exist?(path)
-              File.mtime(path).to_i.to_s
-            else
-              ''
-            end
+          def initialize(template, controller, source, include_host = true)
+            # NOTE: The template arg is temporarily needed for a legacy plugin
+            # hook that is expected to call rewrite_asset_path on the
+            # template. This should eventually be removed.
+            @template = template
+            @controller = controller
+            @source = source
+            @include_host = include_host
           end
-        end
 
-        # Break out the asset path rewrite in case plugins wish to put the asset id
-        # someplace other than the query string.
-        def rewrite_asset_path(source)
-          asset_id = rails_asset_id(source)
-          if asset_id.blank?
-            source
-          else
-            source + &quot;?#{asset_id}&quot;
+          def public_path
+            compute_public_path(@source)
           end
-        end
+          memoize :public_path
 
-        def javascript_src_tag(source, options)
-          content_tag(&quot;script&quot;, &quot;&quot;, { &quot;type&quot; =&gt; Mime::JS, &quot;src&quot; =&gt; path_to_javascript(source) }.merge(options))
+          def asset_file_path
+            File.join(ASSETS_DIR, public_path.split('?').first)
+          end
+          memoize :asset_file_path
+
+          def contents
+            File.read(asset_file_path)
+          end
+
+          def mtime
+            File.mtime(asset_file_path)
+          end
+
+          private
+            def request
+              @controller.request
+            end
+
+            def request?
+              @controller.respond_to?(:request)
+            end
+
+            # Add the the extension +ext+ if not present. Return full URLs otherwise untouched.
+            # Prefix with &lt;tt&gt;/dir/&lt;/tt&gt; if lacking a leading +/+. Account for relative URL
+            # roots. Rewrite the asset path for cache-busting asset ids. Include
+            # asset host, if configured, with the correct request protocol.
+            def compute_public_path(source)
+              source += &quot;.#{extension}&quot; if missing_extension?(source)
+              unless source =~ ProtocolRegexp
+                source = &quot;/#{directory}/#{source}&quot; unless source[0] == ?/
+                source = prepend_relative_url_root(source)
+                source = rewrite_asset_path(source)
+              end
+              source = prepend_asset_host(source)
+              source
+            end
+
+            def missing_extension?(source)
+              extension &amp;&amp; (File.extname(source).blank? || File.exist?(File.join(ASSETS_DIR, directory, &quot;#{source}.#{extension}&quot;)))
+            end
+
+            def prepend_relative_url_root(source)
+              relative_url_root = ActionController::Base.relative_url_root
+              if request? &amp;&amp; @include_host &amp;&amp; source !~ %r{^#{relative_url_root}/}
+                &quot;#{relative_url_root}#{source}&quot;
+              else
+                source
+              end
+            end
+
+            def prepend_asset_host(source)
+              if @include_host &amp;&amp; source !~ ProtocolRegexp
+                host = compute_asset_host(source)
+                if request? &amp;&amp; !host.blank? &amp;&amp; host !~ ProtocolRegexp
+                  host = &quot;#{request.protocol}#{host}&quot;
+                end
+                &quot;#{host}#{source}&quot;
+              else
+                source
+              end
+            end
+
+            # Pick an asset host for this source. Returns +nil+ if no host is set,
+            # the host if no wildcard is set, the host interpolated with the
+            # numbers 0-3 if it contains &lt;tt&gt;%d&lt;/tt&gt; (the number is the source hash mod 4),
+            # or the value returned from invoking the proc if it's a proc.
+            def compute_asset_host(source)
+              if host = ActionController::Base.asset_host
+                if host.is_a?(Proc)
+                  case host.arity
+                  when 2
+                    host.call(source, request)
+                  else
+                    host.call(source)
+                  end
+                else
+                  (host =~ /%d/) ? host % (source.hash % 4) : host
+                end
+              end
+            end
+
+            # Use the RAILS_ASSET_ID environment variable or the source's
+            # modification time as its cache-busting asset id.
+            def rails_asset_id(source)
+              if asset_id = ENV[&quot;RAILS_ASSET_ID&quot;]
+                asset_id
+              else
+                path = File.join(ASSETS_DIR, source)
+
+                if File.exist?(path)
+                  File.mtime(path).to_i.to_s
+                else
+                  ''
+                end
+              end
+            end
+
+            # Break out the asset path rewrite in case plugins wish to put the asset id
+            # someplace other than the query string.
+            def rewrite_asset_path(source)
+              if @template.respond_to?(:rewrite_asset_path)
+                # DEPRECATE: This way to override rewrite_asset_path
+                @template.send(:rewrite_asset_path, source)
+              else
+                asset_id = rails_asset_id(source)
+                if asset_id.blank?
+                  source
+                else
+                  &quot;#{source}?#{asset_id}&quot;
+                end
+              end
+            end
         end
 
-        def stylesheet_tag(source, options)
-          tag(&quot;link&quot;, { &quot;rel&quot; =&gt; &quot;stylesheet&quot;, &quot;type&quot; =&gt; Mime::CSS, &quot;media&quot; =&gt; &quot;screen&quot;, &quot;href&quot; =&gt; html_escape(path_to_stylesheet(source)) }.merge(options), false, false)
+        class ImageTag &lt; AssetTag
+          include ImageAsset
         end
 
-        def compute_javascript_paths(*args)
-          expand_javascript_sources(*args).collect { |source| compute_public_path(source, 'javascripts', 'js', false) }
+        class JavaScriptTag &lt; AssetTag
+          include JavaScriptAsset
         end
 
-        def compute_stylesheet_paths(*args)
-          expand_stylesheet_sources(*args).collect { |source| compute_public_path(source, 'stylesheets', 'css', false) }
+        class StylesheetTag &lt; AssetTag
+          include StylesheetAsset
         end
 
-        def expand_javascript_sources(sources, recursive = false)
-          if sources.include?(:all)
-            all_javascript_files = collect_asset_files(JAVASCRIPTS_DIR, ('**' if recursive), '*.js')
-            @@all_javascript_sources ||= {}
-            @@all_javascript_sources[recursive] ||= ((determine_source(:defaults, @@javascript_expansions).dup &amp; all_javascript_files) + all_javascript_files).uniq
-          else
-            expanded_sources = sources.collect do |source|
-              determine_source(source, @@javascript_expansions)
-            end.flatten
-            expanded_sources &lt;&lt; &quot;application&quot; if sources.include?(:defaults) &amp;&amp; File.exist?(File.join(JAVASCRIPTS_DIR, &quot;application.js&quot;))
-            expanded_sources
+        class AssetCollection
+          extend ActiveSupport::Memoizable
+
+          Cache = {}
+          CacheGuard = Mutex.new
+
+          def self.create(template, controller, sources, recursive)
+            CacheGuard.synchronize do
+              key = [self, sources, recursive]
+              Cache[key] ||= new(template, controller, sources, recursive).freeze
+            end
           end
-        end
 
-        def expand_stylesheet_sources(sources, recursive)
-          if sources.first == :all
-            @@all_stylesheet_sources ||= {}
-            @@all_stylesheet_sources[recursive] ||= collect_asset_files(STYLESHEETS_DIR, ('**' if recursive), '*.css')
-          else
-            sources.collect do |source|
-              determine_source(source, @@stylesheet_expansions)
-            end.flatten
+          def initialize(template, controller, sources, recursive)
+            # NOTE: The template arg is temporarily needed for a legacy plugin
+            # hook. See NOTE under AssetTag#initialize for more details
+            @template = template
+            @controller = controller
+            @sources = sources
+            @recursive = recursive
           end
-        end
 
-        def determine_source(source, collection)
-          case source
-          when Symbol
-            collection[source] || raise(ArgumentError, &quot;No expansion found for #{source.inspect}&quot;)
-          else
-            source
+          def write_asset_file_contents(joined_asset_path)
+            FileUtils.mkdir_p(File.dirname(joined_asset_path))
+            File.open(joined_asset_path, &quot;w+&quot;) { |cache| cache.write(joined_contents) }
+            mt = latest_mtime
+            File.utime(mt, mt, joined_asset_path)
           end
-        end
 
-        def join_asset_file_contents(paths)
-          paths.collect { |path| File.read(asset_file_path(path)) }.join(&quot;\n\n&quot;)
-        end
+          private
+            def determine_source(source, collection)
+              case source
+              when Symbol
+                collection[source] || raise(ArgumentError, &quot;No expansion found for #{source.inspect}&quot;)
+              else
+                source
+              end
+            end
+
+            def validate_sources!
+              @sources.collect { |source| determine_source(source, self.class.expansions) }.flatten
+            end
+
+            def all_asset_files
+              path = [public_directory, ('**' if @recursive), &quot;*.#{extension}&quot;].compact
+              Dir[File.join(*path)].collect { |file|
+                file[-(file.size - public_directory.size - 1)..-1].sub(/\.\w+$/, '')
+              }.sort
+            end
+
+            def tag_sources
+              expand_sources.collect { |source| tag_class.create(@template, @controller, source, false) }
+            end
 
-        def write_asset_file_contents(joined_asset_path, asset_paths)
-          FileUtils.mkdir_p(File.dirname(joined_asset_path))
-          File.open(joined_asset_path, &quot;w+&quot;) { |cache| cache.write(join_asset_file_contents(asset_paths)) }
+            def joined_contents
+              tag_sources.collect { |source| source.contents }.join(&quot;\n\n&quot;)
+            end
 
-          # Set mtime to the latest of the combined files to allow for
-          # consistent ETag without a shared filesystem.
-          mt = asset_paths.map { |p| File.mtime(asset_file_path(p)) }.max
-          File.utime(mt, mt, joined_asset_path)
+            # Set mtime to the latest of the combined files to allow for
+            # consistent ETag without a shared filesystem.
+            def latest_mtime
+              tag_sources.map { |source| source.mtime }.max
+            end
         end
 
-        def asset_file_path(path)
-          File.join(ASSETS_DIR, path.split('?').first)
+        class JavaScriptSources &lt; AssetCollection
+          include JavaScriptAsset
+
+          EXPANSIONS = { :defaults =&gt; JAVASCRIPT_DEFAULT_SOURCES.dup }
+
+          def self.expansions
+            EXPANSIONS
+          end
+
+          APPLICATION_JS = &quot;application&quot;.freeze
+          APPLICATION_FILE = &quot;application.js&quot;.freeze
+
+          def expand_sources
+            if @sources.include?(:all)
+              assets = all_asset_files
+              ((defaults.dup &amp; assets) + assets).uniq!
+            else
+              expanded_sources = validate_sources!
+              expanded_sources &lt;&lt; APPLICATION_JS if include_application?
+              expanded_sources
+            end
+          end
+          memoize :expand_sources
+
+          private
+            def tag_class
+              JavaScriptTag
+            end
+
+            def defaults
+              determine_source(:defaults, self.class.expansions)
+            end
+
+            def include_application?
+              @sources.include?(:defaults) &amp;&amp; File.exist?(File.join(JAVASCRIPTS_DIR, APPLICATION_FILE))
+            end
         end
 
-        def collect_asset_files(*path)
-          dir = path.first
+        class StylesheetSources &lt; AssetCollection
+          include StylesheetAsset
+
+          EXPANSIONS = {}
+
+          def self.expansions
+            EXPANSIONS
+          end
 
-          Dir[File.join(*path.compact)].collect do |file|
-            file[-(file.size - dir.size - 1)..-1].sub(/\.\w+$/, '')
-          end.sort
+          def expand_sources
+            @sources.first == :all ? all_asset_files : validate_sources!
+          end
+          memoize :expand_sources
+
+          private
+            def tag_class
+              StylesheetTag
+            end
         end
     end
   end</diff>
      <filename>vendor/rails/actionpack/lib/action_view/helpers/asset_tag_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -51,6 +51,7 @@ module ActionView
       # * &lt;tt&gt;:schema_date&lt;/tt&gt;: The date at which the tag scheme for the feed was first used. A good default is the year you
       #   created the feed. See http://feedvalidator.org/docs/error/InvalidTAG.html for more information. If not specified,
       #   2005 is used (as an &quot;I don't care&quot; value).
+      # * &lt;tt&gt;:instruct&lt;/tt&gt;: Hash of XML processing instructions in the form {target =&gt; {attribute =&gt; value, }} or {target =&gt; [{attribute =&gt; value, }, ]}
       #
       # Other namespaces can be added to the root element:
       #
@@ -74,8 +75,20 @@ module ActionView
       #       end
       #     end
       #
+      # The Atom spec defines five elements (content rights title subtitle
+      # summary) which may directly contain xhtml content if :type =&gt; 'xhtml'
+      # is specified as an attribute.  If so, this helper will take care of
+      # the enclosing div and xhtml namespace declaration.  Example usage:
       #
-      # atom_feed yields an AtomFeedBuilder instance.
+      #    entry.summary :type =&gt; 'xhtml' do |xhtml|
+      #      xhtml.p pluralize(order.line_items.count, &quot;line item&quot;)
+      #      xhtml.p &quot;Shipped to #{order.address}&quot;
+      #      xhtml.p &quot;Paid by #{order.pay_type}&quot;
+      #    end
+      #
+      #
+      # atom_feed yields an AtomFeedBuilder instance.  Nested elements yield
+      # an AtomBuilder instance.
       def atom_feed(options = {}, &amp;block)
         if options[:schema_date]
           options[:schema_date] = options[:schema_date].strftime(&quot;%Y-%m-%d&quot;) if options[:schema_date].respond_to?(:strftime)
@@ -85,6 +98,15 @@ module ActionView
 
         xml = options[:xml] || eval(&quot;xml&quot;, block.binding)
         xml.instruct!
+        if options[:instruct]
+          options[:instruct].each do |target,attrs|
+            if attrs.respond_to?(:keys)
+              xml.instruct!(target, attrs)
+            elsif attrs.respond_to?(:each)
+              attrs.each { |attr_group| xml.instruct!(target, attr_group) }
+            end
+          end
+        end
 
         feed_opts = {&quot;xml:lang&quot; =&gt; options[:language] || &quot;en-US&quot;, &quot;xmlns&quot; =&gt; 'http://www.w3.org/2005/Atom'}
         feed_opts.merge!(options).reject!{|k,v| !k.to_s.match(/^xml/)}
@@ -98,8 +120,38 @@ module ActionView
         end
       end
 
+      class AtomBuilder
+        def initialize(xml)
+          @xml = xml
+        end
+
+        private
+          # Delegate to xml builder, first wrapping the element in a xhtml
+          # namespaced div element if the method and arguments indicate
+          # that an xhtml_block? is desired.
+          def method_missing(method, *arguments, &amp;block)
+            if xhtml_block?(method, arguments)
+              @xml.__send__(method, *arguments) do
+                @xml.div(:xmlns =&gt; 'http://www.w3.org/1999/xhtml') do |xhtml|
+                  block.call(xhtml)
+                end
+              end
+            else
+              @xml.__send__(method, *arguments, &amp;block)
+            end
+          end
+          
+          # True if the method name matches one of the five elements defined
+          # in the Atom spec as potentially containing XHTML content and
+          # if :type =&gt; 'xhtml' is, in fact, specified.
+          def xhtml_block?(method, arguments)
+            %w( content rights title subtitle summary ).include?(method.to_s) &amp;&amp; 
+                arguments.last.respond_to?(:[]) &amp;&amp; 
+                  arguments.last[:type].to_s == 'xhtml'
+          end
+      end
 
-      class AtomFeedBuilder
+      class AtomFeedBuilder &lt; AtomBuilder
         def initialize(xml, view, feed_options = {})
           @xml, @view, @feed_options = xml, view, feed_options
         end
@@ -131,15 +183,11 @@ module ActionView
 
             @xml.link(:rel =&gt; 'alternate', :type =&gt; 'text/html', :href =&gt; options[:url] || @view.polymorphic_url(record))
 
-            yield @xml
+            yield AtomBuilder.new(@xml)
           end
         end
-
-        private
-          def method_missing(method, *arguments, &amp;block)
-            @xml.__send__(method, *arguments, &amp;block)
-          end
       end
+
     end
   end
 end</diff>
      <filename>vendor/rails/actionpack/lib/action_view/helpers/atom_feed_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -442,10 +442,10 @@ module ActionView
       end
 
       # Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object
-      # assigned to the template (identified by +object+). It's intended that +method+ returns an integer and if that
-      # integer is above zero, then the checkbox is checked. Additional options on the input tag can be passed as a
-      # hash with +options+. The +checked_value+ defaults to 1 while the default +unchecked_value+
-      # is set to 0 which is convenient for boolean values.
+      # assigned to the template (identified by +object+). This object must be an instance object (@object) and not a local object.
+      # It's intended that +method+ returns an integer and if that integer is above zero, then the checkbox is checked. 
+      # Additional options on the input tag can be passed as a hash with +options+. The +checked_value+ defaults to 1 
+      # while the default +unchecked_value+ is set to 0 which is convenient for boolean values.
       #
       # ==== Gotcha
       #</diff>
      <filename>vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -324,9 +324,6 @@ module ActionView
             value == selected
           end
         end
-
-        # All the countries included in the country_options output.
-        COUNTRIES = ActiveSupport::Deprecation::DeprecatedConstantProxy.new 'COUNTRIES', 'ActionView::Helpers::FormCountryHelper::COUNTRIES'
     end
 
     class InstanceTag #:nodoc:</diff>
      <filename>vendor/rails/actionpack/lib/action_view/helpers/form_options_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -62,7 +62,7 @@ module ActionView
       #   #    &lt;option&gt;3&lt;/option&gt;&lt;option&gt;4&lt;/option&gt;&lt;/select&gt;
       #
       #   select_tag &quot;colors&quot;, &quot;&lt;option&gt;Red&lt;/option&gt;&lt;option&gt;Green&lt;/option&gt;&lt;option&gt;Blue&lt;/option&gt;&quot;, :multiple =&gt; true
-      #   # =&gt; &lt;select id=&quot;colors&quot; multiple=&quot;multiple&quot; name=&quot;colors&quot;&gt;&lt;option&gt;Red&lt;/option&gt;
+      #   # =&gt; &lt;select id=&quot;colors&quot; multiple=&quot;multiple&quot; name=&quot;colors[]&quot;&gt;&lt;option&gt;Red&lt;/option&gt;
       #   #    &lt;option&gt;Green&lt;/option&gt;&lt;option&gt;Blue&lt;/option&gt;&lt;/select&gt;
       #
       #   select_tag &quot;locations&quot;, &quot;&lt;option&gt;Home&lt;/option&gt;&lt;option selected=&quot;selected&quot;&gt;Work&lt;/option&gt;&lt;option&gt;Out&lt;/option&gt;&quot;
@@ -70,14 +70,15 @@ module ActionView
       #   #    &lt;option&gt;Out&lt;/option&gt;&lt;/select&gt;
       #
       #   select_tag &quot;access&quot;, &quot;&lt;option&gt;Read&lt;/option&gt;&lt;option&gt;Write&lt;/option&gt;&quot;, :multiple =&gt; true, :class =&gt; 'form_input'
-      #   # =&gt; &lt;select class=&quot;form_input&quot; id=&quot;access&quot; multiple=&quot;multiple&quot; name=&quot;access&quot;&gt;&lt;option&gt;Read&lt;/option&gt;
+      #   # =&gt; &lt;select class=&quot;form_input&quot; id=&quot;access&quot; multiple=&quot;multiple&quot; name=&quot;access[]&quot;&gt;&lt;option&gt;Read&lt;/option&gt;
       #   #    &lt;option&gt;Write&lt;/option&gt;&lt;/select&gt;
       #
       #   select_tag &quot;destination&quot;, &quot;&lt;option&gt;NYC&lt;/option&gt;&lt;option&gt;Paris&lt;/option&gt;&lt;option&gt;Rome&lt;/option&gt;&quot;, :disabled =&gt; true
       #   # =&gt; &lt;select disabled=&quot;disabled&quot; id=&quot;destination&quot; name=&quot;destination&quot;&gt;&lt;option&gt;NYC&lt;/option&gt;
       #   #    &lt;option&gt;Paris&lt;/option&gt;&lt;option&gt;Rome&lt;/option&gt;&lt;/select&gt;
       def select_tag(name, option_tags = nil, options = {})
-        content_tag :select, option_tags, { &quot;name&quot; =&gt; name, &quot;id&quot; =&gt; name }.update(options.stringify_keys)
+        html_name = (options[:multiple] == true &amp;&amp; !name.to_s.ends_with?(&quot;[]&quot;)) ? &quot;#{name}[]&quot; : name
+        content_tag :select, option_tags, { &quot;name&quot; =&gt; html_name, &quot;id&quot; =&gt; name }.update(options.stringify_keys)
       end
 
       # Creates a standard text field; use these text fields to input smaller chunks of text like a username
@@ -403,6 +404,7 @@ module ActionView
       # Creates a field set for grouping HTML form elements.
       #
       # &lt;tt&gt;legend&lt;/tt&gt; will become the fieldset's title (optional as per W3C).
+      # &lt;tt&gt;options&lt;/tt&gt; accept the same values as tag.
       #
       # === Examples
       #   &lt;% field_set_tag do %&gt;
@@ -414,9 +416,14 @@ module ActionView
       #     &lt;p&gt;&lt;%= text_field_tag 'name' %&gt;&lt;/p&gt;
       #   &lt;% end %&gt;
       #   # =&gt; &lt;fieldset&gt;&lt;legend&gt;Your details&lt;/legend&gt;&lt;p&gt;&lt;input id=&quot;name&quot; name=&quot;name&quot; type=&quot;text&quot; /&gt;&lt;/p&gt;&lt;/fieldset&gt;
-      def field_set_tag(legend = nil, &amp;block)
+      #
+      #   &lt;% field_set_tag nil, :class =&gt; 'format' do %&gt;
+      #     &lt;p&gt;&lt;%= text_field_tag 'name' %&gt;&lt;/p&gt;
+      #   &lt;% end %&gt;
+      #   # =&gt; &lt;fieldset class=&quot;format&quot;&gt;&lt;p&gt;&lt;input id=&quot;name&quot; name=&quot;name&quot; type=&quot;text&quot; /&gt;&lt;/p&gt;&lt;/fieldset&gt;
+      def field_set_tag(legend = nil, options = nil, &amp;block)
         content = capture(&amp;block)
-        concat(tag(:fieldset, {}, true))
+        concat(tag(:fieldset, options, true))
         concat(content_tag(:legend, legend)) unless legend.blank?
         concat(content)
         concat(&quot;&lt;/fieldset&gt;&quot;)</diff>
      <filename>vendor/rails/actionpack/lib/action_view/helpers/form_tag_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -405,7 +405,7 @@ module ActionView
       #  # Generates: &lt;input name=&quot;create_btn&quot; onclick=&quot;new Ajax.Request('/testing/create',
       #  #     {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
       #  #     return false;&quot; type=&quot;button&quot; value=&quot;Create&quot; /&gt;
-      #  &lt;%= button_to_remote 'create_btn', 'Create', :url =&gt; { :action =&gt; 'create' } %&gt;
+      #  &lt;%= submit_to_remote 'create_btn', 'Create', :url =&gt; { :action =&gt; 'create' } %&gt;
       #
       #  # Submit to the remote action update and update the DIV succeed or fail based
       #  # on the success or failure of the request
@@ -413,24 +413,18 @@ module ActionView
       #  # Generates: &lt;input name=&quot;update_btn&quot; onclick=&quot;new Ajax.Updater({success:'succeed',failure:'fail'},
       #  #      '/testing/update', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
       #  #      return false;&quot; type=&quot;button&quot; value=&quot;Update&quot; /&gt;
-      #  &lt;%= button_to_remote 'update_btn', 'Update', :url =&gt; { :action =&gt; 'update' },
+      #  &lt;%= submit_to_remote 'update_btn', 'Update', :url =&gt; { :action =&gt; 'update' },
       #     :update =&gt; { :success =&gt; &quot;succeed&quot;, :failure =&gt; &quot;fail&quot; }
       #
       # &lt;tt&gt;options&lt;/tt&gt; argument is the same as in form_remote_tag.
-      #
-      # Note: This method used to be called submit_to_remote, but that's now just an alias for button_to_remote
-      def button_to_remote(name, value, options = {})
+      def submit_to_remote(name, value, options = {})
         options[:with] ||= 'Form.serialize(this.form)'
 
-        options[:html] ||= {}
-        options[:html][:type] = 'button'
-        options[:html][:onclick] = &quot;#{remote_function(options)}; return false;&quot;
-        options[:html][:name] = name
-        options[:html][:value] = value
+        html_options = options.delete(:html) || {}
+        html_options[:name] = name
 
-        tag(&quot;input&quot;, options[:html], false)
+        button_to_remote(value, options, html_options)
       end
-      alias_method :submit_to_remote, :button_to_remote
 
       # Returns '&lt;tt&gt;eval(request.responseText)&lt;/tt&gt;' which is the JavaScript function
       # that +form_remote_tag+ can call in &lt;tt&gt;:complete&lt;/tt&gt; to evaluate a multiple</diff>
      <filename>vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -42,65 +42,46 @@ module ActionView
         output_buffer &lt;&lt; string
       end
 
-      if RUBY_VERSION &lt; '1.9'
-        # Truncates a given +text+ after a given &lt;tt&gt;:length&lt;/tt&gt; if +text+ is longer than &lt;tt&gt;:length&lt;/tt&gt;
-        # (defaults to 30). The last characters will be replaced with the &lt;tt&gt;:omission&lt;/tt&gt; (defaults to &quot;...&quot;).
-        #
-        # ==== Examples
-        #
-        #   truncate(&quot;Once upon a time in a world far far away&quot;)
-        #   # =&gt; Once upon a time in a world f...
-        #
-        #   truncate(&quot;Once upon a time in a world far far away&quot;, :length =&gt; 14)
-        #   # =&gt; Once upon a...
-        #
-        #   truncate(&quot;And they found that many people were sleeping better.&quot;, :length =&gt; 25, &quot;(clipped)&quot;)
-        #   # =&gt; And they found that many (clipped)
-        #
-        #   truncate(&quot;And they found that many people were sleeping better.&quot;, :omission =&gt; &quot;... (continued)&quot;, :length =&gt; 15)
-        #   # =&gt; And they found... (continued)
-        #
-        # You can still use &lt;tt&gt;truncate&lt;/tt&gt; with the old API that accepts the
-        # +length+ as its optional second and the +ellipsis+ as its
-        # optional third parameter:
-        #   truncate(&quot;Once upon a time in a world far far away&quot;, 14)
-        #   # =&gt; Once upon a time in a world f...
-        #
-        #   truncate(&quot;And they found that many people were sleeping better.&quot;, 15, &quot;... (continued)&quot;)
-        #   # =&gt; And they found... (continued)
-        def truncate(text, *args)
-          options = args.extract_options!
-          unless args.empty?
-            ActiveSupport::Deprecation.warn('truncate takes an option hash instead of separate ' +
-              'length and omission arguments', caller)
-
-            options[:length] = args[0] || 30
-            options[:omission] = args[1] || &quot;...&quot;
-          end
-          options.reverse_merge!(:length =&gt; 30, :omission =&gt; &quot;...&quot;)
+      # Truncates a given +text+ after a given &lt;tt&gt;:length&lt;/tt&gt; if +text+ is longer than &lt;tt&gt;:length&lt;/tt&gt;
+      # (defaults to 30). The last characters will be replaced with the &lt;tt&gt;:omission&lt;/tt&gt; (defaults to &quot;...&quot;).
+      #
+      # ==== Examples
+      #
+      #   truncate(&quot;Once upon a time in a world far far away&quot;)
+      #   # =&gt; Once upon a time in a world f...
+      #
+      #   truncate(&quot;Once upon a time in a world far far away&quot;, :length =&gt; 14)
+      #   # =&gt; Once upon a...
+      #
+      #   truncate(&quot;And they found that many people were sleeping better.&quot;, :length =&gt; 25, &quot;(clipped)&quot;)
+      #   # =&gt; And they found that many (clipped)
+      #
+      #   truncate(&quot;And they found that many people were sleeping better.&quot;, :omission =&gt; &quot;... (continued)&quot;, :length =&gt; 15)
+      #   # =&gt; And they found... (continued)
+      #
+      # You can still use &lt;tt&gt;truncate&lt;/tt&gt; with the old API that accepts the
+      # +length+ as its optional second and the +ellipsis+ as its
+      # optional third parameter:
+      #   truncate(&quot;Once upon a time in a world far far away&quot;, 14)
+      #   # =&gt; Once upon a time in a world f...
+      #
+      #   truncate(&quot;And they found that many people were sleeping better.&quot;, 15, &quot;... (continued)&quot;)
+      #   # =&gt; And they found... (continued)
+      def truncate(text, *args)
+        options = args.extract_options!
+        unless args.empty?
+          ActiveSupport::Deprecation.warn('truncate takes an option hash instead of separate ' +
+            'length and omission arguments', caller)
 
-          if text
-            l = options[:length] - options[:omission].chars.length
-            chars = text.chars
-            (chars.length &gt; options[:length] ? chars[0...l] + options[:omission] : text).to_s
-          end
+          options[:length] = args[0] || 30
+          options[:omission] = args[1] || &quot;...&quot;
         end
-      else
-        def truncate(text, *args) #:nodoc:
-          options = args.extract_options!
-          unless args.empty?
-            ActiveSupport::Deprecation.warn('truncate takes an option hash instead of separate ' +
-              'length and omission arguments', caller)
-
-            options[:length] = args[0] || 30
-            options[:omission] = args[1] || &quot;...&quot;
-          end
-          options.reverse_merge!(:length =&gt; 30, :omission =&gt; &quot;...&quot;)
+        options.reverse_merge!(:length =&gt; 30, :omission =&gt; &quot;...&quot;)
 
-          if text
-            l = options[:length].to_i - options[:omission].length
-            (text.length &gt; options[:length].to_i ? text[0...l] + options[:omission] : text).to_s
-          end
+        if text
+          l = options[:length] - options[:omission].mb_chars.length
+          chars = text.mb_chars
+          (chars.length &gt; options[:length] ? chars[0...l] + options[:omission] : text).to_s
         end
       end
 
@@ -140,81 +121,54 @@ module ActionView
         end
       end
 
-      if RUBY_VERSION &lt; '1.9'
-        # Extracts an excerpt from +text+ that matches the first instance of +phrase+.
-        # The &lt;tt&gt;:radius&lt;/tt&gt; option expands the excerpt on each side of the first occurrence of +phrase+ by the number of characters
-        # defined in &lt;tt&gt;:radius&lt;/tt&gt; (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+,
-        # then the &lt;tt&gt;:omission&lt;/tt&gt; option (which defaults to &quot;...&quot;) will be prepended/appended accordingly. The resulting string
-        # will be stripped in any case. If the +phrase+ isn't found, nil is returned.
-        #
-        # ==== Examples
-        #   excerpt('This is an example', 'an', :radius =&gt; 5)
-        #   # =&gt; ...s is an exam...
-        #
-        #   excerpt('This is an example', 'is', :radius =&gt; 5)
-        #   # =&gt; This is a...
-        #
-        #   excerpt('This is an example', 'is')
-        #   # =&gt; This is an example
-        #
-        #   excerpt('This next thing is an example', 'ex', :radius =&gt; 2)
-        #   # =&gt; ...next...
-        #
-        #   excerpt('This is also an example', 'an', :radius =&gt; 8, :omission =&gt; '&lt;chop&gt; ')
-        #   # =&gt; &lt;chop&gt; is also an example
-        #
-        # You can still use &lt;tt&gt;excerpt&lt;/tt&gt; with the old API that accepts the
-        # +radius+ as its optional third and the +ellipsis+ as its
-        # optional forth parameter:
-        #   excerpt('This is an example', 'an', 5)                   # =&gt; ...s is an exam...
-        #   excerpt('This is also an example', 'an', 8, '&lt;chop&gt; ')   # =&gt; &lt;chop&gt; is also an example
-        def excerpt(text, phrase, *args)
-          options = args.extract_options!
-          unless args.empty?
-            options[:radius] = args[0] || 100
-            options[:omission] = args[1] || &quot;...&quot;
-          end
-          options.reverse_merge!(:radius =&gt; 100, :omission =&gt; &quot;...&quot;)
-
-          if text &amp;&amp; phrase
-            phrase = Regexp.escape(phrase)
-
-            if found_pos = text.chars =~ /(#{phrase})/i
-              start_pos = [ found_pos - options[:radius], 0 ].max
-              end_pos   = [ [ found_pos + phrase.chars.length + options[:radius] - 1, 0].max, text.chars.length ].min
-
-              prefix  = start_pos &gt; 0 ? options[:omission] : &quot;&quot;
-              postfix = end_pos &lt; text.chars.length - 1 ? options[:omission] : &quot;&quot;
-
-              prefix + text.chars[start_pos..end_pos].strip + postfix
-            else
-              nil
-            end
-          end
+      # Extracts an excerpt from +text+ that matches the first instance of +phrase+.
+      # The &lt;tt&gt;:radius&lt;/tt&gt; option expands the excerpt on each side of the first occurrence of +phrase+ by the number of characters
+      # defined in &lt;tt&gt;:radius&lt;/tt&gt; (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+,
+      # then the &lt;tt&gt;:omission&lt;/tt&gt; option (which defaults to &quot;...&quot;) will be prepended/appended accordingly. The resulting string
+      # will be stripped in any case. If the +phrase+ isn't found, nil is returned.
+      #
+      # ==== Examples
+      #   excerpt('This is an example', 'an', :radius =&gt; 5)
+      #   # =&gt; ...s is an exam...
+      #
+      #   excerpt('This is an example', 'is', :radius =&gt; 5)
+      #   # =&gt; This is a...
+      #
+      #   excerpt('This is an example', 'is')
+      #   # =&gt; This is an example
+      #
+      #   excerpt('This next thing is an example', 'ex', :radius =&gt; 2)
+      #   # =&gt; ...next...
+      #
+      #   excerpt('This is also an example', 'an', :radius =&gt; 8, :omission =&gt; '&lt;chop&gt; ')
+      #   # =&gt; &lt;chop&gt; is also an example
+      #
+      # You can still use &lt;tt&gt;excerpt&lt;/tt&gt; with the old API that accepts the
+      # +radius+ as its optional third and the +ellipsis+ as its
+      # optional forth parameter:
+      #   excerpt('This is an example', 'an', 5)                   # =&gt; ...s is an exam...
+      #   excerpt('This is also an example', 'an', 8, '&lt;chop&gt; ')   # =&gt; &lt;chop&gt; is also an example
+      def excerpt(text, phrase, *args)
+        options = args.extract_options!
+        unless args.empty?
+          options[:radius] = args[0] || 100
+          options[:omission] = args[1] || &quot;...&quot;
         end
-      else
-        def excerpt(text, phrase, *args) #:nodoc:
-          options = args.extract_options!
-          unless args.empty?
-            options[:radius] = args[0] || 100
-            options[:omission] = args[1] || &quot;...&quot;
-          end
-          options.reverse_merge!(:radius =&gt; 100, :omission =&gt; &quot;...&quot;)
+        options.reverse_merge!(:radius =&gt; 100, :omission =&gt; &quot;...&quot;)
 
-          if text &amp;&amp; phrase
-            phrase = Regexp.escape(phrase)
+        if text &amp;&amp; phrase
+          phrase = Regexp.escape(phrase)
 
-            if found_pos = text =~ /(#{phrase})/i
-              start_pos = [ found_pos - options[:radius], 0 ].max
-              end_pos   = [ [ found_pos + phrase.length + options[:radius] - 1, 0].max, text.length ].min
+          if found_pos = text.mb_chars =~ /(#{phrase})/i
+            start_pos = [ found_pos - options[:radius], 0 ].max
+            end_pos   = [ [ found_pos + phrase.mb_chars.length + options[:radius] - 1, 0].max, text.mb_chars.length ].min
 
-              prefix  = start_pos &gt; 0 ? options[:omission] : &quot;&quot;
-              postfix = end_pos &lt; text.length - 1 ? options[:omission] : &quot;&quot;
+            prefix  = start_pos &gt; 0 ? options[:omission] : &quot;&quot;
+            postfix = end_pos &lt; text.mb_chars.length - 1 ? options[:omission] : &quot;&quot;
 
-              prefix + text[start_pos..end_pos].strip + postfix
-            else
-              nil
-            end
+            prefix + text.mb_chars[start_pos..end_pos].strip + postfix
+          else
+            nil
           end
         end
       end</diff>
      <filename>vendor/rails/actionpack/lib/action_view/helpers/text_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -52,15 +52,20 @@ module ActionView #:nodoc:
     end
     memoize :path_without_format_and_extension
 
+    def relative_path
+      path = File.expand_path(filename)
+      path.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}\//, '') if defined?(RAILS_ROOT)
+      path
+    end
+    memoize :relative_path
+
     def source
       File.read(filename)
     end
     memoize :source
 
     def method_segment
-      segment = File.expand_path(filename)
-      segment.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT)
-      segment.gsub!(/([^a-zA-Z0-9_])/) { $1.ord }
+      relative_path.to_s.gsub(/([^a-zA-Z0-9_])/) { $1.ord }
     end
     memoize :method_segment
 
@@ -69,7 +74,7 @@ module ActionView #:nodoc:
     rescue Exception =&gt; e
       raise e unless filename
       if TemplateError === e
-        e.sub_template_of(filename)
+        e.sub_template_of(self)
         raise e
       else
         raise TemplateError.new(self, view.assigns, e)</diff>
      <filename>vendor/rails/actionpack/lib/action_view/template.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,12 +7,14 @@ module ActionView
     attr_reader :original_exception
 
     def initialize(template, assigns, original_exception)
-      @base_path = template.base_path.to_s
-      @assigns, @source, @original_exception = assigns.dup, template.source, original_exception
-      @file_path = template.filename
+      @template, @assigns, @original_exception = template, assigns.dup, original_exception
       @backtrace = compute_backtrace
     end
 
+    def file_name
+      @template.relative_path
+    end
+
     def message
       ActiveSupport::Deprecation.silence { original_exception.message }
     end
@@ -24,7 +26,7 @@ module ActionView
     def sub_template_message
       if @sub_templates
         &quot;Trace of template inclusion: &quot; +
-        @sub_templates.collect { |template| strip_base_path(template) }.join(&quot;, &quot;)
+        @sub_templates.collect { |template| template.relative_path }.join(&quot;, &quot;)
       else
         &quot;&quot;
       end
@@ -34,18 +36,18 @@ module ActionView
       return unless num = line_number
       num = num.to_i
 
-      source_code = IO.readlines(@file_path)
+      source_code = @template.source.split(&quot;\n&quot;)
 
       start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max
       end_on_line   = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
 
       indent = ' ' * indentation
       line_counter = start_on_line
-      return unless source_code = source_code[start_on_line..end_on_line] 
-      
+      return unless source_code = source_code[start_on_line..end_on_line]
+
       source_code.sum do |line|
         line_counter += 1
-        &quot;#{indent}#{line_counter}: #{line}&quot;
+        &quot;#{indent}#{line_counter}: #{line}\n&quot;
       end
     end
 
@@ -63,12 +65,6 @@ module ActionView
         end
     end
 
-    def file_name
-      stripped = strip_base_path(@file_path)
-      stripped.slice!(0,1) if stripped[0] == ?/
-      stripped
-    end
-
     def to_s
       &quot;\n\n#{self.class} (#{message}) #{source_location}:\n&quot; +
         &quot;#{source_extract}\n    #{clean_backtrace.join(&quot;\n    &quot;)}\n\n&quot;
@@ -88,12 +84,6 @@ module ActionView
         ]
       end
 
-      def strip_base_path(path)
-        stripped_path = File.expand_path(path).gsub(@base_path, &quot;&quot;)
-        stripped_path.gsub!(/^#{Regexp.escape File.expand_path(RAILS_ROOT)}/, '') if defined?(RAILS_ROOT)
-        stripped_path
-      end
-
       def source_location
         if line_number
           &quot;on line ##{line_number} of &quot;</diff>
      <filename>vendor/rails/actionpack/lib/action_view/template_error.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
 $:.unshift(File.dirname(__FILE__) + '/../lib')
-$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib/active_support')
+$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
 $:.unshift(File.dirname(__FILE__) + '/fixtures/helpers')
 
 require 'yaml'</diff>
      <filename>vendor/rails/actionpack/test/abstract_unit.rb</filename>
    </modified>
    <modified>
      <diff>@@ -39,6 +39,16 @@ class TestController &lt; ActionController::Base
       render :action =&gt; 'hello_world'
     end
   end
+  
+  def conditional_hello_with_bangs
+    render :action =&gt; 'hello_world'
+  end
+  before_filter :handle_last_modified_and_etags, :only=&gt;:conditional_hello_with_bangs
+  
+  def handle_last_modified_and_etags
+    last_modified! Time.now.utc.beginning_of_day
+    etag! [:foo, 123]
+  end
 
   def render_hello_world
     render :template =&gt; &quot;test/hello_world&quot;
@@ -1306,6 +1316,7 @@ class EtagRenderTest &lt; Test::Unit::TestCase
     @controller = TestController.new
 
     @request.host = &quot;www.nextangle.com&quot;
+    @expected_bang_etag = etag_for(expand_key([:foo, 123]))
   end
 
   def test_render_200_should_set_etag
@@ -1365,11 +1376,27 @@ class EtagRenderTest &lt; Test::Unit::TestCase
     assert_equal &quot;&lt;wrapper&gt;\n&lt;html&gt;\n  &lt;p&gt;Hello &lt;/p&gt;\n&lt;p&gt;This is grand!&lt;/p&gt;\n&lt;/html&gt;\n&lt;/wrapper&gt;\n&quot;, @response.body
     assert_equal etag_for(&quot;&lt;wrapper&gt;\n&lt;html&gt;\n  &lt;p&gt;Hello &lt;/p&gt;\n&lt;p&gt;This is grand!&lt;/p&gt;\n&lt;/html&gt;\n&lt;/wrapper&gt;\n&quot;), @response.headers['ETag']
   end
-
+  
+  def test_etag_with_bang_should_set_etag
+    get :conditional_hello_with_bangs
+    assert_equal @expected_bang_etag, @response.headers[&quot;ETag&quot;]
+    assert_response :success
+  end
+  
+  def test_etag_with_bang_should_obey_if_none_match
+    @request.if_none_match = @expected_bang_etag
+    get :conditional_hello_with_bangs
+    assert_response :not_modified
+  end
+  
   protected
     def etag_for(text)
       %(&quot;#{Digest::MD5.hexdigest(text)}&quot;)
     end
+    
+    def expand_key(args)
+      ActiveSupport::Cache.expand_cache_key(args)
+    end
 end
 
 class LastModifiedRenderTest &lt; Test::Unit::TestCase
@@ -1402,6 +1429,24 @@ class LastModifiedRenderTest &lt; Test::Unit::TestCase
     assert !@response.body.blank?
     assert_equal @last_modified, @response.headers['Last-Modified']
   end
+  
+  def test_request_with_bang_gets_last_modified
+    get :conditional_hello_with_bangs
+    assert_equal @last_modified, @response.headers['Last-Modified']
+    assert_response :success
+  end
+  
+  def test_request_with_bang_obeys_last_modified
+    @request.if_modified_since = @last_modified
+    get :conditional_hello_with_bangs
+    assert_response :not_modified
+  end
+
+  def test_last_modified_works_with_less_than_too
+    @request.if_modified_since = 5.years.ago.httpdate
+    get :conditional_hello_with_bangs
+    assert_response :not_modified
+  end
 end
 
 class RenderingLoggingTest &lt; Test::Unit::TestCase</diff>
      <filename>vendor/rails/actionpack/test/controller/render_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -75,7 +75,7 @@ class RescueController &lt; ActionController::Base
   def method_not_allowed
     raise ActionController::MethodNotAllowed.new(:get, :head, :put)
   end
-  
+
   def not_implemented
     raise ActionController::NotImplemented.new(:get, :put)
   end
@@ -107,7 +107,7 @@ class RescueController &lt; ActionController::Base
   def record_invalid_raise_as_string
     raise RecordInvalidToRescueAsString
   end
-  
+
   def bad_gateway
     raise BadGateway
   end
@@ -135,18 +135,19 @@ class RescueController &lt; ActionController::Base
     end
 end
 
-class RescueTest &lt; Test::Unit::TestCase
+class RescueControllerTest &lt; ActionController::TestCase
   FIXTURE_PUBLIC = &quot;#{File.dirname(__FILE__)}/../fixtures&quot;.freeze
 
-  def setup
-    @controller = RescueController.new
-    @request    = ActionController::TestRequest.new
-    @response   = ActionController::TestResponse.new
+  setup :set_all_requests_local
+  setup :populate_exception_object
 
+  def set_all_requests_local
     RescueController.consider_all_requests_local = true
     @request.remote_addr = '1.2.3.4'
     @request.host = 'example.com'
+  end
 
+  def populate_exception_object
     begin
       raise 'foo'
     rescue =&gt; @exception
@@ -307,7 +308,7 @@ class RescueTest &lt; Test::Unit::TestCase
       assert_nil @controller.send(:clean_backtrace, Exception.new)
     end
   end
-  
+
   def test_not_implemented
     with_all_requests_local false do
       with_rails_public_path(&quot;.&quot;) do
@@ -463,14 +464,7 @@ class ExceptionInheritanceRescueController &lt; ActionController::Base
   end
 end
 
-class ExceptionInheritanceRescueTest &lt; Test::Unit::TestCase
-
-  def setup
-    @controller = ExceptionInheritanceRescueController.new
-    @request    = ActionController::TestRequest.new
-    @response   = ActionController::TestResponse.new
-  end
-
+class ExceptionInheritanceRescueControllerTest &lt; ActionController::TestCase
   def test_bottom_first
     get :raise_grandchild_exception
     assert_response :no_content
@@ -500,14 +494,7 @@ class ControllerInheritanceRescueController &lt; ExceptionInheritanceRescueControll
   end
 end
 
-class ControllerInheritanceRescueControllerTest &lt; Test::Unit::TestCase
-
-  def setup
-    @controller = ControllerInheritanceRescueController.new
-    @request    = ActionController::TestRequest.new
-    @response   = ActionController::TestResponse.new
-  end
-
+class ControllerInheritanceRescueControllerTest &lt; ActionController::TestCase
   def test_first_exception_in_child_controller
     get :raise_first_exception_in_child_controller
     assert_response :gone</diff>
      <filename>vendor/rails/actionpack/test/controller/rescue_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -924,6 +924,20 @@ uses_mocha 'LegacyRouteSet, Route, RouteSet and RouteLoading' do
 
     end
 
+    def test_named_route_with_name_prefix
+      rs.add_named_route :page, 'page', :controller =&gt; 'content', :action =&gt; 'show_page', :name_prefix =&gt; 'my_'
+      x = setup_for_named_route
+      assert_equal(&quot;http://named.route.test/page&quot;,
+                   x.send(:my_page_url))
+    end
+
+    def test_named_route_with_path_prefix
+      rs.add_named_route :page, 'page', :controller =&gt; 'content', :action =&gt; 'show_page', :path_prefix =&gt; 'my'
+      x = setup_for_named_route
+      assert_equal(&quot;http://named.route.test/my/page&quot;,
+                   x.send(:page_url))
+    end
+
     def test_named_route_with_nested_controller
       rs.add_named_route :users, 'admin/user', :controller =&gt; 'admin/user', :action =&gt; 'index'
       x = setup_for_named_route
@@ -2147,6 +2161,13 @@ uses_mocha 'LegacyRouteSet, Route, RouteSet and RouteLoading' do
       assert_equal [:x], set.extra_keys(args)
     end
 
+    def test_generate_with_path_prefix
+      set.draw { |map| map.connect ':controller/:action/:id', :path_prefix =&gt; 'my' }
+
+      args = { :controller =&gt; &quot;foo&quot;, :action =&gt; &quot;bar&quot;, :id =&gt; &quot;7&quot;, :x =&gt; &quot;y&quot; }
+      assert_equal &quot;/my/foo/bar/7?x=y&quot;, set.generate(args)
+    end
+
     def test_named_routes_are_never_relative_to_modules
       set.draw do |map|
         map.connect &quot;/connection/manage/:action&quot;, :controller =&gt; 'connection/manage'</diff>
      <filename>vendor/rails/actionpack/test/controller/routing_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -667,6 +667,7 @@ class NamedRoutesControllerTest &lt; ActionController::TestCase
     with_routing do |set|
       set.draw { |map| map.resources :contents }
       assert_equal 'http://test.host/contents/new', new_content_url
+      assert_equal 'http://test.host/contents/1', content_url(:id =&gt; 1)
     end
   end
 end</diff>
      <filename>vendor/rails/actionpack/test/controller/test_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -38,7 +38,8 @@ class AssetTagHelperTest &lt; ActionView::TestCase
     @controller.request = @request
 
     ActionView::Helpers::AssetTagHelper::reset_javascript_include_default
-    COMPUTED_PUBLIC_PATHS.clear
+    AssetTag::Cache.clear
+    AssetCollection::Cache.clear
   end
 
   def teardown
@@ -155,12 +156,12 @@ class AssetTagHelperTest &lt; ActionView::TestCase
     PathToJavascriptToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
   end
 
-  def test_javascript_include_tag
+  def test_javascript_include_tag_with_blank_asset_id
     ENV[&quot;RAILS_ASSET_ID&quot;] = &quot;&quot;
     JavascriptIncludeToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
+  end
 
-    COMPUTED_PUBLIC_PATHS.clear
-
+  def test_javascript_include_tag_with_given_asset_id
     ENV[&quot;RAILS_ASSET_ID&quot;] = &quot;1&quot;
     assert_dom_equal(%(&lt;script src=&quot;/javascripts/prototype.js?1&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/effects.js?1&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/dragdrop.js?1&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/controls.js?1&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/application.js?1&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;), javascript_include_tag(:defaults))
   end
@@ -169,6 +170,11 @@ class AssetTagHelperTest &lt; ActionView::TestCase
     ENV[&quot;RAILS_ASSET_ID&quot;] = &quot;&quot;
     ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'slider'
     assert_dom_equal  %(&lt;script src=&quot;/javascripts/prototype.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/effects.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/dragdrop.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/controls.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/slider.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/application.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;), javascript_include_tag(:defaults)
+  end
+
+  def test_register_javascript_include_default_mixed_defaults
+    ENV[&quot;RAILS_ASSET_ID&quot;] = &quot;&quot;
+    ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'slider'
     ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'lib1', '/elsewhere/blub/lib2'
     assert_dom_equal  %(&lt;script src=&quot;/javascripts/prototype.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/effects.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/dragdrop.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/controls.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/slider.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/lib1.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/elsewhere/blub/lib2.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;\n&lt;script src=&quot;/javascripts/application.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;), javascript_include_tag(:defaults)
   end
@@ -224,6 +230,19 @@ class AssetTagHelperTest &lt; ActionView::TestCase
     ImageLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
   end
 
+  uses_mocha 'test image tag with windows behaviour' do
+    def test_image_tag_windows_behaviour
+      old_asset_id, ENV[&quot;RAILS_ASSET_ID&quot;] = ENV[&quot;RAILS_ASSET_ID&quot;], &quot;1&quot;
+      # This simulates the behaviour of File#exist? on windows when testing a file ending in &quot;.&quot;
+      # If the file &quot;rails.png&quot; exists, windows will return true when asked if &quot;rails.png.&quot; exists (notice trailing &quot;.&quot;)
+      # OS X, linux etc will return false in this case.
+      File.stubs(:exist?).with('template/../fixtures/public/images/rails.png.').returns(true)
+      assert_equal '&lt;img alt=&quot;Rails&quot; src=&quot;/images/rails.png?1&quot; /&gt;', image_tag('rails.png')
+    ensure
+      ENV[&quot;RAILS_ASSET_ID&quot;] = old_asset_id
+    end
+  end
+
   def test_timebased_asset_id
     expected_time = File.stat(File.expand_path(File.dirname(__FILE__) + &quot;/../fixtures/public/images/rails.png&quot;)).mtime.to_i.to_s
     assert_equal %(&lt;img alt=&quot;Rails&quot; src=&quot;/images/rails.png?#{expected_time}&quot; /&gt;), image_tag(&quot;rails.png&quot;)
@@ -386,6 +405,31 @@ class AssetTagHelperTest &lt; ActionView::TestCase
     FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'combined.js'))
   end
 
+  def test_caching_javascript_include_tag_with_relative_url_root
+    ENV[&quot;RAILS_ASSET_ID&quot;] = &quot;&quot;
+    ActionController::Base.relative_url_root = &quot;/collaboration/hieraki&quot;
+    ActionController::Base.perform_caching = true
+
+    assert_dom_equal(
+      %(&lt;script src=&quot;/collaboration/hieraki/javascripts/all.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;),
+      javascript_include_tag(:all, :cache =&gt; true)
+    )
+
+    assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js'))
+
+    assert_dom_equal(
+      %(&lt;script src=&quot;/collaboration/hieraki/javascripts/money.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;),
+      javascript_include_tag(:all, :cache =&gt; &quot;money&quot;)
+    )
+
+    assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js'))
+
+  ensure
+    ActionController::Base.relative_url_root = nil
+    FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js'))
+    FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'money.js'))
+  end
+
   def test_caching_javascript_include_tag_when_caching_off
     ENV[&quot;RAILS_ASSET_ID&quot;] = &quot;&quot;
     ActionController::Base.perform_caching = false
@@ -456,6 +500,31 @@ class AssetTagHelperTest &lt; ActionView::TestCase
     FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'styles.css'))
   end
 
+  def test_caching_stylesheet_link_tag_with_relative_url_root
+    ENV[&quot;RAILS_ASSET_ID&quot;] = &quot;&quot;
+    ActionController::Base.relative_url_root = &quot;/collaboration/hieraki&quot;
+    ActionController::Base.perform_caching = true
+
+    assert_dom_equal(
+      %(&lt;link href=&quot;/collaboration/hieraki/stylesheets/all.css&quot; media=&quot;screen&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;),
+      stylesheet_link_tag(:all, :cache =&gt; true)
+    )
+
+    expected = Dir[&quot;#{ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR}/*.css&quot;].map { |p| File.mtime(p) }.max
+    assert_equal expected, File.mtime(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
+
+    assert_dom_equal(
+      %(&lt;link href=&quot;/collaboration/hieraki/stylesheets/money.css&quot; media=&quot;screen&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;),
+      stylesheet_link_tag(:all, :cache =&gt; &quot;money&quot;)
+    )
+
+    assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css'))
+  ensure
+    ActionController::Base.relative_url_root = nil
+    FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
+    FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'money.css'))
+  end
+
   def test_caching_stylesheet_include_tag_when_caching_off
     ENV[&quot;RAILS_ASSET_ID&quot;] = &quot;&quot;
     ActionController::Base.perform_caching = false</diff>
      <filename>vendor/rails/actionpack/test/template/asset_tag_helper_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -92,6 +92,64 @@ class ScrollsController &lt; ActionController::Base
           end
         end
     EOT
+  FEEDS[&quot;feed_with_xml_processing_instructions&quot;] = &lt;&lt;-EOT
+        atom_feed(:schema_date =&gt; '2008',
+          :instruct =&gt; {'xml-stylesheet' =&gt; { :href=&gt; 't.css', :type =&gt; 'text/css' }}) do |feed|
+          feed.title(&quot;My great blog!&quot;)
+          feed.updated((@scrolls.first.created_at))
+
+          for scroll in @scrolls
+            feed.entry(scroll) do |entry|
+              entry.title(scroll.title)
+              entry.content(scroll.body, :type =&gt; 'html')
+
+              entry.author do |author|
+                author.name(&quot;DHH&quot;)
+              end
+            end
+          end
+        end
+    EOT
+  FEEDS[&quot;feed_with_xml_processing_instructions_duplicate_targets&quot;] = &lt;&lt;-EOT
+        atom_feed(:schema_date =&gt; '2008',
+          :instruct =&gt; {'target1' =&gt; [{ :a =&gt; '1', :b =&gt; '2' }, { :c =&gt; '3', :d =&gt; '4' }]}) do |feed|
+          feed.title(&quot;My great blog!&quot;)
+          feed.updated((@scrolls.first.created_at))
+
+          for scroll in @scrolls
+            feed.entry(scroll) do |entry|
+              entry.title(scroll.title)
+              entry.content(scroll.body, :type =&gt; 'html')
+
+              entry.author do |author|
+                author.name(&quot;DHH&quot;)
+              end
+            end
+          end
+        end
+    EOT
+    FEEDS[&quot;feed_with_xhtml_content&quot;] = &lt;&lt;-'EOT'
+        atom_feed do |feed|
+          feed.title(&quot;My great blog!&quot;)
+          feed.updated((@scrolls.first.created_at))
+
+          for scroll in @scrolls
+            feed.entry(scroll) do |entry|
+              entry.title(scroll.title)
+              entry.summary(:type =&gt; 'xhtml') do |xhtml|
+                xhtml.p &quot;before #{scroll.id}&quot;
+                xhtml.p {xhtml &lt;&lt; scroll.body}
+                xhtml.p &quot;after #{scroll.id}&quot;
+              end
+              entry.tag!('app:edited', Time.now)
+
+              entry.author do |author|
+                author.name(&quot;DHH&quot;)
+              end
+            end
+          end
+        end
+    EOT
   def index
     @scrolls = [
       Scroll.new(1, &quot;1&quot;, &quot;Hello One&quot;, &quot;Something &lt;i&gt;COOL!&lt;/i&gt;&quot;, Time.utc(2007, 12, 12, 15), Time.utc(2007, 12, 12, 15)),
@@ -194,6 +252,29 @@ class AtomFeedTest &lt; Test::Unit::TestCase
     end
   end
 
+  def test_feed_xml_processing_instructions
+    with_restful_routing(:scrolls) do
+      get :index, :id =&gt; 'feed_with_xml_processing_instructions'
+      assert_match %r{&lt;\?xml-stylesheet type=&quot;text/css&quot; href=&quot;t.css&quot;\?&gt;}, @response.body
+    end
+  end
+
+  def test_feed_xml_processing_instructions_duplicate_targets
+    with_restful_routing(:scrolls) do
+      get :index, :id =&gt; 'feed_with_xml_processing_instructions_duplicate_targets'
+      assert_match %r{&lt;\?target1 (a=&quot;1&quot; b=&quot;2&quot;|b=&quot;2&quot; a=&quot;1&quot;)\?&gt;}, @response.body
+      assert_match %r{&lt;\?target1 (c=&quot;3&quot; d=&quot;4&quot;|d=&quot;4&quot; c=&quot;3&quot;)\?&gt;}, @response.body
+    end
+  end
+
+  def test_feed_xhtml
+    with_restful_routing(:scrolls) do
+      get :index, :id =&gt; &quot;feed_with_xhtml_content&quot;
+      assert_match %r{xmlns=&quot;http://www.w3.org/1999/xhtml&quot;}, @response.body
+      assert_select &quot;summary div p&quot;, :text =&gt; &quot;Something Boring&quot;
+      assert_select &quot;summary div p&quot;, :text =&gt; &quot;after 2&quot;
+    end
+  end
 private
     def with_restful_routing(resources)
       with_routing do |set|</diff>
      <filename>vendor/rails/actionpack/test/template/atom_feed_helper_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -211,7 +211,8 @@ class FormTagHelperTest &lt; ActionView::TestCase
   def test_boolean_optios
     assert_dom_equal %(&lt;input checked=&quot;checked&quot; disabled=&quot;disabled&quot; id=&quot;admin&quot; name=&quot;admin&quot; readonly=&quot;readonly&quot; type=&quot;checkbox&quot; value=&quot;1&quot; /&gt;), check_box_tag(&quot;admin&quot;, 1, true, 'disabled' =&gt; true, :readonly =&gt; &quot;yes&quot;)
     assert_dom_equal %(&lt;input checked=&quot;checked&quot; id=&quot;admin&quot; name=&quot;admin&quot; type=&quot;checkbox&quot; value=&quot;1&quot; /&gt;), check_box_tag(&quot;admin&quot;, 1, true, :disabled =&gt; false, :readonly =&gt; nil)
-    assert_dom_equal %(&lt;select id=&quot;people&quot; multiple=&quot;multiple&quot; name=&quot;people&quot;&gt;&lt;option&gt;david&lt;/option&gt;&lt;/select&gt;), select_tag(&quot;people&quot;, &quot;&lt;option&gt;david&lt;/option&gt;&quot;, :multiple =&gt; true)
+    assert_dom_equal %(&lt;select id=&quot;people&quot; multiple=&quot;multiple&quot; name=&quot;people[]&quot;&gt;&lt;option&gt;david&lt;/option&gt;&lt;/select&gt;), select_tag(&quot;people&quot;, &quot;&lt;option&gt;david&lt;/option&gt;&quot;, :multiple =&gt; true)
+    assert_dom_equal %(&lt;select id=&quot;people[]&quot; multiple=&quot;multiple&quot; name=&quot;people[]&quot;&gt;&lt;option&gt;david&lt;/option&gt;&lt;/select&gt;), select_tag(&quot;people[]&quot;, &quot;&lt;option&gt;david&lt;/option&gt;&quot;, :multiple =&gt; true)
     assert_dom_equal %(&lt;select id=&quot;people&quot; name=&quot;people&quot;&gt;&lt;option&gt;david&lt;/option&gt;&lt;/select&gt;), select_tag(&quot;people&quot;, &quot;&lt;option&gt;david&lt;/option&gt;&quot;, :multiple =&gt; nil)
   end
 
@@ -271,6 +272,12 @@ class FormTagHelperTest &lt; ActionView::TestCase
 
     expected = %(&lt;fieldset&gt;Hello world!&lt;/fieldset&gt;)
     assert_dom_equal expected, output_buffer
+
+    self.output_buffer = ''
+    field_set_tag('', :class =&gt; 'format') { concat &quot;Hello world!&quot; }
+
+    expected = %(&lt;fieldset class=&quot;format&quot;&gt;Hello world!&lt;/fieldset&gt;)
+    assert_dom_equal expected, output_buffer
   end
 
   def protect_against_forgery?</diff>
      <filename>vendor/rails/actionpack/test/template/form_tag_helper_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -218,9 +218,9 @@ class PrototypeHelperTest &lt; PrototypeHelperBaseTest
 
   end
 
-  def test_button_to_remote
-    assert_dom_equal %(&lt;input name=\&quot;More beer!\&quot; onclick=\&quot;new Ajax.Updater('empty_bottle', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)}); return false;\&quot; type=\&quot;button\&quot; value=\&quot;1000000\&quot; /&gt;),
-      button_to_remote(&quot;More beer!&quot;, 1_000_000, :update =&gt; &quot;empty_bottle&quot;)
+  def test_submit_to_remote
+    assert_dom_equal %(&lt;input name=\&quot;More beer!\&quot; onclick=\&quot;new Ajax.Updater('empty_bottle', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});\&quot; type=\&quot;button\&quot; value=\&quot;1000000\&quot; /&gt;),
+      submit_to_remote(&quot;More beer!&quot;, 1_000_000, :update =&gt; &quot;empty_bottle&quot;)
   end
 
   def test_observe_field</diff>
      <filename>vendor/rails/actionpack/test/template/prototype_helper_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -70,7 +70,23 @@ class ViewRenderTest &lt; Test::Unit::TestCase
   end
 
   def test_render_partial_with_errors
-    assert_raise(ActionView::TemplateError) { @view.render(:partial =&gt; &quot;test/raise&quot;) }
+    @view.render(:partial =&gt; &quot;test/raise&quot;)
+    flunk &quot;Render did not raise TemplateError&quot;
+  rescue ActionView::TemplateError =&gt; e
+    assert_match &quot;undefined local variable or method `doesnt_exist'&quot;, e.message
+    assert_equal &quot;&quot;, e.sub_template_message
+    assert_equal &quot;1&quot;, e.line_number
+    assert_equal File.expand_path(&quot;#{FIXTURE_LOAD_PATH}/test/_raise.html.erb&quot;), e.file_name
+  end
+
+  def test_render_sub_template_with_errors
+    @view.render(:file =&gt; &quot;test/sub_template_raise&quot;)
+    flunk &quot;Render did not raise TemplateError&quot;
+  rescue ActionView::TemplateError =&gt; e
+    assert_match &quot;undefined local variable or method `doesnt_exist'&quot;, e.message
+    assert_equal &quot;Trace of template inclusion: #{File.expand_path(&quot;#{FIXTURE_LOAD_PATH}/test/sub_template_raise.html.erb&quot;)}&quot;, e.sub_template_message
+    assert_equal &quot;1&quot;, e.line_number
+    assert_equal File.expand_path(&quot;#{FIXTURE_LOAD_PATH}/test/_raise.html.erb&quot;), e.file_name
   end
 
   def test_render_partial_collection</diff>
      <filename>vendor/rails/actionpack/test/template/render_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,7 @@
 *Edge*
 
+* Add Model#delete instance method, similar to Model.delete class method. #1086 [Hongli Lai]
+
 * MySQL: cope with quirky default values for not-null text columns.  #1043 [Frederick Cheung]
 
 * Multiparameter attributes skip time zone conversion for time-only columns [#1030 state:resolved] [Geoff Buesing]</diff>
      <filename>vendor/rails/activerecord/CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -77,5 +77,5 @@ require 'active_record/connection_adapters/abstract_adapter'
 
 require 'active_record/schema_dumper'
 
-I18n.load_translations File.dirname(__FILE__) + '/active_record/locale/en-US.yml'
-
+require 'active_record/i18n_interpolation_deprecation'
+I18n.load_path &lt;&lt; File.dirname(__FILE__) + '/active_record/locale/en-US.yml'</diff>
      <filename>vendor/rails/activerecord/lib/active_record.rb</filename>
    </modified>
    <modified>
      <diff>@@ -75,7 +75,7 @@ module ActiveRecord
     #
     #   customer.balance = Money.new(20)     # sets the Money value object and the attribute
     #   customer.balance                     # =&gt; Money value object
-    #   customer.balance.exchanged_to(&quot;DKK&quot;) # =&gt; Money.new(120, &quot;DKK&quot;)
+    #   customer.balance.exchange_to(&quot;DKK&quot;)  # =&gt; Money.new(120, &quot;DKK&quot;)
     #   customer.balance &gt; Money.new(10)     # =&gt; true
     #   customer.balance == Money.new(20)    # =&gt; true
     #   customer.balance &lt; Money.new(5)      # =&gt; false
@@ -99,7 +99,7 @@ module ActiveRecord
     # relational unique identifiers (such as primary keys). Normal ActiveRecord::Base classes are entity objects.
     #
     # It's also important to treat the value objects as immutable. Don't allow the Money object to have its amount changed after
-    # creation. Create a new Money object with the new value instead. This is exemplified by the Money#exchanged_to method that
+    # creation. Create a new Money object with the new value instead. This is exemplified by the Money#exchange_to method that
     # returns a new value object instead of changing its own values. Active Record won't persist value objects that have been
     # changed through means other than the writer method.
     #</diff>
      <filename>vendor/rails/activerecord/lib/active_record/aggregations.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,88 @@
 module ActiveRecord
+  # See ActiveRecord::AssociationPreload::ClassMethods for documentation.
   module AssociationPreload #:nodoc:
     def self.included(base)
       base.extend(ClassMethods)
     end
 
+    # Implements the details of eager loading of ActiveRecord associations.
+    # Application developers should not use this module directly.
+    #
+    # ActiveRecord::Base is extended with this module. The source code in
+    # ActiveRecord::Base references methods defined in this module.
+    #
+    # Note that 'eager loading' and 'preloading' are actually the same thing.
+    # However, there are two different eager loading strategies.
+    #
+    # The first one is by using table joins. This was only strategy available
+    # prior to Rails 2.1. Suppose that you have an Author model with columns
+    # 'name' and 'age', and a Book model with columns 'name' and 'sales'. Using
+    # this strategy, ActiveRecord would try to retrieve all data for an author
+    # and all of its books via a single query:
+    #
+    #   SELECT * FROM authors
+    #   LEFT OUTER JOIN books ON authors.id = books.id
+    #   WHERE authors.name = 'Ken Akamatsu'
+    #
+    # However, this could result in many rows that contain redundant data. After
+    # having received the first row, we already have enough data to instantiate
+    # the Author object. In all subsequent rows, only the data for the joined
+    # 'books' table is useful; the joined 'authors' data is just redundant, and
+    # processing this redundant data takes memory and CPU time. The problem
+    # quickly becomes worse and worse as the level of eager loading increases
+    # (i.e. if ActiveRecord is to eager load the associations' assocations as
+    # well).
+    #
+    # The second strategy is to use multiple database queries, one for each
+    # level of association. Since Rails 2.1, this is the default strategy. In
+    # situations where a table join is necessary (e.g. when the +:conditions+
+    # option references an association's column), it will fallback to the table
+    # join strategy.
+    #
+    # See also ActiveRecord::Associations::ClassMethods, which explains eager
+    # loading in a more high-level (application developer-friendly) manner.
     module ClassMethods
-
-      # Loads the named associations for the activerecord record (or records) given
-      # preload_options is passed only one level deep: don't pass to the child associations when associations is a Hash
       protected
+      
+      # Eager loads the named associations for the given ActiveRecord record(s).
+      #
+      # In this description, 'association name' shall refer to the name passed
+      # to an association creation method. For example, a model that specifies
+      # &lt;tt&gt;belongs_to :author&lt;/tt&gt;, &lt;tt&gt;has_many :buyers&lt;/tt&gt; has association
+      # names +:author+ and +:buyers+.
+      #
+      # == Parameters
+      # +records+ is an array of ActiveRecord::Base. This array needs not be flat,
+      # i.e. +records+ itself may also contain arrays of records. In any case,
+      # +preload_associations+ will preload the associations all records by
+      # flattening +records+.
+      #
+      # +associations+ specifies one or more associations that you want to
+      # preload. It may be:
+      # - a Symbol or a String which specifies a single association name. For
+      #   example, specifiying +:books+ allows this method to preload all books
+      #   for an Author.
+      # - an Array which specifies multiple association names. This array
+      #   is processed recursively. For example, specifying &lt;tt&gt;[:avatar, :books]&lt;/tt&gt;
+      #   allows this method to preload an author's avatar as well as all of his
+      #   books.
+      # - a Hash which specifies multiple association names, as well as
+      #   association names for the to-be-preloaded association objects. For
+      #   example, specifying &lt;tt&gt;{ :author =&gt; :avatar }&lt;/tt&gt; will preload a
+      #   book's author, as well as that author's avatar.
+      #
+      # +:associations+ has the same format as the +:include+ option for
+      # &lt;tt&gt;ActiveRecord::Base.find&lt;/tt&gt;. So +associations+ could look like this:
+      #
+      #   :books
+      #   [ :books, :author ]
+      #   { :author =&gt; :avatar }
+      #   [ :books, { :author =&gt; :avatar } ]
+      #
+      # +preload_options+ contains options that will be passed to ActiveRecord#find
+      # (which is called under the hood for preloading records). But it is passed
+      # only one level deep in the +associations+ argument, i.e. it's not passed
+      # to the child associations when +associations+ is a Hash.
       def preload_associations(records, associations, preload_options={})
         records = [records].flatten.compact.uniq
         return if records.empty?
@@ -30,6 +104,8 @@ module ActiveRecord
 
       private
 
+      # Preloads a specific named association for the given records. This is
+      # called by +preload_associations+ as its base case.
       def preload_one_association(records, association, preload_options={})
         class_to_reflection = {}
         # Not all records have the same class, so group then preload
@@ -37,6 +113,10 @@ module ActiveRecord
         # unnecessarily
         records.group_by {|record| class_to_reflection[record.class] ||= record.class.reflections[association]}.each do |reflection, records|
           raise ConfigurationError, &quot;Association named '#{ association }' was not found; perhaps you misspelled it?&quot; unless reflection
+          
+          # 'reflection.macro' can return 'belongs_to', 'has_many', etc. Thus,
+          # the following could call 'preload_belongs_to_association',
+          # 'preload_has_many_association', etc.
           send(&quot;preload_#{reflection.macro}_association&quot;, records, reflection, preload_options)
         end
       end
@@ -77,12 +157,17 @@ module ActiveRecord
         end
       end
 
-      def construct_id_map(records)
+      # Given a collection of ActiveRecord objects, constructs a Hash which maps
+      # the objects' IDs to the relevant objects. Returns a 2-tuple
+      # &lt;tt&gt;(id_to_record_map, ids)&lt;/tt&gt; where +id_to_record_map+ is the Hash,
+      # and +ids+ is an Array of record IDs.
+      def construct_id_map(records, primary_key=nil)
         id_to_record_map = {}
         ids = []
         records.each do |record|
-          ids &lt;&lt; record.id
-          mapped_records = (id_to_record_map[record.id.to_s] ||= [])
+          primary_key ||= record.class.primary_key
+          ids &lt;&lt; record[primary_key]
+          mapped_records = (id_to_record_map[ids.last.to_s] ||= [])
           mapped_records &lt;&lt; record
         end
         ids.uniq!
@@ -96,7 +181,7 @@ module ActiveRecord
         options = reflection.options
 
         conditions = &quot;t0.#{reflection.primary_key_name} #{in_or_equals_for_ids(ids)}&quot;
-        conditions &lt;&lt; append_conditions(options, preload_options)
+        conditions &lt;&lt; append_conditions(reflection, preload_options)
 
         associated_records = reflection.klass.find(:all, :conditions =&gt; [conditions, ids],
         :include =&gt; options[:include],
@@ -108,6 +193,7 @@ module ActiveRecord
       end
 
       def preload_has_one_association(records, reflection, preload_options={})
+        return if records.first.send(&quot;loaded_#{reflection.name}?&quot;)
         id_to_record_map, ids = construct_id_map(records)        
         options = reflection.options
         records.each {|record| record.send(&quot;set_#{reflection.name}_target&quot;, nil)}
@@ -129,23 +215,25 @@ module ActiveRecord
       end
 
       def preload_has_many_association(records, reflection, preload_options={})
-        id_to_record_map, ids = construct_id_map(records)
-        records.each {|record| record.send(reflection.name).loaded}
+        return if records.first.send(reflection.name).loaded?
         options = reflection.options
 
+        primary_key_name = reflection.through_reflection_primary_key_name
+        id_to_record_map, ids = construct_id_map(records, primary_key_name)
+        records.each {|record| record.send(reflection.name).loaded}
+
         if options[:through]
           through_records = preload_through_records(records, reflection, options[:through])
           through_reflection = reflections[options[:through]]
-          through_primary_key = through_reflection.primary_key_name
           unless through_records.empty?
             source = reflection.source_reflection.name
-            #add conditions from reflection!
-            through_records.first.class.preload_associations(through_records, source, reflection.options)
+            through_records.first.class.preload_associations(through_records, source, options)
             through_records.each do |through_record|
-              add_preloaded_records_to_collection(id_to_record_map[through_record[through_primary_key].to_s],
-                                                 reflection.name, through_record.send(source))
+              through_record_id = through_record[reflection.through_reflection_primary_key].to_s
+              add_preloaded_records_to_collection(id_to_record_map[through_record_id], reflection.name, through_record.send(source))
             end
           end
+
         else
           set_association_collection_records(id_to_record_map, reflection.name, find_associated_records(ids, reflection, preload_options),
                                              reflection.primary_key_name)
@@ -185,6 +273,7 @@ module ActiveRecord
       end
 
       def preload_belongs_to_association(records, reflection, preload_options={})
+        return if records.first.send(&quot;loaded_#{reflection.name}?&quot;)
         options = reflection.options
         primary_key_name = reflection.primary_key_name
 
@@ -233,7 +322,7 @@ module ActiveRecord
             end
           end
           conditions = &quot;#{table_name}.#{connection.quote_column_name(primary_key)} #{in_or_equals_for_ids(ids)}&quot;
-          conditions &lt;&lt; append_conditions(options, preload_options)
+          conditions &lt;&lt; append_conditions(reflection, preload_options)
           associated_records = klass.find(:all, :conditions =&gt; [conditions, ids],
                                           :include =&gt; options[:include],
                                           :select =&gt; options[:select],
@@ -254,7 +343,7 @@ module ActiveRecord
           conditions = &quot;#{reflection.klass.quoted_table_name}.#{foreign_key} #{in_or_equals_for_ids(ids)}&quot;
         end
 
-        conditions &lt;&lt; append_conditions(options, preload_options)
+        conditions &lt;&lt; append_conditions(reflection, preload_options)
 
         reflection.klass.find(:all,
                               :select =&gt; (preload_options[:select] || options[:select] || &quot;#{table_name}.*&quot;),
@@ -270,9 +359,9 @@ module ActiveRecord
         instance_eval(&quot;%@#{sql.gsub('@', '\@')}@&quot;)
       end
 
-      def append_conditions(options, preload_options)
+      def append_conditions(reflection, preload_options)
         sql = &quot;&quot;
-        sql &lt;&lt; &quot; AND (#{interpolate_sql_for_preload(sanitize_sql(options[:conditions]))})&quot; if options[:conditions]
+        sql &lt;&lt; &quot; AND (#{interpolate_sql_for_preload(reflection.sanitized_conditions)})&quot; if reflection.sanitized_conditions
         sql &lt;&lt; &quot; AND (#{sanitize_sql preload_options[:conditions]})&quot; if preload_options[:conditions]
         sql
       end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/association_preload.rb</filename>
    </modified>
    <modified>
      <diff>@@ -955,8 +955,6 @@ module ActiveRecord
       #   destroyed. This requires that a column named &lt;tt&gt;#{table_name}_count&lt;/tt&gt; (such as +comments_count+ for a belonging Comment class)
       #   is used on the associate class (such as a Post class). You can also specify a custom counter cache column by providing
       #   a column name instead of a +true+/+false+ value to this option (e.g., &lt;tt&gt;:counter_cache =&gt; :my_custom_counter&lt;/tt&gt;.)
-      #   When creating a counter cache column, the database statement or migration must specify a default value of &lt;tt&gt;0&lt;/tt&gt;, failing to do 
-      #   this results in a counter with +NULL+ value, which will never increment.
       #   Note: Specifying a counter cache will add it to that model's list of readonly attributes using +attr_readonly+.
       # [:include]
       #   Specify second-order associations that should be eager loaded when this object is loaded.
@@ -1026,7 +1024,7 @@ module ActiveRecord
         # Create the callbacks to update counter cache
         if options[:counter_cache]
           cache_column = options[:counter_cache] == true ?
-            &quot;#{self.to_s.underscore.pluralize}_count&quot; :
+            &quot;#{self.to_s.demodulize.underscore.pluralize}_count&quot; :
             options[:counter_cache]
 
           method_name = &quot;belongs_to_counter_cache_after_create_for_#{reflection.name}&quot;.to_sym
@@ -1237,7 +1235,7 @@ module ActiveRecord
 
             association = instance_variable_get(ivar) if instance_variable_defined?(ivar)
 
-            if association.nil? || !association.loaded? || force_reload
+            if association.nil? || force_reload
               association = association_proxy_class.new(self, reflection)
               retval = association.reload
               if retval.nil? and association_proxy_class == BelongsToAssociation
@@ -1250,6 +1248,11 @@ module ActiveRecord
             association.target.nil? ? nil : association
           end
 
+          define_method(&quot;loaded_#{reflection.name}?&quot;) do
+            association = instance_variable_get(ivar) if instance_variable_defined?(ivar)
+            association &amp;&amp; association.loaded?
+          end
+
           define_method(&quot;#{reflection.name}=&quot;) do |new_value|
             association = instance_variable_get(ivar) if instance_variable_defined?(ivar)
 
@@ -1266,13 +1269,6 @@ module ActiveRecord
             end
           end
 
-          if association_proxy_class == BelongsToAssociation
-            define_method(&quot;#{reflection.primary_key_name}=&quot;) do |target_id|
-              instance_variable_get(ivar).reset if instance_variable_defined?(ivar)
-              write_attribute(reflection.primary_key_name, target_id)
-            end
-          end
-
           define_method(&quot;set_#{reflection.name}_target&quot;) do |target|
             return if target.nil? and association_proxy_class == BelongsToAssociation
             association = association_proxy_class.new(self, reflection)
@@ -1424,15 +1420,23 @@ module ActiveRecord
           []
         end
 
+        # Creates before_destroy callback methods that nullify, delete or destroy
+        # has_many associated objects, according to the defined :dependent rule.
+        #
         # See HasManyAssociation#delete_records.  Dependent associations
         # delete children, otherwise foreign key is set to NULL.
-        def configure_dependency_for_has_many(reflection)
+        #
+        # The +extra_conditions+ parameter, which is not used within the main
+        # Active Record codebase, is meant to allow plugins to define extra
+        # finder conditions.
+        def configure_dependency_for_has_many(reflection, extra_conditions = nil)
           if reflection.options.include?(:dependent)
             # Add polymorphic type if the :as option is present
             dependent_conditions = []
             dependent_conditions &lt;&lt; &quot;#{reflection.primary_key_name} = \#{record.quoted_id}&quot;
             dependent_conditions &lt;&lt; &quot;#{reflection.options[:as]}_type = '#{base_class.name}'&quot; if reflection.options[:as]
             dependent_conditions &lt;&lt; sanitize_sql(reflection.options[:conditions]) if reflection.options[:conditions]
+            dependent_conditions &lt;&lt; extra_conditions if extra_conditions
             dependent_conditions = dependent_conditions.collect {|where| &quot;(#{where})&quot; }.join(&quot; AND &quot;)
 
             case reflection.options[:dependent]
@@ -1443,15 +1447,32 @@ module ActiveRecord
                 end
                 before_destroy method_name
               when :delete_all
-                module_eval &quot;before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }&quot;
+                module_eval %Q{
+                  before_destroy do |record|
+                    delete_all_has_many_dependencies(record,
+                      &quot;#{reflection.name}&quot;,
+                      #{reflection.class_name},
+                      &quot;#{dependent_conditions}&quot;)
+                  end
+                }
               when :nullify
-                module_eval &quot;before_destroy { |record| #{reflection.class_name}.update_all(%(#{reflection.primary_key_name} = NULL),  %(#{dependent_conditions})) }&quot;
+                module_eval %Q{
+                  before_destroy do |record|
+                    nullify_has_many_dependencies(record,
+                      &quot;#{reflection.name}&quot;,
+                      #{reflection.class_name},
+                      &quot;#{reflection.primary_key_name}&quot;,
+                      &quot;#{dependent_conditions}&quot;)
+                  end
+                }
               else
                 raise ArgumentError, &quot;The :dependent option expects either :destroy, :delete_all, or :nullify (#{reflection.options[:dependent].inspect})&quot;
             end
           end
         end
 
+        # Creates before_destroy callback methods that nullify, delete or destroy
+        # has_one associated objects, according to the defined :dependent rule.
         def configure_dependency_for_has_one(reflection)
           if reflection.options.include?(:dependent)
             case reflection.options[:dependent]
@@ -1465,8 +1486,12 @@ module ActiveRecord
               when :delete
                 method_name = &quot;has_one_dependent_delete_for_#{reflection.name}&quot;.to_sym
                 define_method(method_name) do
+                  # Retrieve the associated object and delete it. The retrieval
+                  # is necessary because there may be multiple associated objects
+                  # with foreign keys pointing to this object, and we only want
+                  # to delete the correct one, not all of them.
                   association = send(reflection.name)
-                  association.class.delete(association.id) unless association.nil?
+                  association.delete unless association.nil?
                 end
                 before_destroy method_name
               when :nullify
@@ -1496,7 +1521,7 @@ module ActiveRecord
                 method_name = &quot;belongs_to_dependent_delete_for_#{reflection.name}&quot;.to_sym
                 define_method(method_name) do
                   association = send(reflection.name)
-                  association.class.delete(association.id) unless association.nil?
+                  association.delete unless association.nil?
                 end
                 before_destroy method_name
               else
@@ -1505,6 +1530,14 @@ module ActiveRecord
           end
         end
 
+        def delete_all_has_many_dependencies(record, reflection_name, association_class, dependent_conditions)
+          association_class.delete_all(dependent_conditions)
+        end
+
+        def nullify_has_many_dependencies(record, reflection_name, association_class, primary_key_name, dependent_conditions)
+          association_class.update_all(&quot;#{primary_key_name} = NULL&quot;, dependent_conditions)
+        end
+
         mattr_accessor :valid_keys_for_has_many_association
         @@valid_keys_for_has_many_association = [
           :class_name, :table_name, :foreign_key, :primary_key,
@@ -1751,12 +1784,12 @@ module ActiveRecord
 
         def create_extension_modules(association_id, block_extension, extensions)
           if block_extension
-            extension_module_name = &quot;#{self.to_s}#{association_id.to_s.camelize}AssociationExtension&quot;
+            extension_module_name = &quot;#{self.to_s.demodulize}#{association_id.to_s.camelize}AssociationExtension&quot;
 
             silence_warnings do
-              Object.const_set(extension_module_name, Module.new(&amp;block_extension))
+              self.parent.const_set(extension_module_name, Module.new(&amp;block_extension))
             end
-            Array(extensions).push(extension_module_name.constantize)
+            Array(extensions).push(&quot;#{self.parent}::#{extension_module_name}&quot;.constantize)
           else
             Array(extensions)
           end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/associations.rb</filename>
    </modified>
    <modified>
      <diff>@@ -63,7 +63,7 @@ module ActiveRecord
       
       # Fetches the first one using SQL if possible.
       def first(*args)
-        if fetch_first_or_last_using_find? args
+        if fetch_first_or_last_using_find?(args)
           find(:first, *args)
         else
           load_target unless loaded?
@@ -73,7 +73,7 @@ module ActiveRecord
 
       # Fetches the last one using SQL if possible.
       def last(*args)
-        if fetch_first_or_last_using_find? args
+        if fetch_first_or_last_using_find?(args)
           find(:last, *args)
         else
           load_target unless loaded?
@@ -108,7 +108,7 @@ module ActiveRecord
         result = true
         load_target if @owner.new_record?
 
-        @owner.transaction do
+        transaction do
           flatten_deeper(records).each do |record|
             raise_on_type_mismatch(record)
             add_record_to_target_with_callbacks(record) do |r|
@@ -123,6 +123,21 @@ module ActiveRecord
       alias_method :push, :&lt;&lt;
       alias_method :concat, :&lt;&lt;
 
+      # Starts a transaction in the association class's database connection.
+      #
+      #   class Author &lt; ActiveRecord::Base
+      #     has_many :books
+      #   end
+      #
+      #   Author.find(:first).books.transaction do
+      #     # same effect as calling Book.transaction
+      #   end
+      def transaction(*args)
+        @reflection.klass.transaction(*args) do
+          yield
+        end
+      end
+
       # Remove all records from this association
       def delete_all
         load_target
@@ -173,7 +188,7 @@ module ActiveRecord
         records = flatten_deeper(records)
         records.each { |record| raise_on_type_mismatch(record) }
         
-        @owner.transaction do
+        transaction do
           records.each { |record| callback(:before_remove, record) }
           
           old_records = records.reject {|r| r.new_record? }
@@ -200,7 +215,7 @@ module ActiveRecord
       end
       
       def destroy_all
-        @owner.transaction do
+        transaction do
           each { |record| record.destroy }
         end
 
@@ -292,7 +307,7 @@ module ActiveRecord
         other   = other_array.size &lt; 100 ? other_array : other_array.to_set
         current = @target.size &lt; 100 ? @target : @target.to_set
 
-        @owner.transaction do
+        transaction do
           delete(@target.select { |v| !other.include?(v) })
           concat(other_array.select { |v| !current.include?(v) })
         end
@@ -420,7 +435,8 @@ module ActiveRecord
         end
 
         def fetch_first_or_last_using_find?(args)
-          args.first.kind_of?(Hash) || !(loaded? || @owner.new_record? || @reflection.options[:finder_sql] || !@target.blank? || args.first.kind_of?(Integer))
+          args.first.kind_of?(Hash) || !(loaded? || @owner.new_record? || @reflection.options[:finder_sql] ||
+                                         @target.any? { |record| record.new_record? } || args.first.kind_of?(Integer))
         end
     end
   end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/associations/association_collection.rb</filename>
    </modified>
    <modified>
      <diff>@@ -140,6 +140,15 @@ module ActiveRecord
         @target.inspect
       end
 
+      def send(method, *args)
+        if proxy_respond_to?(method)
+          super
+        else
+          load_target
+          @target.send(method, *args)
+        end
+      end
+
       protected
         # Does the association have a &lt;tt&gt;:dependent&lt;/tt&gt; option?
         def dependent?
@@ -197,6 +206,8 @@ module ActiveRecord
         # Forwards any missing method call to the \target.
         def method_missing(method, *args)
           if load_target
+            raise NoMethodError unless @target.respond_to?(method)
+
             if block_given?
               @target.send(method, *args)  { |*block_args| yield(*block_args) }
             else
@@ -240,7 +251,7 @@ module ActiveRecord
         # the kind of the class of the associated objects. Meant to be used as
         # a sanity check when you are about to assign an associated record.
         def raise_on_type_mismatch(record)
-          unless record.is_a?(@reflection.klass)
+          unless record.is_a?(@reflection.klass) || record.is_a?(@reflection.class_name.constantize)
             message = &quot;#{@reflection.class_name}(##{@reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})&quot;
             raise ActiveRecord::AssociationTypeMismatch, message
           end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,14 +9,14 @@ module ActiveRecord
       alias_method :new, :build
 
       def create!(attrs = nil)
-        @reflection.klass.transaction do
+        transaction do
           self &lt;&lt; (object = attrs ? @reflection.klass.send(:with_scope, :create =&gt; attrs) { @reflection.create_association! } : @reflection.create_association!)
           object
         end
       end
 
       def create(attrs = nil)
-        @reflection.klass.transaction do
+        transaction do
           self &lt;&lt; (object = attrs ? @reflection.klass.send(:with_scope, :create =&gt; attrs) { @reflection.create_association } : @reflection.create_association)
           object
         end
@@ -32,6 +32,14 @@ module ActiveRecord
       end
       
       protected
+        def target_reflection_has_associated_record?
+          if @reflection.through_reflection.macro == :belongs_to &amp;&amp; @owner[@reflection.through_reflection.primary_key_name].blank?
+            false
+          else
+            true
+          end
+        end
+
         def construct_find_options!(options)
           options[:select]  = construct_select(options[:select])
           options[:from]  ||= construct_from
@@ -61,6 +69,7 @@ module ActiveRecord
         end
 
         def find_target
+          return [] unless target_reflection_has_associated_record?
           @reflection.klass.find(:all,
             :select     =&gt; construct_select,
             :conditions =&gt; construct_conditions,
@@ -102,6 +111,8 @@ module ActiveRecord
               &quot;#{as}_type&quot; =&gt; reflection.klass.quote_value(
                 @owner.class.base_class.name.to_s,
                 reflection.klass.columns_hash[&quot;#{as}_type&quot;]) }
+          elsif reflection.macro == :belongs_to
+            { reflection.klass.primary_key =&gt; @owner[reflection.primary_key_name] }
           else
             { reflection.primary_key_name =&gt; owner_quoted_id }
           end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb</filename>
    </modified>
    <modified>
      <diff>@@ -57,7 +57,7 @@ module ActiveRecord
       protected
         def owner_quoted_id
           if @reflection.options[:primary_key]
-            quote_value(@owner.send(@reflection.options[:primary_key]))
+            @owner.class.quote_value(@owner.send(@reflection.options[:primary_key]))
           else
             @owner.quoted_id
           end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/associations/has_one_association.rb</filename>
    </modified>
    <modified>
      <diff>@@ -232,6 +232,10 @@ module ActiveRecord
     def method_missing(method_id, *args, &amp;block)
       method_name = method_id.to_s
 
+      if self.class.private_method_defined?(method_name)
+        raise NoMethodError(&quot;Attempt to call private method&quot;, method_name, args)
+      end
+
       # If we haven't generated any methods yet, generate them, then
       # see if we've created the method we're looking for.
       if !self.class.generated_methods?
@@ -334,10 +338,14 @@ module ActiveRecord
     # &lt;tt&gt;person.respond_to?(:name=)&lt;/tt&gt;, and &lt;tt&gt;person.respond_to?(:name?)&lt;/tt&gt;
     # which will all return +true+.
     alias :respond_to_without_attributes? :respond_to?
-    def respond_to?(method, include_priv = false)
+    def respond_to?(method, include_private_methods = false)
       method_name = method.to_s
       if super
         return true
+      elsif !include_private_methods &amp;&amp; super(method, true)
+        # If we're here than we haven't found among non-private methods
+        # but found among all methods. Which means that given method is private.
+        return false
       elsif !self.class.generated_methods?
         self.class.define_attribute_methods
         if self.class.generated_methods.include?(method_name)</diff>
      <filename>vendor/rails/activerecord/lib/active_record/attribute_methods.rb</filename>
    </modified>
    <modified>
      <diff>@@ -415,6 +415,31 @@ module ActiveRecord #:nodoc:
 
     @@subclasses = {}
 
+    # Contains the database configuration - as is typically stored in config/database.yml -
+    # as a Hash.
+    #
+    # For example, the following database.yml...
+    # 
+    #   development:
+    #     adapter: sqlite3
+    #     database: db/development.sqlite3
+    #   
+    #   production:
+    #     adapter: sqlite3
+    #     database: db/production.sqlite3
+    #
+    # ...would result in ActiveRecord::Base.configurations to look like this:
+    #
+    #   {
+    #      'development' =&gt; {
+    #         'adapter'  =&gt; 'sqlite3',
+    #         'database' =&gt; 'db/development.sqlite3'
+    #      },
+    #      'production' =&gt; {
+    #         'adapter'  =&gt; 'sqlite3',
+    #         'database' =&gt; 'db/production.sqlite3'
+    #      }
+    #   }
     cattr_accessor :configurations, :instance_writer =&gt; false
     @@configurations = {}
 
@@ -487,7 +512,7 @@ module ActiveRecord #:nodoc:
       #
       # All approaches accept an options hash as their last parameter.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * &lt;tt&gt;:conditions&lt;/tt&gt; - An SQL fragment like &quot;administrator = 1&quot; or &lt;tt&gt;[ &quot;user_name = ?&quot;, username ]&lt;/tt&gt;. See conditions in the intro.
       # * &lt;tt&gt;:order&lt;/tt&gt; - An SQL fragment like &quot;created_at DESC, name&quot;.
@@ -585,8 +610,8 @@ module ActiveRecord #:nodoc:
 
       # Executes a custom SQL query against your database and returns all the results.  The results will
       # be returned as an array with columns requested encapsulated as attributes of the model you call
-      # this method from.  If you call +Product.find_by_sql+ then the results will be returned in a Product
-      # object with the attributes you specified in the SQL query.
+      # this method from.  If you call &lt;tt&gt;Product.find_by_sql&lt;/tt&gt; then the results will be returned in
+      # a Product object with the attributes you specified in the SQL query.
       #
       # If you call a complicated SQL query which spans multiple tables the columns specified by the
       # SELECT will be attributes of the model, whether or not they are columns of the corresponding
@@ -595,7 +620,7 @@ module ActiveRecord #:nodoc:
       # The +sql+ parameter is a full SQL query as a string.  It will be called as is, there will be
       # no database agnostic conversions performed.  This should be a last resort because using, for example,
       # MySQL specific terms will lock you to using that particular database engine or require you to
-      # change your call if you switch engines
+      # change your call if you switch engines.
       #
       # ==== Examples
       #   # A simple SQL query spanning multiple tables
@@ -672,7 +697,7 @@ module ActiveRecord #:nodoc:
       # Updates an object (or multiple objects) and saves it to the database, if validations pass.
       # The resulting object is returned whether the object was saved successfully to the database or not.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +id+ - This should be the id or an array of ids to be updated.
       # * +attributes+ - This should be a Hash of attributes to be set on the object, or an array of Hashes.
@@ -700,9 +725,10 @@ module ActiveRecord #:nodoc:
       # is executed on the database which means that no callbacks are fired off running this.  This is an efficient method
       # of deleting records that don't need cleaning up after or other actions to be taken.
       #
-      # Objects are _not_ instantiated with this method.
+      # Objects are _not_ instantiated with this method, and so +:dependent+ rules
+      # defined on associations are not honered.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +id+ - Can be either an Integer or an Array of Integers.
       #
@@ -725,7 +751,7 @@ module ActiveRecord #:nodoc:
       # This essentially finds the object (or multiple objects) with the given id, creates a new object
       # from the attributes, and then calls destroy on it.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +id+ - Can be either an Integer or an Array of Integers.
       #
@@ -749,7 +775,7 @@ module ActiveRecord #:nodoc:
       # also be supplied. This method constructs a single SQL UPDATE statement and sends it straight to the
       # database. It does not instantiate the involved models and it does not trigger Active Record callbacks.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +updates+ - A string of column and value pairs that will be set on any records that match conditions.
       #               What goes into the SET clause.
@@ -795,34 +821,39 @@ module ActiveRecord #:nodoc:
       # many records. If you want to simply delete records without worrying about dependent associations or
       # callbacks, use the much faster +delete_all+ method instead.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +conditions+ - Conditions are specified the same way as with +find+ method.
       #
       # ==== Example
       #
-      #   Person.destroy_all &quot;last_login &lt; '2004-04-04'&quot;
+      #   Person.destroy_all(&quot;last_login &lt; '2004-04-04'&quot;)
       #
       # This loads and destroys each person one by one, including its dependent associations and before_ and
       # after_destroy callbacks.
+      #
+      # +conditions+ can be anything that +find+ also accepts:
+      #
+      #   Person.destroy_all(:last_login =&gt; 6.hours.ago)
       def destroy_all(conditions = nil)
         find(:all, :conditions =&gt; conditions).each { |object| object.destroy }
       end
 
       # Deletes the records matching +conditions+ without instantiating the records first, and hence not
       # calling the +destroy+ method nor invoking callbacks. This is a single SQL DELETE statement that
-      # goes straight to the database, much more efficient than +destroy_all+. Careful with relations
-      # though, in particular &lt;tt&gt;:dependent&lt;/tt&gt; is not taken into account.
+      # goes straight to the database, much more efficient than +destroy_all+. Be careful with relations
+      # though, in particular &lt;tt&gt;:dependent&lt;/tt&gt; rules defined on associations are not honored.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +conditions+ - Conditions are specified the same way as with +find+ method.
       #
       # ==== Example
       #
-      #   Post.delete_all &quot;person_id = 5 AND (category = 'Something' OR category = 'Else')&quot;
+      #   Post.delete_all(&quot;person_id = 5 AND (category = 'Something' OR category = 'Else')&quot;)
+      #   Post.delete_all([&quot;person_id = ? AND (category = ? OR category = ?)&quot;, 5, 'Something', 'Else'])
       #
-      # This deletes the affected posts all at once with a single DELETE statement. If you need to destroy dependent
+      # Both calls delete the affected posts all at once with a single DELETE statement. If you need to destroy dependent
       # associations or call your &lt;tt&gt;before_*&lt;/tt&gt; or +after_destroy+ callbacks, use the +destroy_all+ method instead.
       def delete_all(conditions = nil)
         sql = &quot;DELETE FROM #{quoted_table_name} &quot;
@@ -834,7 +865,7 @@ module ActiveRecord #:nodoc:
       # The use of this method should be restricted to complicated SQL queries that can't be executed
       # using the ActiveRecord::Calculations class methods.  Look into those before using this.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +sql+ - An SQL statement which should return a count query from the database, see the example below.
       #
@@ -852,7 +883,7 @@ module ActiveRecord #:nodoc:
       # with the given ID, altering the given hash of counters by the amount
       # given by the corresponding value:
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +id+ - The id of the object you wish to update a counter on.
       # * +counters+ - An Array of Hashes containing the names of the fields
@@ -882,7 +913,7 @@ module ActiveRecord #:nodoc:
       # For example, a DiscussionBoard may cache post_count and comment_count otherwise every time the board is
       # shown it would have to run an SQL query to find how many posts and comments there are.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +counter_name+ - The name of the field that should be incremented.
       # * +id+ - The id of the object that should be incremented.
@@ -899,7 +930,7 @@ module ActiveRecord #:nodoc:
       #
       # This works the same as increment_counter but reduces the column value by 1 instead of increasing it.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +counter_name+ - The name of the field that should be decremented.
       # * +id+ - The id of the object that should be decremented.
@@ -994,7 +1025,7 @@ module ActiveRecord #:nodoc:
       # The serialization is done through YAML. If +class_name+ is specified, the serialized object must be of that
       # class on retrieval or SerializationTypeMismatch will be raised.
       #
-      # ==== Attributes
+      # ==== Parameters
       #
       # * +attr_name+ - The field name that should be serialized.
       # * +class_name+ - Optional, class name that the object type should be equal to.
@@ -1221,7 +1252,32 @@ module ActiveRecord #:nodoc:
         end
       end
 
-      # Resets all the cached information about columns, which will cause them to be reloaded on the next request.
+      # Resets all the cached information about columns, which will cause them
+      # to be reloaded on the next request.
+      #
+      # The most common usage pattern for this method is probably in a migration,
+      # when just after creating a table you want to populate it with some default
+      # values, eg:
+      #
+      #  class CreateJobLevels &lt; ActiveRecord::Migration
+      #    def self.up
+      #      create_table :job_levels do |t|
+      #        t.integer :id
+      #        t.string :name
+      #
+      #        t.timestamps
+      #      end
+      #
+      #      JobLevel.reset_column_information
+      #      %w{assistant executive manager director}.each do |type|
+      #        JobLevel.create(:name =&gt; type)
+      #      end
+      #    end
+      #
+      #    def self.down
+      #      drop_table :job_levels
+      #    end
+      #  end
       def reset_column_information
         generated_methods.each { |name| undef_method(name) }
         @column_names = @columns = @columns_hash = @content_columns = @dynamic_methods_hash = @generated_methods = @inheritance_column = nil
@@ -1576,19 +1632,19 @@ module ActiveRecord #:nodoc:
          (safe_to_array(first) + safe_to_array(second)).uniq
         end
 
-        def merge_joins(first, second)
-          if first.is_a?(String) &amp;&amp; second.is_a?(String)
-            &quot;#{first} #{second}&quot;
-          elsif first.is_a?(String) || second.is_a?(String)
-            if first.is_a?(String)
-              join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, second, nil)
-              &quot;#{first} #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join}&quot;
-            else
-              join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, first, nil)
-              &quot;#{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} #{second}&quot;
+        def merge_joins(*joins)
+          if joins.any?{|j| j.is_a?(String) || array_of_strings?(j) }
+            joins = joins.collect do |join|
+              join = [join] if join.is_a?(String)
+              unless array_of_strings?(join)
+                join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, join, nil)
+                join = join_dependency.join_associations.collect { |assoc| assoc.association_join }
+              end
+              join
             end
+            joins.flatten.uniq
           else
-            (safe_to_array(first) + safe_to_array(second)).uniq
+            joins.collect{|j| safe_to_array(j)}.flatten.uniq
           end
         end
 
@@ -1604,6 +1660,10 @@ module ActiveRecord #:nodoc:
           end
         end
 
+        def array_of_strings?(o)
+          o.is_a?(Array) &amp;&amp; o.all?{|obj| obj.is_a?(String)}
+        end
+
         def add_order!(sql, order, scope = :auto)
           scope = scope(:find) if :auto == scope
           scoped_order = scope[:order] if scope
@@ -1652,8 +1712,12 @@ module ActiveRecord #:nodoc:
           merged_joins = scope &amp;&amp; scope[:joins] &amp;&amp; joins ? merge_joins(scope[:joins], joins) : (joins || scope &amp;&amp; scope[:joins])
           case merged_joins
           when Symbol, Hash, Array
-            join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, merged_joins, nil)
-            sql &lt;&lt; &quot; #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} &quot;
+            if array_of_strings?(merged_joins)
+              sql &lt;&lt; merged_joins.join(' ') + &quot; &quot;
+            else
+              join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, merged_joins, nil)
+              sql &lt;&lt; &quot; #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} &quot;
+            end
           when String
             sql &lt;&lt; &quot; #{merged_joins} &quot;
           end
@@ -1716,10 +1780,10 @@ module ActiveRecord #:nodoc:
 
                   #{'result = ' if bang}if options[:conditions]
                     with_scope(:find =&gt; finder_options) do
-                      ActiveSupport::Deprecation.silence { send(:#{finder}, options) }
+                      find(:#{finder}, options)
                     end
                   else
-                    ActiveSupport::Deprecation.silence { send(:#{finder}, options.merge(finder_options)) }
+                    find(:#{finder}, options.merge(finder_options))
                   end
                   #{'result || raise(RecordNotFound)' if bang}
                 end
@@ -1742,9 +1806,9 @@ module ActiveRecord #:nodoc:
                   options = { :conditions =&gt; find_attributes }
                   set_readonly_option!(options)
 
-                  record = find_initial(options)
+                  record = find(:first, options)
 
-                   if record.nil?
+                  if record.nil?
                     record = self.new { |r| r.send(:attributes=, attributes, guard_protected_attributes) }
                     #{'yield(record) if block_given?'}
                     #{'record.save' if instantiator == :create}
@@ -1877,6 +1941,9 @@ module ActiveRecord #:nodoc:
         #       end
         #     end
         #   end
+        #
+        # *Note*: the +:find+ scope also has effect on update and deletion methods,
+        # like +update_all+ and +delete_all+.
         def with_scope(method_scoping = {}, action = :merge, &amp;block)
           method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping)
 
@@ -2224,7 +2291,28 @@ module ActiveRecord #:nodoc:
 
       end
 
-      # Enables Active Record objects to be used as URL parameters in Action Pack automatically.
+      # Returns a String, which Action Pack uses for constructing an URL to this
+      # object. The default implementation returns this record's id as a String,
+      # or nil if this record's unsaved.
+      #
+      # For example, suppose that you have a Users model, and that you have a
+      # &lt;tt&gt;map.resources :users&lt;/tt&gt; route. Normally, +users_path+ will
+      # construct an URI with the user object's 'id' in it:
+      #
+      #   user = User.find_by_name('Phusion')
+      #   user_path(path)  # =&gt; &quot;/users/1&quot;
+      #
+      # You can override +to_param+ in your model to make +users_path+ construct
+      # an URI using the user's name instead of the user's id:
+      #
+      #   class User &lt; ActiveRecord::Base
+      #     def to_param  # overridden
+      #       name
+      #     end
+      #   end
+      #   
+      #   user = User.find_by_name('Phusion')
+      #   user_path(path)  # =&gt; &quot;/users/Phusion&quot;
       def to_param
         # We can't use alias_method here, because method 'id' optimizes itself on the fly.
         (id = self.id) ? id.to_s : nil # Be sure to stringify the id for routes
@@ -2306,6 +2394,19 @@ module ActiveRecord #:nodoc:
 
       # Deletes the record in the database and freezes this instance to reflect that no changes should
       # be made (since they can't be persisted).
+      #
+      # Unlike #destroy, this method doesn't run any +before_delete+ and +after_delete+
+      # callbacks, nor will it enforce any association +:dependent+ rules.
+      # 
+      # In addition to deleting this record, any defined +before_delete+ and +after_delete+
+      # callbacks are run, and +:dependent+ rules defined on associations are run.
+      def delete
+        self.class.delete(id) unless new_record?
+        freeze
+      end
+
+      # Deletes the record in the database and freezes this instance to reflect that no changes should
+      # be made (since they can't be persisted).
       def destroy
         unless new_record?
           connection.delete &lt;&lt;-end_sql, &quot;#{self.class.name} Destroy&quot;
@@ -2443,10 +2544,25 @@ module ActiveRecord #:nodoc:
       end
 
       # Allows you to set all the attributes at once by passing in a hash with keys
-      # matching the attribute names (which again matches the column names). Sensitive attributes can be protected
-      # from this form of mass-assignment by using the +attr_protected+ macro. Or you can alternatively
-      # specify which attributes *can* be accessed with the +attr_accessible+ macro. Then all the
+      # matching the attribute names (which again matches the column names).
+      #
+      # If +guard_protected_attributes+ is true (the default), then sensitive
+      # attributes can be protected from this form of mass-assignment by using
+      # the +attr_protected+ macro. Or you can alternatively specify which
+      # attributes *can* be accessed with the +attr_accessible+ macro. Then all the
       # attributes not included in that won't be allowed to be mass-assigned.
+      #
+      #   class User &lt; ActiveRecord::Base
+      #     attr_protected :is_admin
+      #   end
+      #   
+      #   user = User.new
+      #   user.attributes = { :username =&gt; 'Phusion', :is_admin =&gt; true }
+      #   user.username   # =&gt; &quot;Phusion&quot;
+      #   user.is_admin?  # =&gt; false
+      #   
+      #   user.send(:attributes=, { :username =&gt; 'Phusion', :is_admin =&gt; true }, false)
+      #   user.is_admin?  # =&gt; true
       def attributes=(new_attributes, guard_protected_attributes = true)
         return if new_attributes.nil?
         attributes = new_attributes.dup</diff>
      <filename>vendor/rails/activerecord/lib/active_record/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -217,7 +217,7 @@ module ActiveRecord
 
           sql &lt;&lt; &quot; ORDER BY #{options[:order]} &quot;       if options[:order]
           add_limit!(sql, options, scope)
-          sql &lt;&lt; &quot;) AS #{aggregate_alias}_subquery&quot; if use_workaround
+          sql &lt;&lt; &quot;) #{aggregate_alias}_subquery&quot; if use_workaround
           sql
         end
 
@@ -285,11 +285,15 @@ module ActiveRecord
           operation = operation.to_s.downcase
           case operation
             when 'count' then value.to_i
-            when 'sum'   then value =~ /\./ ? value.to_f : value.to_i
-            when 'avg'   then value &amp;&amp; value.to_f
-            else column ? column.type_cast(value) : value
+            when 'sum'   then type_cast_using_column(value || '0', column)
+            when 'avg'   then value &amp;&amp; value.to_d
+            else type_cast_using_column(value, column)
           end
         end
+
+        def type_cast_using_column(value, column)
+          column ? column.type_cast(value) : value
+        end
     end
   end
 end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/calculations.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,6 +11,21 @@ module ActiveRecord
     # Connection pool base class for managing ActiveRecord database
     # connections.
     #
+    # == Introduction
+    #
+    # A connection pool synchronizes thread access to a limited number of
+    # database connections. The basic idea is that each thread checks out a
+    # database connection from the pool, uses that connection, and checks the
+    # connection back in. ConnectionPool is completely thread-safe, and will
+    # ensure that a connection cannot be used by two threads at the same time,
+    # as long as ConnectionPool's contract is correctly followed. It will also
+    # handle cases in which there are more threads than connections: if all
+    # connections have been checked out, and a thread tries to checkout a
+    # connection anyway, then ConnectionPool will wait until some other thread
+    # has checked in a connection.
+    #
+    # == Obtaining (checking out) a connection
+    #
     # Connections can be obtained and used from a connection pool in several
     # ways:
     #
@@ -28,6 +43,11 @@ module ActiveRecord
     #    obtains a connection, yields it as the sole argument to the block,
     #    and returns it to the pool after the block completes.
     #
+    # Connections in the pool are actually AbstractAdapter objects (or objects
+    # compatible with AbstractAdapter's interface).
+    #
+    # == Options
+    #
     # There are two connection-pooling-related options that you can add to
     # your database connection configuration:
     #
@@ -37,6 +57,12 @@ module ActiveRecord
     class ConnectionPool
       attr_reader :spec
 
+      # Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
+      # object which describes database connection information (e.g. adapter,
+      # host name, username, password, etc), as well as the maximum size for
+      # this ConnectionPool.
+      #
+      # The default ConnectionPool maximum size is 5.
       def initialize(spec)
         @spec = spec
         # The cache of reserved connections mapped to threads
@@ -87,7 +113,7 @@ module ActiveRecord
         !@connections.empty?
       end
 
-      # Disconnect all connections in the pool.
+      # Disconnects all connections in the pool, and clears the pool.
       def disconnect!
         @reserved_connections.each do |name,conn|
           checkin conn
@@ -128,29 +154,51 @@ module ActiveRecord
         end
       end
 
-      # Check-out a database connection from the pool.
+      # Check-out a database connection from the pool, indicating that you want
+      # to use it. You should call #checkin when you no longer need this.
+      #
+      # This is done by either returning an existing connection, or by creating
+      # a new connection. If the maximum number of connections for this pool has
+      # already been reached, but the pool is empty (i.e. they're all being used),
+      # then this method will wait until a thread has checked in a connection.
+      # The wait time is bounded however: if no connection can be checked out
+      # within the timeout specified for this pool, then a ConnectionTimeoutError
+      # exception will be raised.
+      #
+      # Returns: an AbstractAdapter object.
+      #
+      # Raises:
+      # - ConnectionTimeoutError: no connection can be obtained from the pool
+      #   within the timeout period.
       def checkout
         # Checkout an available connection
-        conn = @connection_mutex.synchronize do
-          if @checked_out.size &lt; @connections.size
-            checkout_existing_connection
-          elsif @connections.size &lt; @size
-            checkout_new_connection
-          end
-        end
-        return conn if conn
-
-        # No connections available; wait for one
         @connection_mutex.synchronize do
-          if @queue.wait(@timeout)
-            checkout_existing_connection
-          else
-            raise ConnectionTimeoutError, &quot;could not obtain a database connection within #{@timeout} seconds.  The pool size is currently #{@size}, perhaps you need to increase it?&quot;
+          loop do
+            conn = if @checked_out.size &lt; @connections.size
+                     checkout_existing_connection
+                   elsif @connections.size &lt; @size
+                     checkout_new_connection
+                   end
+            return conn if conn
+            # No connections available; wait for one
+            if @queue.wait(@timeout)
+              next
+            else
+              # try looting dead threads
+              clear_stale_cached_connections!
+              if @size == @checked_out.size
+                raise ConnectionTimeoutError, &quot;could not obtain a database connection within #{@timeout} seconds.  The pool size is currently #{@size}, perhaps you need to increase it?&quot;
+              end
+            end
           end
         end
       end
 
-      # Check-in a database connection back into the pool.
+      # Check-in a database connection back into the pool, indicating that you
+      # no longer need this connection.
+      #
+      # +conn+: an AbstractAdapter object, which was obtained by earlier by
+      # calling +checkout+ on this pool.
       def checkin(conn)
         @connection_mutex.synchronize do
           conn.run_callbacks :checkin
@@ -204,6 +252,29 @@ module ActiveRecord
       end
     end
 
+    # ConnectionHandler is a collection of ConnectionPool objects. It is used
+    # for keeping separate connection pools for ActiveRecord models that connect
+    # to different databases.
+    #
+    # For example, suppose that you have 5 models, with the following hierarchy:
+    #
+    #  |
+    #  +-- Book
+    #  |    |
+    #  |    +-- ScaryBook
+    #  |    +-- GoodBook
+    #  +-- Author
+    #  +-- BankAccount
+    #
+    # Suppose that Book is to connect to a separate database (i.e. one other
+    # than the default database). Then Book, ScaryBook and GoodBook will all use
+    # the same connection pool. Likewise, Author and BankAccount will use the
+    # same connection pool. However, the connection pool used by Author/BankAccount
+    # is not the same as the one used by Book/ScaryBook/GoodBook.
+    #
+    # Normally there is only a single ConnectionHandler instance, accessible via
+    # ActiveRecord::Base.connection_handler. ActiveRecord models use this to
+    # determine that connection pool that they should use.
     class ConnectionHandler
       def initialize(pools = {})
         @connection_pools = pools
@@ -275,4 +346,4 @@ module ActiveRecord
       end
     end
   end
-end
\ No newline at end of file
+end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb</filename>
    </modified>
    <modified>
      <diff>@@ -98,8 +98,14 @@ module ActiveRecord
         add_limit_offset!(sql, options) if options
       end
 
-      # Appends +LIMIT+ and +OFFSET+ options to an SQL statement.
+      # Appends +LIMIT+ and +OFFSET+ options to an SQL statement, or some SQL
+      # fragment that has the same semantics as LIMIT and OFFSET.
+      #
+      # +options+ must be a Hash which contains a +:limit+ option (required)
+      # and an +:offset+ option (optional).
+      #
       # This method *modifies* the +sql+ parameter.
+      #
       # ===== Examples
       #  add_limit_offset!('SELECT * FROM suppliers', {:limit =&gt; 10, :offset =&gt; 50})
       # generates
@@ -114,10 +120,6 @@ module ActiveRecord
         sql
       end
 
-      def sanitize_limit(limit)
-        limit.to_s[/,/] ? limit.split(',').map{ |i| i.to_i }.join(',') : limit.to_i
-      end
-
       # Appends a locking clause to an SQL statement.
       # This method *modifies* the +sql+ parameter.
       #   # SELECT * FROM suppliers FOR UPDATE
@@ -179,6 +181,21 @@ module ActiveRecord
         def delete_sql(sql, name = nil)
           update_sql(sql, name)
         end
+
+        # Sanitizes the given LIMIT parameter in order to prevent SQL injection.
+        #
+        # +limit+ may be anything that can evaluate to a string via #to_s. It
+        # should look like an integer, or a comma-delimited list of integers.
+        #
+        # Returns the sanitized limit parameter, either as an integer, or as a
+        # string which contains a comma-delimited list of integers.
+        def sanitize_limit(limit)
+          if limit.to_s =~ /,/
+            limit.to_s.split(',').map{ |i| i.to_i }.join(',')
+          else
+            limit.to_i
+          end
+        end
     end
   end
 end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb</filename>
    </modified>
    <modified>
      <diff>@@ -31,19 +31,25 @@ module ActiveRecord
       # See the concrete implementation for details on the expected parameter values.
       def columns(table_name, name = nil) end
 
-      # Creates a new table
+      # Creates a new table with the name +table_name+. +table_name+ may either
+      # be a String or a Symbol.
+      #
       # There are two ways to work with +create_table+.  You can use the block
       # form or the regular form, like this:
       #
       # === Block form
-      #  # create_table() yields a TableDefinition instance
+      #  # create_table() passes a TableDefinition object to the block.
+      #  # This form will not only create the table, but also columns for the
+      #  # table.
       #  create_table(:suppliers) do |t|
       #    t.column :name, :string, :limit =&gt; 60
       #    # Other fields here
       #  end
       #
       # === Regular form
+      #  # Creates a table called 'suppliers' with no columns.
       #  create_table(:suppliers)
+      #  # Add a column to 'suppliers'.
       #  add_column(:suppliers, :name, :string, {:limit =&gt; 60})
       #
       # The +options+ hash can include the following keys:</diff>
      <filename>vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,15 +13,19 @@ require 'active_record/connection_adapters/abstract/query_cache'
 
 module ActiveRecord
   module ConnectionAdapters # :nodoc:
+    # ActiveRecord supports multiple database systems. AbstractAdapter and
+    # related classes form the abstraction layer which makes this possible.
+    # An AbstractAdapter represents a connection to a database, and provides an
+    # abstract interface for database-specific functionality such as establishing
+    # a connection, escaping values, building the right SQL fragments for ':offset'
+    # and ':limit' options, etc.
+    #
     # All the concrete database adapters follow the interface laid down in this class.
-    # You can use this interface directly by borrowing the database connection from the Base with
-    # Base.connection.
+    # ActiveRecord::Base.connection returns an AbstractAdapter object, which
+    # you can use.
     #
-    # Most of the methods in the adapter are useful during migrations.  Most
-    # notably, SchemaStatements#create_table, SchemaStatements#drop_table,
-    # SchemaStatements#add_index, SchemaStatements#remove_index,
-    # SchemaStatements#add_column, SchemaStatements#change_column and
-    # SchemaStatements#remove_column are very useful.
+    # Most of the methods in the adapter are useful during migrations. Most
+    # notably, the instance methods provided by SchemaStatement are very useful.
     class AbstractAdapter
       include Quoting, DatabaseStatements, SchemaStatements
       include QueryCache
@@ -91,26 +95,31 @@ module ActiveRecord
 
       # CONNECTION MANAGEMENT ====================================
 
-      # Is this connection active and ready to perform queries?
+      # Checks whether the connection to the database is still active. This includes
+      # checking whether the database is actually capable of responding, i.e. whether
+      # the connection isn't stale.
       def active?
         @active != false
       end
 
-      # Close this connection and open a new one in its place.
+      # Disconnects from the database if already connected, and establishes a
+      # new connection with the database.
       def reconnect!
         @active = true
       end
 
-      # Close this connection
+      # Disconnects from the database if already connected. Otherwise, this
+      # method does nothing.
       def disconnect!
         @active = false
       end
 
       # Reset the state of this connection, directing the DBMS to clear
       # transactions and other connection-related server-side state. Usually a
-      # database-dependent operation; the default method simply executes a
-      # ROLLBACK and swallows any exceptions which is probably not enough to
-      # ensure the connection is clean.
+      # database-dependent operation.
+      #
+      # The default implementation does nothing; the implementation should be
+      # overridden by concrete adapters.
       def reset!
         # this should be overridden by concrete adapters
       end
@@ -121,15 +130,19 @@ module ActiveRecord
         false
       end
 
-      # Verify this connection by calling &lt;tt&gt;active?&lt;/tt&gt; and reconnecting if
-      # the connection is no longer active.
+      # Checks whether the connection to the database is still active (i.e. not stale).
+      # This is done under the hood by calling &lt;tt&gt;active?&lt;/tt&gt;. If the connection
+      # is no longer active, then this method will reconnect to the database.
       def verify!(*ignored)
         reconnect! unless active?
       end
 
-      # Provides access to the underlying database connection. Useful for
-      # when you need to call a proprietary method such as postgresql's lo_*
-      # methods
+      # Provides access to the underlying database driver for this adapter. For
+      # example, this method returns a Mysql object in case of MysqlAdapter,
+      # and a PGconn object in case of PostgreSQLAdapter.
+      #
+      # This is useful for when you need to call a proprietary method such as
+      # PostgreSQL's lo_* methods.
       def raw_connection
         @connection
       end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -218,7 +218,7 @@ module ActiveRecord
           s = column.class.string_to_binary(value).unpack(&quot;H*&quot;)[0]
           &quot;x'#{s}'&quot;
         elsif value.kind_of?(BigDecimal)
-          &quot;'#{value.to_s(&quot;F&quot;)}'&quot;
+          value.to_s(&quot;F&quot;)
         else
           super
         end
@@ -371,9 +371,9 @@ module ActiveRecord
         end
       end
 
-      def recreate_database(name) #:nodoc:
+      def recreate_database(name, options = {}) #:nodoc:
         drop_database(name)
-        create_database(name)
+        create_database(name, options)
       end
 
       # Create a new MySQL database with optional &lt;tt&gt;:charset&lt;/tt&gt; and &lt;tt&gt;:collation&lt;/tt&gt;.</diff>
      <filename>vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,11 +6,11 @@ module ActiveRecord
     end
 
     def initialize(method)
-      @finder = :find_initial
+      @finder = :first
       case method.to_s
       when /^find_(all_by|last_by|by)_([_a-zA-Z]\w*)$/
-        @finder = :find_last if $1 == 'last_by'
-        @finder = :find_every if $1 == 'all_by'
+        @finder = :last if $1 == 'last_by'
+        @finder = :all if $1 == 'all_by'
         names = $2
       when /^find_by_([_a-zA-Z]\w*)\!$/
         @bang = true
@@ -31,7 +31,7 @@ module ActiveRecord
     end
 
     def instantiator?
-      @finder == :find_initial &amp;&amp; !@instantiator.nil?
+      @finder == :first &amp;&amp; !@instantiator.nil?
     end
 
     def bang?</diff>
      <filename>vendor/rails/activerecord/lib/active_record/dynamic_finder_match.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,14 +13,15 @@ module ActiveRecord
       def create_reflection(macro, name, options, active_record)
         case macro
           when :has_many, :belongs_to, :has_one, :has_and_belongs_to_many
-            reflection = AssociationReflection.new(macro, name, options, active_record)
+            klass = options[:through] ? ThroughReflection : AssociationReflection
+            reflection = klass.new(macro, name, options, active_record)
           when :composed_of
             reflection = AggregateReflection.new(macro, name, options, active_record)
         end
         write_inheritable_hash :reflections, name =&gt; reflection
         reflection
       end
-      
+
       # Returns a hash containing all AssociationReflection objects for the current class
       # Example:
       #
@@ -30,7 +31,7 @@ module ActiveRecord
       def reflections
         read_inheritable_attribute(:reflections) || write_inheritable_attribute(:reflections, {})
       end
-       
+
       # Returns an array of AggregateReflection objects for all the aggregations in the class.
       def reflect_on_all_aggregations
         reflections.values.select { |reflection| reflection.is_a?(AggregateReflection) }
@@ -116,6 +117,11 @@ module ActiveRecord
         @sanitized_conditions ||= klass.send(:sanitize_sql, options[:conditions]) if options[:conditions]
       end
 
+      # Returns +true+ if +self+ is a +belongs_to+ reflection.
+      def belongs_to?
+        macro == :belongs_to
+      end
+
       private
         def derive_class_name
           name.to_s.camelize
@@ -192,6 +198,52 @@ module ActiveRecord
         end
       end
 
+      def check_validity!
+      end
+
+      def through_reflection
+        false
+      end
+
+      def through_reflection_primary_key_name
+      end
+
+      def source_reflection
+        nil
+      end
+
+      private
+        def derive_class_name
+          class_name = name.to_s.camelize
+          class_name = class_name.singularize if [ :has_many, :has_and_belongs_to_many ].include?(macro)
+          class_name
+        end
+
+        def derive_primary_key_name
+          if belongs_to?
+            &quot;#{name}_id&quot;
+          elsif options[:as]
+            &quot;#{options[:as]}_id&quot;
+          else
+            active_record.name.foreign_key
+          end
+        end
+    end
+
+    # Holds all the meta-data about a :through association as it was specified in the Active Record class.
+    class ThroughReflection &lt; AssociationReflection #:nodoc:
+      # Gets the source of the through reflection.  It checks both a singularized and pluralized form for &lt;tt&gt;:belongs_to&lt;/tt&gt; or &lt;tt&gt;:has_many&lt;/tt&gt;.
+      # (The &lt;tt&gt;:tags&lt;/tt&gt; association on Tagging below.)
+      #
+      #   class Post &lt; ActiveRecord::Base
+      #     has_many :taggings
+      #     has_many :tags, :through =&gt; :taggings
+      #   end
+      #
+      def source_reflection
+        @source_reflection ||= source_reflection_names.collect { |name| through_reflection.klass.reflect_on_association(name) }.compact.first
+      end
+
       # Returns the AssociationReflection object specified in the &lt;tt&gt;:through&lt;/tt&gt; option
       # of a HasManyThrough or HasOneThrough association. Example:
       #
@@ -204,7 +256,7 @@ module ActiveRecord
       #   taggings_reflection = tags_reflection.through_reflection
       #
       def through_reflection
-        @through_reflection ||= options[:through] ? active_record.reflect_on_association(options[:through]) : false
+        @through_reflection ||= active_record.reflect_on_association(options[:through])
       end
 
       # Gets an array of possible &lt;tt&gt;:through&lt;/tt&gt; source reflection names:
@@ -215,63 +267,40 @@ module ActiveRecord
         @source_reflection_names ||= (options[:source] ? [options[:source]] : [name.to_s.singularize, name]).collect { |n| n.to_sym }
       end
 
-      # Gets the source of the through reflection.  It checks both a singularized and pluralized form for &lt;tt&gt;:belongs_to&lt;/tt&gt; or &lt;tt&gt;:has_many&lt;/tt&gt;.
-      # (The &lt;tt&gt;:tags&lt;/tt&gt; association on Tagging below.)
-      # 
-      #   class Post &lt; ActiveRecord::Base
-      #     has_many :taggings
-      #     has_many :tags, :through =&gt; :taggings
-      #   end
-      #
-      def source_reflection
-        return nil unless through_reflection
-        @source_reflection ||= source_reflection_names.collect { |name| through_reflection.klass.reflect_on_association(name) }.compact.first
-      end
-
       def check_validity!
-        if options[:through]
-          if through_reflection.nil?
-            raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
-          end
-          
-          if source_reflection.nil?
-            raise HasManyThroughSourceAssociationNotFoundError.new(self)
-          end
+        if through_reflection.nil?
+          raise HasManyThroughAssociationNotFoundError.new(active_record.name, self)
+        end
 
-          if options[:source_type] &amp;&amp; source_reflection.options[:polymorphic].nil?
-            raise HasManyThroughAssociationPointlessSourceTypeError.new(active_record.name, self, source_reflection)
-          end
-          
-          if source_reflection.options[:polymorphic] &amp;&amp; options[:source_type].nil?
-            raise HasManyThroughAssociationPolymorphicError.new(active_record.name, self, source_reflection)
-          end
-          
-          unless [:belongs_to, :has_many].include?(source_reflection.macro) &amp;&amp; source_reflection.options[:through].nil?
-            raise HasManyThroughSourceAssociationMacroError.new(self)
-          end
+        if source_reflection.nil?
+          raise HasManyThroughSourceAssociationNotFoundError.new(self)
+        end
+
+        if options[:source_type] &amp;&amp; source_reflection.options[:polymorphic].nil?
+          raise HasManyThroughAssociationPointlessSourceTypeError.new(active_record.name, self, source_reflection)
         end
+
+        if source_reflection.options[:polymorphic] &amp;&amp; options[:source_type].nil?
+          raise HasManyThroughAssociationPolymorphicError.new(active_record.name, self, source_reflection)
+        end
+
+        unless [:belongs_to, :has_many].include?(source_reflection.macro) &amp;&amp; source_reflection.options[:through].nil?
+          raise HasManyThroughSourceAssociationMacroError.new(self)
+        end
+      end
+
+      def through_reflection_primary_key
+        through_reflection.belongs_to? ? through_reflection.klass.primary_key : through_reflection.primary_key_name
+      end
+
+      def through_reflection_primary_key_name
+        through_reflection.primary_key_name if through_reflection.belongs_to?
       end
 
       private
         def derive_class_name
           # get the class_name of the belongs_to association of the through reflection
-          if through_reflection
-            options[:source_type] || source_reflection.class_name
-          else
-            class_name = name.to_s.camelize
-            class_name = class_name.singularize if [ :has_many, :has_and_belongs_to_many ].include?(macro)
-            class_name
-          end
-        end
-
-        def derive_primary_key_name
-          if macro == :belongs_to
-            &quot;#{name}_id&quot;
-          elsif options[:as]
-            &quot;#{options[:as]}_id&quot;
-          else
-            active_record.name.foreign_key
-          end
+          options[:source_type] || source_reflection.class_name
         end
     end
   end</diff>
      <filename>vendor/rails/activerecord/lib/active_record/reflection.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,8 @@
 require 'thread'
 
 module ActiveRecord
-  module Transactions # :nodoc:
+  # See ActiveRecord::Transactions::ClassMethods for documentation.
+  module Transactions
     class TransactionError &lt; ActiveRecordError # :nodoc:
     end
 
@@ -15,26 +16,33 @@ module ActiveRecord
       end
     end
 
-    # Transactions are protective blocks where SQL statements are only permanent if they can all succeed as one atomic action.
-    # The classic example is a transfer between two accounts where you can only have a deposit if the withdrawal succeeded and
-    # vice versa. Transactions enforce the integrity of the database and guard the data against program errors or database break-downs.
-    # So basically you should use transaction blocks whenever you have a number of statements that must be executed together or
-    # not at all. Example:
+    # Transactions are protective blocks where SQL statements are only permanent
+    # if they can all succeed as one atomic action. The classic example is a
+    # transfer between two accounts where you can only have a deposit if the
+    # withdrawal succeeded and vice versa. Transactions enforce the integrity of
+    # the database and guard the data against program errors or database
+    # break-downs. So basically you should use transaction blocks whenever you
+    # have a number of statements that must be executed together or not at all.
+    # Example:
     #
-    #   transaction do
+    #   ActiveRecord::Base.transaction do
     #     david.withdrawal(100)
     #     mary.deposit(100)
     #   end
     #
-    # This example will only take money from David and give to Mary if neither +withdrawal+ nor +deposit+ raises an exception.
-    # Exceptions will force a ROLLBACK that returns the database to the state before the transaction was begun. Be aware, though,
-    # that the objects will _not_ have their instance data returned to their pre-transactional state.
+    # This example will only take money from David and give to Mary if neither
+    # +withdrawal+ nor +deposit+ raises an exception. Exceptions will force a
+    # ROLLBACK that returns the database to the state before the transaction was
+    # begun. Be aware, though, that the objects will _not_ have their instance
+    # data returned to their pre-transactional state.
     #
     # == Different Active Record classes in a single transaction
     #
     # Though the transaction class method is called on some Active Record class,
     # the objects within the transaction block need not all be instances of
-    # that class.
+    # that class. This is because transactions are per-database connection, not
+    # per-model.
+    #
     # In this example a &lt;tt&gt;Balance&lt;/tt&gt; record is transactionally saved even
     # though &lt;tt&gt;transaction&lt;/tt&gt; is called on the &lt;tt&gt;Account&lt;/tt&gt; class:
     #
@@ -43,6 +51,14 @@ module ActiveRecord
     #     account.save!
     #   end
     #
+    # Note that the +transaction+ method is also available as a model instance
+    # method. For example, you can also do this:
+    #
+    #   balance.transaction do
+    #     balance.save!
+    #     account.save!
+    #   end
+    #
     # == Transactions are not distributed across database connections
     #
     # A transaction acts on a single database connection.  If you have
@@ -62,17 +78,48 @@ module ActiveRecord
     #
     # == Save and destroy are automatically wrapped in a transaction
     #
-    # Both Base#save and Base#destroy come wrapped in a transaction that ensures that whatever you do in validations or callbacks
-    # will happen under the protected cover of a transaction. So you can use validations to check for values that the transaction
-    # depends on or you can raise exceptions in the callbacks to rollback, including &lt;tt&gt;after_*&lt;/tt&gt; callbacks.
+    # Both Base#save and Base#destroy come wrapped in a transaction that ensures
+    # that whatever you do in validations or callbacks will happen under the
+    # protected cover of a transaction. So you can use validations to check for
+    # values that the transaction depends on or you can raise exceptions in the
+    # callbacks to rollback, including &lt;tt&gt;after_*&lt;/tt&gt; callbacks.
     #
     # == Exception handling and rolling back
     #
-    # Also have in mind that exceptions thrown within a transaction block will be propagated (after triggering the ROLLBACK), so you
-    # should be ready to catch those in your application code.
+    # Also have in mind that exceptions thrown within a transaction block will
+    # be propagated (after triggering the ROLLBACK), so you should be ready to
+    # catch those in your application code.
     #
-    # One exception is the ActiveRecord::Rollback exception, which will trigger a ROLLBACK when raised,
-    # but not be re-raised by the transaction block.
+    # One exception is the ActiveRecord::Rollback exception, which will trigger
+    # a ROLLBACK when raised, but not be re-raised by the transaction block.
+    #
+    # *Warning*: one should not catch ActiveRecord::StatementInvalid exceptions
+    # inside a transaction block. StatementInvalid exceptions indicate that an
+    # error occurred at the database level, for example when a unique constraint
+    # is violated. On some database systems, such as PostgreSQL, database errors
+    # inside a transaction causes the entire transaction to become unusable
+    # until it's restarted from the beginning. Here is an example which
+    # demonstrates the problem:
+    #
+    #   # Suppose that we have a Number model with a unique column called 'i'.
+    #   Number.transaction do
+    #     Number.create(:i =&gt; 0)
+    #     begin
+    #       # This will raise a unique constraint error...
+    #       Number.create(:i =&gt; 0)
+    #     rescue ActiveRecord::StatementInvalid
+    #       # ...which we ignore.
+    #     end
+    #     
+    #     # On PostgreSQL, the transaction is now unusable. The following
+    #     # statement will cause a PostgreSQL error, even though the unique
+    #     # constraint is no longer violated:
+    #     Number.create(:i =&gt; 1)
+    #     # =&gt; &quot;PGError: ERROR:  current transaction is aborted, commands
+    #     #     ignored until end of transaction block&quot;
+    #   end
+    #
+    # One should restart the entire transaction if a StatementError occurred.
     module ClassMethods
       # See ActiveRecord::Transactions::ClassMethods for detailed documentation.
       def transaction(&amp;block)
@@ -86,6 +133,7 @@ module ActiveRecord
       end
     end
 
+    # See ActiveRecord::Transactions::ClassMethods for detailed documentation.
     def transaction(&amp;block)
       self.class.transaction(&amp;block)
     end
@@ -122,6 +170,9 @@ module ActiveRecord
     # Executes +method+ within a transaction and captures its return value as a
     # status flag. If the status is true the transaction is committed, otherwise
     # a ROLLBACK is issued. In any case the status flag is returned.
+    #
+    # This method is available within the context of an ActiveRecord::Base
+    # instance.
     def with_transaction_returning_status(method, *args)
       status = nil
       transaction do</diff>
      <filename>vendor/rails/activerecord/lib/active_record/transactions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -472,7 +472,7 @@ module ActiveRecord
 
         db_cols = begin
           column_names
-        rescue ActiveRecord::StatementInvalid
+        rescue Exception # To ignore both statement and connection errors
           []
         end
         names = attr_names.reject { |name| db_cols.include?(name.to_s) }
@@ -625,10 +625,6 @@ module ActiveRecord
       # When the record is created, a check is performed to make sure that no record exists in the database with the given value for the specified
       # attribute (that maps to a column). When the record is updated, the same check is made but disregarding the record itself.
       #
-      # Because this check is performed outside the database there is still a chance that duplicate values
-      # will be inserted in two parallel transactions.  To guarantee against this you should create a
-      # unique index on the field. See +add_index+ for more information.
-      #
       # Configuration options:
       # * &lt;tt&gt;:message&lt;/tt&gt; - Specifies a custom error message (default is: &quot;has already been taken&quot;).
       # * &lt;tt&gt;:scope&lt;/tt&gt; - One or more columns by which to limit the scope of the uniqueness constraint.
@@ -641,6 +637,70 @@ module ActiveRecord
       # * &lt;tt&gt;:unless&lt;/tt&gt; - Specifies a method, proc or string to call to determine if the validation should
       #   not occur (e.g. &lt;tt&gt;:unless =&gt; :skip_validation&lt;/tt&gt;, or &lt;tt&gt;:unless =&gt; Proc.new { |user| user.signup_step &lt;= 2 }&lt;/tt&gt;).  The
       #   method, proc or string should return or evaluate to a true or false value.
+      #
+      # === Concurrency and integrity
+      #
+      # Using this validation method in conjunction with ActiveRecord::Base#save
+      # does not guarantee the absence of duplicate record insertions, because
+      # uniqueness checks on the application level are inherently prone to race
+      # conditions. For example, suppose that two users try to post a Comment at
+      # the same time, and a Comment's title must be unique. At the database-level,
+      # the actions performed by these users could be interleaved in the following manner:
+      #
+      #               User 1                 |               User 2
+      #  ------------------------------------+--------------------------------------
+      #  # User 1 checks whether there's     |
+      #  # already a comment with the title  |
+      #  # 'My Post'. This is not the case.  |
+      #  SELECT * FROM comments              |
+      #  WHERE title = 'My Post'             |
+      #                                      |
+      #                                      | # User 2 does the same thing and also
+      #                                      | # infers that his title is unique.
+      #                                      | SELECT * FROM comments
+      #                                      | WHERE title = 'My Post'
+      #                                      |
+      #  # User 1 inserts his comment.       |
+      #  INSERT INTO comments                |
+      #  (title, content) VALUES             |
+      #  ('My Post', 'hi!')                  |
+      #                                      |
+      #                                      | # User 2 does the same thing.
+      #                                      | INSERT INTO comments
+      #                                      | (title, content) VALUES
+      #                                      | ('My Post', 'hello!')
+      #                                      |
+      #                                      | # ^^^^^^
+      #                                      | # Boom! We now have a duplicate
+      #                                      | # title!
+      #
+      # This could even happen if you use transactions with the 'serializable'
+      # isolation level. There are several ways to get around this problem:
+      # - By locking the database table before validating, and unlocking it after
+      #   saving. However, table locking is very expensive, and thus not
+      #   recommended.
+      # - By locking a lock file before validating, and unlocking it after saving.
+      #   This does not work if you've scaled your Rails application across
+      #   multiple web servers (because they cannot share lock files, or cannot
+      #   do that efficiently), and thus not recommended.
+      # - Creating a unique index on the field, by using
+      #   ActiveRecord::ConnectionAdapters::SchemaStatements#add_index. In the
+      #   rare case that a race condition occurs, the database will guarantee
+      #   the field's uniqueness.
+      #   
+      #   When the database catches such a duplicate insertion,
+      #   ActiveRecord::Base#save will raise an ActiveRecord::StatementInvalid
+      #   exception. You can either choose to let this error propagate (which
+      #   will result in the default Rails exception page being shown), or you
+      #   can catch it and restart the transaction (e.g. by telling the user
+      #   that the title already exists, and asking him to re-enter the title).
+      #   This technique is also known as optimistic concurrency control:
+      #   http://en.wikipedia.org/wiki/Optimistic_concurrency_control
+      #   
+      #   Active Record currently provides no way to distinguish unique
+      #   index constraint errors from other types of database errors, so you
+      #   will have to parse the (database-specific) exception message to detect
+      #   such a case.
       def validates_uniqueness_of(*attr_names)
         configuration = { :case_sensitive =&gt; true }
         configuration.update(attr_names.extract_options!)
@@ -678,7 +738,7 @@ module ActiveRecord
             condition_params = [value]
           else
             condition_sql = &quot;LOWER(#{sql_attribute}) #{comparison_operator}&quot;
-            condition_params = [value.chars.downcase]
+            condition_params = [value.mb_chars.downcase]
           end
 
           if scope = configuration[:scope]</diff>
      <filename>vendor/rails/activerecord/lib/active_record/validations.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 module ActiveRecord
   module VERSION #:nodoc:
     MAJOR = 2
-    MINOR = 1
+    MINOR = 2
     TINY  = 0
 
     STRING = [MAJOR, MINOR, TINY].join('.')</diff>
      <filename>vendor/rails/activerecord/lib/active_record/version.rb</filename>
    </modified>
    <modified>
      <diff>@@ -25,6 +25,11 @@ class ActiveSchemaTest &lt; ActiveRecord::TestCase
       assert_equal &quot;CREATE DATABASE `aimonetti` DEFAULT CHARACTER SET `latin1`&quot;, create_database(:aimonetti, {:charset =&gt; 'latin1'})
       assert_equal &quot;CREATE DATABASE `matt_aimonetti` DEFAULT CHARACTER SET `big5` COLLATE `big5_chinese_ci`&quot;, create_database(:matt_aimonetti, {:charset =&gt; :big5, :collation =&gt; :big5_chinese_ci})
     end
+
+    def test_recreate_mysql_database_with_encoding
+      create_database(:luca, {:charset =&gt; 'latin1'})
+      assert_equal &quot;CREATE DATABASE `luca` DEFAULT CHARACTER SET `latin1`&quot;, recreate_database(:luca, {:charset =&gt; 'latin1'})
+    end
   end
 
   def test_add_column</diff>
      <filename>vendor/rails/activerecord/test/cases/active_schema_test_mysql.rb</filename>
    </modified>
    <modified>
      <diff>@@ -47,19 +47,6 @@ class BelongsToAssociationsTest &lt; ActiveRecord::TestCase
     assert_equal apple.id, citibank.firm_id
   end
 
-  def test_foreign_key_assignment
-    # Test using an existing record
-    signals37 = accounts(:signals37)
-    assert_equal companies(:first_firm), signals37.firm
-    signals37.firm_id = companies(:another_firm).id
-    assert_equal companies(:another_firm), signals37.firm
-
-    # Test using a new record
-    account = Account.new
-    account.firm_id = companies(:another_firm).id
-    assert_equal companies(:another_firm), account.firm
-  end
-
   def test_no_unexpected_aliasing
     first_firm = companies(:first_firm)
     another_firm = companies(:another_firm)
@@ -441,4 +428,14 @@ class BelongsToAssociationsTest &lt; ActiveRecord::TestCase
     assert log.valid?
     assert log.save
   end
+
+  def test_belongs_to_proxy_should_not_respond_to_private_methods
+    assert_raises(NoMethodError) { companies(:first_firm).private_method }
+    assert_raises(NoMethodError) { companies(:second_client).firm.private_method }
+  end
+
+  def test_belongs_to_proxy_should_respond_to_private_methods_via_send
+    companies(:first_firm).send(:private_method)
+    companies(:second_client).firm.send(:private_method)
+  end
 end</diff>
      <filename>vendor/rails/activerecord/test/cases/associations/belongs_to_associations_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,7 +18,7 @@ require 'models/developer'
 require 'models/project'
 
 class EagerAssociationTest &lt; ActiveRecord::TestCase
-  fixtures :posts, :comments, :authors, :categories, :categories_posts,
+  fixtures :posts, :comments, :authors, :author_addresses, :categories, :categories_posts,
             :companies, :accounts, :tags, :taggings, :people, :readers,
             :owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books,
             :developers, :projects, :developers_projects
@@ -111,11 +111,58 @@ class EagerAssociationTest &lt; ActiveRecord::TestCase
     end
   end
 
+  def test_finding_with_includes_on_has_many_association_with_same_include_includes_only_once
+    author_id = authors(:david).id
+    author = assert_queries(3) { Author.find(author_id, :include =&gt; {:posts_with_comments =&gt; :comments}) } # find the author, then find the posts, then find the comments
+    author.posts_with_comments.each do |post_with_comments|
+      assert_equal post_with_comments.comments.length, post_with_comments.comments.count
+      assert_equal nil, post_with_comments.comments.uniq!
+    end
+  end
+
+  def test_finding_with_includes_on_has_one_assocation_with_same_include_includes_only_once
+    author = authors(:david)
+    post = author.post_about_thinking_with_last_comment
+    last_comment = post.last_comment
+    author = assert_queries(3) { Author.find(author.id, :include =&gt; {:post_about_thinking_with_last_comment =&gt; :last_comment})} # find the author, then find the posts, then find the comments
+    assert_no_queries do
+      assert_equal post, author.post_about_thinking_with_last_comment
+      assert_equal last_comment, author.post_about_thinking_with_last_comment.last_comment
+    end
+  end
+
+  def test_finding_with_includes_on_belongs_to_association_with_same_include_includes_only_once
+    post = posts(:welcome)
+    author = post.author
+    author_address = author.author_address
+    post = assert_queries(3) { Post.find(post.id, :include =&gt; {:author_with_address =&gt; :author_address}) } # find the post, then find the author, then find the address
+    assert_no_queries do
+      assert_equal author, post.author_with_address
+      assert_equal author_address, post.author_with_address.author_address
+    end
+  end
+
+  def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
+    post = posts(:welcome)
+    post.update_attributes!(:author =&gt; nil)
+    post = assert_queries(2) { Post.find(post.id, :include =&gt; {:author_with_address =&gt; :author_address}) } # find the post, then find the author which is null so no query for the address
+    assert_no_queries do
+      assert_equal nil, post.author_with_address
+    end
+  end
+
   def test_loading_from_an_association
     posts = authors(:david).posts.find(:all, :include =&gt; :comments, :order =&gt; &quot;posts.id&quot;)
     assert_equal 2, posts.first.comments.size
   end
 
+  def test_loading_from_an_association_that_has_a_hash_of_conditions
+    assert_nothing_raised do
+      Author.find(:all, :include =&gt; :hello_posts_with_hash_conditions)
+    end
+    assert !Author.find(authors(:david).id, :include =&gt; :hello_posts_with_hash_conditions).hello_posts.empty?
+  end
+
   def test_loading_with_no_associations
     assert_nil Post.find(posts(:authorless).id, :include =&gt; :author).author
   end
@@ -268,6 +315,15 @@ class EagerAssociationTest &lt; ActiveRecord::TestCase
     assert_equal authors(:david), assert_no_queries { posts_with_comments_and_author.first.author }
   end
 
+  def test_eager_with_has_many_through_a_belongs_to_association
+    author = authors(:mary)
+    post = Post.create!(:author =&gt; author, :title =&gt; &quot;TITLE&quot;, :body =&gt; &quot;BODY&quot;)
+    author.author_favorites.create(:favorite_author_id =&gt; 1)
+    author.author_favorites.create(:favorite_author_id =&gt; 2)
+    posts_with_author_favorites = author.posts.find(:all, :include =&gt; :author_favorites)
+    assert_no_queries { posts_with_author_favorites.first.author_favorites.first.author_id }
+  end
+
   def test_eager_with_has_many_through_an_sti_join_model
     author = Author.find(:first, :include =&gt; :special_post_comments, :order =&gt; 'authors.id')
     assert_equal [comments(:does_it_hurt)], assert_no_queries { author.special_post_comments }</diff>
      <filename>vendor/rails/activerecord/test/cases/associations/eager_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,7 @@ require 'models/post'
 require 'models/comment'
 require 'models/project'
 require 'models/developer'
+require 'models/company_in_module'
 
 class AssociationsExtensionsTest &lt; ActiveRecord::TestCase
   fixtures :projects, :developers, :developers_projects, :comments, :posts
@@ -44,4 +45,18 @@ class AssociationsExtensionsTest &lt; ActiveRecord::TestCase
     david = Marshal.load(Marshal.dump(david))
     assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
   end
+
+
+	def test_extension_name
+	  extension = Proc.new {}
+	  name = :association_name
+
+	  assert_equal 'DeveloperAssociationNameAssociationExtension', Developer.send(:create_extension_modules, name, extension, []).first.name
+	  assert_equal 'MyApplication::Business::DeveloperAssociationNameAssociationExtension',
+MyApplication::Business::Developer.send(:create_extension_modules, name, extension, []).first.name
+    assert_equal 'MyApplication::Business::DeveloperAssociationNameAssociationExtension', MyApplication::Business::Developer.send(:create_extension_modules, name, extension, []).first.name
+    assert_equal 'MyApplication::Business::DeveloperAssociationNameAssociationExtension', MyApplication::Business::Developer.send(:create_extension_modules, name, extension, []).first.name
+  end
+
+
 end</diff>
      <filename>vendor/rails/activerecord/test/cases/associations/extension_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -253,7 +253,7 @@ class HasAndBelongsToManyAssociationsTest &lt; ActiveRecord::TestCase
     assert !devel.projects.loaded?
 
     assert_equal devel.projects.last, proj
-    assert devel.projects.loaded?
+    assert !devel.projects.loaded?
 
     assert !proj.new_record?
     assert_equal Developer.find(1).projects.sort_by(&amp;:id).last, proj  # prove join table is updated
@@ -738,4 +738,13 @@ class HasAndBelongsToManyAssociationsTest &lt; ActiveRecord::TestCase
     # Array#count in Ruby &gt;=1.8.7, which would raise an ArgumentError
     assert_nothing_raised { david.projects.count(:all, :conditions =&gt; '1=1') }
   end
+
+  uses_mocha 'mocking Post.transaction' do
+    def test_association_proxy_transaction_method_starts_transaction_in_association_class
+      Post.expects(:transaction)
+      Category.find(:first).posts.transaction do
+        # nothing
+      end
+    end
+  end
 end</diff>
      <filename>vendor/rails/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1009,6 +1009,19 @@ class HasManyAssociationsTest &lt; ActiveRecord::TestCase
     assert firm.clients.loaded?
   end
 
+  def test_calling_first_or_last_on_existing_record_with_create_should_not_load_association
+    firm = companies(:first_firm)
+    firm.clients.create(:name =&gt; 'Foo')
+    assert !firm.clients.loaded?
+
+    assert_queries 2 do
+      firm.clients.first
+      firm.clients.last
+    end
+
+    assert !firm.clients.loaded?
+  end
+
   def test_calling_first_or_last_on_new_record_should_not_run_queries
     firm = Firm.new
 
@@ -1058,4 +1071,14 @@ class HasManyAssociationsTest &lt; ActiveRecord::TestCase
     ActiveRecord::Base.store_full_sti_class = old
   end
 
+  uses_mocha 'mocking Comment.transaction' do
+    def test_association_proxy_transaction_method_starts_transaction_in_association_class
+      Comment.expects(:transaction)
+      Post.find(:first).comments.transaction do
+        # nothing
+      end
+    end
+  end
+
 end
+</diff>
      <filename>vendor/rails/activerecord/test/cases/associations/has_many_associations_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@ require 'models/reader'
 require 'models/comment'
 
 class HasManyThroughAssociationsTest &lt; ActiveRecord::TestCase
-  fixtures :posts, :readers, :people, :comments
+  fixtures :posts, :readers, :people, :comments, :authors
 
   def test_associate_existing
     assert_queries(2) { posts(:thinking);people(:david) }
@@ -220,4 +220,28 @@ class HasManyThroughAssociationsTest &lt; ActiveRecord::TestCase
     assert_equal [posts(:welcome).id, posts(:authorless).id].sort, person.post_ids.sort
     assert !person.posts.loaded?
   end
+
+  uses_mocha 'mocking Tag.transaction' do
+    def test_association_proxy_transaction_method_starts_transaction_in_association_class
+      Tag.expects(:transaction)
+      Post.find(:first).tags.transaction do
+        # nothing
+      end
+    end
+  end
+
+  def test_has_many_association_through_a_belongs_to_association_where_the_association_doesnt_exist
+    author = authors(:mary)
+    post = Post.create!(:title =&gt; &quot;TITLE&quot;, :body =&gt; &quot;BODY&quot;)
+    assert_equal [], post.author_favorites
+  end
+
+  def test_has_many_association_through_a_belongs_to_association
+    author = authors(:mary)
+    post = Post.create!(:author =&gt; author, :title =&gt; &quot;TITLE&quot;, :body =&gt; &quot;BODY&quot;)
+    author.author_favorites.create(:favorite_author_id =&gt; 1)
+    author.author_favorites.create(:favorite_author_id =&gt; 2)
+    author.author_favorites.create(:favorite_author_id =&gt; 3)
+    assert_equal post.author.author_favorites, post.author_favorites
+  end
 end</diff>
      <filename>vendor/rails/activerecord/test/cases/associations/has_many_through_associations_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -349,4 +349,14 @@ class HasOneAssociationsTest &lt; ActiveRecord::TestCase
     assert companies(:first_firm).readonly_account.readonly?
   end
 
+  def test_has_one_proxy_should_not_respond_to_private_methods
+    assert_raises(NoMethodError) { accounts(:signals37).private_method }
+    assert_raises(NoMethodError) { companies(:first_firm).account.private_method }
+  end
+
+  def test_has_one_proxy_should_respond_to_private_methods_via_send
+    accounts(:signals37).send(:private_method)
+    companies(:first_firm).account.send(:private_method)
+  end
+
 end</diff>
      <filename>vendor/rails/activerecord/test/cases/associations/has_one_associations_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -110,4 +110,14 @@ class HasOneThroughAssociationsTest &lt; ActiveRecord::TestCase
     new_member.club = new_club = Club.create(:name =&gt; &quot;LRUG&quot;)
     assert_equal new_club, new_member.club.target
   end
+
+  def test_has_one_through_proxy_should_not_respond_to_private_methods
+    assert_raises(NoMethodError) { clubs(:moustache_club).private_method }
+    assert_raises(NoMethodError) { @member.club.private_method }
+  end
+
+  def test_has_one_through_proxy_should_respond_to_private_methods_via_send
+    clubs(:moustache_club).send(:private_method)
+    @member.club.send(:private_method)
+  end
 end</diff>
      <filename>vendor/rails/activerecord/test/cases/associations/has_one_through_associations_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -182,18 +182,6 @@ class AssociationProxyTest &lt; ActiveRecord::TestCase
     assert_nil p.author.reset
   end
 
-  def test_reset_loads_association_next_time
-    welcome = posts(:welcome)
-    david = authors(:david)
-    author_assoc = welcome.author
-
-    assert_equal david, welcome.author # So we can be sure the test works correctly
-    author_assoc.reset
-    assert !author_assoc.loaded?
-    assert_nil author_assoc.target
-    assert_equal david, welcome.author
-  end
-
   def test_reload_returns_assocition
     david = developers(:david)
     assert_nothing_raised do</diff>
      <filename>vendor/rails/activerecord/test/cases/associations_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -58,19 +58,19 @@ class AttributeMethodsTest &lt; ActiveRecord::TestCase
 
   def test_kernel_methods_not_implemented_in_activerecord
     %w(test name display y).each do |method|
-      assert_equal false, ActiveRecord::Base.instance_method_already_implemented?(method), &quot;##{method} is defined&quot;
+      assert !ActiveRecord::Base.instance_method_already_implemented?(method), &quot;##{method} is defined&quot;
     end
   end
 
   def test_primary_key_implemented
-    assert_equal true, Class.new(ActiveRecord::Base).instance_method_already_implemented?('id')
+    assert Class.new(ActiveRecord::Base).instance_method_already_implemented?('id')
   end
 
   def test_defined_kernel_methods_implemented_in_model
     %w(test name display y).each do |method|
       klass = Class.new ActiveRecord::Base
       klass.class_eval &quot;def #{method}() 'defined #{method}' end&quot;
-      assert_equal true, klass.instance_method_already_implemented?(method), &quot;##{method} is not defined&quot;
+      assert klass.instance_method_already_implemented?(method), &quot;##{method} is not defined&quot;
     end
   end
 
@@ -80,7 +80,7 @@ class AttributeMethodsTest &lt; ActiveRecord::TestCase
       abstract.class_eval &quot;def #{method}() 'defined #{method}' end&quot;
       abstract.abstract_class = true
       klass = Class.new abstract
-      assert_equal true, klass.instance_method_already_implemented?(method), &quot;##{method} is not defined&quot;
+      assert klass.instance_method_already_implemented?(method), &quot;##{method} is not defined&quot;
     end
   end
 
@@ -228,6 +228,40 @@ class AttributeMethodsTest &lt; ActiveRecord::TestCase
     assert_equal [:field_b], Minimalistic.skip_time_zone_conversion_for_attributes 
   end
 
+  def test_read_attributes_respect_access_control
+    privatize(&quot;title&quot;)
+
+    topic = @target.new(:title =&gt; &quot;The pros and cons of programming naked.&quot;)
+    assert !topic.respond_to?(:title)
+    assert_raise(NoMethodError) { topic.title }
+    topic.send(:title)
+  end
+
+  def test_write_attributes_respect_access_control
+    privatize(&quot;title=(value)&quot;)
+
+    topic = @target.new
+    assert !topic.respond_to?(:title=)
+    assert_raise(NoMethodError) { topic.title = &quot;Pants&quot;}
+    topic.send(:title=, &quot;Very large pants&quot;)
+  end
+
+  def test_question_attributes_respect_access_control
+    privatize(&quot;title?&quot;)
+
+    topic = @target.new(:title =&gt; &quot;Isaac Newton's pants&quot;)
+    assert !topic.respond_to?(:title?)
+    assert_raise(NoMethodError) { topic.title? }
+    assert topic.send(:title?)
+  end
+
+  def test_bulk_update_respects_access_control
+    privatize(&quot;title=(value)&quot;)
+
+    assert_raise(ActiveRecord::UnknownAttributeError) { topic = @target.new(:title =&gt; &quot;Rants about pants&quot;) }
+    assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title =&gt; &quot;Ants in pants&quot; } }
+  end
+
   private
   def time_related_columns_on_topic
     Topic.columns.select{|c| [:time, :date, :datetime, :timestamp].include?(c.type)}.map(&amp;:name)
@@ -244,4 +278,13 @@ class AttributeMethodsTest &lt; ActiveRecord::TestCase
     Time.zone = old_zone
     ActiveRecord::Base.time_zone_aware_attributes = old_tz
   end
+
+  def privatize(method_signature)
+    @target.class_eval &lt;&lt;-private_method
+      private
+      def #{method_signature}
+        &quot;I'm private&quot;
+      end
+    private_method
+  end
 end</diff>
      <filename>vendor/rails/activerecord/test/cases/attribute_methods_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -472,6 +472,18 @@ class BasicsTest &lt; ActiveRecord::TestCase
     assert topic.instance_variable_get(&quot;@custom_approved&quot;)
   end
 
+  def test_delete
+    topic = Topic.find(1)
+    assert_equal topic, topic.delete, 'topic.delete did not return self'
+    assert topic.frozen?, 'topic not frozen after delete'
+    assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
+  end
+
+  def test_delete_doesnt_run_callbacks
+    Topic.find(1).delete
+    assert_not_nil Topic.find(2)
+  end
+
   def test_destroy
     topic = Topic.find(1)
     assert_equal topic, topic.destroy, 'topic.destroy did not return self'
@@ -820,6 +832,20 @@ class BasicsTest &lt; ActiveRecord::TestCase
     assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] &amp; [ Topic.find(1) ]
   end
 
+  def test_delete_new_record
+    client = Client.new
+    client.delete
+    assert client.frozen?
+  end
+
+  def test_delete_record_with_associations
+    client = Client.find(3)
+    client.delete
+    assert client.frozen?
+    assert_kind_of Firm, client.firm
+    assert_raises(ActiveSupport::FrozenObjectError) { client.name = &quot;something else&quot; }
+  end
+
   def test_destroy_new_record
     client = Client.new
     client.destroy
@@ -1438,15 +1464,17 @@ class BasicsTest &lt; ActiveRecord::TestCase
 
   if RUBY_VERSION &lt; '1.9'
     def test_quote_chars
-      str = 'The Narrator'
-      topic = Topic.create(:author_name =&gt; str)
-      assert_equal str, topic.author_name
+      with_kcode('UTF8') do
+        str = 'The Narrator'
+        topic = Topic.create(:author_name =&gt; str)
+        assert_equal str, topic.author_name
 
-      assert_kind_of ActiveSupport::Multibyte::Chars, str.chars
-      topic = Topic.find_by_author_name(str.chars)
+        assert_kind_of ActiveSupport::Multibyte.proxy_class, str.mb_chars
+        topic = Topic.find_by_author_name(str.mb_chars)
 
-      assert_kind_of Topic, topic
-      assert_equal str, topic.author_name, &quot;The right topic should have been found by name even with name passed as Chars&quot;
+        assert_kind_of Topic, topic
+        assert_equal str, topic.author_name, &quot;The right topic should have been found by name even with name passed as Chars&quot;
+      end
     end
   end
 
@@ -2039,4 +2067,18 @@ class BasicsTest &lt; ActiveRecord::TestCase
   ensure
     ActiveRecord::Base.logger = original_logger
   end
+
+  private
+    def with_kcode(kcode)
+      if RUBY_VERSION &lt; '1.9'
+        orig_kcode, $KCODE = $KCODE, kcode
+        begin
+          yield
+        ensure
+          $KCODE = orig_kcode
+        end
+      else
+        yield
+      end
+    end
 end</diff>
      <filename>vendor/rails/activerecord/test/cases/base_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,8 +18,8 @@ class CalculationsTest &lt; ActiveRecord::TestCase
 
   def test_should_average_field
     value = Account.average(:credit_limit)
-    assert_kind_of Float, value
-    assert_in_delta 53.0, value, 0.001
+    assert_kind_of BigDecimal, value
+    assert_equal BigDecimal.new('53.0'), value
   end
 
   def test_should_return_nil_as_average
@@ -273,7 +273,7 @@ class CalculationsTest &lt; ActiveRecord::TestCase
   end
 
   def test_should_sum_expression
-    assert_equal 636, Account.sum(&quot;2 * credit_limit&quot;)
+    assert_equal '636', Account.sum(&quot;2 * credit_limit&quot;)
   end
 
   def test_count_with_from_option</diff>
      <filename>vendor/rails/activerecord/test/cases/calculations_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,7 +21,7 @@ class DynamicFinderMatchTest &lt; ActiveRecord::TestCase
     match = ActiveRecord::DynamicFinderMatch.match(&quot;find_by_age_and_sex_and_location&quot;)
     assert_not_nil match
     assert match.finder?
-    assert_equal :find_initial, match.finder
+    assert_equal :first, match.finder
     assert_equal %w(age sex location), match.attribute_names
   end
 
@@ -30,7 +30,7 @@ class DynamicFinderMatchTest &lt; ActiveRecord::TestCase
     assert_not_nil match
     assert match.finder?
     assert match.bang?
-    assert_equal :find_initial, match.finder
+    assert_equal :first, match.finder
     assert_equal %w(age sex location), match.attribute_names
   end
 
@@ -38,7 +38,7 @@ class DynamicFinderMatchTest &lt; ActiveRecord::TestCase
     match = ActiveRecord::DynamicFinderMatch.match(&quot;find_all_by_age_and_sex_and_location&quot;)
     assert_not_nil match
     assert match.finder?
-    assert_equal :find_every, match.finder
+    assert_equal :all, match.finder
     assert_equal %w(age sex location), match.attribute_names
   end
 
@@ -47,7 +47,7 @@ class DynamicFinderMatchTest &lt; ActiveRecord::TestCase
     assert_not_nil match
     assert !match.finder?
     assert match.instantiator?
-    assert_equal :find_initial, match.finder
+    assert_equal :first, match.finder
     assert_equal :new, match.instantiator
     assert_equal %w(age sex location), match.attribute_names
   end
@@ -57,7 +57,7 @@ class DynamicFinderMatchTest &lt; ActiveRecord::TestCase
     assert_not_nil match
     assert !match.finder?
     assert match.instantiator?
-    assert_equal :find_initial, match.finder
+    assert_equal :first, match.finder
     assert_equal :create, match.instantiator
     assert_equal %w(age sex location), match.attribute_names
   end
@@ -465,8 +465,8 @@ class FinderTest &lt; ActiveRecord::TestCase
     quoted_bambi_and_thumper = ActiveRecord::Base.connection.quote(&quot;Bambi\nand\nThumper&quot;)
     assert_equal &quot;name=#{quoted_bambi}&quot;, bind('name=?', &quot;Bambi&quot;)
     assert_equal &quot;name=#{quoted_bambi_and_thumper}&quot;, bind('name=?', &quot;Bambi\nand\nThumper&quot;)
-    assert_equal &quot;name=#{quoted_bambi}&quot;, bind('name=?', &quot;Bambi&quot;.chars)
-    assert_equal &quot;name=#{quoted_bambi_and_thumper}&quot;, bind('name=?', &quot;Bambi\nand\nThumper&quot;.chars)
+    assert_equal &quot;name=#{quoted_bambi}&quot;, bind('name=?', &quot;Bambi&quot;.mb_chars)
+    assert_equal &quot;name=#{quoted_bambi_and_thumper}&quot;, bind('name=?', &quot;Bambi\nand\nThumper&quot;.mb_chars)
   end
 
   def test_bind_record
@@ -500,6 +500,23 @@ class FinderTest &lt; ActiveRecord::TestCase
     assert_equal(2, Entrant.count_by_sql([&quot;SELECT COUNT(*) FROM entrants WHERE id &gt; ?&quot;, 1]))
   end
 
+  uses_mocha('test_dynamic_finder_should_go_through_the_find_class_method') do
+    def test_dynamic_finders_should_go_through_the_find_class_method
+      Topic.expects(:find).with(:first, :conditions =&gt; { :title =&gt; 'The First Topic!' })
+      Topic.find_by_title(&quot;The First Topic!&quot;)
+
+      Topic.expects(:find).with(:last, :conditions =&gt; { :title =&gt; 'The Last Topic!' })
+      Topic.find_last_by_title(&quot;The Last Topic!&quot;)
+
+      Topic.expects(:find).with(:all, :conditions =&gt; { :title =&gt; 'A Topic.' })
+      Topic.find_all_by_title(&quot;A Topic.&quot;)
+
+      Topic.expects(:find).with(:first, :conditions =&gt; { :title =&gt; 'Does not exist yet for sure!' }).times(2)
+      Topic.find_or_initialize_by_title('Does not exist yet for sure!')
+      Topic.find_or_create_by_title('Does not exist yet for sure!')
+    end
+  end
+
   def test_find_by_one_attribute
     assert_equal topics(:first), Topic.find_by_title(&quot;The First Topic&quot;)
     assert_nil Topic.find_by_title(&quot;The First Topic!&quot;)
@@ -935,6 +952,17 @@ class FinderTest &lt; ActiveRecord::TestCase
     assert_equal 1, first.id
   end
 
+  def test_joins_with_string_array
+    person_with_reader_and_post = Post.find(
+      :all,
+      :joins =&gt; [
+        &quot;INNER JOIN categorizations ON categorizations.post_id = posts.id&quot;,
+        &quot;INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'&quot;
+      ]
+    )
+    assert_equal 1, person_with_reader_and_post.size
+  end
+
   def test_find_by_id_with_conditions_with_or
     assert_nothing_raised do
       Post.find([1,2,3],</diff>
      <filename>vendor/rails/activerecord/test/cases/finder_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -138,6 +138,36 @@ class MethodScopingTest &lt; ActiveRecord::TestCase
     assert_equal authors(:david).attributes, scoped_authors.first.attributes
   end
 
+  def test_scoped_find_merges_string_array_style_and_string_style_joins
+    scoped_authors = Author.with_scope(:find =&gt; { :joins =&gt; [&quot;INNER JOIN posts ON posts.author_id = authors.id&quot;]}) do
+      Author.find(:all, :select =&gt; 'DISTINCT authors.*', :joins =&gt; 'INNER JOIN comments ON posts.id = comments.post_id', :conditions =&gt; 'comments.id = 1')
+    end
+    assert scoped_authors.include?(authors(:david))
+    assert !scoped_authors.include?(authors(:mary))
+    assert_equal 1, scoped_authors.size
+    assert_equal authors(:david).attributes, scoped_authors.first.attributes
+  end
+
+  def test_scoped_find_merges_string_array_style_and_hash_style_joins
+    scoped_authors = Author.with_scope(:find =&gt; { :joins =&gt; :posts}) do
+      Author.find(:all, :select =&gt; 'DISTINCT authors.*', :joins =&gt; ['INNER JOIN comments ON posts.id = comments.post_id'], :conditions =&gt; 'comments.id = 1')
+    end
+    assert scoped_authors.include?(authors(:david))
+    assert !scoped_authors.include?(authors(:mary))
+    assert_equal 1, scoped_authors.size
+    assert_equal authors(:david).attributes, scoped_authors.first.attributes
+  end
+
+  def test_scoped_find_merges_joins_and_eliminates_duplicate_string_joins
+    scoped_authors = Author.with_scope(:find =&gt; { :joins =&gt; 'INNER JOIN posts ON posts.author_id = authors.id'}) do
+      Author.find(:all, :select =&gt; 'DISTINCT authors.*', :joins =&gt; [&quot;INNER JOIN posts ON posts.author_id = authors.id&quot;, &quot;INNER JOIN comments ON posts.id = comments.post_id&quot;], :conditions =&gt; 'comments.id = 1')
+    end
+    assert scoped_authors.include?(authors(:david))
+    assert !scoped_authors.include?(authors(:mary))
+    assert_equal 1, scoped_authors.size
+    assert_equal authors(:david).attributes, scoped_authors.first.attributes
+  end
+
   def test_scoped_count_include
     # with the include, will retrieve only developers for the given project
     Developer.with_scope(:find =&gt; { :include =&gt; :projects }) do</diff>
      <filename>vendor/rails/activerecord/test/cases/method_scoping_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -271,4 +271,10 @@ class NamedScopeTest &lt; ActiveRecord::TestCase
       topics.size # use loaded (no query)
     end
   end
+
+  def test_chaining_with_duplicate_joins
+    join = &quot;INNER JOIN comments ON comments.post_id = posts.id&quot;
+    post = Post.find(1)
+    assert_equal post.comments.size, Post.scoped(:joins =&gt; join).scoped(:joins =&gt; join, :conditions =&gt; &quot;posts.id = #{post.id}&quot;).size
+  end
 end</diff>
      <filename>vendor/rails/activerecord/test/cases/named_scope_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -170,6 +170,10 @@ class ReflectionTest &lt; ActiveRecord::TestCase
     assert_nothing_raised { Firm.reflections[:clients] == Object.new }
   end
 
+  def test_has_many_through_reflection
+    assert_kind_of ActiveRecord::Reflection::ThroughReflection, Subscriber.reflect_on_association(:books)
+  end
+
   private
     def assert_reflection(klass, association, options)
       assert reflection = klass.reflect_on_association(association)</diff>
      <filename>vendor/rails/activerecord/test/cases/reflection_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,18 +8,18 @@ class SanitizeTest &lt; ActiveRecord::TestCase
   def test_sanitize_sql_array_handles_string_interpolation
     quoted_bambi = ActiveRecord::Base.connection.quote_string(&quot;Bambi&quot;)
     assert_equal &quot;name=#{quoted_bambi}&quot;, Binary.send(:sanitize_sql_array, [&quot;name=%s&quot;, &quot;Bambi&quot;])
-    assert_equal &quot;name=#{quoted_bambi}&quot;, Binary.send(:sanitize_sql_array, [&quot;name=%s&quot;, &quot;Bambi&quot;.chars])
+    assert_equal &quot;name=#{quoted_bambi}&quot;, Binary.send(:sanitize_sql_array, [&quot;name=%s&quot;, &quot;Bambi&quot;.mb_chars])
     quoted_bambi_and_thumper = ActiveRecord::Base.connection.quote_string(&quot;Bambi\nand\nThumper&quot;)
     assert_equal &quot;name=#{quoted_bambi_and_thumper}&quot;,Binary.send(:sanitize_sql_array, [&quot;name=%s&quot;, &quot;Bambi\nand\nThumper&quot;])
-    assert_equal &quot;name=#{quoted_bambi_and_thumper}&quot;,Binary.send(:sanitize_sql_array, [&quot;name=%s&quot;, &quot;Bambi\nand\nThumper&quot;.chars])
+    assert_equal &quot;name=#{quoted_bambi_and_thumper}&quot;,Binary.send(:sanitize_sql_array, [&quot;name=%s&quot;, &quot;Bambi\nand\nThumper&quot;.mb_chars])
   end
 
   def test_sanitize_sql_array_handles_bind_variables
     quoted_bambi = ActiveRecord::Base.connection.quote(&quot;Bambi&quot;)
     assert_equal &quot;name=#{quoted_bambi}&quot;, Binary.send(:sanitize_sql_array, [&quot;name=?&quot;, &quot;Bambi&quot;])
-    assert_equal &quot;name=#{quoted_bambi}&quot;, Binary.send(:sanitize_sql_array, [&quot;name=?&quot;, &quot;Bambi&quot;.chars])
+    assert_equal &quot;name=#{quoted_bambi}&quot;, Binary.send(:sanitize_sql_array, [&quot;name=?&quot;, &quot;Bambi&quot;.mb_chars])
     quoted_bambi_and_thumper = ActiveRecord::Base.connection.quote(&quot;Bambi\nand\nThumper&quot;)
     assert_equal &quot;name=#{quoted_bambi_and_thumper}&quot;, Binary.send(:sanitize_sql_array, [&quot;name=?&quot;, &quot;Bambi\nand\nThumper&quot;])
-    assert_equal &quot;name=#{quoted_bambi_and_thumper}&quot;, Binary.send(:sanitize_sql_array, [&quot;name=?&quot;, &quot;Bambi\nand\nThumper&quot;.chars])
+    assert_equal &quot;name=#{quoted_bambi_and_thumper}&quot;, Binary.send(:sanitize_sql_array, [&quot;name=?&quot;, &quot;Bambi\nand\nThumper&quot;.mb_chars])
   end
 end</diff>
      <filename>vendor/rails/activerecord/test/cases/sanitize_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,12 +6,16 @@ class ActiveRecordValidationsI18nTests &lt; Test::Unit::TestCase
   def setup
     reset_callbacks Topic
     @topic = Topic.new
+    @old_load_path, @old_backend = I18n.load_path, I18n.backend
+    I18n.load_path.clear
+    I18n.backend = I18n::Backend::Simple.new
     I18n.backend.store_translations('en-US', :activerecord =&gt; {:errors =&gt; {:messages =&gt; {:custom =&gt; nil}}})
   end
 
   def teardown
     reset_callbacks Topic
-    I18n.load_translations File.dirname(__FILE__) + '/../../lib/active_record/locale/en-US.yml'
+    I18n.load_path.replace @old_load_path
+    I18n.backend = @old_backend
   end
 
   def unique_topic</diff>
      <filename>vendor/rails/activerecord/test/cases/validations_i18n_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -17,6 +17,8 @@ class Author &lt; ActiveRecord::Base
       proxy_target
     end
   end
+  has_one  :post_about_thinking, :class_name =&gt; 'Post', :conditions =&gt; &quot;posts.title like '%thinking%'&quot;
+  has_one  :post_about_thinking_with_last_comment, :class_name =&gt; 'Post', :conditions =&gt; &quot;posts.title like '%thinking%'&quot;, :include =&gt; :last_comment
   has_many :comments, :through =&gt; :posts
   has_many :comments_containing_the_letter_e, :through =&gt; :posts, :source =&gt; :comments
   has_many :comments_with_order_and_conditions, :through =&gt; :posts, :source =&gt; :comments, :order =&gt; 'comments.body', :conditions =&gt; &quot;comments.body like 'Thank%'&quot;</diff>
      <filename>vendor/rails/activerecord/test/models/author.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,4 +4,10 @@ class Club &lt; ActiveRecord::Base
   has_many :current_memberships
   has_one :sponsor
   has_one :sponsored_member, :through =&gt; :sponsor, :source =&gt; :sponsorable, :source_type =&gt; &quot;Member&quot;
+
+  private
+
+  def private_method
+    &quot;I'm sorry sir, this is a *private* club, not a *pirate* club&quot;
+  end
 end
\ No newline at end of file</diff>
      <filename>vendor/rails/activerecord/test/models/club.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,6 +13,12 @@ class Company &lt; AbstractCompany
   def arbitrary_method
     &quot;I am Jack's profound disappointment&quot;
   end
+
+  private
+
+  def private_method
+    &quot;I am Jack's innermost fears and aspirations&quot;
+  end
 end
 
 module Namespaced
@@ -129,9 +135,14 @@ class Account &lt; ActiveRecord::Base
     true
   end
 
-
   protected
     def validate
       errors.add_on_empty &quot;credit_limit&quot;
     end
+
+  private
+
+  def private_method
+    &quot;Sir, yes sir!&quot;
+  end
 end</diff>
      <filename>vendor/rails/activerecord/test/models/company.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,6 +13,7 @@ class Post &lt; ActiveRecord::Base
   end
 
   belongs_to :author_with_posts, :class_name =&gt; &quot;Author&quot;, :foreign_key =&gt; :author_id, :include =&gt; :posts
+  belongs_to :author_with_address, :class_name =&gt; &quot;Author&quot;, :foreign_key =&gt; :author_id, :include =&gt; :author_address
 
   has_one :last_comment, :class_name =&gt; 'Comment', :order =&gt; 'id desc'
 
@@ -22,6 +23,8 @@ class Post &lt; ActiveRecord::Base
     end
   end
 
+  has_many :author_favorites, :through =&gt; :author
+
   has_many :comments_with_interpolated_conditions, :class_name =&gt; 'Comment',
       :conditions =&gt; ['#{&quot;#{aliased_table_name}.&quot; rescue &quot;&quot;}body = ?', 'Thank you for the welcome']
 </diff>
      <filename>vendor/rails/activerecord/test/models/post.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,7 @@
 *Edge*
 
+* Add ActiveResource::Base#to_xml and ActiveResource::Base#to_json. #1011 [Rasik Pandey, Cody Fauser]
+
 * Add ActiveResource::Base.find(:last). [#754 state:resolved] (Adrian Mugnolo)
 
 * Fixed problems with the logger used if the logging string included %'s [#840 state:resolved] (Jamis Buck)</diff>
      <filename>vendor/rails/activeresource/CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -854,6 +854,42 @@ module ActiveResource
     #
     #   my_group.to_xml(:skip_instruct =&gt; true)
     #   # =&gt; &lt;subsidiary_group&gt; [...] &lt;/subsidiary_group&gt;
+    def to_xml(options={})
+      attributes.to_xml({:root =&gt; self.class.element_name}.merge(options))
+    end
+
+    # Returns a JSON string representing the model. Some configuration is
+    # available through +options+.
+    #
+    # ==== Options
+    # The +options+ are passed to the +to_json+ method on each
+    # attribute, so the same options as the +to_json+ methods in
+    # Active Support.
+    #
+    # * &lt;tt&gt;:only&lt;/tt&gt; - Only include the specified attribute or list of
+    #   attributes in the serialized output. Attribute names must be specified
+    #   as strings.
+    # * &lt;tt&gt;:except&lt;/tt&gt; - Do not include the specified attribute or list of
+    #   attributes in the serialized output. Attribute names must be specified
+    #   as strings.
+    #
+    # ==== Examples
+    #   person = Person.new(:first_name =&gt; &quot;Jim&quot;, :last_name =&gt; &quot;Smith&quot;)
+    #   person.to_json
+    #   # =&gt; {&quot;first_name&quot;: &quot;Jim&quot;, &quot;last_name&quot;: &quot;Smith&quot;}
+    #
+    #   person.to_json(:only =&gt; [&quot;first_name&quot;])
+    #   # =&gt; {&quot;first_name&quot;: &quot;Jim&quot;}
+    #
+    #   person.to_json(:except =&gt; [&quot;first_name&quot;])
+    #   # =&gt; {&quot;last_name&quot;: &quot;Smith&quot;}
+    def to_json(options={})
+      attributes.to_json(options)
+    end
+
+    # Returns the serialized string representation of the resource in the configured
+    # serialization format specified in ActiveResource::Base.format. The options
+    # applicable depend on the configured encoding format.
     def encode(options={})
       case self.class.format
         when ActiveResource::Formats[:xml]
@@ -884,6 +920,7 @@ module ActiveResource
     #
     # ==== Examples
     #   my_attrs = {:name =&gt; 'J&amp;J Textiles', :industry =&gt; 'Cloth and textiles'}
+    #   my_attrs = {:name =&gt; 'Marty', :colors =&gt; [&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;]}
     #
     #   the_supplier = Supplier.find(:first)
     #   the_supplier.name # =&gt; 'J&amp;M Textiles'
@@ -906,7 +943,7 @@ module ActiveResource
           case value
             when Array
               resource = find_or_create_resource_for_collection(key)
-              value.map { |attrs| resource.new(attrs) }
+              value.map { |attrs| attrs.is_a?(String) ? attrs.dup : resource.new(attrs) }
             when Hash
               resource = find_or_create_resource_for(key)
               resource.new(value)</diff>
      <filename>vendor/rails/activeresource/lib/active_resource/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -199,7 +199,7 @@ module ActiveResource
 
       # Builds headers for request to remote service.
       def build_request_headers(headers, http_method=nil)
-        authorization_header.update(default_header).update(headers).update(http_format_header(http_method))
+        authorization_header.update(default_header).update(http_format_header(http_method)).update(headers)
       end
 
       # Sets authorization header</diff>
      <filename>vendor/rails/activeresource/lib/active_resource/connection.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,7 +12,7 @@ module ActiveResource
       end
 
       def encode(hash, options={})
-        hash.to_json
+        hash.to_json(options)
       end
 
       def decode(json)</diff>
      <filename>vendor/rails/activeresource/lib/active_resource/formats/json_format.rb</filename>
    </modified>
    <modified>
      <diff>@@ -46,10 +46,24 @@ class BaseTest &lt; Test::Unit::TestCase
                                            :children =&gt; [{:name =&gt; 'Natacha'}]},
                                           {:name =&gt; 'Milena',
                                            :children =&gt; []}]}]}.to_xml(:root =&gt; 'customer')
+    # - resource with yaml array of strings; for ActiveRecords using serialize :bar, Array
+    @marty = &lt;&lt;-eof
+      &lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;UTF-8\&quot;?&gt;
+      &lt;person&gt;
+        &lt;id type=\&quot;integer\&quot;&gt;5&lt;/id&gt;
+        &lt;name&gt;Marty&lt;/name&gt;
+        &lt;colors type=\&quot;yaml\&quot;&gt;---
+      - \&quot;red\&quot;
+      - \&quot;green\&quot;
+      - \&quot;blue\&quot;
+      &lt;/colors&gt;
+      &lt;/person&gt;
+    eof
 
     ActiveResource::HttpMock.respond_to do |mock|
       mock.get    &quot;/people/1.xml&quot;,                {}, @matz
       mock.get    &quot;/people/2.xml&quot;,                {}, @david
+      mock.get    &quot;/people/5.xml&quot;,                {}, @marty
       mock.get    &quot;/people/Greg.xml&quot;,             {}, @greg
       mock.get    &quot;/people/4.xml&quot;,                {'key' =&gt; 'value'}, nil, 404
       mock.put    &quot;/people/1.xml&quot;,                {}, nil, 204
@@ -851,4 +865,14 @@ class BaseTest &lt; Test::Unit::TestCase
       end
     end
   end
+
+  def test_load_yaml_array
+    assert_nothing_raised do
+      marty = Person.find(5)
+      assert_equal 3, marty.colors.size
+      marty.colors.each do |color|
+        assert_kind_of String, color
+      end
+    end
+  end
 end</diff>
      <filename>vendor/rails/activeresource/test/base_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -168,12 +168,20 @@ class ConnectionTest &lt; Test::Unit::TestCase
     assert_equal 200, response.code
   end
 
-  uses_mocha('test_timeout') do
+  uses_mocha('test_timeout, test_accept_http_header') do
     def test_timeout
       @http = mock('new Net::HTTP')
       @conn.expects(:http).returns(@http)
       @http.expects(:get).raises(Timeout::Error, 'execution expired')
-      assert_raises(ActiveResource::TimeoutError) { @conn.get('/people_timeout.xml') }
+      assert_raise(ActiveResource::TimeoutError) { @conn.get('/people_timeout.xml') }
+    end
+
+    def test_accept_http_header
+      @http = mock('new Net::HTTP')
+      @conn.expects(:http).returns(@http)
+      path = '/people/1.xml'
+      @http.expects(:get).with(path,  {'Accept' =&gt; 'application/xhtml+xml'}).returns(ActiveResource::Response.new(@matz, 200, {'Content-Type' =&gt; 'text/xhtml'}))
+      assert_nothing_raised(Mocha::ExpectationError) { @conn.get(path, {'Accept' =&gt; 'application/xhtml+xml'}) }
     end
   end
 </diff>
      <filename>vendor/rails/activeresource/test/connection_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,6 @@
 require 'abstract_unit'
 require &quot;fixtures/person&quot;
+require &quot;fixtures/street_address&quot;
 
 class FormatTest &lt; Test::Unit::TestCase
   def setup
@@ -83,6 +84,22 @@ class FormatTest &lt; Test::Unit::TestCase
     assert_equal ActiveResource::Formats[:json], resource.connection.format
   end
 
+  def test_serialization_of_nested_resource
+   address  = { :street =&gt; '12345 Street' }
+   person  = { :name=&gt; 'Rus', :address =&gt; address}
+
+   [:json, :xml].each do |format|
+     encoded_person = ActiveResource::Formats[format].encode(person)
+     assert_match /12345 Street/, encoded_person
+     remote_person = Person.new(person.update({:address =&gt; StreetAddress.new(address)}))
+     assert_kind_of StreetAddress, remote_person.address
+     using_format(Person, format) do
+       ActiveResource::HttpMock.respond_to.post &quot;/people.#{format}&quot;, {'Content-Type' =&gt; ActiveResource::Formats[format].mime_type}, encoded_person, 201, {'Location' =&gt; &quot;/people/5.#{format}&quot;}
+       remote_person.save
+     end
+   end
+ end
+
   private
     def using_format(klass, mime_type_reference)
       previous_format = klass.format</diff>
      <filename>vendor/rails/activeresource/test/format_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,13 @@
 *Edge*
 
+* Time#advance recognizes fractional days and weeks. Deprecate Durations of fractional months and years #970 [Tom Lea]
+
+* Add ActiveSupport::Rescuable module abstracting ActionController::Base rescue_from features. [Norbert Crombach, Pratik]
+
+* Switch from String#chars to String#mb_chars for the unicode proxy.  [Manfred Stienstra]
+
+  This helps with 1.8.7 compatibility and also improves performance for some operations by reducing indirection.
+
 * TimeWithZone #wday, #yday and #to_date avoid trip through #method_missing [Geoff Buesing]
 
 * Added Time, Date, DateTime and TimeWithZone #past?, #future? and #today? #720 [Clemens Kofler, Geoff Buesing]</diff>
      <filename>vendor/rails/activesupport/CHANGELOG</filename>
    </modified>
    <modified>
      <diff>@@ -56,7 +56,9 @@ require 'active_support/time_with_zone'
 
 require 'active_support/secure_random'
 
-I18n.load_translations File.dirname(__FILE__) + '/active_support/locale/en-US.yml'
+require 'active_support/rescuable'
+
+I18n.load_path &lt;&lt; File.dirname(__FILE__) + '/active_support/locale/en-US.yml'
 
 Inflector = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Inflector', 'ActiveSupport::Inflector')
 Dependencies = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Dependencies', 'ActiveSupport::Dependencies')</diff>
      <filename>vendor/rails/activesupport/lib/active_support.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,13 +7,24 @@ module ActiveSupport
   if defined? ::Base64
     Base64 = ::Base64
   else
-    # Ruby 1.9 doesn't provide base64, so we wrap this here
+    # Base64 provides utility methods for encoding and de-coding binary data 
+    # using a base 64 representation. A base 64 representation of binary data
+    # consists entirely of printable US-ASCII characters. The Base64 module
+    # is included in Ruby 1.8, but has been removed in Ruby 1.9.
     module Base64
-
+      # Encodes a string to its base 64 representation. Each 60 characters of
+      # output is separated by a newline character.
+      #
+      #  ActiveSupport::Base64.encode64(&quot;Original unencoded string&quot;) 
+      #  # =&gt; &quot;T3JpZ2luYWwgdW5lbmNvZGVkIHN0cmluZw==\n&quot;
       def self.encode64(data)
         [data].pack(&quot;m&quot;)
       end
 
+      # Decodes a base 64 encoded string to its original representation.
+      #
+      #  ActiveSupport::Base64.decode64(&quot;T3JpZ2luYWwgdW5lbmNvZGVkIHN0cmluZw==&quot;) 
+      #  # =&gt; &quot;Original unencoded string&quot;
       def self.decode64(data)
         data.unpack(&quot;m&quot;).first
       end</diff>
      <filename>vendor/rails/activesupport/lib/active_support/base64.rb</filename>
    </modified>
    <modified>
      <diff>@@ -116,7 +116,7 @@ module ActiveSupport
       end
 
       def clear_buffer
-        @buffer[Thread.current] = []
+        @buffer.delete(Thread.current)
       end
   end
 end</diff>
      <filename>vendor/rails/activesupport/lib/active_support/buffered_logger.rb</filename>
    </modified>
    <modified>
      <diff>@@ -23,47 +23,47 @@ module ActiveSupport #:nodoc:
           self[0..position]
         end
 
-        # Equals to &lt;tt&gt;self[1]&lt;/tt&gt;.
+        # Equal to &lt;tt&gt;self[1]&lt;/tt&gt;.
         def second
           self[1]
         end
 
-        # Equals to &lt;tt&gt;self[2]&lt;/tt&gt;.
+        # Equal to &lt;tt&gt;self[2]&lt;/tt&gt;.
         def third
           self[2]
         end
 
-        # Equals to &lt;tt&gt;self[3]&lt;/tt&gt;.
+        # Equal to &lt;tt&gt;self[3]&lt;/tt&gt;.
         def fourth
           self[3]
         end
 
-        # Equals to &lt;tt&gt;self[4]&lt;/tt&gt;.
+        # Equal to &lt;tt&gt;self[4]&lt;/tt&gt;.
         def fifth
           self[4]
         end
 
-        # Equals to &lt;tt&gt;self[5]&lt;/tt&gt;.
+        # Equal to &lt;tt&gt;self[5]&lt;/tt&gt;.
         def sixth
           self[5]
         end
 
-        # Equals to &lt;tt&gt;self[6]&lt;/tt&gt;.
+        # Equal to &lt;tt&gt;self[6]&lt;/tt&gt;.
         def seventh
           self[6]
         end
 
-        # Equals to &lt;tt&gt;self[7]&lt;/tt&gt;.
+        # Equal to &lt;tt&gt;self[7]&lt;/tt&gt;.
         def eighth
           self[7]
         end
 
-        # Equals to &lt;tt&gt;self[8]&lt;/tt&gt;.
+        # Equal to &lt;tt&gt;self[8]&lt;/tt&gt;.
         def ninth
           self[8]
         end
 
-        # Equals to &lt;tt&gt;self[9]&lt;/tt&gt;.
+        # Equal to &lt;tt&gt;self[9]&lt;/tt&gt;.
         def tenth
           self[9]
         end</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/array/access.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,8 @@ module ActiveSupport #:nodoc:
           options.assert_valid_keys(:connector, :skip_last_comma, :locale)
           
           default = I18n.translate(:'support.array.sentence_connector', :locale =&gt; options[:locale])
-          options.reverse_merge! :connector =&gt; default, :skip_last_comma =&gt; false
+          default_skip_last_comma = I18n.translate(:'support.array.skip_last_comma', :locale =&gt; options[:locale])
+          options.reverse_merge! :connector =&gt; default, :skip_last_comma =&gt; default_skip_last_comma
           options[:connector] = &quot;#{options[:connector]} &quot; unless options[:connector].nil? || options[:connector].strip == ''
 
           case length</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/array/conversions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,6 +4,9 @@ module ActiveSupport #:nodoc:
       module Encoding
         # Encodes the value as base64 without the newline breaks. This makes the base64 encoding readily usable as URL parameters 
         # or memcache keys without further processing.
+        #
+        #  ActiveSupport::Base64.encode64s(&quot;Original unencoded string&quot;) 
+        #  # =&gt; &quot;T3JpZ2luYWwgdW5lbmNvZGVkIHN0cmluZw==&quot;
         def encode64s(value)
           encode64(value).gsub(/\n/, '')
         end</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/base64/encoding.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,7 @@
 require 'active_support/core_ext/float/rounding'
+require 'active_support/core_ext/float/time'
 
 class Float #:nodoc:
   include ActiveSupport::CoreExtensions::Float::Rounding
+  include ActiveSupport::CoreExtensions::Float::Time
 end</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/float.rb</filename>
    </modified>
    <modified>
      <diff>@@ -18,7 +18,7 @@ module ActiveSupport #:nodoc:
         # Returns a new hash with only the given keys.
         def slice(*keys)
           keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
-          hash = {}
+          hash = self.class.new
           keys.each { |k| hash[k] = self[k] if has_key?(k) }
           hash
         end</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/hash/slice.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,9 @@
 require 'active_support/core_ext/integer/even_odd'
 require 'active_support/core_ext/integer/inflections'
+require 'active_support/core_ext/integer/time'
 
 class Integer #:nodoc:
   include ActiveSupport::CoreExtensions::Integer::EvenOdd
   include ActiveSupport::CoreExtensions::Integer::Inflections
+  include ActiveSupport::CoreExtensions::Integer::Time
 end</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/integer.rb</filename>
    </modified>
    <modified>
      <diff>@@ -60,16 +60,6 @@ module ActiveSupport #:nodoc:
         end
         alias :fortnight :fortnights
         
-        def months
-          ActiveSupport::Duration.new(self * 30.days, [[:months, self]])
-        end
-        alias :month :months
-
-        def years
-          ActiveSupport::Duration.new(self * 365.25.days, [[:years, self]])
-        end
-        alias :year :years
-
         # Reads best without arguments:  10.minutes.ago
         def ago(time = ::Time.now)
           time - self</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/numeric/time.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,22 +3,43 @@ class Object
     Class.remove_class(*subclasses_of(*superclasses))
   end
 
-  # Exclude this class unless it's a subclass of our supers and is defined.
-  # We check defined? in case we find a removed class that has yet to be
-  # garbage collected. This also fails for anonymous classes -- please
-  # submit a patch if you have a workaround.
-  def subclasses_of(*superclasses) #:nodoc:
-    subclasses = []
-
-    superclasses.each do |sup|
-      ObjectSpace.each_object(class &lt;&lt; sup; self; end) do |k|
-        if k != sup &amp;&amp; (k.name.blank? || eval(&quot;defined?(::#{k}) &amp;&amp; ::#{k}.object_id == k.object_id&quot;))
-          subclasses &lt;&lt; k
+  begin
+    ObjectSpace.each_object(Class.new) {}
+
+    # Exclude this class unless it's a subclass of our supers and is defined.
+    # We check defined? in case we find a removed class that has yet to be
+    # garbage collected. This also fails for anonymous classes -- please
+    # submit a patch if you have a workaround.
+    def subclasses_of(*superclasses) #:nodoc:
+      subclasses = []
+
+      superclasses.each do |sup|
+        ObjectSpace.each_object(class &lt;&lt; sup; self; end) do |k|
+          if k != sup &amp;&amp; (k.name.blank? || eval(&quot;defined?(::#{k}) &amp;&amp; ::#{k}.object_id == k.object_id&quot;))
+            subclasses &lt;&lt; k
+          end
         end
       end
+
+      subclasses
     end
+  rescue RuntimeError
+    # JRuby and any implementations which cannot handle the objectspace traversal
+    # above fall back to this implementation
+    def subclasses_of(*superclasses) #:nodoc:
+      subclasses = []
 
-    subclasses
+      superclasses.each do |sup|
+        ObjectSpace.each_object(Class) do |k|
+          if superclasses.any? { |superclass| k &lt; superclass } &amp;&amp;
+            (k.name.blank? || eval(&quot;defined?(::#{k}) &amp;&amp; ::#{k}.object_id == k.object_id&quot;))
+            subclasses &lt;&lt; k
+          end
+        end
+        subclasses.uniq!
+      end
+      subclasses
+    end
   end
 
   def extended_by #:nodoc:</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/object/extending.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,30 +1,50 @@
 class Object
-  # A Ruby-ized realization of the K combinator, courtesy of Mikael Brockman.
+  # Returns +value+ after yielding +value+ to the block. This simplifies the
+  # process of constructing an object, performing work on the object, and then
+  # returning the object from a method. It is a Ruby-ized realization of the K
+  # combinator, courtesy of Mikael Brockman.
   #
-  #   def foo
-  #     returning values = [] do
-  #       values &lt;&lt; 'bar'
-  #       values &lt;&lt; 'baz'
-  #     end
-  #   end
+  # ==== Examples
   #
-  #   foo # =&gt; ['bar', 'baz']
+  #  # Without returning
+  #  def foo
+  #    values = []
+  #    values &lt;&lt; &quot;bar&quot;
+  #    values &lt;&lt; &quot;baz&quot;
+  #    return values
+  #  end
   #
-  #   def foo
-  #     returning [] do |values|
-  #       values &lt;&lt; 'bar'
-  #       values &lt;&lt; 'baz'
-  #     end
-  #   end
+  #  foo # =&gt; ['bar', 'baz']
   #
-  #   foo # =&gt; ['bar', 'baz']
+  #  # returning with a local variable
+  #  def foo
+  #    returning values = [] do
+  #      values &lt;&lt; 'bar'
+  #      values &lt;&lt; 'baz'
+  #    end
+  #  end
   #
+  #  foo # =&gt; ['bar', 'baz']
+  #  
+  #  # returning with a block argument
+  #  def foo
+  #    returning [] do |values|
+  #      values &lt;&lt; 'bar'
+  #      values &lt;&lt; 'baz'
+  #    end
+  #  end
+  #  
+  #  foo # =&gt; ['bar', 'baz']
   def returning(value)
     yield(value)
     value
   end
 
-  # An elegant way to refactor out common options
+  # An elegant way to factor duplication out of options passed to a series of
+  # method calls. Each method called in the block, with the block variable as
+  # the receiver, will have its options merged with the default +options+ hash
+  # provided. Each method called on the block variable must take an options
+  # hash as its final argument.
   # 
   #   with_options :order =&gt; 'created_at', :class_name =&gt; 'Comment' do |post|
   #     post.has_many :comments, :conditions =&gt; ['approved = ?', true], :dependent =&gt; :delete_all</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/object/misc.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,11 @@
+# encoding: utf-8
+
 require 'active_support/core_ext/string/inflections'
 require 'active_support/core_ext/string/conversions'
 require 'active_support/core_ext/string/access'
 require 'active_support/core_ext/string/starts_ends_with'
 require 'active_support/core_ext/string/iterators'
-require 'active_support/core_ext/string/unicode'
+require 'active_support/core_ext/string/multibyte'
 require 'active_support/core_ext/string/xchar'
 require 'active_support/core_ext/string/filters'
 require 'active_support/core_ext/string/behavior'
@@ -15,6 +17,6 @@ class String #:nodoc:
   include ActiveSupport::CoreExtensions::String::Inflections
   include ActiveSupport::CoreExtensions::String::StartsEndsWith
   include ActiveSupport::CoreExtensions::String::Iterators
-  include ActiveSupport::CoreExtensions::String::Unicode
   include ActiveSupport::CoreExtensions::String::Behavior
+  include ActiveSupport::CoreExtensions::String::Multibyte
 end</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/string.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,7 @@ module ActiveSupport #:nodoc:
           #   &quot;hello&quot;.at(4)  # =&gt; &quot;o&quot;
           #   &quot;hello&quot;.at(10) # =&gt; nil
           def at(position)
-            chars[position, 1].to_s
+            mb_chars[position, 1].to_s
           end
           
           # Returns the remaining of the string from the +position+ treating the string as an array (where 0 is the first character).
@@ -21,7 +21,7 @@ module ActiveSupport #:nodoc:
           #   &quot;hello&quot;.from(2)  # =&gt; &quot;llo&quot;
           #   &quot;hello&quot;.from(10) # =&gt; nil
           def from(position)
-            chars[position..-1].to_s
+            mb_chars[position..-1].to_s
           end
           
           # Returns the beginning of the string up to the +position+ treating the string as an array (where 0 is the first character).
@@ -31,7 +31,7 @@ module ActiveSupport #:nodoc:
           #   &quot;hello&quot;.to(2)  # =&gt; &quot;hel&quot;
           #   &quot;hello&quot;.to(10) # =&gt; &quot;hello&quot;
           def to(position)
-            chars[0..position].to_s
+            mb_chars[0..position].to_s
           end
 
           # Returns the first character of the string or the first +limit+ characters.
@@ -41,7 +41,7 @@ module ActiveSupport #:nodoc:
           #   &quot;hello&quot;.first(2)  # =&gt; &quot;he&quot;
           #   &quot;hello&quot;.first(10) # =&gt; &quot;hello&quot;
           def first(limit = 1)
-            chars[0..(limit - 1)].to_s
+            mb_chars[0..(limit - 1)].to_s
           end
           
           # Returns the last character of the string or the last +limit+ characters.
@@ -51,7 +51,7 @@ module ActiveSupport #:nodoc:
           #   &quot;hello&quot;.last(2)  # =&gt; &quot;lo&quot;
           #   &quot;hello&quot;.last(10) # =&gt; &quot;hello&quot;
           def last(limit = 1)
-            (chars[(-limit)..-1] || self).to_s
+            (mb_chars[(-limit)..-1] || self).to_s
           end
         end
       else</diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/string/access.rb</filename>
    </modified>
    <modified>
      <diff>@@ -98,6 +98,16 @@ module ActiveSupport #:nodoc:
         # &lt;tt&gt;:months&lt;/tt&gt;, &lt;tt&gt;:weeks&lt;/tt&gt;, &lt;tt&gt;:days&lt;/tt&gt;, &lt;tt&gt;:hours&lt;/tt&gt;,
         # &lt;tt&gt;:minutes&lt;/tt&gt;, &lt;tt&gt;:seconds&lt;/tt&gt;.
         def advance(options)
+          unless options[:weeks].nil?
+            options[:weeks], partial_weeks = options[:weeks].divmod(1)
+            options[:days] = (options[:days] || 0) + 7 * partial_weeks
+          end
+          
+          unless options[:days].nil?
+            options[:days], partial_days = options[:days].divmod(1)
+            options[:hours] = (options[:hours] || 0) + 24 * partial_days
+          end
+          
           d = to_date.advance(options)
           time_advanced_by_date = change(:year =&gt; d.year, :month =&gt; d.month, :day =&gt; d.day)
           seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
@@ -223,7 +233,7 @@ module ActiveSupport #:nodoc:
 
         # Returns a new Time representing the end of the quarter (last day of march, june, september, december, 23:59:59)
         def end_of_quarter
-          change(:month =&gt; [3, 6, 9, 12].detect { |m| m &gt;= self.month }).end_of_month
+          beginning_of_month.change(:month =&gt; [3, 6, 9, 12].detect { |m| m &gt;= self.month }).end_of_month
         end
         alias :at_end_of_quarter :end_of_quarter
 </diff>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/time/calculations.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,5 @@
 require 'singleton'
+require 'iconv'
 
 module ActiveSupport
   # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
@@ -240,9 +241,9 @@ module ActiveSupport
     def demodulize(class_name_in_module)
       class_name_in_module.to_s.gsub(/^.*::/, '')
     end
-    
+
     # Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
-    # 
+    #
     # ==== Examples
     #
     #   class Person
@@ -250,14 +251,39 @@ module ActiveSupport
     #       &quot;#{id}-#{name.parameterize}&quot;
     #     end
     #   end
-    # 
+    #
     #   @person = Person.find(1)
     #   # =&gt; #&lt;Person id: 1, name: &quot;Donald E. Knuth&quot;&gt;
-    # 
+    #
     #   &lt;%= link_to(@person.name, person_path %&gt;
     #   # =&gt; &lt;a href=&quot;/person/1-donald-e-knuth&quot;&gt;Donald E. Knuth&lt;/a&gt;
     def parameterize(string, sep = '-')
-      string.chars.normalize(:kd).to_s.gsub(/[^\x00-\x7F]+/, '').gsub(/[^a-z0-9_\-]+/i, sep).downcase
+      re_sep = Regexp.escape(sep)
+      # replace accented chars with ther ascii equivalents
+      parameterized_string = transliterate(string)
+      # Turn unwanted chars into the seperator
+      parameterized_string.gsub!(/[^a-z0-9\-_\+]+/i, sep)
+      # No more than one of the separator in a row.
+      parameterized_string.squeeze!(sep)
+      # Remove leading/trailing separator.
+      parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '')
+      parameterized_string.downcase
+    end
+
+
+    # Replaces accented characters with their ascii equivalents.
+    def transliterate(string)
+      Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s
+    end
+
+    # The iconv transliteration code doesn't function correctly
+    # on some platforms, but it's very fast where it does function.
+    if &quot;foo&quot; != Inflector.transliterate(&quot;f&#246;&#246;&quot;)
+      undef_method :transliterate
+      def transliterate(string)
+        string.mb_chars.normalize(:kd). # Decompose accented characters
+          gsub(/[^\x00-\x7F]+/, '')     # Remove anything non-ASCII entirely (e.g. diacritics).
+      end
     end
 
     # Create the name of a table like Rails does for models to table names. This method</diff>
      <filename>vendor/rails/activesupport/lib/active_support/inflector.rb</filename>
    </modified>
    <modified>
      <diff>@@ -29,3 +29,4 @@ en-US:
   support:
     array:
       sentence_connector: &quot;and&quot;
+      skip_last_comma: false</diff>
      <filename>vendor/rails/activesupport/lib/active_support/locale/en-US.yml</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,9 @@
 module ActiveSupport
   module Memoizable
+    MEMOIZED_IVAR = Proc.new do |symbol|
+      &quot;@_memoized_#{symbol.to_s.sub(/\?\Z/, '_query').sub(/!\Z/, '_bang')}&quot;.to_sym
+    end
+
     module Freezable
       def self.included(base)
         base.class_eval do
@@ -20,7 +24,7 @@ module ActiveSupport
             if method(m).arity == 0
               __send__($1)
             else
-              ivar = :&quot;@_memoized_#{$1}&quot;
+              ivar = MEMOIZED_IVAR.call($1)
               instance_variable_set(ivar, {})
             end
           end
@@ -30,7 +34,7 @@ module ActiveSupport
       def unmemoize_all
         methods.each do |m|
           if m.to_s =~ /^_unmemoized_(.*)/
-            ivar = :&quot;@_memoized_#{$1}&quot;
+            ivar = MEMOIZED_IVAR.call($1)
             instance_variable_get(ivar).clear if instance_variable_defined?(ivar)
           end
         end
@@ -40,7 +44,7 @@ module ActiveSupport
     def memoize(*symbols)
       symbols.each do |symbol|
         original_method = :&quot;_unmemoized_#{symbol}&quot;
-        memoized_ivar = :&quot;@_memoized_#{symbol.to_s.sub(/\?\Z/, '_query').sub(/!\Z/, '_bang')}&quot;
+        memoized_ivar = MEMOIZED_IVAR.call(symbol)
 
         class_eval &lt;&lt;-EOS, __FILE__, __LINE__
           include Freezable</diff>
      <filename>vendor/rails/activesupport/lib/active_support/memoizable.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,33 @@
-module ActiveSupport
-  module Multibyte #:nodoc:
-    DEFAULT_NORMALIZATION_FORM = :kc
-    NORMALIZATIONS_FORMS = [:c, :kc, :d, :kd]
-    UNICODE_VERSION = '5.0.0'
-  end
-end
+# encoding: utf-8
 
 require 'active_support/multibyte/chars'
+require 'active_support/multibyte/exceptions'
+require 'active_support/multibyte/unicode_database'
+
+module ActiveSupport #:nodoc:
+  module Multibyte
+    # A list of all available normalization forms. See http://www.unicode.org/reports/tr15/tr15-29.html for more
+    # information about normalization.
+    NORMALIZATION_FORMS = [:c, :kc, :d, :kd]
+
+    # The Unicode version that is supported by the implementation
+    UNICODE_VERSION = '5.1.0'
+
+    # The default normalization used for operations that require normalization. It can be set to any of the
+    # normalizations in NORMALIZATION_FORMS.
+    #
+    # Example:
+    #   ActiveSupport::Multibyte.default_normalization_form = :c
+    mattr_accessor :default_normalization_form
+    self.default_normalization_form = :kc
+
+    # The proxy class returned when calling mb_chars. You can use this accessor to configure your own proxy
+    # class so you can support other encodings. See the ActiveSupport::Multibyte::Chars implementation for
+    # an example how to do this.
+    #
+    # Example:
+    #   ActiveSupport::Multibyte.proxy_class = CharsForUTF32
+    mattr_accessor :proxy_class
+    self.proxy_class = ActiveSupport::Multibyte::Chars
+  end
+end</diff>
      <filename>vendor/rails/activesupport/lib/active_support/multibyte.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,142 +1,679 @@
-require 'active_support/multibyte/handlers/utf8_handler'
-require 'active_support/multibyte/handlers/passthru_handler'
-
-# Encapsulates all the functionality related to the Chars proxy.
-module ActiveSupport::Multibyte #:nodoc:
-  # Chars enables you to work transparently with multibyte encodings in the Ruby String class without having extensive
-  # knowledge about the encoding. A Chars object accepts a string upon initialization and proxies String methods in an
-  # encoding safe manner. All the normal String methods are also implemented on the proxy.
-  #
-  # String methods are proxied through the Chars object, and can be accessed through the +chars+ method. Methods
-  # which would normally return a String object now return a Chars object so methods can be chained.
-  #
-  #   &quot;The Perfect String  &quot;.chars.downcase.strip.normalize # =&gt; &quot;the perfect string&quot;
-  #
-  # Chars objects are perfectly interchangeable with String objects as long as no explicit class checks are made.
-  # If certain methods do explicitly check the class, call +to_s+ before you pass chars objects to them.
-  #
-  #   bad.explicit_checking_method &quot;T&quot;.chars.downcase.to_s
-  #
-  # The actual operations on the string are delegated to handlers. Theoretically handlers can be implemented for
-  # any encoding, but the default handler handles UTF-8. This handler is set during initialization, if you want to
-  # use you own handler, you can set it on the Chars class. Look at the UTF8Handler source for an example how to
-  # implement your own handler. If you your own handler to work on anything but UTF-8 you probably also
-  # want to override Chars#handler.
-  #
-  #   ActiveSupport::Multibyte::Chars.handler = MyHandler
-  #
-  # Note that a few methods are defined on Chars instead of the handler because they are defined on Object or Kernel
-  # and method_missing can't catch them.
-  class Chars
-    
-    attr_reader :string # The contained string
-    alias_method :to_s, :string
-    
-    include Comparable
-    
-    # The magic method to make String and Chars comparable
-    def to_str
-      # Using any other ways of overriding the String itself will lead you all the way from infinite loops to
-      # core dumps. Don't go there.
-      @string
-    end
+# encoding: utf-8
+
+module ActiveSupport #:nodoc:
+  module Multibyte #:nodoc:
+    # Chars enables you to work transparently with UTF-8 encoding in the Ruby String class without having extensive
+    # knowledge about the encoding. A Chars object accepts a string upon initialization and proxies String methods in an
+    # encoding safe manner. All the normal String methods are also implemented on the proxy.
+    #
+    # String methods are proxied through the Chars object, and can be accessed through the +mb_chars+ method. Methods
+    # which would normally return a String object now return a Chars object so methods can be chained.
+    #
+    #   &quot;The Perfect String  &quot;.mb_chars.downcase.strip.normalize #=&gt; &quot;the perfect string&quot;
+    #
+    # Chars objects are perfectly interchangeable with String objects as long as no explicit class checks are made.
+    # If certain methods do explicitly check the class, call +to_s+ before you pass chars objects to them.
+    #
+    #   bad.explicit_checking_method &quot;T&quot;.mb_chars.downcase.to_s
+    #
+    # The default Chars implementation assumes that the encoding of the string is UTF-8, if you want to handle different
+    # encodings you can write your own multibyte string handler and configure it through 
+    # ActiveSupport::Multibyte.proxy_class.
+    #
+    #   class CharsForUTF32
+    #     def size
+    #       @wrapped_string.size / 4
+    #     end
+    #
+    #     def self.accepts?(string)
+    #       string.length % 4 == 0
+    #     end
+    #   end
+    #
+    #   ActiveSupport::Multibyte.proxy_class = CharsForUTF32
+    class Chars
+      # Hangul character boundaries and properties
+      HANGUL_SBASE = 0xAC00
+      HANGUL_LBASE = 0x1100
+      HANGUL_VBASE = 0x1161
+      HANGUL_TBASE = 0x11A7
+      HANGUL_LCOUNT = 19
+      HANGUL_VCOUNT = 21
+      HANGUL_TCOUNT = 28
+      HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT
+      HANGUL_SCOUNT = 11172
+      HANGUL_SLAST = HANGUL_SBASE + HANGUL_SCOUNT
+      HANGUL_JAMO_FIRST = 0x1100
+      HANGUL_JAMO_LAST = 0x11FF
+
+      # All the unicode whitespace
+      UNICODE_WHITESPACE = [
+        (0x0009..0x000D).to_a, # White_Space # Cc   [5] &lt;control-0009&gt;..&lt;control-000D&gt;
+        0x0020,                # White_Space # Zs       SPACE
+        0x0085,                # White_Space # Cc       &lt;control-0085&gt;
+        0x00A0,                # White_Space # Zs       NO-BREAK SPACE
+        0x1680,                # White_Space # Zs       OGHAM SPACE MARK
+        0x180E,                # White_Space # Zs       MONGOLIAN VOWEL SEPARATOR
+        (0x2000..0x200A).to_a, # White_Space # Zs  [11] EN QUAD..HAIR SPACE
+        0x2028,                # White_Space # Zl       LINE SEPARATOR
+        0x2029,                # White_Space # Zp       PARAGRAPH SEPARATOR
+        0x202F,                # White_Space # Zs       NARROW NO-BREAK SPACE
+        0x205F,                # White_Space # Zs       MEDIUM MATHEMATICAL SPACE
+        0x3000,                # White_Space # Zs       IDEOGRAPHIC SPACE
+      ].flatten.freeze
+
+      # BOM (byte order mark) can also be seen as whitespace, it's a non-rendering character used to distinguish
+      # between little and big endian. This is not an issue in utf-8, so it must be ignored.
+      UNICODE_LEADERS_AND_TRAILERS = UNICODE_WHITESPACE + [65279] # ZERO-WIDTH NO-BREAK SPACE aka BOM
+
+      # Returns a regular expression pattern that matches the passed Unicode codepoints
+      def self.codepoints_to_pattern(array_of_codepoints) #:nodoc:
+        array_of_codepoints.collect{ |e| [e].pack 'U*' }.join('|')
+      end
+      UNICODE_TRAILERS_PAT = /(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+\Z/
+      UNICODE_LEADERS_PAT = /\A(#{codepoints_to_pattern(UNICODE_LEADERS_AND_TRAILERS)})+/
+
+      # Borrowed from the Kconv library by Shinji KONO - (also as seen on the W3C site)
+      UTF8_PAT = /\A(?:
+                     [\x00-\x7f]                                     |
+                     [\xc2-\xdf] [\x80-\xbf]                         |
+                     \xe0        [\xa0-\xbf] [\x80-\xbf]             |
+                     [\xe1-\xef] [\x80-\xbf] [\x80-\xbf]             |
+                     \xf0        [\x90-\xbf] [\x80-\xbf] [\x80-\xbf] |
+                     [\xf1-\xf3] [\x80-\xbf] [\x80-\xbf] [\x80-\xbf] |
+                     \xf4        [\x80-\x8f] [\x80-\xbf] [\x80-\xbf]
+                    )*\z/xn
+
+      attr_reader :wrapped_string
+      alias to_s wrapped_string
+      alias to_str wrapped_string
+
+      if '1.9'.respond_to?(:force_encoding)
+        # Creates a new Chars instance by wrapping _string_.
+        def initialize(string)
+          @wrapped_string = string
+          @wrapped_string.force_encoding(Encoding::UTF_8) unless @wrapped_string.frozen?
+        end
+      else
+        def initialize(string) #:nodoc:
+          @wrapped_string = string
+        end
+      end
+
+      # Forward all undefined methods to the wrapped string.
+      def method_missing(method, *args, &amp;block)
+        if method.to_s =~ /!$/
+          @wrapped_string.__send__(method, *args, &amp;block)
+          self
+        else
+          result = @wrapped_string.__send__(method, *args, &amp;block)
+          result.kind_of?(String) ? chars(result) : result
+        end
+      end
+
+      # Returns +true+ if _obj_ responds to the given method. Private methods are included in the search
+      # only if the optional second parameter evaluates to +true+.
+      def respond_to?(method, include_private=false)
+        super || @wrapped_string.respond_to?(method, include_private) || false
+      end
+
+      # Enable more predictable duck-typing on String-like classes. See Object#acts_like?.
+      def acts_like_string?
+        true
+      end
+
+      # Returns +true+ if the Chars class can and should act as a proxy for the string _string_. Returns
+      # +false+ otherwise.
+      def self.wants?(string)
+        $KCODE == 'UTF8' &amp;&amp; consumes?(string)
+      end
 
-    # Make duck-typing with String possible
-    def respond_to?(method, include_priv = false)
-      super || @string.respond_to?(method, include_priv) ||
-        handler.respond_to?(method, include_priv) ||
-        (method.to_s =~ /(.*)!/ &amp;&amp; handler.respond_to?($1, include_priv)) ||
+      # Returns +true+ when the proxy class can handle the string. Returns +false+ otherwise.
+      def self.consumes?(string)
+        # Unpack is a little bit faster than regular expressions.
+        string.unpack('U*')
+        true
+      rescue ArgumentError
         false
-    end
+      end
 
-    # Enable more predictable duck-typing on String-like classes. See Object#acts_like?.
-    def acts_like_string?
-      true
-    end
+      include Comparable
 
-    # Create a new Chars instance.
-    def initialize(str)
-      @string = str.respond_to?(:string) ? str.string : str
-    end
-    
-    # Returns -1, 0 or +1 depending on whether the Chars object is to be sorted before, equal or after the
-    # object on the right side of the operation. It accepts any object that implements +to_s+. See String.&lt;=&gt;
-    # for more details.
-    def &lt;=&gt;(other); @string &lt;=&gt; other.to_s; end
-    
-    # Works just like String#split, with the exception that the items in the resulting list are Chars
-    # instances instead of String. This makes chaining methods easier.
-    def split(*args)
-      @string.split(*args).map { |i| i.chars }
-    end
-    
-    # Gsub works exactly the same as gsub on a normal string.
-    def gsub(*a, &amp;b); @string.gsub(*a, &amp;b).chars; end
-    
-    # Like String.=~ only it returns the character offset (in codepoints) instead of the byte offset.
-    def =~(other)
-      handler.translate_offset(@string, @string =~ other)
-    end
-    
-    # Try to forward all undefined methods to the handler, when a method is not defined on the handler, send it to
-    # the contained string. Method_missing is also responsible for making the bang! methods destructive.
-    def method_missing(m, *a, &amp;b)
-      begin
-        # Simulate methods with a ! at the end because we can't touch the enclosed string from the handlers.
-        if m.to_s =~ /^(.*)\!$/ &amp;&amp; handler.respond_to?($1)
-          result = handler.send($1, @string, *a, &amp;b)
-          if result == @string
-            result = nil
+      # Returns &lt;tt&gt;-1&lt;/tt&gt;, &lt;tt&gt;0&lt;/tt&gt; or &lt;tt&gt;+1&lt;/tt&gt; depending on whether the Chars object is to be sorted before,
+      # equal or after the object on the right side of the operation. It accepts any object that implements +to_s+.
+      # See &lt;tt&gt;String#&lt;=&gt;&lt;/tt&gt; for more details.
+      #
+      # Example:
+      #   '&#233;'.mb_chars &lt;=&gt; '&#252;'.mb_chars #=&gt; -1
+      def &lt;=&gt;(other)
+        @wrapped_string &lt;=&gt; other.to_s
+      end
+
+      # Returns a new Chars object containing the _other_ object concatenated to the string.
+      #
+      # Example:
+      #   ('Caf&#233;'.mb_chars + ' p&#233;rifer&#244;l').to_s #=&gt; &quot;Caf&#233; p&#233;rifer&#244;l&quot;
+      def +(other)
+        self &lt;&lt; other
+      end
+
+      # Like &lt;tt&gt;String#=~&lt;/tt&gt; only it returns the character offset (in codepoints) instead of the byte offset.
+      #
+      # Example:
+      #   'Caf&#233; p&#233;rifer&#244;l'.mb_chars =~ /&#244;/ #=&gt; 12
+      def =~(other)
+        translate_offset(@wrapped_string =~ other)
+      end
+
+      # Works just like &lt;tt&gt;String#split&lt;/tt&gt;, with the exception that the items in the resulting list are Chars
+      # instances instead of String. This makes chaining methods easier.
+      #
+      # Example:
+      #   'Caf&#233; p&#233;rifer&#244;l'.mb_chars.split(/&#233;/).map { |part| part.upcase.to_s } #=&gt; [&quot;CAF&quot;, &quot; P&quot;, &quot;RIFER&#212;L&quot;]
+      def split(*args)
+        @wrapped_string.split(*args).map { |i| i.mb_chars }
+      end
+
+      # Inserts the passed string at specified codepoint offsets.
+      #
+      # Example:
+      #   'Caf&#233;'.mb_chars.insert(4, ' p&#233;rifer&#244;l').to_s #=&gt; &quot;Caf&#233; p&#233;rifer&#244;l&quot;
+      def insert(offset, fragment)
+        unpacked = self.class.u_unpack(@wrapped_string)
+        unless offset &gt; unpacked.length
+          @wrapped_string.replace(
+            self.class.u_unpack(@wrapped_string).insert(offset, *self.class.u_unpack(fragment)).pack('U*')
+          )
+        else
+          raise IndexError, &quot;index #{offset} out of string&quot;
+        end
+        self
+      end
+
+      # Returns +true+ if contained string contains _other_. Returns +false+ otherwise.
+      #
+      # Example:
+      #   'Caf&#233;'.mb_chars.include?('&#233;') #=&gt; true
+      def include?(other)
+        # We have to redefine this method because Enumerable defines it.
+        @wrapped_string.include?(other)
+      end
+
+      # Returns the position _needle_ in the string, counting in codepoints. Returns +nil+ if _needle_ isn't found.
+      #
+      # Example:
+      #   'Caf&#233; p&#233;rifer&#244;l'.mb_chars.index('&#244;') #=&gt; 12
+      #   'Caf&#233; p&#233;rifer&#244;l'.mb_chars.index(/\w/u) #=&gt; 0
+      def index(needle, offset=0)
+        index = @wrapped_string.index(needle, offset)
+        index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil
+      end
+
+      # Like &lt;tt&gt;String#[]=&lt;/tt&gt;, except instead of byte offsets you specify character offsets.
+      #
+      # Example:
+      #
+      #   s = &quot;M&#252;ller&quot;
+      #   s.mb_chars[2] = &quot;e&quot; # Replace character with offset 2
+      #   s
+      #   #=&gt; &quot;M&#252;eler&quot;
+      #
+      #   s = &quot;M&#252;ller&quot;
+      #   s.mb_chars[1, 2] = &quot;&#246;&quot; # Replace 2 characters at character offset 1
+      #   s
+      #   #=&gt; &quot;M&#246;ler&quot;
+      def []=(*args)
+        replace_by = args.pop
+        # Indexed replace with regular expressions already works
+        if args.first.is_a?(Regexp)
+          @wrapped_string[*args] = replace_by
+        else
+          result = self.class.u_unpack(@wrapped_string)
+          if args[0].is_a?(Fixnum)
+            raise IndexError, &quot;index #{args[0]} out of string&quot; if args[0] &gt;= result.length
+            min = args[0]
+            max = args[1].nil? ? min : (min + args[1] - 1)
+            range = Range.new(min, max)
+            replace_by = [replace_by].pack('U') if replace_by.is_a?(Fixnum)
+          elsif args.first.is_a?(Range)
+            raise RangeError, &quot;#{args[0]} out of range&quot; if args[0].min &gt;= result.length
+            range = args[0]
           else
-            @string.replace result
+            needle = args[0].to_s
+            min = index(needle)
+            max = min + self.class.u_unpack(needle).length - 1
+            range = Range.new(min, max)
           end
-        elsif handler.respond_to?(m)
-          result = handler.send(m, @string, *a, &amp;b)
-        else
-          result = @string.send(m, *a, &amp;b)
+          result[range] = self.class.u_unpack(replace_by)
+          @wrapped_string.replace(result.pack('U*'))
         end
-      rescue Handlers::EncodingError
-        @string.replace handler.tidy_bytes(@string)
-        retry
       end
-      
-      if result.kind_of?(String)
-        result.chars
-      else
-        result
+
+      # Works just like &lt;tt&gt;String#rjust&lt;/tt&gt;, only integer specifies characters instead of bytes.
+      #
+      # Example:
+      #
+      #   &quot;&#190; cup&quot;.mb_chars.rjust(8).to_s
+      #   #=&gt; &quot;   &#190; cup&quot;
+      #
+      #   &quot;&#190; cup&quot;.mb_chars.rjust(8, &quot;&#160;&quot;).to_s # Use non-breaking whitespace
+      #   #=&gt; &quot;&#160;&#160;&#160;&#190; cup&quot;
+      def rjust(integer, padstr=' ')
+        justify(integer, :right, padstr)
       end
-    end
-    
-    # Set the handler class for the Char objects.
-    def self.handler=(klass)
-      @@handler = klass
-    end
 
-    # Returns the proper handler for the contained string depending on $KCODE and the encoding of the string. This
-    # method is used internally to always redirect messages to the proper classes depending on the context.
-    def handler
-      if utf8_pragma?
-        @@handler
-      else
-        ActiveSupport::Multibyte::Handlers::PassthruHandler
+      # Works just like &lt;tt&gt;String#ljust&lt;/tt&gt;, only integer specifies characters instead of bytes.
+      #
+      # Example:
+      #
+      #   &quot;&#190; cup&quot;.mb_chars.rjust(8).to_s
+      #   #=&gt; &quot;&#190; cup   &quot;
+      #
+      #   &quot;&#190; cup&quot;.mb_chars.rjust(8, &quot;&#160;&quot;).to_s # Use non-breaking whitespace
+      #   #=&gt; &quot;&#190; cup&#160;&#160;&#160;&quot;
+      def ljust(integer, padstr=' ')
+        justify(integer, :left, padstr)
+      end
+
+      # Works just like &lt;tt&gt;String#center&lt;/tt&gt;, only integer specifies characters instead of bytes.
+      #
+      # Example:
+      #
+      #   &quot;&#190; cup&quot;.mb_chars.center(8).to_s
+      #   #=&gt; &quot; &#190; cup  &quot;
+      #
+      #   &quot;&#190; cup&quot;.mb_chars.center(8, &quot;&#160;&quot;).to_s # Use non-breaking whitespace
+      #   #=&gt; &quot;&#160;&#190; cup&#160;&#160;&quot;
+      def center(integer, padstr=' ')
+        justify(integer, :center, padstr)
       end
-    end
 
-    private
+      # Strips entire range of Unicode whitespace from the right of the string.
+      def rstrip
+        chars(@wrapped_string.gsub(UNICODE_TRAILERS_PAT, ''))
+      end
+      
+      # Strips entire range of Unicode whitespace from the left of the string.
+      def lstrip
+        chars(@wrapped_string.gsub(UNICODE_LEADERS_PAT, ''))
+      end
+      
+      # Strips entire range of Unicode whitespace from the right and left of the string.
+      def strip
+        rstrip.lstrip
+      end
+      
+      # Returns the number of codepoints in the string
+      def size
+        self.class.u_unpack(@wrapped_string).size
+      end
+      alias_method :length, :size
       
-      # +utf8_pragma+ checks if it can send this string to the handlers. It makes sure @string isn't nil and $KCODE is
-      # set to 'UTF8'.
-      def utf8_pragma?
-        !@string.nil? &amp;&amp; ($KCODE == 'UTF8')
+      # Reverses all characters in the string.
+      #
+      # Example:
+      #   'Caf&#233;'.mb_chars.reverse.to_s #=&gt; '&#233;faC'
+      def reverse
+        chars(self.class.u_unpack(@wrapped_string).reverse.pack('U*'))
       end
+      
+      # Implements Unicode-aware slice with codepoints. Slicing on one point returns the codepoints for that
+      # character.
+      #
+      # Example:
+      #   '&#12371;&#12395;&#12385;&#12431;'.mb_chars.slice(2..3).to_s #=&gt; &quot;&#12385;&#12431;&quot;
+      def slice(*args)
+        if args.size &gt; 2
+          raise ArgumentError, &quot;wrong number of arguments (#{args.size} for 1)&quot; # Do as if we were native
+        elsif (args.size == 2 &amp;&amp; !(args.first.is_a?(Numeric) || args.first.is_a?(Regexp)))
+          raise TypeError, &quot;cannot convert #{args.first.class} into Integer&quot; # Do as if we were native
+        elsif (args.size == 2 &amp;&amp; !args[1].is_a?(Numeric))
+          raise TypeError, &quot;cannot convert #{args[1].class} into Integer&quot; # Do as if we were native
+        elsif args[0].kind_of? Range
+          cps = self.class.u_unpack(@wrapped_string).slice(*args)
+          result = cps.nil? ? nil : cps.pack('U*')
+        elsif args[0].kind_of? Regexp
+          result = @wrapped_string.slice(*args)
+        elsif args.size == 1 &amp;&amp; args[0].kind_of?(Numeric)
+          character = self.class.u_unpack(@wrapped_string)[args[0]]
+          result = character.nil? ? nil : [character].pack('U')
+        else
+          result = self.class.u_unpack(@wrapped_string).slice(*args).pack('U*')
+        end
+        result.nil? ? nil : chars(result)
+      end
+      alias_method :[], :slice
+
+      # Convert characters in the string to uppercase.
+      #
+      # Example:
+      #   'Laurent, &#242;u sont les tests?'.mb_chars.upcase.to_s #=&gt; &quot;LAURENT, &#210;U SONT LES TESTS?&quot;
+      def upcase
+        apply_mapping :uppercase_mapping
+      end
+
+      # Convert characters in the string to lowercase.
+      #
+      # Example:
+      #   'V&#282;DA A V&#221;ZKUM'.mb_chars.downcase.to_s #=&gt; &quot;v&#283;da a v&#253;zkum&quot;
+      def downcase
+        apply_mapping :lowercase_mapping
+      end
+
+      # Converts the first character to uppercase and the remainder to lowercase.
+      #
+      # Example:
+      #  '&#252;ber'.mb_chars.capitalize.to_s #=&gt; &quot;&#220;ber&quot;
+      def capitalize
+        (slice(0) || chars('')).upcase + (slice(1..-1) || chars('')).downcase
+      end
+
+      # Returns the KC normalization of the string by default. NFKC is considered the best normalization form for
+      # passing strings to databases and validations.
+      #
+      # * &lt;tt&gt;str&lt;/tt&gt; - The string to perform normalization on.
+      # * &lt;tt&gt;form&lt;/tt&gt; - The form you want to normalize in. Should be one of the following:
+      #   &lt;tt&gt;:c&lt;/tt&gt;, &lt;tt&gt;:kc&lt;/tt&gt;, &lt;tt&gt;:d&lt;/tt&gt;, or &lt;tt&gt;:kd&lt;/tt&gt;. Default is
+      #   ActiveSupport::Multibyte.default_normalization_form
+      def normalize(form=ActiveSupport::Multibyte.default_normalization_form)
+        # See http://www.unicode.org/reports/tr15, Table 1
+        codepoints = self.class.u_unpack(@wrapped_string)
+        chars(case form
+          when :d
+            self.class.reorder_characters(self.class.decompose_codepoints(:canonical, codepoints))
+          when :c
+            self.class.compose_codepoints(self.class.reorder_characters(self.class.decompose_codepoints(:canonical, codepoints)))
+          when :kd
+            self.class.reorder_characters(self.class.decompose_codepoints(:compatability, codepoints))
+          when :kc
+            self.class.compose_codepoints(self.class.reorder_characters(self.class.decompose_codepoints(:compatability, codepoints)))
+          else
+            raise ArgumentError, &quot;#{form} is not a valid normalization variant&quot;, caller
+        end.pack('U*'))
+      end
+
+      # Performs canonical decomposition on all the characters.
+      #
+      # Example:
+      #   '&#233;'.length #=&gt; 2
+      #   '&#233;'.mb_chars.decompose.to_s.length #=&gt; 3
+      def decompose
+        chars(self.class.decompose_codepoints(:canonical, self.class.u_unpack(@wrapped_string)).pack('U*'))
+      end
+
+      # Performs composition on all the characters.
+      #
+      # Example:
+      #   '&#233;'.length #=&gt; 3
+      #   '&#233;'.mb_chars.compose.to_s.length #=&gt; 2
+      def compose
+        chars(self.class.compose_codepoints(self.class.u_unpack(@wrapped_string)).pack('U*'))
+      end
+
+      # Returns the number of grapheme clusters in the string.
+      #
+      # Example:
+      #   '&#2325;&#2381;&#2359;&#2367;'.mb_chars.length #=&gt; 4
+      #   '&#2325;&#2381;&#2359;&#2367;'.mb_chars.g_length #=&gt; 3
+      def g_length
+        self.class.g_unpack(@wrapped_string).length
+      end
+
+      # Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.
+      def tidy_bytes
+        chars(self.class.tidy_bytes(@wrapped_string))
+      end
+
+      %w(lstrip rstrip strip reverse upcase downcase slice tidy_bytes capitalize).each do |method|
+        define_method(&quot;#{method}!&quot;) do |*args|
+          unless args.nil?
+            @wrapped_string = send(method, *args).to_s
+          else
+            @wrapped_string = send(method).to_s
+          end
+          self
+        end
+      end
+
+      class &lt;&lt; self
+
+        # Unpack the string at codepoints boundaries. Raises an EncodingError when the encoding of the string isn't
+        # valid UTF-8.
+        #
+        # Example:
+        #   Chars.u_unpack('Caf&#233;') #=&gt; [67, 97, 102, 233]
+        def u_unpack(string)
+          begin
+            string.unpack 'U*'
+          rescue ArgumentError
+            raise EncodingError, 'malformed UTF-8 character'
+          end
+        end
+
+        # Detect whether the codepoint is in a certain character class. Returns +true+ when it's in the specified
+        # character class and +false+ otherwise. Valid character classes are: &lt;tt&gt;:cr&lt;/tt&gt;, &lt;tt&gt;:lf&lt;/tt&gt;, &lt;tt&gt;:l&lt;/tt&gt;,
+        # &lt;tt&gt;:v&lt;/tt&gt;, &lt;tt&gt;:lv&lt;/tt&gt;, &lt;tt&gt;:lvt&lt;/tt&gt; and &lt;tt&gt;:t&lt;/tt&gt;.
+        #
+        # Primarily used by the grapheme cluster support.
+        def in_char_class?(codepoint, classes)
+          classes.detect { |c| UCD.boundary[c] === codepoint } ? true : false
+        end
+
+        # Unpack the string at grapheme boundaries. Returns a list of character lists.
+        #
+        # Example:
+        #   Chars.g_unpack('&#2325;&#2381;&#2359;&#2367;') #=&gt; [[2325, 2381], [2359], [2367]]
+        #   Chars.g_unpack('Caf&#233;') #=&gt; [[67], [97], [102], [233]]
+        def g_unpack(string)
+          codepoints = u_unpack(string)
+          unpacked = []
+          pos = 0
+          marker = 0
+          eoc = codepoints.length
+          while(pos &lt; eoc)
+            pos += 1
+            previous = codepoints[pos-1]
+            current = codepoints[pos]
+            if (
+                # CR X LF
+                one = ( previous == UCD.boundary[:cr] and current == UCD.boundary[:lf] ) or
+                # L X (L|V|LV|LVT)
+                two = ( UCD.boundary[:l] === previous and in_char_class?(current, [:l,:v,:lv,:lvt]) ) or
+                # (LV|V) X (V|T)
+                three = ( in_char_class?(previous, [:lv,:v]) and in_char_class?(current, [:v,:t]) ) or
+                # (LVT|T) X (T)
+                four = ( in_char_class?(previous, [:lvt,:t]) and UCD.boundary[:t] === current ) or
+                # X Extend
+                five = (UCD.boundary[:extend] === current)
+              )
+            else
+              unpacked &lt;&lt; codepoints[marker..pos-1]
+              marker = pos
+            end
+          end 
+          unpacked
+        end
+
+        # Reverse operation of g_unpack.
+        #
+        # Example:
+        #   Chars.g_pack(Chars.g_unpack('&#2325;&#2381;&#2359;&#2367;')) #=&gt; '&#2325;&#2381;&#2359;&#2367;'
+        def g_pack(unpacked)
+          (unpacked.flatten).pack('U*')
+        end
+
+        def padding(padsize, padstr=' ') #:nodoc:
+          if padsize != 0
+            new(padstr * ((padsize / u_unpack(padstr).size) + 1)).slice(0, padsize)
+          else
+            ''
+          end
+        end
+
+        # Re-order codepoints so the string becomes canonical.
+        def reorder_characters(codepoints)
+          length = codepoints.length- 1
+          pos = 0
+          while pos &lt; length do
+            cp1, cp2 = UCD.codepoints[codepoints[pos]], UCD.codepoints[codepoints[pos+1]]
+            if (cp1.combining_class &gt; cp2.combining_class) &amp;&amp; (cp2.combining_class &gt; 0)
+              codepoints[pos..pos+1] = cp2.code, cp1.code
+              pos += (pos &gt; 0 ? -1 : 1)
+            else
+              pos += 1
+            end
+          end
+          codepoints
+        end
+
+        # Decompose composed characters to the decomposed form.
+        def decompose_codepoints(type, codepoints)
+          codepoints.inject([]) do |decomposed, cp|
+            # if it's a hangul syllable starter character
+            if HANGUL_SBASE &lt;= cp and cp &lt; HANGUL_SLAST
+              sindex = cp - HANGUL_SBASE
+              ncp = [] # new codepoints
+              ncp &lt;&lt; HANGUL_LBASE + sindex / HANGUL_NCOUNT
+              ncp &lt;&lt; HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
+              tindex = sindex % HANGUL_TCOUNT
+              ncp &lt;&lt; (HANGUL_TBASE + tindex) unless tindex == 0
+              decomposed.concat ncp
+            # if the codepoint is decomposable in with the current decomposition type
+            elsif (ncp = UCD.codepoints[cp].decomp_mapping) and (!UCD.codepoints[cp].decomp_type || type == :compatability)
+              decomposed.concat decompose_codepoints(type, ncp.dup)
+            else
+              decomposed &lt;&lt; cp
+            end
+          end
+        end
+
+        # Compose decomposed characters to the composed form.
+        def compose_codepoints(codepoints)
+          pos = 0
+          eoa = codepoints.length - 1
+          starter_pos = 0
+          starter_char = codepoints[0]
+          previous_combining_class = -1
+          while pos &lt; eoa
+            pos += 1
+            lindex = starter_char - HANGUL_LBASE
+            # -- Hangul
+            if 0 &lt;= lindex and lindex &lt; HANGUL_LCOUNT
+              vindex = codepoints[starter_pos+1] - HANGUL_VBASE rescue vindex = -1
+              if 0 &lt;= vindex and vindex &lt; HANGUL_VCOUNT
+                tindex = codepoints[starter_pos+2] - HANGUL_TBASE rescue tindex = -1
+                if 0 &lt;= tindex and tindex &lt; HANGUL_TCOUNT
+                  j = starter_pos + 2
+                  eoa -= 2
+                else
+                  tindex = 0
+                  j = starter_pos + 1
+                  eoa -= 1
+                end
+                codepoints[starter_pos..j] = (lindex * HANGUL_VCOUNT + vindex) * HANGUL_TCOUNT + tindex + HANGUL_SBASE
+              end
+              starter_pos += 1
+              starter_char = codepoints[starter_pos]
+            # -- Other characters
+            else
+              current_char = codepoints[pos]
+              current = UCD.codepoints[current_char]
+              if current.combining_class &gt; previous_combining_class
+                if ref = UCD.composition_map[starter_char]
+                  composition = ref[current_char]
+                else
+                  composition = nil
+                end
+                unless composition.nil?
+                  codepoints[starter_pos] = composition
+                  starter_char = composition
+                  codepoints.delete_at pos
+                  eoa -= 1
+                  pos -= 1
+                  previous_combining_class = -1
+                else
+                  previous_combining_class = current.combining_class
+                end
+              else
+                previous_combining_class = current.combining_class
+              end
+              if current.combining_class == 0
+                starter_pos = pos
+                starter_char = codepoints[pos]
+              end
+            end
+          end
+          codepoints
+        end
+
+        # Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.
+        def tidy_bytes(string)
+          string.split(//u).map do |c|
+            if !UTF8_PAT.match(c)
+              n = c.unpack('C')[0]
+              n &lt; 128 ? n.chr :
+              n &lt; 160 ? [UCD.cp1252[n] || n].pack('U') :
+              n &lt; 192 ? &quot;\xC2&quot; + n.chr : &quot;\xC3&quot; + (n-64).chr
+            else
+              c
+            end
+          end.join
+        end
+      end
+
+      protected
+
+        def translate_offset(byte_offset) #:nodoc:
+          return nil if byte_offset.nil?
+          return 0   if @wrapped_string == ''
+          chunk = @wrapped_string[0..byte_offset]
+          begin
+            begin
+              chunk.unpack('U*').length - 1
+            rescue ArgumentError =&gt; e
+              chunk = @wrapped_string[0..(byte_offset+=1)]
+              # Stop retrying at the end of the string
+              raise e unless byte_offset &lt; chunk.length 
+              # We damaged a character, retry
+              retry
+            end
+          # Catch the ArgumentError so we can throw our own
+          rescue ArgumentError 
+            raise EncodingError, 'malformed UTF-8 character'
+          end
+        end
+
+        def justify(integer, way, padstr=' ') #:nodoc:
+          raise ArgumentError, &quot;zero width padding&quot; if padstr.length == 0
+          padsize = integer - size
+          padsize = padsize &gt; 0 ? padsize : 0
+          case way
+          when :right
+            result = @wrapped_string.dup.insert(0, self.class.padding(padsize, padstr))
+          when :left
+            result = @wrapped_string.dup.insert(-1, self.class.padding(padsize, padstr))
+          when :center
+            lpad = self.class.padding((padsize / 2.0).floor, padstr)
+            rpad = self.class.padding((padsize / 2.0).ceil, padstr)
+            result = @wrapped_string.dup.insert(0, lpad).insert(-1, rpad)
+          end
+          chars(result)
+        end
+
+        def apply_mapping(mapping) #:nodoc:
+          chars(self.class.u_unpack(@wrapped_string).map do |codepoint|
+            cp = UCD.codepoints[codepoint]
+            if cp and (ncp = cp.send(mapping)) and ncp &gt; 0
+              ncp
+            else
+              codepoint
+            end
+          end.pack('U*'))
+        end
+
+        def chars(string) #:nodoc:
+          self.class.new(string)
+        end
+    end
   end
-end
-
-# When we can load the utf8proc library, override normalization with the faster methods
-begin
-  require 'utf8proc_native'
-  require 'active_support/multibyte/handlers/utf8_handler_proc'
-  ActiveSupport::Multibyte::Chars.handler = ActiveSupport::Multibyte::Handlers::UTF8HandlerProc
-rescue LoadError
-  ActiveSupport::Multibyte::Chars.handler = ActiveSupport::Multibyte::Handlers::UTF8Handler
-end
+end
\ No newline at end of file</diff>
      <filename>vendor/rails/activesupport/lib/active_support/multibyte/chars.rb</filename>
    </modified>
    <modified>
      <diff>@@ -164,13 +164,13 @@ module ActiveSupport
           hex = n.to_s(16)
           hex = '0' + hex if (hex.length &amp; 1) == 1
           bin = [hex].pack(&quot;H*&quot;)
-          mask = bin[0].ord
+          mask = bin[0]
           mask |= mask &gt;&gt; 1
           mask |= mask &gt;&gt; 2
           mask |= mask &gt;&gt; 4
           begin
             rnd = SecureRandom.random_bytes(bin.length)
-            rnd[0] = (rnd[0].ord &amp; mask).chr
+            rnd[0] = rnd[0] &amp; mask
           end until rnd &lt; bin
           rnd.unpack(&quot;H*&quot;)[0].hex
         else</diff>
      <filename>vendor/rails/activesupport/lib/active_support/secure_random.rb</filename>
    </modified>
    <modified>
      <diff>@@ -37,15 +37,18 @@ module Test
       #   end
       def assert_difference(expressions, difference = 1, message = nil, &amp;block)
         expression_evaluations = Array(expressions).map do |expression|
-          lambda do
+          [expression, lambda do
             eval(expression, block.__send__(:binding))
-          end
+          end]
         end
 
-        original_values = expression_evaluations.inject([]) { |memo, expression| memo &lt;&lt; expression.call }
+        original_values = expression_evaluations.inject([]) { |memo, expression| memo &lt;&lt; expression[1].call }
         yield
         expression_evaluations.each_with_index do |expression, i|
-          assert_equal original_values[i] + difference, expression.call, message
+          full_message = &quot;&quot;
+          full_message &lt;&lt; &quot;#{message}.\n&quot; if message
+          full_message &lt;&lt; &quot;&lt;#{expression[0]}&gt; was the expression that failed&quot;
+          assert_equal original_values[i] + difference, expression[1].call, full_message
         end
       end
 </diff>
      <filename>vendor/rails/activesupport/lib/active_support/testing/core_ext/test/unit/assertions.rb</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>vendor/rails/activesupport/lib/active_support/values/unicode_tables.dat</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,8 @@ require 'i18n/exceptions'
 
 module I18n  
   @@backend = nil
-  @@default_locale = 'en-US'
+  @@load_path = nil
+  @@default_locale = :'en-US'
   @@exception_handler = :default_exception_handler
     
   class &lt;&lt; self
@@ -49,14 +50,22 @@ module I18n
       @@exception_handler = exception_handler
     end
     
-    # Allows client libraries to pass arguments that specify a source for 
-    # translation data to be loaded by the backend. The backend defines
-    # acceptable sources. 
+    # Allow clients to register paths providing translation data sources. The
+    # backend defines acceptable sources.
+    #
     # E.g. the provided SimpleBackend accepts a list of paths to translation
     # files which are either named *.rb and contain plain Ruby Hashes or are
-    # named *.yml and contain YAML data.)
-    def load_translations(*args)
-      backend.load_translations(*args)
+    # named *.yml and contain YAML data. So for the SimpleBackend clients may
+    # register translation files like this:
+    #   I18n.load_path &lt;&lt; 'path/to/locale/en-US.yml'
+    def load_path
+      @@load_path ||= []
+    end
+
+    # Sets the load path instance. Custom implementations are expected to
+    # behave like a Ruby Array.
+    def load_path=(load_path)
+      @@load_path = load_path
     end
     
     # Translates, pluralizes and interpolates a given key using a given locale, 
@@ -175,6 +184,4 @@ module I18n
       keys.flatten.map{|k| k.to_sym}
     end
   end
-end
-
-
+end
\ No newline at end of file</diff>
      <filename>vendor/rails/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,9 @@
-require 'strscan'
+require 'yaml'
 
 module I18n
   module Backend
     class Simple
       INTERPOLATION_RESERVED_KEYS = %w(scope default)
-      DEPRECATED_INTERPOLATORS = { '%d' =&gt; '{{count}}', '%s' =&gt; '{{value}}' }
       MATCH = /(\\\\)?\{\{([^\}]+)\}\}/
 
       # Accepts a list of paths to translation files. Loads translations from 
@@ -31,7 +30,13 @@ module I18n
         options.delete(:default)
         values = options.reject{|name, value| reserved.include? name }
 
-        entry = lookup(locale, key, scope) || default(locale, default, options) || raise(I18n::MissingTranslationData.new(locale, key, options))
+        entry = lookup(locale, key, scope)
+        if entry.nil?
+          entry = default(locale, default, options)
+          if entry.nil?
+            raise(I18n::MissingTranslationData.new(locale, key, options))
+          end
+        end
         entry = pluralize locale, entry, count
         entry = interpolate locale, entry, values
         entry
@@ -60,7 +65,16 @@ module I18n
         object.strftime(format)
       end
       
+      def initialized?
+        @initialized ||= false
+      end
+
       protected
+
+        def init_translations
+          load_translations(*I18n.load_path)
+          @initialized = true
+        end
         
         def translations
           @translations ||= {}
@@ -73,8 +87,15 @@ module I18n
         # &lt;tt&gt;%w(currency format)&lt;/tt&gt;.
         def lookup(locale, key, scope = [])
           return unless key
+          init_translations unless initialized?
           keys = I18n.send :normalize_translation_keys, locale, key, scope
-          keys.inject(translations){|result, k| result[k.to_sym] or return nil }
+          keys.inject(translations) do |result, k|
+            if (x = result[k.to_sym]).nil?
+              return nil
+            else
+              x
+            end
+          end
         end
       
         # Evaluates a default translation. 
@@ -95,7 +116,7 @@ module I18n
         rescue MissingTranslationData
           nil
         end
-      
+
         # Picks a translation from an array according to English pluralization
         # rules. It will pick the first translation if count is not equal to 1
         # and the second translation if it is equal to 1. Other backends can
@@ -120,12 +141,6 @@ module I18n
         def interpolate(locale, string, values = {})
           return string unless string.is_a?(String)
 
-          string = string.gsub(/%d|%s/) do |s|
-            instead = DEPRECATED_INTERPOLATORS[s]
-            ActiveSupport::Deprecation.warn &quot;using #{s} in messages is deprecated; use #{instead} instead.&quot;
-            instead
-          end
-
           if string.respond_to?(:force_encoding)
             original_encoding = string.encoding
             string.force_encoding(Encoding::BINARY)</diff>
      <filename>vendor/rails/activesupport/lib/active_support/vendor/i18n-0.0.1/i18n/backend/simple.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 module ActiveSupport
   module VERSION #:nodoc:
     MAJOR = 2
-    MINOR = 1
+    MINOR = 2
     TINY  = 0
 
     STRING = [MAJOR, MINOR, TINY].join('.')</diff>
      <filename>vendor/rails/activesupport/lib/active_support/version.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,15 @@
+# encoding: utf-8
+
 require 'test/unit'
 
 $:.unshift &quot;#{File.dirname(__FILE__)}/../lib&quot;
 $:.unshift File.dirname(__FILE__)
 require 'active_support'
 
+if RUBY_VERSION &lt; '1.9'
+  $KCODE = 'UTF8'
+end
+
 def uses_gem(gem_name, test_name, version = '&gt; 0')
   require 'rubygems'
   gem gem_name.to_s, version
@@ -22,3 +28,16 @@ end
 
 # Show backtraces for deprecated behavior for quicker cleanup.
 ActiveSupport::Deprecation.debug = true
+
+def with_kcode(code)
+  if RUBY_VERSION &lt; '1.9'
+    begin
+      old_kcode, $KCODE = $KCODE, code
+      yield
+    ensure
+      $KCODE = old_kcode
+    end
+  else
+    yield
+  end
+end
\ No newline at end of file</diff>
      <filename>vendor/rails/activesupport/test/abstract_unit.rb</filename>
    </modified>
    <modified>
      <diff>@@ -30,7 +30,57 @@ class DurationTest &lt; Test::Unit::TestCase
     end
   end
 
+  def test_fractional_weeks
+    assert_equal (86400 * 7) * 1.5, 1.5.weeks
+    assert_equal (86400 * 7) * 1.7, 1.7.weeks
+  end
+
+  def test_fractional_days
+    assert_equal 86400 * 1.5, 1.5.days
+    assert_equal 86400 * 1.7, 1.7.days
+  end
+
   uses_mocha 'TestDurationSinceAndAgoWithCurrentTime' do
+    def test_since_and_ago_with_fractional_days
+      Time.stubs(:now).returns Time.local(2000)
+      # since
+      assert_equal 36.hours.since, 1.5.days.since
+      assert_equal((24 * 1.7).hours.since, 1.7.days.since)
+      # ago
+      assert_equal 36.hours.ago, 1.5.days.ago
+      assert_equal((24 * 1.7).hours.ago, 1.7.days.ago)
+    end
+
+    def test_since_and_ago_with_fractional_weeks
+      Time.stubs(:now).returns Time.local(2000)
+      # since
+      assert_equal((7 * 36).hours.since, 1.5.weeks.since)
+      assert_equal((7 * 24 * 1.7).hours.since, 1.7.weeks.since)
+      # ago
+      assert_equal((7 * 36).hours.ago, 1.5.weeks.ago)
+      assert_equal((7 * 24 * 1.7).hours.ago, 1.7.weeks.ago)
+    end
+    
+    def test_deprecated_fractional_years
+      years_re = /Fractional years are not respected\. Convert value to integer before calling #years\./
+      assert_deprecated(years_re){1.0.years}
+      assert_deprecated(years_re){1.5.years}
+      assert_not_deprecated{1.years}
+      assert_deprecated(years_re){1.0.year}
+      assert_deprecated(years_re){1.5.year}
+      assert_not_deprecated{1.year}
+    end
+    
+    def test_deprecated_fractional_months
+      months_re = /Fractional months are not respected\. Convert value to integer before calling #months\./
+      assert_deprecated(months_re){1.5.months}
+      assert_deprecated(months_re){1.0.months}
+      assert_not_deprecated{1.months}
+      assert_deprecated(months_re){1.5.month}
+      assert_deprecated(months_re){1.0.month}
+      assert_not_deprecated{1.month}
+    end
+
     def test_since_and_ago_anchored_to_time_now_when_time_zone_default_not_set
       Time.zone_default = nil
       with_env_tz 'US/Eastern' do</diff>
      <filename>vendor/rails/activesupport/test/core_ext/duration_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -329,6 +329,16 @@ class HashExtTest &lt; Test::Unit::TestCase
     end
   end
 
+  def test_indifferent_slice_access_with_symbols
+    original = {'login' =&gt; 'bender', 'password' =&gt; 'shiny', 'stuff' =&gt; 'foo'}
+    original = original.with_indifferent_access
+
+    slice = original.slice(:login, :password)
+
+    assert_equal 'bender', slice[:login]
+    assert_equal 'bender', slice['login']
+  end
+
   def test_except
     original = { :a =&gt; 'x', :b =&gt; 'y', :c =&gt; 10 }
     expected = { :a =&gt; 'x', :b =&gt; 'y' }</diff>
      <filename>vendor/rails/activesupport/test/core_ext/hash_ext_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -191,13 +191,12 @@ class StringInflectionsTest &lt; Test::Unit::TestCase
 
   if RUBY_VERSION &lt; '1.9'
     def test_each_char_with_utf8_string_when_kcode_is_utf8
-      old_kcode, $KCODE = $KCODE, 'UTF8'
-      '&#8364;2.99'.each_char do |char|
-        assert_not_equal 1, char.length
-        break
+      with_kcode('UTF8') do
+        '&#8364;2.99'.each_char do |char|
+          assert_not_equal 1, char.length
+          break
+        end
       end
-    ensure
-      $KCODE = old_kcode
     end
   end
 end
@@ -206,4 +205,52 @@ class StringBehaviourTest &lt; Test::Unit::TestCase
   def test_acts_like_string
     assert 'Bambi'.acts_like_string?
   end
+end
+
+class CoreExtStringMultibyteTest &lt; Test::Unit::TestCase
+  UNICODE_STRING = '&#12371;&#12395;&#12385;&#12431;'
+  ASCII_STRING = 'ohayo'
+  BYTE_STRING = &quot;\270\236\010\210\245&quot;
+
+  def test_core_ext_adds_mb_chars
+    assert UNICODE_STRING.respond_to?(:mb_chars)
+  end
+
+  def test_string_should_recognize_utf8_strings
+    assert UNICODE_STRING.is_utf8?
+    assert ASCII_STRING.is_utf8?
+    assert !BYTE_STRING.is_utf8?
+  end
+
+  if RUBY_VERSION &lt; '1.8.7'
+    def test_core_ext_adds_chars
+      assert UNICODE_STRING.respond_to?(:chars)
+    end
+
+    def test_chars_warns_about_deprecation
+      assert_deprecated(&quot;String#chars&quot;) do
+        ''.chars
+      end
+    end
+  end
+
+  if RUBY_VERSION &lt; '1.9'
+    def test_mb_chars_returns_self_when_kcode_not_set
+      with_kcode('none') do
+        assert UNICODE_STRING.mb_chars.kind_of?(String)
+      end
+    end
+
+    def test_mb_chars_returns_an_instance_of_the_chars_proxy_when_kcode_utf8
+      with_kcode('UTF8') do
+        assert UNICODE_STRING.mb_chars.kind_of?(ActiveSupport::Multibyte.proxy_class)
+      end
+    end
+  end
+
+  if RUBY_VERSION &gt;= '1.9'
+    def test_mb_chars_returns_string
+      assert UNICODE_STRING.mb_chars.kind_of?(String)
+    end
+  end
 end
\ No newline at end of file</diff>
      <filename>vendor/rails/activesupport/test/core_ext/string_ext_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -117,6 +117,7 @@ class TimeExtCalculationsTest &lt; Test::Unit::TestCase
     assert_equal Time.local(2007,3,31,23,59,59), Time.local(2007,3,31,0,0,0).end_of_quarter
     assert_equal Time.local(2007,12,31,23,59,59), Time.local(2007,12,21,10,10,10).end_of_quarter
     assert_equal Time.local(2007,6,30,23,59,59), Time.local(2007,4,1,0,0,0).end_of_quarter
+    assert_equal Time.local(2008,6,30,23,59,59), Time.local(2008,5,31,0,0,0).end_of_quarter
   end
 
   def test_end_of_year
@@ -380,7 +381,11 @@ class TimeExtCalculationsTest &lt; Test::Unit::TestCase
     assert_equal Time.local(2006,2,28,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years =&gt; 1)
     assert_equal Time.local(2005,6,28,15,15,10), Time.local(2005,2,28,15,15,10).advance(:months =&gt; 4)
     assert_equal Time.local(2005,3,21,15,15,10), Time.local(2005,2,28,15,15,10).advance(:weeks =&gt; 3)
+    assert_equal Time.local(2005,3,25,3,15,10), Time.local(2005,2,28,15,15,10).advance(:weeks =&gt; 3.5)
+    assert_equal Time.local(2005,3,26,12,51,10), Time.local(2005,2,28,15,15,10).advance(:weeks =&gt; 3.7)
     assert_equal Time.local(2005,3,5,15,15,10), Time.local(2005,2,28,15,15,10).advance(:days =&gt; 5)
+    assert_equal Time.local(2005,3,6,3,15,10), Time.local(2005,2,28,15,15,10).advance(:days =&gt; 5.5)
+    assert_equal Time.local(2005,3,6,8,3,10), Time.local(2005,2,28,15,15,10).advance(:days =&gt; 5.7)
     assert_equal Time.local(2012,9,28,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years =&gt; 7, :months =&gt; 7)
     assert_equal Time.local(2013,10,3,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years =&gt; 7, :months =&gt; 19, :days =&gt; 5)
     assert_equal Time.local(2013,10,17,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years =&gt; 7, :months =&gt; 19, :weeks =&gt; 2, :days =&gt; 5)
@@ -398,7 +403,11 @@ class TimeExtCalculationsTest &lt; Test::Unit::TestCase
     assert_equal Time.utc(2006,2,22,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:years =&gt; 1)
     assert_equal Time.utc(2005,6,22,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:months =&gt; 4)
     assert_equal Time.utc(2005,3,21,15,15,10), Time.utc(2005,2,28,15,15,10).advance(:weeks =&gt; 3)
+    assert_equal Time.utc(2005,3,25,3,15,10), Time.utc(2005,2,28,15,15,10).advance(:weeks =&gt; 3.5)
+    assert_equal Time.utc(2005,3,26,12,51,10), Time.utc(2005,2,28,15,15,10).advance(:weeks =&gt; 3.7)
     assert_equal Time.utc(2005,3,5,15,15,10), Time.utc(2005,2,28,15,15,10).advance(:days =&gt; 5)
+    assert_equal Time.utc(2005,3,6,3,15,10), Time.utc(2005,2,28,15,15,10).advance(:days =&gt; 5.5)
+    assert_equal Time.utc(2005,3,6,8,3,10), Time.utc(2005,2,28,15,15,10).advance(:days =&gt; 5.7)
     assert_equal Time.utc(2012,9,22,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:years =&gt; 7, :months =&gt; 7)
     assert_equal Time.utc(2013,10,3,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:years =&gt; 7, :months =&gt; 19, :days =&gt; 11)
     assert_equal Time.utc(2013,10,17,15,15,10), Time.utc(2005,2,28,15,15,10).advance(:years =&gt; 7, :months =&gt; 19, :weeks =&gt; 2, :days =&gt; 5)</diff>
      <filename>vendor/rails/activesupport/test/core_ext/time_ext_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -72,4 +72,20 @@ class I18nTest &lt; Test::Unit::TestCase
   def test_time_pm
     assert_equal 'pm', I18n.translate(:'time.pm')
   end
+
+  def test_sentence_connector
+    assert_equal 'and', I18n.translate(:'support.array.sentence_connector')
+  end
+
+  def test_skip_last_comma
+    assert_equal false, I18n.translate(:'support.array.skip_last_comma')
+  end
+
+  def test_to_sentence
+    assert_equal 'a, b, and c', %w[a b c].to_sentence
+    I18n.backend.store_translations 'en-US', :support =&gt; { :array =&gt; { :skip_last_comma =&gt; true } }
+    assert_equal 'a, b and c', %w[a b c].to_sentence
+  ensure
+    I18n.backend.store_translations 'en-US', :support =&gt; { :array =&gt; { :skip_last_comma =&gt; false } }
+  end
 end</diff>
      <filename>vendor/rails/activesupport/test/i18n_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -104,6 +104,12 @@ class InflectorTest &lt; Test::Unit::TestCase
     end
   end
 
+  def test_parameterize_with_custom_separator
+    StringToParameterized.each do |some_string, parameterized_string|
+      assert_equal(parameterized_string.gsub('-', '_'), ActiveSupport::Inflector.parameterize(some_string, '_'))
+    end
+  end
+
   def test_classify
     ClassNameToTableName.each do |class_name, table_name|
       assert_equal(class_name, ActiveSupport::Inflector.classify(table_name))</diff>
      <filename>vendor/rails/activesupport/test/inflector_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,5 @@
+# encoding: utf-8
+
 module InflectorTestCases
   SingularToPlural = {
     &quot;search&quot;      =&gt; &quot;searches&quot;,
@@ -147,7 +149,10 @@ module InflectorTestCases
     &quot;Random text with *(bad)* characters&quot; =&gt; &quot;random-text-with-bad-characters&quot;,
     &quot;Malm&#246;&quot;                               =&gt; &quot;malmo&quot;,
     &quot;Gar&#231;ons&quot;                             =&gt; &quot;garcons&quot;,
-    &quot;Allow_Under_Scores&quot;                  =&gt; &quot;allow_under_scores&quot;
+    &quot;Allow_Under_Scores&quot;                  =&gt; &quot;allow_under_scores&quot;,
+    &quot;Trailing bad characters!@#&quot;          =&gt; &quot;trailing-bad-characters&quot;,
+    &quot;!@#Leading bad characters&quot;           =&gt; &quot;leading-bad-characters&quot;,
+    &quot;Squeeze   separators&quot;                =&gt; &quot;squeeze-separators&quot;
   }
 
   UnderscoreToHuman = {</diff>
      <filename>vendor/rails/activesupport/test/inflector_test_cases.rb</filename>
    </modified>
    <modified>
      <diff>@@ -100,19 +100,19 @@ class TestJSONEncoding &lt; Test::Unit::TestCase
     ActiveSupport.use_standard_json_time_format = false
   end
 
-  protected
-    def with_kcode(code)
-      if RUBY_VERSION &lt; '1.9'
-        begin
-          old_kcode, $KCODE = $KCODE, 'UTF8'
-          yield
-        ensure
-          $KCODE = old_kcode
-        end
-      else
-        yield
-      end
+  def test_nested_hash_with_float
+    assert_nothing_raised do
+      hash = {
+        &quot;CHI&quot; =&gt; {
+          :dislay_name =&gt; &quot;chicago&quot;,
+          :latitude =&gt; 123.234
+        }
+      }
+      result = hash.to_json
     end
+  end
+
+  protected
 
     def object_keys(json_object)
       json_object[1..-2].scan(/([^{}:,\s]+):/).flatten.sort</diff>
      <filename>vendor/rails/activesupport/test/json/encoding_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -100,6 +100,11 @@ uses_mocha 'Memoizable' do
 
     def test_memoization_with_punctuation
       assert_equal true, @person.name?
+
+      assert_nothing_raised(NameError) do
+        @person.memoize_all
+        @person.unmemoize_all
+      end
     end
 
     def test_memoization_with_nil_value</diff>
      <filename>vendor/rails/activesupport/test/memoizable_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,186 +1,569 @@
 # encoding: utf-8
+
 require 'abstract_unit'
+require 'multibyte_test_helpers'
 
-if RUBY_VERSION &lt; '1.9'
+class String
+  def __method_for_multibyte_testing_with_integer_result; 1; end
+  def __method_for_multibyte_testing; 'result'; end
+  def __method_for_multibyte_testing!; 'result'; end
+end
 
-$KCODE = 'UTF8'
+class MultibyteCharsTest &lt; Test::Unit::TestCase
+  include MultibyteTestHelpers
 
-class CharsTest &lt; Test::Unit::TestCase
-  
   def setup
-    @s = {
-      :utf8 =&gt; &quot;Abcd &#1041;&#1083;&#229; &#64259; &#1073;&#1083;a  &#22475;&quot;,
-      :ascii =&gt; &quot;asci ias c iia s&quot;,
-      :bytes =&gt; &quot;\270\236\010\210\245&quot;
-    }
+    @proxy_class = ActiveSupport::Multibyte::Chars
+    @chars = @proxy_class.new UNICODE_STRING
+  end
+
+  def test_wraps_the_original_string
+    assert_equal UNICODE_STRING, @chars.to_s
+    assert_equal UNICODE_STRING, @chars.wrapped_string
   end
-  
-  def test_sanity
-    @s.each do |t, s|
-      assert s.respond_to?(:chars), &quot;All string should have the chars method (#{t})&quot;
-      assert s.respond_to?(:to_s), &quot;All string should have the to_s method (#{t})&quot;
-      assert_kind_of ActiveSupport::Multibyte::Chars, s.chars, &quot;#chars should return an instance of Chars (#{t})&quot;
+
+  def test_should_allow_method_calls_to_string
+    assert_nothing_raised do
+      @chars.__method_for_multibyte_testing
+    end
+    assert_raises NoMethodError do
+      @chars.__unknown_method
     end
   end
-  
-  def test_comparability
-    @s.each do |t, s|
-      assert_equal s, s.chars.to_s, &quot;Chars#to_s should return enclosed string unchanged&quot;
+
+  def test_forwarded_method_calls_should_return_new_chars_instance
+    assert @chars.__method_for_multibyte_testing.kind_of?(@proxy_class)
+    assert_not_equal @chars.object_id, @chars.__method_for_multibyte_testing.object_id
+  end
+
+  def test_forwarded_bang_method_calls_should_return_the_original_chars_instance
+    assert @chars.__method_for_multibyte_testing!.kind_of?(@proxy_class)
+    assert_equal @chars.object_id, @chars.__method_for_multibyte_testing!.object_id
+  end
+
+  def test_methods_are_forwarded_to_wrapped_string_for_byte_strings
+    assert_equal BYTE_STRING.class, BYTE_STRING.mb_chars.class
+  end
+
+  def test_forwarded_method_with_non_string_result_should_be_returned_vertabim
+    assert_equal ''.__method_for_multibyte_testing_with_integer_result, @chars.__method_for_multibyte_testing_with_integer_result
+  end
+
+  def test_should_concatenate
+    assert_equal 'ab', 'a'.mb_chars + 'b'
+    assert_equal 'ab', 'a' + 'b'.mb_chars
+    assert_equal 'ab', 'a'.mb_chars + 'b'.mb_chars
+
+    assert_equal 'ab', 'a'.mb_chars &lt;&lt; 'b'
+    assert_equal 'ab', 'a' &lt;&lt; 'b'.mb_chars
+    assert_equal 'ab', 'a'.mb_chars &lt;&lt; 'b'.mb_chars
+  end
+
+  def test_consumes_utf8_strings
+    assert @proxy_class.consumes?(UNICODE_STRING)
+    assert @proxy_class.consumes?(ASCII_STRING)
+    assert !@proxy_class.consumes?(BYTE_STRING)
+  end
+
+  def test_unpack_utf8_strings
+    assert_equal 4, @proxy_class.u_unpack(UNICODE_STRING).length
+    assert_equal 5, @proxy_class.u_unpack(ASCII_STRING).length
+  end
+
+  def test_unpack_raises_encoding_error_on_broken_strings
+    assert_raises(ActiveSupport::Multibyte::EncodingError) do
+      @proxy_class.u_unpack(BYTE_STRING)
     end
-    assert_nothing_raised do
-      assert_equal &quot;a&quot;, &quot;a&quot;, &quot;Normal string comparisons should be unaffected&quot;
-      assert_not_equal &quot;a&quot;, &quot;b&quot;, &quot;Normal string comparisons should be unaffected&quot;
-      assert_not_equal &quot;a&quot;.chars, &quot;b&quot;.chars, &quot;Chars objects should be comparable&quot;
-      assert_equal &quot;a&quot;.chars, &quot;A&quot;.downcase.chars, &quot;Chars objects should be comparable to each other&quot;
-      assert_equal &quot;a&quot;.chars, &quot;A&quot;.downcase, &quot;Chars objects should be comparable to strings coming from elsewhere&quot;
-    end
-    
-    assert !@s[:utf8].eql?(@s[:utf8].chars), &quot;Strict comparison is not supported&quot;
-    assert_equal @s[:utf8], @s[:utf8].chars, &quot;Chars should be compared by their enclosed string&quot;
-
-    other_string = @s[:utf8].dup
-    assert_equal other_string, @s[:utf8].chars, &quot;Chars should be compared by their enclosed string&quot;
-    assert_equal other_string.chars, @s[:utf8].chars, &quot;Chars should be compared by their enclosed string&quot;
-    
-    strings = ['builder'.chars, 'armor'.chars, 'zebra'.chars]
-    strings.sort!
-    assert_equal ['armor', 'builder', 'zebra'], strings, &quot;Chars should be sortable based on their enclosed string&quot;
-
-    # This leads to a StackLevelTooDeep exception if the comparison is not wired properly
-    assert_raise(NameError) do
-      Chars
-    end
-  end
-  
-  def test_utf8?
-    assert @s[:utf8].is_utf8?, &quot;UTF-8 strings are UTF-8&quot;
-    assert @s[:ascii].is_utf8?, &quot;All ASCII strings are also valid UTF-8&quot;
-    assert !@s[:bytes].is_utf8?, &quot;This bytestring isn't UTF-8&quot;
-  end
-  
-  # The test for the following methods are defined here because they can only be defined on the Chars class for
-  # various reasons 
-  
-  def test_gsub
-    assert_equal '&#233;xa', '&#233;da'.chars.gsub(/d/, 'x')
-    with_kcode('none') do
-      assert_equal '&#233;xa', '&#233;da'.chars.gsub(/d/, 'x')
-    end
-  end
-  
-  def test_split
-    word = &quot;e&#64259;cient&quot;
-    chars = [&quot;e&quot;, &quot;&#64259;&quot;, &quot;c&quot;, &quot;i&quot;, &quot;e&quot;, &quot;n&quot;, &quot;t&quot;]
-    assert_equal chars, word.split(//)
-    assert_equal chars, word.chars.split(//)
-    assert_kind_of ActiveSupport::Multibyte::Chars, word.chars.split(//).first, &quot;Split should return Chars instances&quot;
-  end
-  
-  def test_regexp
-    with_kcode('none') do
-      assert_equal 12, (@s[:utf8].chars =~ /&#64259;/),
-        &quot;Regex matching should be bypassed to String&quot;
-    end
-    with_kcode('UTF8') do
-      assert_equal 9, (@s[:utf8].chars =~ /&#64259;/),
-        &quot;Regex matching should be unicode aware&quot;
-      assert_nil((''.chars =~ /\d+/),
-        &quot;Non-matching regular expressions should return nil&quot;)
-    end
-  end
-
-  def test_pragma
-    if RUBY_VERSION &lt; '1.9'
-      with_kcode('UTF8') do
-        assert &quot; &quot;.chars.send(:utf8_pragma?), &quot;UTF8 pragma should be on because KCODE is UTF8&quot;
+  end
+
+  if RUBY_VERSION &lt; '1.9'
+    def test_concatenation_should_return_a_proxy_class_instance
+      assert_equal ActiveSupport::Multibyte.proxy_class, ('a'.mb_chars + 'b').class
+      assert_equal ActiveSupport::Multibyte.proxy_class, ('a'.mb_chars &lt;&lt; 'b').class
+    end
+
+    def test_ascii_strings_are_treated_at_utf8_strings
+      assert_equal ActiveSupport::Multibyte.proxy_class, ASCII_STRING.mb_chars.class
+    end
+
+    def test_concatenate_should_return_proxy_instance
+      assert(('a'.mb_chars + 'b').kind_of?(@proxy_class))
+      assert(('a'.mb_chars + 'b'.mb_chars).kind_of?(@proxy_class))
+      assert(('a'.mb_chars &lt;&lt; 'b').kind_of?(@proxy_class))
+      assert(('a'.mb_chars &lt;&lt; 'b'.mb_chars).kind_of?(@proxy_class))
+    end
+  end
+end
+
+class MultibyteCharsUTF8BehaviourTest &lt; Test::Unit::TestCase
+  include MultibyteTestHelpers
+
+  def setup
+    @chars = UNICODE_STRING.dup.mb_chars
+
+    # NEWLINE, SPACE, EM SPACE
+    @whitespace = &quot;\n#{[32, 8195].pack('U*')}&quot;
+    @whitespace.force_encoding(Encoding::UTF_8) if @whitespace.respond_to?(:force_encoding)
+    @byte_order_mark = [65279].pack('U')
+  end
+
+  if RUBY_VERSION &lt; '1.9'
+    def test_split_should_return_an_array_of_chars_instances
+      @chars.split(//).each do |character|
+        assert character.kind_of?(ActiveSupport::Multibyte.proxy_class)
       end
-      with_kcode('none') do
-        assert !&quot; &quot;.chars.send(:utf8_pragma?), &quot;UTF8 pragma should be off because KCODE is not UTF8&quot;
+    end
+
+    def test_indexed_insert_accepts_fixnums
+      @chars[2] = 32
+      assert_equal '&#12371;&#12395; &#12431;', @chars
+    end
+
+    def test_overridden_bang_methods_return_self
+      [:rstrip!, :lstrip!, :strip!, :reverse!, :upcase!, :downcase!, :capitalize!].each do |method|
+        assert_equal @chars.object_id, @chars.send(method).object_id
       end
-    else
-      assert !&quot; &quot;.chars.send(:utf8_pragma?), &quot;UTF8 pragma should be off in Ruby 1.9&quot;
-    end
-  end
-
-  def test_handler_setting
-    handler = ''.chars.handler
-    
-    ActiveSupport::Multibyte::Chars.handler = :first
-    assert_equal :first, ''.chars.handler
-    ActiveSupport::Multibyte::Chars.handler = :second
-    assert_equal :second, ''.chars.handler
-    assert_raise(NoMethodError) do
-      ''.chars.handler.split
-    end
-    
-    ActiveSupport::Multibyte::Chars.handler = handler
-  end
-  
-  def test_method_chaining
-    assert_kind_of ActiveSupport::Multibyte::Chars, ''.chars.downcase
-    assert_kind_of ActiveSupport::Multibyte::Chars, ''.chars.strip, &quot;Strip should return a Chars object&quot;
-    assert_kind_of ActiveSupport::Multibyte::Chars, ''.chars.downcase.strip, &quot;The Chars object should be &quot; +
-        &quot;forwarded down the call path for chaining&quot;
-    assert_equal 'foo', &quot;  FOO   &quot;.chars.normalize.downcase.strip, &quot;The Chars that results from the &quot; +
-      &quot; operations should be comparable to the string value of the result&quot;
-  end
-  
-  def test_passthrough_on_kcode
-    # The easiest way to check if the passthrough is in place is through #size
-    with_kcode('none') do
-      assert_equal 26, @s[:utf8].chars.size
-    end
-    with_kcode('UTF8') do
-      assert_equal 17, @s[:utf8].chars.size
-    end
-  end
-    
-  def test_destructiveness  
-    # Note that we're testing the destructiveness here and not the correct behaviour of the methods
-    str = 'ac'
-    str.chars.insert(1, 'b')
-    assert_equal 'abc', str, 'Insert should be destructive for a string'
-    
-    str = 'ac'
-    str.chars.reverse!
-    assert_equal 'ca', str, 'reverse! should be destructive for a string'
-  end
-  
-  def test_resilience
-    assert_nothing_raised do
-      assert_equal 5, @s[:bytes].chars.size, &quot;The sequence contains five interpretable bytes&quot;
+      assert_equal @chars.object_id, @chars.slice!(1).object_id
     end
-    reversed = [0xb8, 0x17e, 0x8, 0x2c6, 0xa5].reverse.pack('U*')
-    assert_nothing_raised do
-      assert_equal reversed, @s[:bytes].chars.reverse.to_s, &quot;Reversing the string should only yield interpretable bytes&quot;
+
+    def test_overridden_bang_methods_change_wrapped_string
+      [:rstrip!, :lstrip!, :strip!, :reverse!, :upcase!, :downcase!].each do |method|
+        original = ' Caf&#233; '
+        proxy = chars(original.dup)
+        proxy.send(method)
+        assert_not_equal original, proxy.to_s
+      end
+      proxy = chars('Caf&#233;')
+      proxy.slice!(3)
+      assert_equal '&#233;', proxy.to_s
+
+      proxy = chars('&#242;u')
+      proxy.capitalize!
+      assert_equal '&#210;u', proxy.to_s
     end
-    assert_nothing_raised do
-      @s[:bytes].chars.reverse!
-      assert_equal reversed, @s[:bytes].to_s, &quot;Reversing the string should only yield interpretable bytes&quot;
+  end
+
+  if RUBY_VERSION &gt;= '1.9'
+    def test_unicode_string_should_have_utf8_encoding
+      assert_equal Encoding::UTF_8, UNICODE_STRING.encoding
     end
   end
-  
-  def test_duck_typing
-    assert_equal true,  'test'.chars.respond_to?(:strip)
-    assert_equal true,  'test'.chars.respond_to?(:normalize)
-    assert_equal true,  'test'.chars.respond_to?(:normalize!)
-    assert_equal false, 'test'.chars.respond_to?(:a_method_that_doesnt_exist)
+
+  def test_identity
+    assert_equal @chars, @chars
+    assert @chars.eql?(@chars)
+    if RUBY_VERSION &lt;= '1.9'
+      assert !@chars.eql?(UNICODE_STRING)
+    else
+      assert @chars.eql?(UNICODE_STRING)
+    end
   end
-  
-  def test_acts_like_string
-    assert 'Bambi'.chars.acts_like_string?
+
+  def test_string_methods_are_chainable
+    assert chars('').insert(0, '').kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').rjust(1).kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').ljust(1).kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').center(1).kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').rstrip.kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').lstrip.kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').strip.kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').reverse.kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars(' ').slice(0).kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').upcase.kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').downcase.kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').capitalize.kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').normalize.kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').decompose.kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').compose.kind_of?(ActiveSupport::Multibyte.proxy_class)
+    assert chars('').tidy_bytes.kind_of?(ActiveSupport::Multibyte.proxy_class)
   end
 
-  protected
+  def test_should_be_equal_to_the_wrapped_string
+    assert_equal UNICODE_STRING, @chars
+    assert_equal @chars, UNICODE_STRING
+  end
 
-  def with_kcode(kcode)
-    old_kcode, $KCODE = $KCODE, kcode
-    begin
-      yield
-    ensure
-      $KCODE = old_kcode
+  def test_should_not_be_equal_to_an_other_string
+    assert_not_equal @chars, 'other'
+    assert_not_equal 'other', @chars
+  end
+
+  def test_sortability
+    words = %w(builder armor zebra).map(&amp;:mb_chars).sort
+    assert_equal %w(armor builder zebra), words
+  end
+
+  def test_should_return_character_offset_for_regexp_matches
+    assert_nil(@chars =~ /wrong/u)
+    assert_equal 0, (@chars =~ /&#12371;/u)
+    assert_equal 1, (@chars =~ /&#12395;/u)
+    assert_equal 3, (@chars =~ /&#12431;/u)
+  end
+
+  def test_should_use_character_offsets_for_insert_offsets
+    assert_equal '', ''.mb_chars.insert(0, '')
+    assert_equal '&#12371;&#12431;&#12395;&#12385;&#12431;', @chars.insert(1, '&#12431;')
+    assert_equal '&#12371;&#12431;&#12431;&#12431;&#12395;&#12385;&#12431;', @chars.insert(2, '&#12431;&#12431;')
+    assert_equal '&#12431;&#12371;&#12431;&#12431;&#12431;&#12395;&#12385;&#12431;', @chars.insert(0, '&#12431;')
+    assert_equal '&#12431;&#12371;&#12431;&#12431;&#12431;&#12395;&#12385;&#12431;', @chars.wrapped_string if RUBY_VERSION &lt; '1.9'
+  end
+
+  def test_insert_should_be_destructive
+    @chars.insert(1, '&#12431;')
+    assert_equal '&#12371;&#12431;&#12395;&#12385;&#12431;', @chars
+  end
+
+  def test_insert_throws_index_error
+    assert_raises(IndexError) { @chars.insert(-12, '&#12431;')}
+    assert_raises(IndexError) { @chars.insert(12, '&#12431;') }
+  end
+
+  def test_should_know_if_one_includes_the_other
+    assert @chars.include?('')
+    assert @chars.include?('&#12385;')
+    assert @chars.include?('&#12431;')
+    assert !@chars.include?('&#12371;&#12385;&#12431;')
+    assert !@chars.include?('a')
+  end
+
+  def test_include_raises_type_error_when_nil_is_passed
+    assert_raises(TypeError) do
+      @chars.include?(nil)
     end
   end
+
+  def test_index_should_return_character_offset
+    assert_nil @chars.index('u')
+    assert_equal 0, @chars.index('&#12371;&#12395;')
+    assert_equal 2, @chars.index('&#12385;')
+    assert_equal 3, @chars.index('&#12431;')
+  end
+
+  def test_indexed_insert_should_take_character_offsets
+    @chars[2] = 'a'
+    assert_equal '&#12371;&#12395;a&#12431;', @chars
+    @chars[2] = '&#951;&#951;'
+    assert_equal '&#12371;&#12395;&#951;&#951;&#12431;', @chars
+    @chars[3, 2] = '&#955;&#955;&#955;'
+    assert_equal '&#12371;&#12395;&#951;&#955;&#955;&#955;', @chars
+    @chars[1, 0] = &quot;&#955;&quot;
+    assert_equal '&#12371;&#955;&#12395;&#951;&#955;&#955;&#955;', @chars
+    @chars[4..6] = &quot;&#951;&#951;&quot;
+    assert_equal '&#12371;&#955;&#12395;&#951;&#951;&#951;', @chars
+    @chars[/&#951;&#951;/] = &quot;&#955;&#955;&#955;&quot;
+    assert_equal '&#12371;&#955;&#12395;&#955;&#955;&#955;&#951;', @chars
+    @chars[/(&#955;&#955;)(.)/, 2] = &quot;&#945;&quot;
+    assert_equal '&#12371;&#955;&#12395;&#955;&#955;&#945;&#951;', @chars
+    @chars[&quot;&#945;&quot;] = &quot;&#162;&quot;
+    assert_equal '&#12371;&#955;&#12395;&#955;&#955;&#162;&#951;', @chars
+    @chars[&quot;&#955;&#955;&quot;] = &quot;&#945;&#945;&#945;&quot;
+    assert_equal '&#12371;&#955;&#12395;&#945;&#945;&#945;&#162;&#951;', @chars
+  end
+
+  def test_indexed_insert_should_raise_on_index_overflow
+    before = @chars.to_s
+    assert_raises(IndexError) { @chars[10] = 'a' }
+    assert_raises(IndexError) { @chars[10, 4] = 'a' }
+    assert_raises(IndexError) { @chars[/ii/] = 'a' }
+    assert_raises(IndexError) { @chars[/()/, 10] = 'a' }
+    assert_equal before, @chars
+  end
+
+  def test_indexed_insert_should_raise_on_range_overflow
+    before = @chars.to_s
+    assert_raises(RangeError) { @chars[10..12] = 'a' }
+    assert_equal before, @chars
+  end
+
+  def test_rjust_should_raise_argument_errors_on_bad_arguments
+    assert_raises(ArgumentError) { @chars.rjust(10, '') }
+    assert_raises(ArgumentError) { @chars.rjust }
+  end
+
+  def test_rjust_should_count_characters_instead_of_bytes
+    assert_equal UNICODE_STRING, @chars.rjust(-3)
+    assert_equal UNICODE_STRING, @chars.rjust(0)
+    assert_equal UNICODE_STRING, @chars.rjust(4)
+    assert_equal &quot; #{UNICODE_STRING}&quot;, @chars.rjust(5)
+    assert_equal &quot;   #{UNICODE_STRING}&quot;, @chars.rjust(7)
+    assert_equal &quot;---#{UNICODE_STRING}&quot;, @chars.rjust(7, '-')
+    assert_equal &quot;&#945;&#945;&#945;#{UNICODE_STRING}&quot;, @chars.rjust(7, '&#945;')
+    assert_equal &quot;aba#{UNICODE_STRING}&quot;, @chars.rjust(7, 'ab')
+    assert_equal &quot;&#945;&#951;&#945;#{UNICODE_STRING}&quot;, @chars.rjust(7, '&#945;&#951;')
+    assert_equal &quot;&#945;&#951;&#945;&#951;#{UNICODE_STRING}&quot;, @chars.rjust(8, '&#945;&#951;')
+  end
+
+  def test_ljust_should_raise_argument_errors_on_bad_arguments
+    assert_raises(ArgumentError) { @chars.ljust(10, '') }
+    assert_raises(ArgumentError) { @chars.ljust }
+  end
+
+  def test_ljust_should_count_characters_instead_of_bytes
+    assert_equal UNICODE_STRING, @chars.ljust(-3)
+    assert_equal UNICODE_STRING, @chars.ljust(0)
+    assert_equal UNICODE_STRING, @chars.ljust(4)
+    assert_equal &quot;#{UNICODE_STRING} &quot;, @chars.ljust(5)
+    assert_equal &quot;#{UNICODE_STRING}   &quot;, @chars.ljust(7)
+    assert_equal &quot;#{UNICODE_STRING}---&quot;, @chars.ljust(7, '-')
+    assert_equal &quot;#{UNICODE_STRING}&#945;&#945;&#945;&quot;, @chars.ljust(7, '&#945;')
+    assert_equal &quot;#{UNICODE_STRING}aba&quot;, @chars.ljust(7, 'ab')
+    assert_equal &quot;#{UNICODE_STRING}&#945;&#951;&#945;&quot;, @chars.ljust(7, '&#945;&#951;')
+    assert_equal &quot;#{UNICODE_STRING}&#945;&#951;&#945;&#951;&quot;, @chars.ljust(8, '&#945;&#951;')
+  end
+
+  def test_center_should_raise_argument_errors_on_bad_arguments
+    assert_raises(ArgumentError) { @chars.center(10, '') }
+    assert_raises(ArgumentError) { @chars.center }
+  end
+
+  def test_center_should_count_charactes_instead_of_bytes
+    assert_equal UNICODE_STRING, @chars.center(-3)
+    assert_equal UNICODE_STRING, @chars.center(0)
+    assert_equal UNICODE_STRING, @chars.center(4)
+    assert_equal &quot;#{UNICODE_STRING} &quot;, @chars.center(5)
+    assert_equal &quot; #{UNICODE_STRING} &quot;, @chars.center(6)
+    assert_equal &quot; #{UNICODE_STRING}  &quot;, @chars.center(7)
+    assert_equal &quot;--#{UNICODE_STRING}--&quot;, @chars.center(8, '-')
+    assert_equal &quot;--#{UNICODE_STRING}---&quot;, @chars.center(9, '-')
+    assert_equal &quot;&#945;&#945;#{UNICODE_STRING}&#945;&#945;&quot;, @chars.center(8, '&#945;')
+    assert_equal &quot;&#945;&#945;#{UNICODE_STRING}&#945;&#945;&#945;&quot;, @chars.center(9, '&#945;')
+    assert_equal &quot;a#{UNICODE_STRING}ab&quot;, @chars.center(7, 'ab')
+    assert_equal &quot;ab#{UNICODE_STRING}ab&quot;, @chars.center(8, 'ab')
+    assert_equal &quot;abab#{UNICODE_STRING}abab&quot;, @chars.center(12, 'ab')
+    assert_equal &quot;&#945;#{UNICODE_STRING}&#945;&#951;&quot;, @chars.center(7, '&#945;&#951;')
+    assert_equal &quot;&#945;&#951;#{UNICODE_STRING}&#945;&#951;&quot;, @chars.center(8, '&#945;&#951;')
+  end
+
+  def test_lstrip_strips_whitespace_from_the_left_of_the_string
+    assert_equal UNICODE_STRING, UNICODE_STRING.mb_chars.lstrip
+    assert_equal UNICODE_STRING, (@whitespace + UNICODE_STRING).mb_chars.lstrip
+    assert_equal UNICODE_STRING + @whitespace, (@whitespace + UNICODE_STRING + @whitespace).mb_chars.lstrip
+  end
+
+  def test_rstrip_strips_whitespace_from_the_right_of_the_string
+    assert_equal UNICODE_STRING, UNICODE_STRING.mb_chars.rstrip
+    assert_equal UNICODE_STRING, (UNICODE_STRING + @whitespace).mb_chars.rstrip
+    assert_equal @whitespace + UNICODE_STRING, (@whitespace + UNICODE_STRING + @whitespace).mb_chars.rstrip
+  end
+
+  def test_strip_strips_whitespace
+    assert_equal UNICODE_STRING, UNICODE_STRING.mb_chars.strip
+    assert_equal UNICODE_STRING, (@whitespace + UNICODE_STRING).mb_chars.strip
+    assert_equal UNICODE_STRING, (UNICODE_STRING + @whitespace).mb_chars.strip
+    assert_equal UNICODE_STRING, (@whitespace + UNICODE_STRING + @whitespace).mb_chars.strip
+  end
+
+  def test_stripping_whitespace_leaves_whitespace_within_the_string_intact
+    string_with_whitespace = UNICODE_STRING + @whitespace + UNICODE_STRING
+    assert_equal string_with_whitespace, string_with_whitespace.mb_chars.strip
+    assert_equal string_with_whitespace, string_with_whitespace.mb_chars.lstrip
+    assert_equal string_with_whitespace, string_with_whitespace.mb_chars.rstrip
+  end
+
+  def test_size_returns_characters_instead_of_bytes
+    assert_equal 0, ''.mb_chars.size
+    assert_equal 4, @chars.size
+    assert_equal 4, @chars.length
+    assert_equal 5, ASCII_STRING.mb_chars.size
+  end
+
+  def test_reverse_reverses_characters
+    assert_equal '', ''.mb_chars.reverse
+    assert_equal '&#12431;&#12385;&#12395;&#12371;', @chars.reverse
+  end
+
+  def test_slice_should_take_character_offsets
+    assert_equal nil, ''.mb_chars.slice(0)
+    assert_equal '&#12371;', @chars.slice(0)
+    assert_equal '&#12431;', @chars.slice(3)
+    assert_equal nil, ''.mb_chars.slice(-1..1)
+    assert_equal '', ''.mb_chars.slice(0..10)
+    assert_equal '&#12395;&#12385;&#12431;', @chars.slice(1..3)
+    assert_equal '&#12395;&#12385;&#12431;', @chars.slice(1, 3)
+    assert_equal '&#12371;', @chars.slice(0, 1)
+    assert_equal '&#12385;&#12431;', @chars.slice(2..10)
+    assert_equal '', @chars.slice(4..10)
+    assert_equal '&#12395;', @chars.slice(/&#12395;/u)
+    assert_equal '&#12395;&#12385;', @chars.slice(/&#12395;\w/u)
+    assert_equal nil, @chars.slice(/unknown/u)
+    assert_equal '&#12395;&#12385;', @chars.slice(/(&#12395;&#12385;)/u, 1)
+    assert_equal nil, @chars.slice(/(&#12395;&#12385;)/u, 2)
+    assert_equal nil, @chars.slice(7..6)
+  end
+
+  def test_slice_should_throw_exceptions_on_invalid_arguments
+    assert_raise(TypeError) { @chars.slice(2..3, 1) }
+    assert_raise(TypeError) { @chars.slice(1, 2..3) }
+    assert_raise(ArgumentError) { @chars.slice(1, 1, 1) }
+  end
+
+  def test_upcase_should_upcase_ascii_characters
+    assert_equal '', ''.mb_chars.upcase
+    assert_equal 'ABC', 'aBc'.mb_chars.upcase
+  end
+
+  def test_downcase_should_downcase_ascii_characters
+    assert_equal '', ''.mb_chars.downcase
+    assert_equal 'abc', 'aBc'.mb_chars.downcase
+  end
+
+  def test_capitalize_should_work_on_ascii_characters
+    assert_equal '', ''.mb_chars.capitalize
+    assert_equal 'Abc', 'abc'.mb_chars.capitalize
+  end
+
+  def test_respond_to_knows_which_methods_the_proxy_responds_to
+    assert ''.mb_chars.respond_to?(:slice) # Defined on Chars
+    assert ''.mb_chars.respond_to?(:capitalize!) # Defined on Chars
+    assert ''.mb_chars.respond_to?(:gsub) # Defined on String
+    assert !''.mb_chars.respond_to?(:undefined_method) # Not defined
+  end
+
+  def test_acts_like_string
+    assert 'Bambi'.mb_chars.acts_like_string?
+  end
 end
 
+# The default Multibyte Chars proxy has more features than the normal string implementation. Tests
+# for the implementation of these features should run on all Ruby versions and shouldn't be tested
+# through the proxy methods.
+class MultibyteCharsExtrasTest &lt; Test::Unit::TestCase
+  include MultibyteTestHelpers
+
+  if RUBY_VERSION &gt;= '1.9'
+    def test_tidy_bytes_is_broken_on_1_9_0
+      assert_raises(ArgumentError) do
+        assert_equal_codepoints [0xfffd].pack('U'), chars(&quot;\xef\xbf\xbd&quot;).tidy_bytes
+      end
+    end
+  end
+
+  def test_upcase_should_be_unicode_aware
+    assert_equal &quot;&#1040;&#1041;&#1042;&#1043;&#1044;\0F&quot;, chars(&quot;&#1072;&#1041;&#1074;&#1075;&#1076;\0f&quot;).upcase
+    assert_equal '&#12371;&#12395;&#12385;&#12431;', chars('&#12371;&#12395;&#12385;&#12431;').upcase
+  end
+
+  def test_downcase_should_be_unicode_aware
+    assert_equal &quot;&#1072;&#1073;&#1074;&#1075;&#1076;\0f&quot;, chars(&quot;&#1072;&#1041;&#1074;&#1075;&#1076;\0f&quot;).downcase
+    assert_equal '&#12371;&#12395;&#12385;&#12431;', chars('&#12371;&#12395;&#12385;&#12431;').downcase
+  end
+
+  def test_capitalize_should_be_unicode_aware
+    { '&#1072;&#1041;&#1074;&#1075; &#1072;&#1041;&#1074;&#1075;' =&gt; '&#1040;&#1073;&#1074;&#1075; &#1072;&#1073;&#1074;&#1075;',
+      '&#1072;&#1041;&#1074;&#1075; &#1040;&#1041;&#1042;&#1043;' =&gt; '&#1040;&#1073;&#1074;&#1075; &#1072;&#1073;&#1074;&#1075;',
+      '&#1040;&#1041;&#1042;&#1043; &#1040;&#1041;&#1042;&#1043;' =&gt; '&#1040;&#1073;&#1074;&#1075; &#1072;&#1073;&#1074;&#1075;',
+      '' =&gt; '' }.each do |f,t|
+        assert_equal t, chars(f).capitalize
+    end
+  end
+
+  def test_composition_exclusion_is_set_up_properly
+    # Normalization of DEVANAGARI LETTER QA breaks when composition exclusion isn't used correctly
+    qa = [0x915, 0x93c].pack('U*')
+    assert_equal qa, chars(qa).normalize(:c)
+  end
+
+  # Test for the Public Review Issue #29, bad explanation of composition might lead to a
+  # bad implementation: http://www.unicode.org/review/pr-29.html
+  def test_normalization_C_pri_29
+    [
+      [0x0B47, 0x0300, 0x0B3E],
+      [0x1100, 0x0300, 0x1161]
+    ].map { |c| c.pack('U*') }.each do |c|
+      assert_equal_codepoints c, chars(c).normalize(:c)
+    end
+  end
+
+  def test_normalization_shouldnt_strip_null_bytes
+    null_byte_str = &quot;Test\0test&quot;
+
+    assert_equal null_byte_str, chars(null_byte_str).normalize(:kc)
+    assert_equal null_byte_str, chars(null_byte_str).normalize(:c)
+    assert_equal null_byte_str, chars(null_byte_str).normalize(:d)
+    assert_equal null_byte_str, chars(null_byte_str).normalize(:kd)
+    assert_equal null_byte_str, chars(null_byte_str).decompose
+    assert_equal null_byte_str, chars(null_byte_str).compose
+  end
+
+  def test_simple_normalization
+    comp_str = [
+      44,  # LATIN CAPITAL LETTER D
+      307, # COMBINING DOT ABOVE
+      328, # COMBINING OGONEK
+      323 # COMBINING DOT BELOW
+    ].pack(&quot;U*&quot;)
+
+    assert_equal_codepoints '', chars('').normalize
+    assert_equal_codepoints [44,105,106,328,323].pack(&quot;U*&quot;), chars(comp_str).normalize(:kc).to_s
+    assert_equal_codepoints [44,307,328,323].pack(&quot;U*&quot;), chars(comp_str).normalize(:c).to_s
+    assert_equal_codepoints [44,307,110,780,78,769].pack(&quot;U*&quot;), chars(comp_str).normalize(:d).to_s
+    assert_equal_codepoints [44,105,106,110,780,78,769].pack(&quot;U*&quot;), chars(comp_str).normalize(:kd).to_s
+  end
+
+  def test_should_compute_grapheme_length
+    [
+      ['', 0],
+      ['abc', 3],
+      ['&#12371;&#12395;&#12385;&#12431;', 4],
+      [[0x0924, 0x094D, 0x0930].pack('U*'), 2],
+      [%w(cr lf), 1],
+      [%w(l l), 1],
+      [%w(l v), 1],
+      [%w(l lv), 1],
+      [%w(l lvt), 1],
+      [%w(lv v), 1],
+      [%w(lv t), 1],
+      [%w(v v), 1],
+      [%w(v t), 1],
+      [%w(lvt t), 1],
+      [%w(t t), 1],
+      [%w(n extend), 1],
+      [%w(n n), 2],
+      [%w(n cr lf n), 3],
+      [%w(n l v t), 2]
+    ].each do |input, expected_length|
+      if input.kind_of?(Array)
+        str = string_from_classes(input)
+      else
+        str = input
+      end
+      assert_equal expected_length, chars(str).g_length
+    end
+  end
+
+  def test_tidy_bytes_should_tidy_bytes
+    byte_string = &quot;\270\236\010\210\245&quot;
+    tidy_string = [0xb8, 0x17e, 0x8, 0x2c6, 0xa5].pack('U*')
+    ascii_padding = 'aa'
+    utf8_padding = '&#233;&#233;'
+
+    assert_equal_codepoints tidy_string, chars(byte_string).tidy_bytes
+
+    assert_equal_codepoints ascii_padding.dup.insert(1, tidy_string),
+      chars(ascii_padding.dup.insert(1, byte_string)).tidy_bytes
+    assert_equal_codepoints utf8_padding.dup.insert(2, tidy_string),
+      chars(utf8_padding.dup.insert(2, byte_string)).tidy_bytes
+    assert_nothing_raised { chars(byte_string).tidy_bytes.to_s.unpack('U*') }
+
+    assert_equal_codepoints &quot;\xC3\xA7&quot;, chars(&quot;\xE7&quot;).tidy_bytes # iso_8859_1: small c cedilla
+    assert_equal_codepoints &quot;\xE2\x80\x9C&quot;, chars(&quot;\x93&quot;).tidy_bytes # win_1252: left smart quote
+    assert_equal_codepoints &quot;\xE2\x82\xAC&quot;, chars(&quot;\x80&quot;).tidy_bytes # win_1252: euro
+    assert_equal_codepoints &quot;\x00&quot;, chars(&quot;\x00&quot;).tidy_bytes # null char
+    assert_equal_codepoints [0xfffd].pack('U'), chars(&quot;\xef\xbf\xbd&quot;).tidy_bytes # invalid char
+  rescue ArgumentError =&gt; e
+    raise e if RUBY_VERSION &lt; '1.9'
+  end
+
+  private
+
+  def string_from_classes(classes)
+    # Characters from the character classes as described in UAX #29
+    character_from_class = {
+      :l =&gt; 0x1100, :v =&gt; 0x1160, :t =&gt; 0x11A8, :lv =&gt; 0xAC00, :lvt =&gt; 0xAC01, :cr =&gt; 0x000D, :lf =&gt; 0x000A,
+      :extend =&gt; 0x094D, :n =&gt; 0x64
+    }
+    classes.collect do |k|
+      character_from_class[k.intern]
+    end.pack('U*')
+  end
 end</diff>
      <filename>vendor/rails/activesupport/test/multibyte_chars_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,13 +1,11 @@
-require 'abstract_unit'
-require 'open-uri'
-
-if RUBY_VERSION &lt; '1.9'
+# encoding: utf-8
 
-$KCODE = 'UTF8'
+require 'abstract_unit'
+require 'multibyte_test_helpers'
 
-UNIDATA_URL = &quot;http://www.unicode.org/Public/#{ActiveSupport::Multibyte::UNICODE_VERSION}/ucd&quot;
-UNIDATA_FILE = '/NormalizationTest.txt'
-CACHE_DIR = File.dirname(__FILE__) + '/cache'
+require 'fileutils'
+require 'open-uri'
+require 'tmpdir'
 
 class Downloader
   def self.download(from, to)
@@ -27,17 +25,19 @@ class Downloader
   end
 end
 
-class String
-  # Unicode Inspect returns the codepoints of the string in hex
-  def ui
-    &quot;#{self} &quot; + (&quot;[%s]&quot; % unpack(&quot;U*&quot;).map{|cp| cp.to_s(16) }.join(' '))
-  end unless ''.respond_to?(:ui)
-end
-
-Dir.mkdir(CACHE_DIR) unless File.exist?(CACHE_DIR)
-Downloader.download(UNIDATA_URL + UNIDATA_FILE, CACHE_DIR + UNIDATA_FILE)
-
-module ConformanceTest
+class MultibyteConformanceTest &lt; Test::Unit::TestCase
+  include MultibyteTestHelpers
+  
+  UNIDATA_URL = &quot;http://www.unicode.org/Public/#{ActiveSupport::Multibyte::UNICODE_VERSION}/ucd&quot;
+  UNIDATA_FILE = '/NormalizationTest.txt'
+  CACHE_DIR = File.join(Dir.tmpdir, 'cache')
+  
+  def setup
+    FileUtils.mkdir_p(CACHE_DIR)
+    Downloader.download(UNIDATA_URL + UNIDATA_FILE, CACHE_DIR + UNIDATA_FILE)
+    @proxy = ActiveSupport::Multibyte::Chars
+  end
+  
   def test_normalizations_C
     each_line_of_norm_tests do |*cols|
       col1, col2, col3, col4, col5, comment = *cols
@@ -47,13 +47,13 @@ module ConformanceTest
       #
       #    NFC
       #      c2 ==  NFC(c1) ==  NFC(c2) ==  NFC(c3)
-      assert_equal col2.ui, @handler.normalize(col1, :c).ui, &quot;Form C - Col 2 has to be NFC(1) - #{comment}&quot;
-      assert_equal col2.ui, @handler.normalize(col2, :c).ui, &quot;Form C - Col 2 has to be NFC(2) - #{comment}&quot;
-      assert_equal col2.ui, @handler.normalize(col3, :c).ui, &quot;Form C - Col 2 has to be NFC(3) - #{comment}&quot;
+      assert_equal_codepoints col2, @proxy.new(col1).normalize(:c), &quot;Form C - Col 2 has to be NFC(1) - #{comment}&quot;
+      assert_equal_codepoints col2, @proxy.new(col2).normalize(:c), &quot;Form C - Col 2 has to be NFC(2) - #{comment}&quot;
+      assert_equal_codepoints col2, @proxy.new(col3).normalize(:c), &quot;Form C - Col 2 has to be NFC(3) - #{comment}&quot;
       #
       #      c4 ==  NFC(c4) ==  NFC(c5)
-      assert_equal col4.ui, @handler.normalize(col4, :c).ui, &quot;Form C - Col 4 has to be C(4) - #{comment}&quot;
-      assert_equal col4.ui, @handler.normalize(col5, :c).ui, &quot;Form C - Col 4 has to be C(5) - #{comment}&quot;
+      assert_equal_codepoints col4, @proxy.new(col4).normalize(:c), &quot;Form C - Col 4 has to be C(4) - #{comment}&quot;
+      assert_equal_codepoints col4, @proxy.new(col5).normalize(:c), &quot;Form C - Col 4 has to be C(5) - #{comment}&quot;
     end
   end
   
@@ -63,12 +63,12 @@ module ConformanceTest
       #
       #    NFD
       #      c3 ==  NFD(c1) ==  NFD(c2) ==  NFD(c3)
-      assert_equal col3.ui, @handler.normalize(col1, :d).ui, &quot;Form D - Col 3 has to be NFD(1) - #{comment}&quot;
-      assert_equal col3.ui, @handler.normalize(col2, :d).ui, &quot;Form D - Col 3 has to be NFD(2) - #{comment}&quot;
-      assert_equal col3.ui, @handler.normalize(col3, :d).ui, &quot;Form D - Col 3 has to be NFD(3) - #{comment}&quot;
+      assert_equal_codepoints col3, @proxy.new(col1).normalize(:d), &quot;Form D - Col 3 has to be NFD(1) - #{comment}&quot;
+      assert_equal_codepoints col3, @proxy.new(col2).normalize(:d), &quot;Form D - Col 3 has to be NFD(2) - #{comment}&quot;
+      assert_equal_codepoints col3, @proxy.new(col3).normalize(:d), &quot;Form D - Col 3 has to be NFD(3) - #{comment}&quot;
       #      c5 ==  NFD(c4) ==  NFD(c5)
-      assert_equal col5.ui, @handler.normalize(col4, :d).ui, &quot;Form D - Col 5 has to be NFD(4) - #{comment}&quot;
-      assert_equal col5.ui, @handler.normalize(col5, :d).ui, &quot;Form D - Col 5 has to be NFD(5) - #{comment}&quot;
+      assert_equal_codepoints col5, @proxy.new(col4).normalize(:d), &quot;Form D - Col 5 has to be NFD(4) - #{comment}&quot;
+      assert_equal_codepoints col5, @proxy.new(col5).normalize(:d), &quot;Form D - Col 5 has to be NFD(5) - #{comment}&quot;
     end
   end
   
@@ -78,11 +78,11 @@ module ConformanceTest
       #
       #    NFKC
       #      c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
-      assert_equal col4.ui, @handler.normalize(col1, :kc).ui, &quot;Form D - Col 4 has to be NFKC(1) - #{comment}&quot;
-      assert_equal col4.ui, @handler.normalize(col2, :kc).ui, &quot;Form D - Col 4 has to be NFKC(2) - #{comment}&quot;
-      assert_equal col4.ui, @handler.normalize(col3, :kc).ui, &quot;Form D - Col 4 has to be NFKC(3) - #{comment}&quot;
-      assert_equal col4.ui, @handler.normalize(col4, :kc).ui, &quot;Form D - Col 4 has to be NFKC(4) - #{comment}&quot;
-      assert_equal col4.ui, @handler.normalize(col5, :kc).ui, &quot;Form D - Col 4 has to be NFKC(5) - #{comment}&quot;
+      assert_equal_codepoints col4, @proxy.new(col1).normalize(:kc), &quot;Form D - Col 4 has to be NFKC(1) - #{comment}&quot;
+      assert_equal_codepoints col4, @proxy.new(col2).normalize(:kc), &quot;Form D - Col 4 has to be NFKC(2) - #{comment}&quot;
+      assert_equal_codepoints col4, @proxy.new(col3).normalize(:kc), &quot;Form D - Col 4 has to be NFKC(3) - #{comment}&quot;
+      assert_equal_codepoints col4, @proxy.new(col4).normalize(:kc), &quot;Form D - Col 4 has to be NFKC(4) - #{comment}&quot;
+      assert_equal_codepoints col4, @proxy.new(col5).normalize(:kc), &quot;Form D - Col 4 has to be NFKC(5) - #{comment}&quot;
     end
   end
   
@@ -92,11 +92,11 @@ module ConformanceTest
       #
       #    NFKD
       #      c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
-      assert_equal col5.ui, @handler.normalize(col1, :kd).ui, &quot;Form KD - Col 5 has to be NFKD(1) - #{comment}&quot;
-      assert_equal col5.ui, @handler.normalize(col2, :kd).ui, &quot;Form KD - Col 5 has to be NFKD(2) - #{comment}&quot;
-      assert_equal col5.ui, @handler.normalize(col3, :kd).ui, &quot;Form KD - Col 5 has to be NFKD(3) - #{comment}&quot;
-      assert_equal col5.ui, @handler.normalize(col4, :kd).ui, &quot;Form KD - Col 5 has to be NFKD(4) - #{comment}&quot;
-      assert_equal col5.ui, @handler.normalize(col5, :kd).ui, &quot;Form KD - Col 5 has to be NFKD(5) - #{comment}&quot;
+      assert_equal_codepoints col5, @proxy.new(col1).normalize(:kd), &quot;Form KD - Col 5 has to be NFKD(1) - #{comment}&quot;
+      assert_equal_codepoints col5, @proxy.new(col2).normalize(:kd), &quot;Form KD - Col 5 has to be NFKD(2) - #{comment}&quot;
+      assert_equal_codepoints col5, @proxy.new(col3).normalize(:kd), &quot;Form KD - Col 5 has to be NFKD(3) - #{comment}&quot;
+      assert_equal_codepoints col5, @proxy.new(col4).normalize(:kd), &quot;Form KD - Col 5 has to be NFKD(4) - #{comment}&quot;
+      assert_equal_codepoints col5, @proxy.new(col5).normalize(:kd), &quot;Form KD - Col 5 has to be NFKD(5) - #{comment}&quot;
     end
   end
   
@@ -104,7 +104,7 @@ module ConformanceTest
     def each_line_of_norm_tests(&amp;block)
       lines = 0
       max_test_lines = 0 # Don't limit below 38, because that's the header of the testfile
-      File.open(File.dirname(__FILE__) + '/cache' + UNIDATA_FILE, 'r') do | f |
+      File.open(File.join(CACHE_DIR, UNIDATA_FILE), 'r') do | f |
         until f.eof? || (max_test_lines &gt; 38 and lines &gt; max_test_lines)
           lines += 1
           line = f.gets.chomp!
@@ -122,25 +122,8 @@ module ConformanceTest
         end
       end
     end
-end
-
-begin
-  require_library_or_gem('utf8proc_native')
-  require 'active_record/multibyte/handlers/utf8_handler_proc'
-  class ConformanceTestProc &lt; Test::Unit::TestCase
-    include ConformanceTest
-    def setup
-      @handler = ::ActiveSupport::Multibyte::Handlers::UTF8HandlerProc
+    
+    def inspect_codepoints(str)
+      str.to_s.unpack(&quot;U*&quot;).map{|cp| cp.to_s(16) }.join(' ')
     end
-  end
-rescue LoadError
-end
-
-class ConformanceTestPure &lt; Test::Unit::TestCase
-  include ConformanceTest
-  def setup
-    @handler = ::ActiveSupport::Multibyte::Handlers::UTF8Handler
-  end
-end
-
-end
+end
\ No newline at end of file</diff>
      <filename>vendor/rails/activesupport/test/multibyte_conformance.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,4 +12,8 @@ class SecureRandomTest &lt; Test::Unit::TestCase
     b2 = ActiveSupport::SecureRandom.hex(64)
     assert_not_equal b1, b2
   end
+
+  def test_random_number
+    assert ActiveSupport::SecureRandom.random_number(5000) &lt; 5000
+  end
 end</diff>
      <filename>vendor/rails/activesupport/test/secure_random_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -60,6 +60,24 @@ class AssertDifferenceTest &lt; Test::Unit::TestCase
         @object.increment
       end
     end
+
+    def test_array_of_expressions_identify_failure
+      assert_difference ['@object.num', '1 + 1'] do
+        @object.increment
+      end
+      fail 'should not get to here'
+    rescue Test::Unit::AssertionFailedError =&gt; e
+      assert_equal &quot;&lt;1 + 1&gt; was the expression that failed.\n&lt;3&gt; expected but was\n&lt;2&gt;.&quot;, e.message
+    end
+
+    def test_array_of_expressions_identify_failure_when_message_provided
+      assert_difference ['@object.num', '1 + 1'], 1, 'something went wrong' do
+        @object.increment
+      end
+      fail 'should not get to here'
+    rescue Test::Unit::AssertionFailedError =&gt; e
+      assert_equal &quot;something went wrong.\n&lt;1 + 1&gt; was the expression that failed.\n&lt;3&gt; expected but was\n&lt;2&gt;.&quot;, e.message
+    end
   else
     def default_test; end
   end</diff>
      <filename>vendor/rails/activesupport/test/test_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -277,14 +277,19 @@ Rake::RDocTask.new { |rdoc|
 # doesn't equal its folder name, then specify a hash: { 'folder_name' =&gt; 'basename' }
 guides = [
   'getting_started_with_rails',
-  'securing_rails_applications',
-  'testing_rails_applications',
+   # 'testing_rails_applications',
   'creating_plugins',
+  'actioncontroller',
   'migrations',
+  { 'securing_rails_applications' =&gt; 'security' },
   { 'routing' =&gt; 'routing_outside_in' },
   { 'forms' =&gt;'form_helpers' },
   { 'activerecord' =&gt; 'association_basics' },
-  { 'debugging' =&gt; 'debugging_rails_applications' }
+  { 'activerecord' =&gt; 'finders' },
+  { 'debugging' =&gt; 'debugging_rails_applications' },
+  { 'caching' =&gt; 'caching_with_rails' },
+  { 'benchmarking_and_profiling' =&gt; 'preamble' },
+  { 'actionview' =&gt; 'layouts_and_rendering' }
 ]
 
 guides_html_files = []  # autogenerated from the 'guides' variable.
@@ -306,15 +311,18 @@ guides.each do |entry|
   end
 end
 
-task 'doc/guides/index.html' =&gt; 'doc/guides/index.txt' do
-  ENV.delete('MANUALSONRAILS_INDEX_URL')
-  ENV['MANUALSONRAILS_TOC'] = 'no'
-  sh &quot;mizuho&quot;, 'doc/guides/index.txt', &quot;--template&quot;, &quot;manualsonrails&quot;, &quot;--icons-dir&quot;, &quot;icons&quot;
+['index', 'authors'].each do |guide|
+  task &quot;doc/guides/#{guide}.html&quot; =&gt; &quot;doc/guides/#{guide}.txt&quot; do
+    ENV.delete('MANUALSONRAILS_INDEX_URL')
+    ENV['MANUALSONRAILS_TOC'] = 'no'
+    sh &quot;mizuho&quot;, &quot;doc/guides/#{guide}.txt&quot;, &quot;--template&quot;, &quot;manualsonrails&quot;, &quot;--icons-dir&quot;, &quot;icons&quot;
+  end
 end
 
 desc &quot;Generate HTML output for the guides&quot;
 task :generate_guides =&gt; guides_html_files
 task :generate_guides =&gt; 'doc/guides/index.html'
+task :generate_guides =&gt; 'doc/guides/authors.html'
 
 # Generate GEM ----------------------------------------------------------------------------
 </diff>
      <filename>vendor/rails/railties/Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
-ActiveRecord::Base.send :increment_open_transactions
+ActiveRecord::Base.connection.increment_open_transactions
 ActiveRecord::Base.connection.begin_db_transaction
 at_exit do
   ActiveRecord::Base.connection.rollback_db_transaction
-  ActiveRecord::Base.send :decrement_open_transactions
+  ActiveRecord::Base.connection.decrement_open_transactions
 end</diff>
      <filename>vendor/rails/railties/lib/console_sandbox.rb</filename>
    </modified>
    <modified>
      <diff>@@ -212,6 +212,7 @@ module Rails
           Gem.loaded_specs[stub] = Gem::Specification.new do |s|
             s.name = stub
             s.version = Rails::VERSION::STRING
+            s.loaded_from = &quot;&quot;
           end
         end
       end
@@ -878,7 +879,6 @@ Run `rake gems:install` to install the missing gems.
           components
           config
           lib
-          vendor
         ).map { |dir| &quot;#{root_path}/#{dir}&quot; }.select { |dir| File.directory?(dir) }
 
         paths.concat builtin_directories</diff>
      <filename>vendor/rails/railties/lib/initializer.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,10 +12,10 @@ module Rails
       @spec    = spec
       @gem_dir = gem_dir
     end
-    
+
     # silence the underlying builder
     def say(message)
     end
-    
+
   end
-end
\ No newline at end of file
+end</diff>
      <filename>vendor/rails/railties/lib/rails/gem_builder.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,50 +1,76 @@
+require 'rails/vendor_gem_source_index'
+
+module Gem
+  def self.source_index=(index)
+    @@source_index = index
+  end
+end
+
 module Rails
   class GemDependency
-    attr_accessor :name, :requirement, :version, :lib, :source
+    attr_accessor :lib, :source
 
     def self.unpacked_path
       @unpacked_path ||= File.join(RAILS_ROOT, 'vendor', 'gems')
     end
 
+    @@framework_gems = {}
+
+    def self.add_frozen_gem_path
+      @@paths_loaded ||= begin
+        Gem.source_index = Rails::VendorGemSourceIndex.new(Gem.source_index)
+        # loaded before us - we can't change them, so mark them
+        Gem.loaded_specs.each do |name, spec|
+          @@framework_gems[name] = spec
+        end
+      end
+    end
+
+    def framework_gem?
+      @@framework_gems.has_key?(name)
+    end
+
+    def vendor_rails?
+      Gem.loaded_specs.has_key?(name) &amp;&amp; Gem.loaded_specs[name].loaded_from.empty?
+    end
+
+    def vendor_gem?
+      Gem.loaded_specs.has_key?(name) &amp;&amp; Gem.loaded_specs[name].loaded_from.include?(self.class.unpacked_path)
+    end
+
     def initialize(name, options = {})
       require 'rubygems' unless Object.const_defined?(:Gem)
 
       if options[:requirement]
-        @requirement = options[:requirement]
+        req = options[:requirement]
       elsif options[:version]
-        @requirement = Gem::Requirement.create(options[:version])
+        req = Gem::Requirement.create(options[:version])
+      else
+        req = Gem::Requirement.default
       end
 
-      @version  = @requirement.instance_variable_get(&quot;@requirements&quot;).first.last if @requirement
-      @name     = name.to_s
+      @dep = Gem::Dependency.new(name, req)
       @lib      = options[:lib]
       @source   = options[:source]
       @loaded   = @frozen = @load_paths_added = false
-      @unpack_directory = nil
-    end
-
-    def unpacked_paths
-      Dir[File.join(self.class.unpacked_path, &quot;#{@name}-#{@version || &quot;*&quot;}&quot;)]
     end
 
     def add_load_paths
+      self.class.add_frozen_gem_path
       return if @loaded || @load_paths_added
-      unpacked_paths = self.unpacked_paths
-      if unpacked_paths.empty?
-        args = [@name]
-        args &lt;&lt; @requirement.to_s if @requirement
-        gem *args
-      else
-        $LOAD_PATH.unshift File.join(unpacked_paths.first, 'lib')
-        ext = File.join(unpacked_paths.first, 'ext')
-        $LOAD_PATH.unshift(ext) if File.exist?(ext)
-        @frozen = true
+      if framework_gem?
+        @load_paths_added = @loaded = @frozen = true
+        return
       end
+      gem @dep
+      @spec = Gem.loaded_specs[name]
+      @frozen = @spec.loaded_from.include?(self.class.unpacked_path) if @spec
       @load_paths_added = true
     rescue Gem::LoadError
     end
 
     def dependencies
+      return [] if framework_gem?
       all_dependencies = specification.dependencies.map do |dependency|
         GemDependency.new(dependency.name, :requirement =&gt; dependency.version_requirements)
       end
@@ -56,24 +82,59 @@ module Rails
       File.join(base_directory, specification.full_name)
     end
 
+    def spec_filename(base_directory)
+      File.join(gem_dir(base_directory), '.specification')
+    end
+
     def load
       return if @loaded || @load_paths_added == false
-      require(@lib || @name) unless @lib == false
+      require(@lib || name) unless @lib == false
       @loaded = true
     rescue LoadError
       puts $!.to_s
       $!.backtrace.each { |b| puts b }
     end
 
+    def name
+      @dep.name.to_s
+    end
+
+    def requirement
+      r = @dep.version_requirements
+      (r == Gem::Requirement.default) ? nil : r
+    end
+
     def frozen?
-      @frozen
+      @frozen ||= vendor_rails? || vendor_gem?
     end
 
     def loaded?
-      @loaded
+      @loaded ||= begin
+        if vendor_rails?
+          true
+        elsif specification.nil?
+          false
+        else
+          # check if the gem is loaded by inspecting $&quot;
+          # specification.files lists all the files contained in the gem
+          gem_files = specification.files
+          # select only the files contained in require_paths - typically in bin and lib
+          require_paths_regexp = Regexp.new(&quot;^(#{specification.require_paths*'|'})/&quot;)
+          gem_lib_files = gem_files.select { |f| require_paths_regexp.match(f) }
+          # chop the leading directory off - a typical file might be in
+          # lib/gem_name/file_name.rb, but it will be 'require'd as gem_name/file_name.rb
+          gem_lib_files.map! { |f| f.split('/', 2)[1] }
+          # if any of the files from the above list appear in $&quot;, the gem is assumed to
+          # have been loaded
+          !(gem_lib_files &amp; $&quot;).empty?
+        end
+      end
     end
 
     def load_paths_added?
+      # always try to add load paths - even if a gem is loaded, it may not
+      # be a compatible version (ie random_gem 0.4 is loaded and a later spec
+      # needs &gt;= 0.5 - gem 'random_gem' will catch this and error out)
       @load_paths_added
     end
 
@@ -89,21 +150,73 @@ module Rails
         Gem::GemRunner.new.run(unpack_command)
       end
 
+      # Gem.activate changes the spec - get the original
+      real_spec = Gem::Specification.load(spec.loaded_from)
+      write_spec(directory, real_spec)
+
+    end
+
+    def write_spec(directory, spec)
       # copy the gem's specification into GEMDIR/.specification so that
       # we can access information about the gem on deployment systems
       # without having the gem installed
-      spec_filename = File.join(gem_dir(directory), '.specification')
-      File.open(spec_filename, 'w') do |file|
-        file.puts specification.to_yaml
+      File.open(spec_filename(directory), 'w') do |file|
+        file.puts spec.to_yaml
+      end
+    end
+
+    def refresh_spec(directory)
+      real_gems = Gem.source_index.installed_source_index
+      exact_dep = Gem::Dependency.new(name, &quot;= #{specification.version}&quot;)
+      matches = real_gems.search(exact_dep)
+      installed_spec = matches.first
+      if installed_spec
+        # we have a real copy
+        # get a fresh spec - matches should only have one element
+        # note that there is no reliable method to check that the loaded
+        # spec is the same as the copy from real_gems - Gem.activate changes
+        # some of the fields
+        real_spec = Gem::Specification.load(matches.first.loaded_from)
+        write_spec(directory, real_spec)
+        puts &quot;Reloaded specification for #{name} from installed gems.&quot;
+      else
+        # the gem isn't installed locally - write out our current specs
+        write_spec(directory, specification)
+        puts &quot;Gem #{name} not loaded locally - writing out current spec.&quot;
       end
     end
 
     def ==(other)
       self.name == other.name &amp;&amp; self.requirement == other.requirement
     end
+    alias_method :&quot;eql?&quot;, :&quot;==&quot;
+
+    def hash
+      @dep.hash
+    end
 
     def specification
-      @spec ||= Gem.source_index.search(Gem::Dependency.new(@name, @requirement)).sort_by { |s| s.version }.last
+      # code repeated from Gem.activate. Find a matching spec, or the currently loaded version.
+      # error out if loaded version and requested version are incompatible.
+      @spec ||= begin
+        matches = Gem.source_index.search(@dep)
+        matches &lt;&lt; @@framework_gems[name] if framework_gem?
+        if Gem.loaded_specs[name] then
+          # This gem is already loaded.  If the currently loaded gem is not in the
+          # list of candidate gems, then we have a version conflict.
+          existing_spec = Gem.loaded_specs[name]
+          unless matches.any? { |spec| spec.version == existing_spec.version } then
+            raise Gem::Exception,
+                  &quot;can't activate #{@dep}, already activated #{existing_spec.full_name}&quot;
+          end
+          # we're stuck with it, so change to match
+          @dep.version_requirements = Gem::Requirement.create(&quot;=#{existing_spec.version}&quot;)
+          existing_spec
+        else
+          # new load
+          matches.last
+        end
+      end
     end
 
     private
@@ -112,15 +225,15 @@ module Rails
       end
 
       def install_command
-        cmd = %w(install) &lt;&lt; @name
-        cmd &lt;&lt; &quot;--version&quot; &lt;&lt; %(&quot;#{@requirement.to_s}&quot;) if @requirement
+        cmd = %w(install) &lt;&lt; name
+        cmd &lt;&lt; &quot;--version&quot; &lt;&lt; %(&quot;#{requirement.to_s}&quot;) if requirement
         cmd &lt;&lt; &quot;--source&quot;  &lt;&lt; @source  if @source
         cmd
       end
 
       def unpack_command
-        cmd = %w(unpack) &lt;&lt; @name
-        cmd &lt;&lt; &quot;--version&quot; &lt;&lt; %(&quot;#{@requirement.to_s}&quot;) if @requirement
+        cmd = %w(unpack) &lt;&lt; name
+        cmd &lt;&lt; &quot;--version&quot; &lt;&lt; &quot;= &quot;+specification.version.to_s if requirement
         cmd
       end
   end</diff>
      <filename>vendor/rails/railties/lib/rails/gem_dependency.rb</filename>
    </modified>
    <modified>
      <diff>@@ -44,7 +44,7 @@ module Rails
         env_location = &quot;#{defaults[:cwd]}/config/environment&quot;
         require env_location
 
-        ActionController::AbstractRequest.relative_url_root = defaults[:prefix]
+        ActionController::Base.relative_url_root = defaults[:prefix]
         uri prefix, :handler =&gt; Rails::MongrelServer::RailsHandler.new
       end
     end</diff>
      <filename>vendor/rails/railties/lib/rails/mongrel_server/commands.rb</filename>
    </modified>
    <modified>
      <diff>@@ -112,7 +112,7 @@ module Rails
   class GemPlugin &lt; Plugin
     # Initialize this plugin from a Gem::Specification.
     def initialize(spec, gem)
-      directory = (gem.frozen? &amp;&amp; gem.unpacked_paths.first) || File.join(spec.full_gem_path)
+      directory = spec.full_gem_path
       super(directory)
       @name = spec.name
     end</diff>
      <filename>vendor/rails/railties/lib/rails/plugin.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 module Rails
   module VERSION #:nodoc:
     MAJOR = 2
-    MINOR = 1
+    MINOR = 2
     TINY  = 0
 
     STRING = [MAJOR, MINOR, TINY].join('.')</diff>
      <filename>vendor/rails/railties/lib/rails/version.rb</filename>
    </modified>
    <modified>
      <diff>@@ -169,6 +169,7 @@ HELP
         # Ruby or Rails.  In the future, expand to check other namespaces
         # such as the rest of the user's app.
         def class_collisions(*class_names)
+          path = class_names.shift
           class_names.flatten.each do |class_name|
             # Convert to string to allow symbol arguments.
             class_name = class_name.to_s</diff>
      <filename>vendor/rails/railties/lib/rails_generator/commands.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@ class AppGenerator &lt; Rails::Generator::Base
   DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
                               Config::CONFIG['ruby_install_name'])
 
-  DATABASES = %w(mysql oracle postgresql sqlite2 sqlite3 frontbase)
+  DATABASES = %w(mysql oracle postgresql sqlite2 sqlite3 frontbase ibm_db)
   DEFAULT_DATABASE = 'sqlite3'
 
   default_options   :db =&gt; (ENV[&quot;RAILS_DEFAULT_DATABASE&quot;] || DEFAULT_DATABASE),</diff>
      <filename>vendor/rails/railties/lib/rails_generator/generators/applications/app/app_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@ class ControllerGenerator &lt; Rails::Generator::NamedBase
   def manifest
     record do |m|
       # Check for class naming collisions.
-      m.class_collisions class_path, &quot;#{class_name}Controller&quot;, &quot;#{class_name}ControllerTest&quot;, &quot;#{class_name}Helper&quot;
+      m.class_collisions &quot;#{class_name}Controller&quot;, &quot;#{class_name}ControllerTest&quot;, &quot;#{class_name}Helper&quot;
 
       # Controller, helper, views, and test directories.
       m.directory File.join('app/controllers', class_path)</diff>
      <filename>vendor/rails/railties/lib/rails_generator/generators/components/controller/controller_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ class IntegrationTestGenerator &lt; Rails::Generator::NamedBase
   def manifest
     record do |m|
       # Check for class naming collisions.
-      m.class_collisions class_path, class_name, &quot;#{class_name}Test&quot;
+      m.class_collisions class_name, &quot;#{class_name}Test&quot;
 
       # integration test directory
       m.directory File.join('test/integration', class_path)</diff>
      <filename>vendor/rails/railties/lib/rails_generator/generators/components/integration_test/integration_test_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@ class MailerGenerator &lt; Rails::Generator::NamedBase
   def manifest
     record do |m|
       # Check for class naming collisions.
-      m.class_collisions class_path, class_name, &quot;#{class_name}Test&quot;
+      m.class_collisions class_name, &quot;#{class_name}Test&quot;
 
       # Mailer, view, test, and fixture directories.
       m.directory File.join('app/models', class_path)</diff>
      <filename>vendor/rails/railties/lib/rails_generator/generators/components/mailer/mailer_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ class ModelGenerator &lt; Rails::Generator::NamedBase
   def manifest
     record do |m|
       # Check for class naming collisions.
-      m.class_collisions class_path, class_name, &quot;#{class_name}Test&quot;
+      m.class_collisions class_name, &quot;#{class_name}Test&quot;
 
       # Model, test, and fixture directories.
       m.directory File.join('app/models', class_path)</diff>
      <filename>vendor/rails/railties/lib/rails_generator/generators/components/model/model_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,7 @@ class ObserverGenerator &lt; Rails::Generator::NamedBase
   def manifest
     record do |m|
       # Check for class naming collisions.
-      m.class_collisions class_path, &quot;#{class_name}Observer&quot;, &quot;#{class_name}ObserverTest&quot;
+      m.class_collisions &quot;#{class_name}Observer&quot;, &quot;#{class_name}ObserverTest&quot;
 
       # Observer, and test directories.
       m.directory File.join('app/models', class_path)</diff>
      <filename>vendor/rails/railties/lib/rails_generator/generators/components/observer/observer_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ class PerformanceTestGenerator &lt; Rails::Generator::NamedBase
   def manifest
     record do |m|
       # Check for class naming collisions.
-      m.class_collisions class_path, class_name, &quot;#{class_name}Test&quot;
+      m.class_collisions class_name, &quot;#{class_name}Test&quot;
 
       # performance test directory
       m.directory File.join('test/performance', class_path)</diff>
      <filename>vendor/rails/railties/lib/rails_generator/generators/components/performance_test/performance_test_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,7 @@ class PluginGenerator &lt; Rails::Generator::NamedBase
   def manifest
     record do |m|
       # Check for class naming collisions.
-      m.class_collisions class_path, class_name
+      m.class_collisions class_name
 
       m.directory &quot;#{plugin_path}/lib&quot;
       m.directory &quot;#{plugin_path}/tasks&quot;</diff>
      <filename>vendor/rails/railties/lib/rails_generator/generators/components/plugin/plugin_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -30,8 +30,8 @@ class ResourceGenerator &lt; Rails::Generator::NamedBase
   def manifest
     record do |m|
       # Check for class naming collisions.
-      m.class_collisions(controller_class_path, &quot;#{controller_class_name}Controller&quot;, &quot;#{controller_class_name}Helper&quot;)
-      m.class_collisions(class_path, &quot;#{class_name}&quot;)
+      m.class_collisions(&quot;#{controller_class_name}Controller&quot;, &quot;#{controller_class_name}Helper&quot;)
+      m.class_collisions(class_name)
 
       # Controller, helper, views, and test directories.
       m.directory(File.join('app/models', class_path))</diff>
      <filename>vendor/rails/railties/lib/rails_generator/generators/components/resource/resource_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -36,8 +36,8 @@ class ScaffoldGenerator &lt; Rails::Generator::NamedBase
   def manifest
     record do |m|
       # Check for class naming collisions.
-      m.class_collisions(controller_class_path, &quot;#{controller_class_name}Controller&quot;, &quot;#{controller_class_name}Helper&quot;)
-      m.class_collisions(class_path, &quot;#{class_name}&quot;)
+      m.class_collisions(&quot;#{controller_class_name}Controller&quot;, &quot;#{controller_class_name}Helper&quot;)
+      m.class_collisions(class_name)
 
       # Controller, helper, views, test and stylesheets directories.
       m.directory(File.join('app/models', class_path))</diff>
      <filename>vendor/rails/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -341,7 +341,7 @@ namespace :db do
       case abcs[&quot;test&quot;][&quot;adapter&quot;]
       when &quot;mysql&quot;
         ActiveRecord::Base.establish_connection(:test)
-        ActiveRecord::Base.connection.recreate_database(abcs[&quot;test&quot;][&quot;database&quot;])
+        ActiveRecord::Base.connection.recreate_database(abcs[&quot;test&quot;][&quot;database&quot;], abcs[&quot;test&quot;])
       when &quot;postgresql&quot;
         ActiveRecord::Base.clear_active_connections!
         drop_database(abcs['test'])</diff>
      <filename>vendor/rails/railties/lib/tasks/databases.rake</filename>
    </modified>
    <modified>
      <diff>@@ -55,6 +55,7 @@ namespace :doc do
   namespace :plugins do
     # Define doc tasks for each plugin
     plugins.each do |plugin|
+      desc &quot;Generate documentation for the #{plugin} plugin&quot;
       task(plugin =&gt; :environment) do
         plugin_base   = &quot;vendor/plugins/#{plugin}&quot;
         options       = []</diff>
      <filename>vendor/rails/railties/lib/tasks/documentation.rake</filename>
    </modified>
    <modified>
      <diff>@@ -1,14 +1,19 @@
 desc &quot;List the gems that this rails application depends on&quot;
 task :gems =&gt; 'gems:base' do
   Rails.configuration.gems.each do |gem|
-    code = gem.loaded? ? (gem.frozen? ? &quot;F&quot; : &quot;I&quot;) : &quot; &quot;
-    puts &quot;[#{code}] #{gem.name} #{gem.requirement.to_s}&quot;
+    print_gem_status(gem)
   end
   puts
   puts &quot;I = Installed&quot;
   puts &quot;F = Frozen&quot;
 end
 
+def print_gem_status(gem, indent=1)
+  code = gem.loaded? ? (gem.frozen? ? &quot;F&quot; : &quot;I&quot;) : &quot; &quot;
+  puts &quot;   &quot;*(indent-1)+&quot; - [#{code}] #{gem.name} #{gem.requirement.to_s}&quot;
+  gem.dependencies.each { |g| print_gem_status(g, indent+1)}
+end
+
 namespace :gems do
   task :base do
     $rails_gem_installer = true
@@ -19,7 +24,7 @@ namespace :gems do
   task :build do
     $rails_gem_installer = true
     require 'rails/gem_builder'
-    Dir[File.join(RAILS_ROOT, 'vendor', 'gems', '*')].each do |gem_dir|
+    Dir[File.join(Rails::GemDependency.unpacked_path, '*')].each do |gem_dir|
       spec_file = File.join(gem_dir, '.specification')
       next unless File.exists?(spec_file)
       specification = YAML::load_file(spec_file)
@@ -28,7 +33,7 @@ namespace :gems do
       puts &quot;Built gem: '#{gem_dir}'&quot;
     end
   end
-  
+
   desc &quot;Installs all required gems for this application.&quot;
   task :install =&gt; :base do
     require 'rubygems'
@@ -42,10 +47,10 @@ namespace :gems do
     require 'rubygems/gem_runner'
     Rails.configuration.gems.each do |gem|
       next unless !gem.frozen? &amp;&amp; (ENV['GEM'].blank? || ENV['GEM'] == gem.name)
-      gem.unpack_to(File.join(RAILS_ROOT, 'vendor', 'gems')) if gem.loaded?
+      gem.unpack_to(Rails::GemDependency.unpacked_path) if gem.loaded?
     end
   end
-  
+
   namespace :unpack do
     desc &quot;Unpacks the specified gems and its dependencies into vendor/gems&quot;
     task :dependencies =&gt; :unpack do
@@ -54,11 +59,20 @@ namespace :gems do
       Rails.configuration.gems.each do |gem|
         next unless ENV['GEM'].blank? || ENV['GEM'] == gem.name
         gem.dependencies.each do |dependency|
-          dependency.add_load_paths # double check that we have not already unpacked
           next if dependency.frozen?
-          dependency.unpack_to(File.join(RAILS_ROOT, 'vendor', 'gems'))
+          dependency.unpack_to(Rails::GemDependency.unpacked_path)
         end
       end
     end
   end
+
+  desc &quot;Regenerate gem specifications in correct format.&quot;
+  task :refresh_specs =&gt; :base do
+    require 'rubygems'
+    require 'rubygems/gem_runner'
+    Rails.configuration.gems.each do |gem|
+      next unless gem.frozen? &amp;&amp; (ENV['GEM'].blank? || ENV['GEM'] == gem.name)
+      gem.refresh_spec(Rails::GemDependency.unpacked_path) if gem.loaded?
+    end
+  end
 end
\ No newline at end of file</diff>
      <filename>vendor/rails/railties/lib/tasks/gems.rake</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,6 @@
+require 'lib/rails/vendor_gem_source_index'
+Rails::VendorGemSourceIndex.silence_spec_warnings = true
+
 require 'plugin_test_helper'
 
 class Rails::GemDependency
@@ -37,39 +40,95 @@ uses_mocha &quot;Plugin Tests&quot; do
     end
 
     def test_gem_with_version_unpack_install_command
-      assert_equal [&quot;unpack&quot;, &quot;hpricot&quot;, &quot;--version&quot;, '&quot;= 0.6&quot;'], @gem_with_version.unpack_command
+      # stub out specification method, or else test will fail if hpricot 0.6 isn't installed
+      mock_spec = mock()
+      mock_spec.stubs(:version).returns('0.6')
+      @gem_with_version.stubs(:specification).returns(mock_spec)
+      assert_equal [&quot;unpack&quot;, &quot;hpricot&quot;, &quot;--version&quot;, '= 0.6'], @gem_with_version.unpack_command
     end
 
     def test_gem_adds_load_paths
-      @gem.expects(:gem).with(@gem.name)
+      @gem.expects(:gem).with(Gem::Dependency.new(@gem.name, nil))
       @gem.add_load_paths
     end
 
     def test_gem_with_version_adds_load_paths
-      @gem_with_version.expects(:gem).with(@gem_with_version.name, @gem_with_version.requirement.to_s)
+      @gem_with_version.expects(:gem).with(Gem::Dependency.new(@gem_with_version.name, @gem_with_version.requirement.to_s))
       @gem_with_version.add_load_paths
     end
 
     def test_gem_loading
-      @gem.expects(:gem).with(@gem.name)
+      @gem.expects(:gem).with(Gem::Dependency.new(@gem.name, nil))
       @gem.expects(:require).with(@gem.name)
       @gem.add_load_paths
       @gem.load
     end
 
     def test_gem_with_lib_loading
-      @gem_with_lib.expects(:gem).with(@gem_with_lib.name)
+      @gem_with_lib.expects(:gem).with(Gem::Dependency.new(@gem_with_lib.name, nil))
       @gem_with_lib.expects(:require).with(@gem_with_lib.lib)
       @gem_with_lib.add_load_paths
       @gem_with_lib.load
     end
 
     def test_gem_without_lib_loading
-      @gem_without_load.expects(:gem).with(@gem_without_load.name)
+      @gem_without_load.expects(:gem).with(Gem::Dependency.new(@gem_without_load.name, nil))
       @gem_without_load.expects(:require).with(@gem_without_load.lib).never
       @gem_without_load.add_load_paths
       @gem_without_load.load
     end
 
+    def test_gem_dependencies_compare_for_uniq
+      gem1 = Rails::GemDependency.new &quot;gem1&quot;
+      gem1a = Rails::GemDependency.new &quot;gem1&quot;
+      gem2 = Rails::GemDependency.new &quot;gem2&quot;
+      gem2a = Rails::GemDependency.new &quot;gem2&quot;
+      gem3 = Rails::GemDependency.new &quot;gem2&quot;, :version =&gt; &quot;&gt;=0.1&quot;
+      gem3a = Rails::GemDependency.new &quot;gem2&quot;, :version =&gt; &quot;&gt;=0.1&quot;
+      gem4 = Rails::GemDependency.new &quot;gem3&quot;
+      gems = [gem1, gem2, gem1a, gem3, gem2a, gem4, gem3a, gem2, gem4]
+      assert_equal 4, gems.uniq.size
+    end
+
+    def test_gem_load_frozen
+      dummy_gem = Rails::GemDependency.new &quot;dummy-gem-a&quot;
+      dummy_gem.add_load_paths
+      dummy_gem.load
+      assert_not_nil DUMMY_GEM_A_VERSION
+    end
+
+    def test_gem_load_frozen_specific_version
+      dummy_gem = Rails::GemDependency.new &quot;dummy-gem-b&quot;, :version =&gt; '0.4.0'
+      dummy_gem.add_load_paths
+      dummy_gem.load
+      assert_not_nil DUMMY_GEM_B_VERSION
+      assert_equal '0.4.0', DUMMY_GEM_B_VERSION
+    end
+
+    def test_gem_load_frozen_minimum_version
+      dummy_gem = Rails::GemDependency.new &quot;dummy-gem-c&quot;, :version =&gt; '&gt;=0.5.0'
+      dummy_gem.add_load_paths
+      dummy_gem.load
+      assert_not_nil DUMMY_GEM_C_VERSION
+      assert_equal '0.6.0', DUMMY_GEM_C_VERSION
+    end
+
+    def test_gem_load_missing_specification
+      dummy_gem = Rails::GemDependency.new &quot;dummy-gem-d&quot;
+      dummy_gem.add_load_paths
+      dummy_gem.load
+      assert_not_nil DUMMY_GEM_D_VERSION
+      assert_equal '1.0.0', DUMMY_GEM_D_VERSION
+      assert_equal ['lib', 'lib/dummy-gem-d.rb'], dummy_gem.specification.files
+    end
+
+    def test_gem_load_bad_specification
+      dummy_gem = Rails::GemDependency.new &quot;dummy-gem-e&quot;, :version =&gt; &quot;= 1.0.0&quot;
+      dummy_gem.add_load_paths
+      dummy_gem.load
+      assert_not_nil DUMMY_GEM_E_VERSION
+      assert_equal '1.0.0', DUMMY_GEM_E_VERSION
+    end
+
   end
 end</diff>
      <filename>vendor/rails/railties/test/gem_dependency_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,8 @@
 require 'generators/generator_test_helper'
 
+module Admin
+end
+
 class RailsControllerGeneratorTest &lt; GeneratorTestCase
 
   def test_controller_generates_controller</diff>
      <filename>vendor/rails/railties/test/generators/rails_controller_generator_test.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>vendor/plugins/searchgasm/test/libs/acts_as_tree.rb</filename>
    </removed>
    <removed>
      <filename>vendor/plugins/searchgasm/test/libs/ordered_hash.rb</filename>
    </removed>
    <removed>
      <filename>vendor/plugins/searchgasm/test/libs/rexml_fix.rb</filename>
    </removed>
    <removed>
      <filename>vendor/rails/actionpack/lib/action_view/helpers/form_country_helper.rb</filename>
    </removed>
    <removed>
      <filename>vendor/rails/actionpack/test/template/form_country_helper_test.rb</filename>
    </removed>
    <removed>
      <filename>vendor/rails/activesupport/lib/active_support/core_ext/string/unicode.rb</filename>
    </removed>
    <removed>
      <filename>vendor/rails/activesupport/lib/active_support/multibyte/generators/generate_tables.rb</filename>
    </removed>
    <removed>
      <filename>vendor/rails/activesupport/lib/active_support/multibyte/handlers/passthru_handler.rb</filename>
    </removed>
    <removed>
      <filename>vendor/rails/activesupport/lib/active_support/multibyte/handlers/utf8_handler.rb</filename>
    </removed>
    <removed>
      <filename>vendor/rails/activesupport/lib/active_support/multibyte/handlers/utf8_handler_proc.rb</filename>
    </removed>
    <removed>
      <filename>vendor/rails/activesupport/test/multibyte_handler_test.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>2e406572083a5a63c76b1a62d881fc13f1aff0e1</id>
    </parent>
  </parents>
  <author>
    <name>binarylogic</name>
    <email>bjohnson@binarylogic.com</email>
  </author>
  <url>http://github.com/binarylogic/searchlogic_example/commit/82b98b21d1f6edaf2fa6d6114d1db218ba50b590</url>
  <id>82b98b21d1f6edaf2fa6d6114d1db218ba50b590</id>
  <committed-date>2008-10-20T19:35:32-07:00</committed-date>
  <authored-date>2008-10-20T19:35:32-07:00</authored-date>
  <message>Updated searchgasm</message>
  <tree>d565e41010239e56e6423898802e3b84d00bac78</tree>
  <committer>
    <name>binarylogic</name>
    <email>bjohnson@binarylogic.com</email>
  </committer>
</commit>
