Class: Searchgasm::Conditions::Base
- Inherits:
-
Object
- Object
- Searchgasm::Conditions::Base
- Includes:
- Protection, Shared::Utilities, Shared::VirtualClasses
- Defined in:
- lib/searchgasm/conditions/base.rb,
lib/searchgasm.rb
Overview
Conditions
Represents a collection of conditions and performs various tasks on that collection. For information on each condition see Searchgasm::Condition. Each condition has its own file and class and the source for each condition is pretty self explanatory.
Class Attribute Summary collapse
-
.added_associations ⇒ Object
Returns the value of attribute added_associations.
-
.added_column_equals_conditions ⇒ Object
Returns the value of attribute added_column_equals_conditions.
-
.added_klass_conditions ⇒ Object
Returns the value of attribute added_klass_conditions.
Instance Attribute Summary collapse
-
#any ⇒ Object
:nodoc:.
-
#relationship_name ⇒ Object
Returns the value of attribute relationship_name.
Class Method Summary collapse
-
.association_names ⇒ Object
A list of all associations created, used for caching and performance.
-
.column_details ⇒ Object
:nodoc:.
-
.condition_names ⇒ Object
A list of all conditions available, users for caching and performance.
-
.conditions ⇒ Object
A list of available condition type classes.
-
.modifiers ⇒ Object
A list of available modifier classes.
-
.needed?(model_class, conditions) ⇒ Boolean
:nodoc:.
-
.register_condition(condition_class) ⇒ Object
Registers a condition as an available condition for a column or a class.
-
.register_modifier(modifier_class) ⇒ Object
Registers a modifier as an available modifier for each column.
Instance Method Summary collapse
-
#any? ⇒ Boolean
Convenience method for determining if we should join the conditions with “AND” or “OR”.
-
#auto_joins ⇒ Object
A list of joins to use when searching, includes relationships.
-
#conditions ⇒ Object
All of the active conditions (conditions that have been set).
-
#conditions=(value) ⇒ Object
Allows you to set the conditions via a hash.
-
#initialize(init_conditions = {}) ⇒ Base
constructor
A new instance of Base.
- #inspect ⇒ Object
-
#sanitize ⇒ Object
Sanitizes the conditions down into conditions that ActiveRecord::Base.find can understand.
Methods included from Shared::VirtualClasses
Methods included from Protection
#conditions_with_protection=, included, #protect=, #protect?
Constructor Details
#initialize(init_conditions = {}) ⇒ Base
Returns a new instance of Base.
150 151 152 153 154 |
# File 'lib/searchgasm/conditions/base.rb', line 150 def initialize(init_conditions = {}) add_associations! add_column_equals_conditions! self.conditions = init_conditions end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object (private)
350 351 352 353 354 355 356 |
# File 'lib/searchgasm/conditions/base.rb', line 350 def method_missing(name, *args, &block) if setup_condition(name) send(name, *args, &block) else super end end |
Class Attribute Details
.added_associations ⇒ Object
Returns the value of attribute added_associations.
14 15 16 |
# File 'lib/searchgasm/conditions/base.rb', line 14 def added_associations @added_associations end |
.added_column_equals_conditions ⇒ Object
Returns the value of attribute added_column_equals_conditions.
14 15 16 |
# File 'lib/searchgasm/conditions/base.rb', line 14 def added_column_equals_conditions @added_column_equals_conditions end |
.added_klass_conditions ⇒ Object
Returns the value of attribute added_klass_conditions.
14 15 16 |
# File 'lib/searchgasm/conditions/base.rb', line 14 def added_klass_conditions @added_klass_conditions end |
Instance Attribute Details
#any ⇒ Object
:nodoc:
167 168 169 |
# File 'lib/searchgasm/conditions/base.rb', line 167 def any @any end |
#relationship_name ⇒ Object
Returns the value of attribute relationship_name.
11 12 13 |
# File 'lib/searchgasm/conditions/base.rb', line 11 def relationship_name @relationship_name end |
Class Method Details
.association_names ⇒ Object
A list of all associations created, used for caching and performance
123 124 125 |
# File 'lib/searchgasm/conditions/base.rb', line 123 def association_names @association_names ||= [] end |
.column_details ⇒ Object
:nodoc:
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/searchgasm/conditions/base.rb', line 16 def column_details # :nodoc: return @column_details if @column_details @column_details = [] klass.columns.each do |column| column_detail = {:column => column} column_detail[:aliases] = case column.type when :datetime, :time, :timestamp [column.name.gsub(/_at$/, "")] when :date [column.name.gsub(/_at$/, "")] else [] end @column_details << column_detail end @column_details end |
.condition_names ⇒ Object
A list of all conditions available, users for caching and performance
128 129 130 |
# File 'lib/searchgasm/conditions/base.rb', line 128 def condition_names @condition_names ||= [] end |
.conditions ⇒ Object
A list of available condition type classes
67 68 69 |
# File 'lib/searchgasm/conditions/base.rb', line 67 def conditions @@conditions ||= [] end |
.modifiers ⇒ Object
A list of available modifier classes
118 119 120 |
# File 'lib/searchgasm/conditions/base.rb', line 118 def modifiers @@modifiers ||= [] end |
.needed?(model_class, conditions) ⇒ Boolean
:nodoc:
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/searchgasm/conditions/base.rb', line 132 def needed?(model_class, conditions) # :nodoc: return false if conditions.blank? if conditions.is_a?(Hash) return true if conditions[:any] stringified_conditions = conditions.stringify_keys stringified_conditions.keys.each { |condition| return false if condition.include?(".") } # setting conditions on associations, which is just another way of writing SQL, and we ignore SQL column_names = model_class.column_names stringified_conditions.keys.each do |condition| return true unless column_names.include?(condition) end end false end |
.register_condition(condition_class) ⇒ Object
Registers a condition as an available condition for a column or a class. MySQL supports a “sounds like” function. I want to use it, so let’s add it.
Example
# config/initializers/searchgasm.rb
# Actual function for MySQL databases only
class SoundsLike < Searchgasm::Condition::Base
# The name of the conditions. By default its the name of the class, if you want alternate or alias conditions just add them on.
# If you don't want to add aliases you don't even need to define this method
def self.name_for_column(column)
super
end
# You can return an array or a string. NOT a hash, because all of these conditions
# need to eventually get merged together. The array or string can be anything you would put in
# the :conditions option for ActiveRecord::Base.find(). Also notice the column_sql variable. This is essentail
# for applying modifiers and should be used in your conditions wherever you want the column.
def to_conditions(value)
["#{column_sql} SOUNDS LIKE ?", value]
end
end
Searchgasm::Seearch::Conditions.register_condition(SoundsLike)
61 62 63 64 |
# File 'lib/searchgasm/conditions/base.rb', line 61 def register_condition(condition_class) raise(ArgumentError, "You can only register conditions that extend Searchgasm::Condition::Base") unless condition_class.ancestors.include?(Searchgasm::Condition::Base) conditions << condition_class unless conditions.include?(condition_class) end |
.register_modifier(modifier_class) ⇒ Object
Registers a modifier as an available modifier for each column.
Example
# config/initializers/searchgasm.rb
class Ceil < Searchgasm::Modifiers::Base
# The name of the modifier. By default its the name of the class, if you want alternate or alias modifiers just add them on.
# If you don't want to add aliases you don't even need to define this method
def self.modifier_names
super + ["round_up"]
end
# The name of the method in the connection adapters (see below). By default its the name of your class suffixed with "_sql".
# So in this example it would be "ceil_sql". Unless you want to change that you don't need to define this method.
def self.adapter_method_name
super
end
# This is the type of value returned from the modifier. This is neccessary for typcasting values for the modifier when
# applied to a column
def self.return_type
:integer
end
end
Searchgasm::Seearch::Conditions.register_modifiers(Ceil)
Now here’s the fun part, applying this modifier to each connection adapter. Some databases call modifiers differently. If they all apply them the same you can add in the function to ActiveRecord::ConnectionAdapters::AbstractAdapter, otherwise you need to add them to each individually: ActiveRecord::ConnectionAdapters::MysqlAdapter, ActiveRecord::ConnectionAdapters::PostgreSQLAdapter, ActiveRecord::ConnectionAdapters::SQLiteAdapter
Do this by includine a model with your method. The name of your method, by default, is: #modifier_name_sql. So in the example above it would be “ceil_sql”
module CeilAdapterMethod
def ceil_sql(column_name)
"CEIL(#{column_name})"
end
end
ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:include, CeilAdapterMethod)
# ... include for the rest of the adapters
112 113 114 115 |
# File 'lib/searchgasm/conditions/base.rb', line 112 def register_modifier(modifier_class) raise(ArgumentError, "You can only register conditions that extend Searchgasm::Modifiers::Base") unless modifier_class.ancestors.include?(Searchgasm::Modifiers::Base) modifiers << modifier_class unless modifiers.include?(modifier_class) end |
Instance Method Details
#any? ⇒ Boolean
Convenience method for determining if we should join the conditions with “AND” or “OR”.
172 173 174 |
# File 'lib/searchgasm/conditions/base.rb', line 172 def any? @any == true || @any == "true" || @any == "1" || @any == "yes" end |
#auto_joins ⇒ Object
A list of joins to use when searching, includes relationships
177 178 179 180 181 182 183 184 185 |
# File 'lib/searchgasm/conditions/base.rb', line 177 def auto_joins j = [] associations.each do |name, association| next if association.conditions.blank? association_joins = association.auto_joins j << (association_joins.blank? ? name : {name => association_joins}) end j.blank? ? nil : (j.size == 1 ? j.first : j) end |
#conditions ⇒ Object
All of the active conditions (conditions that have been set)
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/searchgasm/conditions/base.rb', line 227 def conditions return @conditions if @conditions return if objects.blank? conditions_hash = {} objects.each do |name, object| if object.class < Searchgasm::Conditions::Base relationship_conditions = object.conditions next if relationship_conditions.blank? conditions_hash[name] = relationship_conditions else next if object.value_is_meaningless? conditions_hash[name] = object.value end end conditions_hash end |
#conditions=(value) ⇒ Object
Allows you to set the conditions via a hash.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/searchgasm/conditions/base.rb', line 198 def conditions=(value) case value when Hash assert_valid_conditions(value) remove_conditions_from_protected_assignement(value).each do |condition, condition_value| # delete all blanks from mass assignments, forms submit blanks, blanks are meaningless # equals condition thinks everything is meaningful, and arrays can be pased new_condition_value = nil case condition_value when Array new_condition_value = [] condition_value.each { |v| new_condition_value << v unless v == "" } next if new_condition_value.size == 0 new_condition_value = new_condition_value.first if new_condition_value.size == 1 else next if condition_value == "" new_condition_value = condition_value end send("#{condition}=", new_condition_value) end else reset_objects! @conditions = value end end |
#inspect ⇒ Object
187 188 189 |
# File 'lib/searchgasm/conditions/base.rb', line 187 def inspect "#<#{klass}Conditions#{conditions.blank? ? "" : " #{conditions.inspect}"}>" end |
#sanitize ⇒ Object
Sanitizes the conditions down into conditions that ActiveRecord::Base.find can understand.
192 193 194 195 |
# File 'lib/searchgasm/conditions/base.rb', line 192 def sanitize return @conditions if @conditions merge_conditions(*(objects.collect { |name, object| object.sanitize } << {:any => any})) end |