Class: MetaSearch::Where
- Inherits:
-
Object
- Object
- MetaSearch::Where
- Defined in:
- lib/meta_search/where.rb
Overview
Wheres are how MetaSearch does its magic. Wheres have a name (and possible aliases) which are appended to your model and association attributes. When you instantiate a MetaSearch::Builder against a model (manually or by calling your model’s search method) the builder responds to methods named for your model’s attributes and associations, suffixed by the name of the Where.
These are the default Wheres, broken down by the types of ActiveRecord columns they can search against:
All data types
-
equals (alias: eq) - Just as it sounds.
-
does_not_equal (aliases: ne, noteq) - The opposite of equals, oddly enough.
-
in - Takes an array, matches on equality with any of the items in the array.
-
not_in (aliases: ni, notin) - Like above, but negated.
-
is_null - The column has an SQL NULL value.
-
is_not_null - The column contains anything but NULL.
Strings
-
contains (aliases: like, matches) - Substring match.
-
does_not_contain (aliases: nlike, nmatches) - Negative substring match.
-
starts_with (alias: sw) - Match strings beginning with the entered term.
-
does_not_start_with (alias: dnsw) - The opposite of above.
-
ends_with (alias: ew) - Match strings ending with the entered term.
-
does_not_end_with (alias: dnew) - Negative of above.
Numbers, dates, and times
-
greater_than (alias: gt) - Greater than.
-
greater_than_or_equal_to (aliases: gte, gteq) - Greater than or equal to.
-
less_than (alias: lt) - Less than.
-
less_than_or_equal_to (aliases: lte, lteq) - Less than or equal to.
Booleans
-
is_true - Is true. Useful for a checkbox like “only show admin users”.
-
is_false - The complement of is_true.
Non-boolean data types
-
is_present - As with is_true, useful with a checkbox. Not NULL or the empty string.
-
is_blank - Returns records with a value of NULL or the empty string in the column.
So, given a model like this…
class Article < ActiveRecord::Base
belongs_to :author
has_many :comments
has_many :moderations, :through => :comments
end
…you might end up with attributes like title_contains, comments_title_starts_with, moderations_value_less_than, author_name_equals, and so on.
Additionally, all of the above predicate types also have an _any and _all version, which expects an array of the corresponding parameter type, and requires any or all of the parameters to be a match, respectively. So:
Article.search :author_name_starts_with_any => ['Jim', 'Bob', 'Fred']
will match articles authored by Jimmy, Bobby, or Freddy, but not Winifred.
Instance Attribute Summary collapse
-
#aliases ⇒ Object
readonly
Returns the value of attribute aliases.
-
#cast ⇒ Object
readonly
Returns the value of attribute cast.
-
#formatter ⇒ Object
readonly
Returns the value of attribute formatter.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#predicate ⇒ Object
readonly
Returns the value of attribute predicate.
-
#types ⇒ Object
readonly
Returns the value of attribute types.
-
#validator ⇒ Object
readonly
Returns the value of attribute validator.
Class Method Summary collapse
-
.add(*args) ⇒ Object
At application initialization, you can add additional custom Wheres to the mix.
-
.all ⇒ Object
Returns the complete array of Wheres.
-
.get(method_id_or_predicate) ⇒ Object
Get the where matching a method or predicate.
-
.initialize_wheres ⇒ Object
Set the wheres to their default values, removing any customized settings.
Instance Method Summary collapse
-
#evaluate(relation, attributes, param) ⇒ Object
Evaluate the Where for the given relation, attribute, and parameter(s).
-
#format_param(param) ⇒ Object
Format a parameter for searching using the Where’s defined formatter.
-
#initialize(where) ⇒ Where
constructor
A new instance of Where.
- #skip_compounds? ⇒ Boolean
- #splat_param? ⇒ Boolean
-
#validate(param) ⇒ Object
Validate the parameter for use in a search using the Where’s defined validator.
Constructor Details
#initialize(where) ⇒ Where
Returns a new instance of Where.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/meta_search/where.rb', line 68 def initialize(where) if [String,Symbol].include?(where.class) where = Where.get(where) or raise ArgumentError("A where could not be instantiated for the argument #{where}") end @name = where[:name] @aliases = where[:aliases] @types = where[:types] @cast = where[:cast] @predicate = where[:predicate] @validator = where[:validator] @formatter = where[:formatter] @splat_param = where[:splat_param] @skip_compounds = where[:skip_compounds] end |
Instance Attribute Details
#aliases ⇒ Object (readonly)
Returns the value of attribute aliases.
67 68 69 |
# File 'lib/meta_search/where.rb', line 67 def aliases @aliases end |
#cast ⇒ Object (readonly)
Returns the value of attribute cast.
67 68 69 |
# File 'lib/meta_search/where.rb', line 67 def cast @cast end |
#formatter ⇒ Object (readonly)
Returns the value of attribute formatter.
67 68 69 |
# File 'lib/meta_search/where.rb', line 67 def formatter @formatter end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
67 68 69 |
# File 'lib/meta_search/where.rb', line 67 def name @name end |
#predicate ⇒ Object (readonly)
Returns the value of attribute predicate.
67 68 69 |
# File 'lib/meta_search/where.rb', line 67 def predicate @predicate end |
#types ⇒ Object (readonly)
Returns the value of attribute types.
67 68 69 |
# File 'lib/meta_search/where.rb', line 67 def types @types end |
#validator ⇒ Object (readonly)
Returns the value of attribute validator.
67 68 69 |
# File 'lib/meta_search/where.rb', line 67 def validator @validator end |
Class Method Details
.add(*args) ⇒ Object
At application initialization, you can add additional custom Wheres to the mix. in your application’s config/initializers/meta_search.rb, place lines like this:
MetaSearch::Where.add :between, :btw,
:predicate => :in,
:types => [:integer, :float, :decimal, :date, :datetime, :timestamp, :time],
:formatter => Proc.new {|param| Range.new(param.first, param.last)},
:validator => Proc.new {|param|
param.is_a?(Array) && !(param[0].blank? || param[1].blank?)
}
The first options are all names for the where. Well, the first is a name, the rest are aliases, really. They will determine the suffix you will use to access your Where.
types is an array of types the comparison is valid for. The where will not be available against columns that are not one of these types. Default is ALL_TYPES, Which is one of several MetaSearch constants available for type assignment (the others being DATES, TIIMES, STRINGS, and NUMBERS).
predicate is the Arel::Attribute predication (read: conditional operator) used for the comparison. Default is :eq, or equality.
formatter is the Proc that will do any formatting to the variables to be substituted. The default proc is {|param| param}, which doesn’t really do anything. If you pass a string, it will be evaled in the context of this Proc.
For example, this is the definition of the “contains” Where:
['contains', 'like', {:types => STRINGS, :predicate => :matches, :formatter => '"%#{param}%"'}]
Be sure to single-quote the string, so that variables aren’t interpolated until later. If in doubt, just use a Proc.
validator is the Proc that will be used to check whether a parameter supplied to the Where is valid. If it is not valid, it won’t be used in the query. The default is {|param| !param.blank?}, so that empty parameters aren’t added to the search, but you can get more complex if you desire, like the one in the between example, above.
splat_param, if true, will cause the parameters sent to the predicate in question to be splatted (converted to an argument list). This is not normally useful and defaults to false, but is used when automatically creating compound Wheres (*_any, *_all) so that the Arel attribute method gets the correct parameter list.
skip_compounds will prevent creation of compound condition methods (ending in any or all) for situations where they wouldn’t make sense, such as the built-in conditions is_true and is_false.
cast will override the normal cast of the parameter when using this Where condition. Normally, the value supplied to a condition is cast to the type of the column it’s being compared against. In cases where this isn’t desirable, because the value you intend to accept isn’t the same kind of data you’ll be comparing against, you can override that cast here, using one of the standard DB type symbols such as :integer, :string, :boolean and so on.
167 168 169 170 |
# File 'lib/meta_search/where.rb', line 167 def add(*args) where = create_where_from_args(*args) create_where_compounds_for(where) unless where.skip_compounds? end |
.all ⇒ Object
Returns the complete array of Wheres
173 174 175 |
# File 'lib/meta_search/where.rb', line 173 def all @@wheres end |
.get(method_id_or_predicate) ⇒ Object
Get the where matching a method or predicate.
178 179 180 181 182 183 184 185 |
# File 'lib/meta_search/where.rb', line 178 def get(method_id_or_predicate) return nil unless where_key = @@wheres.keys. sort {|a,b| b.length <=> a.length}. detect {|n| method_id_or_predicate.to_s.match(/#{n}=?$/)} where = @@wheres[where_key] where = @@wheres[where] if where.is_a?(String) where end |
.initialize_wheres ⇒ Object
Set the wheres to their default values, removing any customized settings.
188 189 190 191 192 193 |
# File 'lib/meta_search/where.rb', line 188 def initialize_wheres @@wheres = {} DEFAULT_WHERES.each do |where| add(*where) end end |
Instance Method Details
#evaluate(relation, attributes, param) ⇒ Object
Evaluate the Where for the given relation, attribute, and parameter(s)
102 103 104 105 106 107 108 109 110 |
# File 'lib/meta_search/where.rb', line 102 def evaluate(relation, attributes, param) if splat_param? conditions = attributes.map {|a| a.send(predicate, *format_param(param))} else conditions = attributes.map {|a| a.send(predicate, format_param(param))} end relation.where(conditions.inject(nil) {|memo, c| memo ? memo.or(c) : c}) end |
#format_param(param) ⇒ Object
Format a parameter for searching using the Where’s defined formatter.
92 93 94 |
# File 'lib/meta_search/where.rb', line 92 def format_param(param) formatter.call(param) end |
#skip_compounds? ⇒ Boolean
87 88 89 |
# File 'lib/meta_search/where.rb', line 87 def skip_compounds? !!@skip_compounds end |
#splat_param? ⇒ Boolean
83 84 85 |
# File 'lib/meta_search/where.rb', line 83 def splat_param? !!@splat_param end |
#validate(param) ⇒ Object
Validate the parameter for use in a search using the Where’s defined validator.
97 98 99 |
# File 'lib/meta_search/where.rb', line 97 def validate(param) validator.call(param) end |