Class: Searchlogic::Search

Inherits:
Object
  • Object
show all
Defined in:
lib/searchlogic/search.rb

Overview

A class that acts like a model, creates attr_accessors for named_scopes, and then chains together everything when an “action” method is called. It basically makes implementing search forms in your application effortless:

search = User.search
search.username_like = "bjohnson"
search.all

Is equivalent to:

User.search(:username_like => "bjohnson").all

Is equivalent to:

User.username_like("bjohnson").all

Defined Under Namespace

Modules: Implementation Classes: UnknownConditionError

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(klass, current_scope, conditions = {}) ⇒ Search

Creates a new search object for the given class. Ex:

Searchlogic::Search.new(User, {}, {:username_like => "bjohnson"})


47
48
49
50
51
52
# File 'lib/searchlogic/search.rb', line 47

def initialize(klass, current_scope, conditions = {})
  self.klass = klass
  self.current_scope = current_scope
  @conditions ||= {}
  self.conditions = conditions if conditions.is_a?(Hash)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object (private)



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/searchlogic/search.rb', line 83

def method_missing(name, *args, &block)
  condition_name = condition_name(name)
  scope_name = scope_name(condition_name)
  
  if setter?(name)
    if scope?(scope_name)
      if args.size == 1
        write_condition(condition_name, type_cast(args.first, cast_type(scope_name)))
      else
        write_condition(condition_name, args)
      end
    else
      raise UnknownConditionError.new(condition_name)
    end
  elsif scope?(scope_name) && args.size <= 1
    if args.size == 0
      read_condition(condition_name)
    else
      send("#{condition_name}=", *args)
      self
    end
  else
    scope = conditions_array.inject(klass.scoped(current_scope) || {}) do |scope, condition|
      scope_name, value = condition
      scope_name = normalize_scope_name(scope_name)
      klass.send(scope_name, value) if !klass.respond_to?(scope_name)
      arity = klass.named_scope_arity(scope_name)
      
      if !arity || arity == 0
        if value == true
          scope.send(scope_name)
        else
          scope
        end
      elsif arity == -1
        scope.send(scope_name, *(value.is_a?(Array) ? value : [value]))
      else
        scope.send(scope_name, value)
      end
    end
    scope.send(name, *args, &block)
  end
end

Instance Attribute Details

#conditionsObject

Returns a hash of the current conditions set.



59
60
61
# File 'lib/searchlogic/search.rb', line 59

def conditions
  @conditions
end

#current_scopeObject

Returns the value of attribute current_scope.



41
42
43
# File 'lib/searchlogic/search.rb', line 41

def current_scope
  @current_scope
end

#klassObject

Returns the value of attribute klass.



41
42
43
# File 'lib/searchlogic/search.rb', line 41

def klass
  @klass
end

Instance Method Details

#cloneObject



54
55
56
# File 'lib/searchlogic/search.rb', line 54

def clone
  self.class.new(klass, current_scope && current_scope.clone, conditions.clone)
end

#delete(*names) ⇒ Object

Delete a condition from the search. Since conditions map to named scopes, if a named scope accepts a parameter there is no way to actually delete the scope if you do not want it anymore. A nil value might be meaningful to that scope.



77
78
79
80
# File 'lib/searchlogic/search.rb', line 77

def delete(*names)
  names.each { |name| @conditions.delete(name.to_sym) }
  self
end