lib/searchlogic/named_scopes/or_conditions.rb in searchlogic-2.4.32 vs lib/searchlogic/named_scopes/or_conditions.rb in searchlogic-2.5.0

- old
+ new

@@ -3,34 +3,34 @@ # Handles dynamically creating named scopes for 'OR' conditions. Please see the README for a more # detailed explanation. module OrConditions class NoConditionSpecifiedError < StandardError; end class UnknownConditionError < StandardError; end - + def condition?(name) # :nodoc: super || or_condition?(name) end - + def named_scope_options(name) # :nodoc: super || super(or_conditions(name).try(:join, "_or_")) end - + private def or_condition?(name) !or_conditions(name).nil? end - - def method_missing(name, *args, &block) + + def create_condition(name) if conditions = or_conditions(name) - create_or_condition(conditions, args) - (class << self; self; end).class_eval { alias_method name, conditions.join("_or_") } if !respond_to?(name) - send(name, *args) + create_or_condition(conditions) + alias_name = conditions.join("_or_") + (class << self; self; end).class_eval { alias_method name, conditions.join("_or_") } if name != alias_name else super end end - + def or_conditions(name) # First determine if we should even work on the name, we want to be as quick as possible # with this. if (parts = split_or_condition(name)).size > 1 conditions = interpolate_or_conditions(parts) @@ -39,11 +39,11 @@ else nil end end end - + def split_or_condition(name) parts = name.to_s.split("_or_") new_parts = [] parts.each do |part| if part =~ /^equal_to(_any|_all)?$/ @@ -52,11 +52,11 @@ new_parts << part end end new_parts end - + # The purpose of this method is to convert the method name parts into actual condition names. # # Example: # # ["first_name", "last_name_like"] @@ -79,26 +79,26 @@ last_condition = details[:condition] elsif association_details = association_condition_details(part, last_condition) path = full_association_path(part, last_condition, association_details[:association]) conditions << "#{path[:path].join("_").to_sym}_#{path[:column]}_#{path[:condition]}" last_condition = path[:condition] || nil - elsif local_condition?(part) + elsif column_condition?(part) # We are a custom scope conditions << part elsif column_names.include?(part) # we are a column, use the last condition if last_condition.nil? raise NoConditionSpecifiedError.new("The '#{part}' column doesn't know which condition to use, if you use an exact column " + "name you need to specify a condition sometime after (ex: id_or_created_at_lt), where id would use the 'lt' condition.") end - + conditions << "#{part}_#{last_condition}" else raise UnknownConditionError.new("The condition '#{part}' is not a valid condition, we could not find any scopes that match this.") end end - + conditions.reverse end def full_association_path(part, last_condition, given_assoc) path = [given_assoc.name] @@ -114,20 +114,20 @@ return { :path => path, :column => details[:column], :condition => details[:condition] } end end { :path => path, :column => part, :condition => last_condition } end - - def create_or_condition(scopes, args) + + def create_or_condition(scopes) scopes_options = scopes.collect { |scope, *args| send(scope, *args).proxy_options } # We're using first scope to determine column's type scope = named_scope_options(scopes.first) column_type = scope.respond_to?(:searchlogic_options) ? scope.searchlogic_options[:type] : :string named_scope scopes.join("_or_"), searchlogic_lambda(column_type) { |*args| merge_scopes_with_or(scopes.collect { |scope| clone.send(scope, *args) }) } end - + def merge_scopes_with_or(scopes) scopes_options = scopes.collect { |scope| scope.scope(:find) } conditions = scopes_options.reject { |o| o[:conditions].nil? }.collect { |o| sanitize_sql(o[:conditions]) } scope = scopes_options.inject(scoped({})) { |current_scope, options| current_scope.scoped(options) } options = {}