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
53
54
55
# File 'lib/searchlogic/search.rb', line 47

def initialize(klass, current_scope, conditions = {})
  self.klass = klass
  if current_scope
    current_scope = current_scope.dup
    self.default_order = current_scope.delete(:order)
    self.current_scope = current_scope
  end
  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)



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
# File 'lib/searchlogic/search.rb', line 85

def method_missing(name, *args, &block)
  condition_name = condition_name(name)
  scope_name = scope_name(condition_name)

  if setter?(name)
    if scope?(scope_name)
      conditions[condition_name] = type_cast(args.first, cast_type(scope_name))
    else
      raise UnknownConditionError.new(condition_name)
    end
  elsif scope?(scope_name)
    if args.size > 0
      send("#{condition_name}=", *args)
      self
    else
      conditions[condition_name]
    end
  else
    scope = conditions.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
      else
        scope.send(scope_name, value)
      end
    end
    scope = scope.scoped(:order => default_order) if
      default_order && !scope.proxy_options.has_key?(:order)
    scope.send(name, *args, &block)
  end
end

Instance Attribute Details

#conditionsObject

Returns a hash of the current conditions set.



62
63
64
# File 'lib/searchlogic/search.rb', line 62

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

#default_orderObject

Returns the value of attribute default_order.



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

def default_order
  @default_order
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



57
58
59
# File 'lib/searchlogic/search.rb', line 57

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.



79
80
81
82
# File 'lib/searchlogic/search.rb', line 79

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