lib/searchlogic/named_scopes/associations.rb in binarylogic-searchlogic-2.0.1 vs lib/searchlogic/named_scopes/associations.rb in binarylogic-searchlogic-2.1.0
- old
+ new
@@ -27,28 +27,10 @@
# An alias being "gt" for "greater_than", etc.
def association_alias_condition?(name)
!association_alias_condition_details(name).nil?
end
- # Leverages ActiveRecord's JoinDependency class to create a left outer join. Searchlogic uses left outer joins so that
- # records with no associations are included in the result when the association is optional. You can use this method
- # internally when creating your own named scopes that need joins. You need to do this because then ActiveRecord will
- # remove any duplicate joins for you when you chain named scopes that require the same join. If you are using a
- # LEFT OUTER JOIN and an INNER JOIN, ActiveRecord will add both to the query, causing SQL errors.
- #
- # Bottom line, this is convenience method that you can use when creating your own named scopes. Ex:
- #
- # named_scope :orders_line_items_price_expensive, :joins => left_out_joins(:orders => :line_items), :conditions => "line_items.price > 100"
- #
- # Now your joins are consistent with Searchlogic allowing you to avoid SQL errors with duplicate joins.
- def left_outer_joins(association_name)
- ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, association_name, nil).join_associations.collect do |assoc|
- sql = assoc.association_join.strip
- sql.split(/LEFT OUTER JOIN/).delete_if { |join| join.strip.blank? }.collect { |join| "LEFT OUTER JOIN #{join.strip}"}
- end.flatten
- end
-
private
def method_missing(name, *args, &block)
if details = association_condition_details(name)
create_association_condition(details[:association], details[:column], details[:condition], args)
send(name, *args)
@@ -108,11 +90,12 @@
if !arity || arity == 0
# The underlying condition doesn't require any parameters, so let's just create a simple
# named scope that is based on a hash.
options = scope.proxy_options
- add_left_outer_joins(options, association)
+ options[:joins] = options[:joins].blank? ? association.name : {association.name => options[:joins]}
+ #add_left_outer_joins(options, association)
options
else
# The underlying condition requires parameters, let's match the parameters it requires
# and pass those onto the named scope. We can't use proxy_options because that returns the
# result after a value has been passed.
@@ -130,33 +113,14 @@
end
end
eval <<-"end_eval"
searchlogic_lambda(:#{scope_options.searchlogic_arg_type}) { |#{proc_args.join(",")}|
options = association.klass.named_scope_options(association_condition).call(#{proc_args.join(",")})
- add_left_outer_joins(options, association)
+ options[:joins] = options[:joins].blank? ? association.name : {association.name => options[:joins]}
options
}
end_eval
end
- end
-
- # In a named scope you have 2 options for adding joins: :include and :joins.
- #
- # :include will execute multiple queries for each association and instantiate objects for each association.
- # This is not what we want when we are searching. The only other option left is :joins. We can pass the
- # name of the association directly, but AR creates an INNER JOIN. If we are ordering by an association's
- # attribute, and that association is optional, the records without an association will be omitted. Again,
- # not what we want.
- #
- # So the only option left is to use :joins with manually written SQL. We can still have AR generate this SQL
- # for us by leveraging it's join dependency classes. Instead of using the InnerJoinDependency we use the regular
- # JoinDependency which creates a LEFT OUTER JOIN, which is what we want.
- #
- # The code below was extracted out of AR's add_joins! method and then modified.
- def add_left_outer_joins(options, association)
- joins = left_outer_joins(association.name)
- options[:joins] ||= []
- options[:joins] = joins + options[:joins]
end
end
end
end
\ No newline at end of file