Class: SimpleSearch::Search
- Inherits:
-
Object
- Object
- SimpleSearch::Search
- Defined in:
- lib/simple_search/search.rb
Overview
How it works
Okay, so form_for
is a really handy helper, right? Yes. But it expects that whatever object you are building a form… er, for, responds to methods that match the name of the first parameter. So, for instance …
f.text_field :headly_von_headdington
… expects that the object you passed to form_for responds to the headly_von_headdington
method. SimpleSearch uses this to its advantage by auto-creating methods that will help it build a set of conditions to search on.
So, when you instantiate an object of class SimpleSearch::Search, it takes a look at the model you want it to search, and goes about creating a bunch of methods you will find handy to have available in your form_for block, based on the persistent attributes of your model – that is, the columns in the database table.
The methods vary by the type of data to be searched. For example purposes, let’s assume the attribute is question is named “gipe”, and see what kinds of conditions SimpleSearch will create depending on its data type.
Strings
-
gipe
- Matches if the searched attribute contains this string. In SQL terms, this is a fragment that looks likegipe LIKE '%value%'
-
gipe_starts_with
- Matches if the attribute starts with this string. SQL:gipe LIKE 'value%'
-
gipe_exact
- Exact match. In SQL terms:gipe = 'value'
-
gipe_not
,gipe_not_starts_with
,gipe_not_exact
- Negation of the previous examples. Matches if the attribute doesn’t contain, start with, or equal the value, respectively.
Numbers
-
gipe
- Matches if the searched attribute equals the supplied numeric value. -
gipe_not
- Matches if the searched attribute doesn’t equal the value. -
gipe_min
- Matches if the searched attribute is greater than or equal to the value. -
gipe_max
- Matches if the searched attribute is less than or equal to the value.
Dates/DateTimes
-
gipe
- Supplied value can be a String, Date or DateTime. This method will always search on a range against a datetime column.If a string, it will be parsed to a Date or DateTime, depending on the type of column it is being compared against, and converted to a range from beginning_of_day to end_of_day in the current time zone, if a range is needed. If it contains the text “ to ” it will be treated as a specific date range. So “12/25/2009 to 12/31/2009” will return results from midnight on Christmas day to just before the ball drops at Times Square.
-
gipe_from
,gipe_to
- Sets the start or endpoint of a date/time range explicitly, much as min/max do on numeric values. Keep in mind that range specifications are still locked to a day boundary, sogipe_from
will be beginning_of_day andgipe_to
will be end_of_day when searching against datetime columns.
Associations
When you pass a list of associations to SimpleSearch::Search#new (in the :search_associations
option) SimpleSearch will add methods for that association as well. These work as you might expect, so a :search_association => [:manufacturer, :owner, :users]
on a model that belongs_to
a manufacturer and owner, and has_many
users will gain methods like users_first_name_starts_with and manufacturer_years_in_operation_min, depending on the attributes of the associated models.
Instance Attribute Summary collapse
-
#associations ⇒ Object
readonly
Returns the value of attribute associations.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Instance Method Summary collapse
-
#conditions ⇒ Object
Returns the array of conditions that is passed to ActiveRecord’s find or paginate method by this search.
-
#count(args = {}) ⇒ Object
Get the count of records matched by the current search.
-
#initialize(model, options = {}) ⇒ Search
constructor
SimpleSearch always needs a
model
parameter to know which ActiveRecord model it will be wrapping around and squeezing juicy attribute goodness from. -
#search(args = {}) ⇒ Object
Runs the current search against the database, returning all results, or paginated results, depending on whether a
:page
parameter has been received (and, of course, whether your model responds to paginate).
Constructor Details
#initialize(model, options = {}) ⇒ Search
SimpleSearch always needs a model
parameter to know which ActiveRecord model it will be wrapping around and squeezing juicy attribute goodness from. options
are, oddly enough, optional. That being said, without at least a few search criteria specified, SimpleSearch isn’t going to be doing much besides providing a poorly-optimized alternative to Model.all in its search
method.
One special option is the :search_associations
option. This is a list of one or more associations on the model (as referenced by has_many
, belongs_to
, etc) that you would like to autogenerate search methods for, as well.
Wait, what? Scroll up and read “How it works” for more details.
76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/simple_search/search.rb', line 76 def initialize(model, = {}) @model = model @associations = [*.delete(:search_associations)].compact @association_objects = @associations.map do |a| @model.reflect_on_association(a) end initialize_option_methods # Need to make sure to keep multipart date stuff around dates = dates_from_hash(Hash[*.select {|k, v| k =~ /\(.*\)$/}.flatten]) @options = .reject{|k, v| !respond_to?(k)}.merge dates end |
Instance Attribute Details
#associations ⇒ Object (readonly)
Returns the value of attribute associations.
63 64 65 |
# File 'lib/simple_search/search.rb', line 63 def associations @associations end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
63 64 65 |
# File 'lib/simple_search/search.rb', line 63 def @options end |
Instance Method Details
#conditions ⇒ Object
Returns the array of conditions that is passed to ActiveRecord’s find or paginate method by this search. Useful for debugging or to do your own custom searches without using the search
or count
methods.
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/simple_search/search.rb', line 91 def conditions conditions = [] parameters = [] return [] if .empty? @options.keys.select{|k| self.respond_to?("#{k}_conditions".to_sym)}.each do |opt| next if self.send(opt.to_sym).blank? condition = self.send("#{opt}_conditions".to_sym) parameter = self.send("#{opt}_parameters".to_sym) if condition.is_a?(Array) concat = respond_to?("#{opt}_concat".to_sym) ? send("#{opt}_concat".to_sym) : 'OR' condition = '(' + condition.join(" #{concat} ") + ')' end conditions << condition parameters.concat [*parameter] end conditions.blank? ? [] : [conditions.join(" AND "), *parameters] end |
#count(args = {}) ⇒ Object
Get the count of records matched by the current search. All arguments are passed to ActiveRecord’s count method.
130 131 132 133 134 135 136 |
# File 'lib/simple_search/search.rb', line 130 def count(args = {}) args.merge!( :conditions => self.conditions, :include => (self.associations + [*args[:include]]).compact.uniq ) @model.count(args) end |
#search(args = {}) ⇒ Object
Runs the current search against the database, returning all results, or paginated results, depending on whether a :page
parameter has been received (and, of course, whether your model responds to paginate). All other options are passed through to the paginate/find call.
116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/simple_search/search.rb', line 116 def search(args = {}) args.merge!( :conditions => self.conditions, :include => (self.associations + [*args[:include]]).compact.uniq ) if @model.respond_to?(:paginate) && args.has_key?(:page) @model.paginate(:all, args) else @model.find(:all, args) end end |