<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -390,7 +390,7 @@ module ActiveRecord #:nodoc:
   # So it's possible to assign a logger to the class through &lt;tt&gt;Base.logger=&lt;/tt&gt; which will then be used by all
   # instances in the current object space.
   class Base
-    ##  
+    ##
     # :singleton-method:
     # Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed
     # on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+.
@@ -424,11 +424,11 @@ module ActiveRecord #:nodoc:
     # as a Hash.
     #
     # For example, the following database.yml...
-    # 
+    #
     #   development:
     #     adapter: sqlite3
     #     database: db/development.sqlite3
-    #   
+    #
     #   production:
     #     adapter: sqlite3
     #     database: db/production.sqlite3
@@ -1351,7 +1351,7 @@ module ActiveRecord #:nodoc:
       def self_and_descendants_from_active_record#nodoc:
         klass = self
         classes = [klass]
-        while klass != klass.base_class  
+        while klass != klass.base_class
           classes &lt;&lt; klass = klass.superclass
         end
         classes
@@ -1385,7 +1385,7 @@ module ActiveRecord #:nodoc:
       def human_name(options = {})
         defaults = self_and_descendants_from_active_record.map do |klass|
           :&quot;#{klass.name.underscore}&quot;
-        end 
+        end
         defaults &lt;&lt; self.name.humanize
         I18n.translate(defaults.shift, {:scope =&gt; [:activerecord, :models], :count =&gt; 1, :default =&gt; defaults}.merge(options))
       end
@@ -1689,20 +1689,85 @@ module ActiveRecord #:nodoc:
 
         def construct_finder_sql(options)
           scope = scope(:find)
-          sql  = &quot;SELECT #{options[:select] || (scope &amp;&amp; scope[:select]) || default_select(options[:joins] || (scope &amp;&amp; scope[:joins]))} &quot;
-          sql &lt;&lt; &quot;FROM #{options[:from]  || (scope &amp;&amp; scope[:from]) || quoted_table_name} &quot;
 
-          add_joins!(sql, options[:joins], scope)
-          add_conditions!(sql, options[:conditions], scope)
+          # TODO add lock to Arel
+          Arel(table_name).
+            join(construct_join(options[:joins], scope)).
+            where(construct_conditions(options[:conditions], scope)).
+            project(options[:select] || (scope &amp;&amp; scope[:select]) || default_select(options[:joins] || (scope &amp;&amp; scope[:joins]))).
+            group(construct_group(options[:group], options[:having], scope)).
+            order(construct_order(options[:order], scope)).
+            take(construct_limit(options, scope)).
+            skip(construct_offset(options, scope)
+          ).to_sql
+        end
 
-          add_group!(sql, options[:group], options[:having], scope)
-          add_order!(sql, options[:order], scope)
-          add_limit!(sql, options, scope)
-          add_lock!(sql, options, scope)
+        def construct_join(joins, scope = :auto)
+          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 array_of_strings?(merged_joins)
+              merged_joins.join(' ') + &quot; &quot;
+            else
+              join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, merged_joins, nil)
+              &quot; #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} &quot;
+            end
+          when String
+            &quot; #{merged_joins} &quot;
+          end
+        end
+
+        def construct_group(group, having, scope = :auto)
+          sql = ''
+          if group
+            sql &lt;&lt; group.to_s
+            sql &lt;&lt; &quot; HAVING #{sanitize_sql_for_conditions(having)}&quot; if having
+          else
+            scope = scope(:find) if :auto == scope
+            if scope &amp;&amp; (scoped_group = scope[:group])
+              sql &lt;&lt; scoped_group.to_s
+              sql &lt;&lt; &quot; HAVING #{sanitize_sql_for_conditions(scope[:having])}&quot; if scope[:having]
+            end
+          end
+          sql
+        end
 
+        def construct_order(order, scope = :auto)
+          sql = ''
+          scope = scope(:find) if :auto == scope
+          scoped_order = scope[:order] if scope
+          if order
+            sql &lt;&lt; order.to_s
+            if scoped_order &amp;&amp; scoped_order != order
+              sql &lt;&lt; &quot;, #{scoped_order}&quot;
+            end
+          else
+            sql &lt;&lt; scoped_order.to_s if scoped_order
+          end
           sql
         end
 
+        def construct_limit(options, scope = :auto)
+          scope = scope(:find) if :auto == scope
+          options[:limit] ||= scope[:limit] if scope
+          options[:limit]
+        end
+
+        def construct_offset(options, scope = :auto)
+          scope = scope(:find) if :auto == scope
+          options[:offset] ||= scope[:offset] if scope
+          options[:offset]
+        end
+
+        def construct_conditions(conditions, scope = :auto)
+          scope = scope(:find) if :auto == scope
+          conditions = [conditions]
+          conditions &lt;&lt; scope[:conditions] if scope
+          conditions &lt;&lt; type_condition if finder_needs_type_condition?
+          merge_conditions(*conditions)
+        end
+
         # Merges includes so that the result is a valid +include+
         def merge_includes(first, second)
          (safe_to_array(first) + safe_to_array(second)).uniq
@@ -1958,7 +2023,7 @@ module ActiveRecord #:nodoc:
                   attributes = construct_attributes_from_arguments( #   attributes = construct_attributes_from_arguments(
                     [:#{attribute_names.join(',:')}], args          #     [:user_name, :password], args
                   )                                                 #   )
-                                                                    # 
+                                                                    #
                   scoped(:conditions =&gt; attributes)                 #   scoped(:conditions =&gt; attributes)
                 end                                                 # end
               }, __FILE__, __LINE__
@@ -2478,7 +2543,7 @@ module ActiveRecord #:nodoc:
       #       name
       #     end
       #   end
-      #   
+      #
       #   user = User.find_by_name('Phusion')
       #   user_path(user)  # =&gt; &quot;/users/Phusion&quot;
       def to_param
@@ -2533,12 +2598,12 @@ module ActiveRecord #:nodoc:
       # If +perform_validation+ is true validations run. If any of them fail
       # the action is cancelled and +save+ returns +false+. If the flag is
       # false validations are bypassed altogether. See
-      # ActiveRecord::Validations for more information. 
+      # ActiveRecord::Validations for more information.
       #
       # There's a series of callbacks associated with +save+. If any of the
       # &lt;tt&gt;before_*&lt;/tt&gt; callbacks return +false+ the action is cancelled and
       # +save+ returns +false+. See ActiveRecord::Callbacks for further
-      # details. 
+      # details.
       def save
         create_or_update
       end
@@ -2550,12 +2615,12 @@ module ActiveRecord #:nodoc:
       #
       # With &lt;tt&gt;save!&lt;/tt&gt; validations always run. If any of them fail
       # ActiveRecord::RecordInvalid gets raised. See ActiveRecord::Validations
-      # for more information. 
+      # for more information.
       #
       # There's a series of callbacks associated with &lt;tt&gt;save!&lt;/tt&gt;. If any of
       # the &lt;tt&gt;before_*&lt;/tt&gt; callbacks return +false+ the action is cancelled
       # and &lt;tt&gt;save!&lt;/tt&gt; raises ActiveRecord::RecordNotSaved. See
-      # ActiveRecord::Callbacks for further details. 
+      # ActiveRecord::Callbacks for further details.
       def save!
         create_or_update || raise(RecordNotSaved)
       end
@@ -2726,12 +2791,12 @@ module ActiveRecord #:nodoc:
       #   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)</diff>
      <filename>activerecord/lib/active_record/base.rb</filename>
    </modified>
    <modified>
      <diff>@@ -211,7 +211,7 @@ module ActiveRecord
       def supports_migrations? #:nodoc:
         true
       end
-      
+
       def supports_savepoints? #:nodoc:
         true
       end</diff>
      <filename>activerecord/lib/active_record/connection_adapters/mysql_adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -20,7 +20,7 @@ module ActiveRecord
       patterns_to_match.each do |pattern|
         failed_patterns &lt;&lt; pattern unless $queries_executed.any?{ |sql| pattern === sql }
       end
-      assert failed_patterns.empty?, &quot;Query pattern(s) #{failed_patterns.map(&amp;:inspect).join(', ')} not found.&quot;
+      assert failed_patterns.empty?, &quot;Query pattern(s) #{failed_patterns.map(&amp;:inspect).join(', ')} not found in #{$queries_executed}&quot;
     end
 
     def assert_queries(num = 1)</diff>
      <filename>activerecord/lib/active_record/test_case.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,7 +26,7 @@ class InnerJoinAssociationTest &lt; ActiveRecord::TestCase
 
   def test_construct_finder_sql_applies_association_conditions
     sql = Author.send(:construct_finder_sql, :joins =&gt; :categories_like_general, :conditions =&gt; &quot;TERMINATING_MARKER&quot;)
-    assert_match /INNER JOIN .?categories.? ON.*AND.*.?General.?.*TERMINATING_MARKER/, sql
+    assert_match /INNER JOIN .?categories.? ON.*AND.*.?General.?(.|\n)*TERMINATING_MARKER/, sql
   end
 
   def test_construct_finder_sql_applies_aliases_tables_on_association_conditions</diff>
      <filename>activerecord/test/cases/associations/inner_join_association_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -379,7 +379,7 @@ class NestedScopingTest &lt; ActiveRecord::TestCase
     poor_jamis = developers(:poor_jamis)
     Developer.with_scope(:find =&gt; { :conditions =&gt; &quot;salary &lt; 100000&quot; }) do
       Developer.with_scope(:find =&gt; { :offset =&gt; 1, :order =&gt; 'id asc' }) do
-        assert_sql /ORDER BY id asc / do
+        assert_sql /ORDER BY  id asc/ do
           assert_equal(poor_jamis, Developer.find(:first, :order =&gt; 'id asc'))
         end
       end</diff>
      <filename>activerecord/test/cases/method_scoping_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1 +1 @@
-Subproject commit 1b1fc880bf7129a422901417bd6b9fede292aa7e
+Subproject commit 45646ec54c4c4a3c7340b79deea9e3cf76554f0b</diff>
      <filename>arel</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>0e113a040d934958ce3805ce6cda73c655def444</id>
    </parent>
  </parents>
  <author>
    <name>Emilio Tagua</name>
    <email>miloops@gmail.com</email>
  </author>
  <url>http://github.com/findsyou/rails/commit/090539604b7685d838302c1773520622d87bd3d7</url>
  <id>090539604b7685d838302c1773520622d87bd3d7</id>
  <committed-date>2009-04-24T17:48:45-07:00</committed-date>
  <authored-date>2009-04-24T17:48:45-07:00</authored-date>
  <message>construct_finder_sql now use Arel</message>
  <tree>20d5c72838ab239e7eb67038467016af6848a7df</tree>
  <committer>
    <name>Emilio Tagua</name>
    <email>miloops@gmail.com</email>
  </committer>
</commit>
