ernie/meta_search — Issue #72: Quick fix for multiple attributes with different types (with OR)
Author: eLod
Created: 2011-11-10 20:08:46+00:00
State: open

I'm using this workaround to enable something like `search(:title_matches_or_description_starts_with => 'foo')`. However my solution lifts the functionality that applies the condition from `Where#evaluate` to `Builder` (because we need to OR together different kind of predicates and that is out of scope for a single where), so it's not optimal:

```ruby
module MetaSearch
module MultiAttributes
private
def method_missing(method_id, *args, &block)
if match = matches_multi_attributes_method(method_id)
(args.any? || method_name =~ /=$/) ? set_multi_attributes_method_value(match, args.first) : get_multi_attributes_method_value(match, predicates)
else
super
end
end

def matches_multi_attributes_method(method_id)
attributes = method_id.to_s.split(/_or_/)
attributes.collect do |attribute_with_predicate|
return unless match = matches_attribute_method(attribute_with_predicate)
match.captures
end
end

def get_multi_attributes_method_value(attributes_with_predicates)
search_attributes[multi_attributes_key(attributes_with_predicates)]
end

def set_multi_attributes_method_value(attributes_with_predicates, val)
search_attributes[multi_attributes_key(attributes_with_predicates)] = val
conditions = attributes_with_predicates.collect do |(attribute, predicate)|
where = Where.new(predicate)
casted_val = cast_attributes(where.cast || column_type(attribute), val)
if where.validate(casted_val)
arel_attribute = get_attribute(attribute)
if where.splat_param?
arel_attribute.send(where.predicate, *where.format_param(casted_val))
else
arel_attribute.send(where.predicate, where.format_param(casted_val))
end
end
end.compact
@relation = @relation.where(conditions.inject(nil) {|memo, c| memo ? memo.or(c) : c}) if conditions.any?
end

def multi_attributes_key(attributes_with_predicates)
attributes_with_predicates.collect {|a_w_p| a_w_p.join('_')}.join('_or_')
end
end

Builder.send :include, MultiAttributes
end
```