From cabb43409d61fbaec01ac3a8960dd7d599290416 Mon Sep 17 00:00:00 2001 From: Steffen Bartsch Date: Tue, 24 Feb 2009 22:51:01 +0100 Subject: [PATCH] Added :join_operator parameter to find, letting you choose the join operator for hash joins --- activerecord/lib/active_record/base.rb | 15 +++++++++++---- activerecord/test/cases/finder_test.rb | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 55ab1fa..7de3c9e 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -549,6 +549,8 @@ module ActiveRecord #:nodoc: # or an array containing a mixture of both strings and named associations. # If the value is a string, then the records will be returned read-only since they will have attributes that do not correspond to the table's columns. # Pass :readonly => false to override. + # * :join_operator - If using :joins in hash form, you can pass :left_join in here to cause LEFT JOINs to be used + # for joining associations. This defaults to :inner_join. # * :include - Names associations that should be loaded alongside. The symbols named refer # to already defined associations. See eager loading under Associations. # * :select - By default, this is "*" as in "SELECT * FROM", but can be changed if you, for example, want to do a join but not @@ -1692,7 +1694,7 @@ module ActiveRecord #:nodoc: sql = "SELECT #{options[:select] || (scope && scope[:select]) || default_select(options[:joins] || (scope && scope[:joins]))} " sql << "FROM #{(scope && scope[:from]) || options[:from] || quoted_table_name} " - add_joins!(sql, options[:joins], scope) + add_joins!(sql, options[:joins], scope, options[:join_operator]) add_conditions!(sql, options[:conditions], scope) add_group!(sql, options[:group], options[:having], scope) @@ -1785,7 +1787,7 @@ module ActiveRecord #:nodoc: end # The optional scope argument is for the current :find scope. - def add_joins!(sql, joins, scope = :auto) + def add_joins!(sql, joins, scope = :auto, join_operator = :inner_join) scope = scope(:find) if :auto == scope merged_joins = scope && scope[:joins] && joins ? merge_joins(scope[:joins], joins) : (joins || scope && scope[:joins]) case merged_joins @@ -1793,7 +1795,12 @@ module ActiveRecord #:nodoc: if array_of_strings?(merged_joins) sql << merged_joins.join(' ') + " " else - join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, merged_joins, nil) + join_dependency = + if join_operator == :left_join + ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, merged_joins, nil) + else + ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, merged_joins, nil) + end sql << " #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} " end when String @@ -2400,7 +2407,7 @@ module ActiveRecord #:nodoc: end end - VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, + VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :join_operator, :limit, :offset, :order, :select, :readonly, :group, :having, :from, :lock ] def validate_find_options(options) #:nodoc: diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index ee8f490..a549cae 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -994,6 +994,20 @@ class FinderTest < ActiveRecord::TestCase assert_equal 1, person_with_reader_and_post.size end + def test_joins_with_left_join_operator + posts_with_or_without_categorizations_string_join = Post.find( + :all, + :joins => "LEFT JOIN categorizations ON categorizations.post_id = posts.id" + ) + posts_with_or_without_categorizations_hash_join = Post.find( + :all, + :joins => :categorizations, + :join_operator => :left_join + ) + assert_equal posts_with_or_without_categorizations_string_join.size, + posts_with_or_without_categorizations_hash_join.size + end + def test_find_by_id_with_conditions_with_or assert_nothing_raised do Post.find([1,2,3], -- 1.5.4.3