module Sunspot module Restriction #:nodoc: class <<self # # Return the names of all of the restriction classes that should be made # available to the DSL. # # ==== Returns # # Array:: Collection of restriction class names # def names constants - %w(Base SameAs) #XXX this seems ugly end end # # Subclasses of this class represent restrictions that can be applied to # a Sunspot query. The Sunspot::DSL::Restriction class presents a builder # API for instances of this class. # # Implementations of this class must respond to #to_params and # #to_negative_params. Instead of implementing those methods, they may # choose to implement any of: # # * #to_positive_boolean_phrase, and optionally #to_negative_boolean_phrase # * #to_solr_conditional # class Base #:nodoc: def initialize(field, value, negative = false) @field, @value, @negative = field, value, negative end # # A hash representing this restriction in solr-ruby's parameter format. # All restriction implementations must respond to this method; however, # the base implementation delegates to the #to_positive_boolean_phrase method, so # subclasses may (and probably should) choose to implement that method # instead. # # ==== Returns # # Hash:: Representation of this restriction as solr-ruby parameters # def to_params { :filter_queries => [to_boolean_phrase] } end # # Return the boolean phrase associated with this restriction object. # Differentiates between positive and negative boolean phrases depending # on whether this restriction is negated. # def to_boolean_phrase unless negative? to_positive_boolean_phrase else to_negative_boolean_phrase end end # # Boolean phrase representing this restriction in the positive. Subclasses # may choose to implement this method rather than #to_params; however, # this method delegates to the abstract #to_solr_conditional method, which # in most cases will be what subclasses will want to implement. # #to_solr_conditional contains the boolean phrase representing the # condition but leaves out the field name (see built-in implementations # for examples) # # ==== Returns # # String:: Boolean phrase for restriction in the positive # def to_positive_boolean_phrase "#{@field.indexed_name}:#{to_solr_conditional}" end # # Boolean phrase representing this restriction in the negative. Subclasses # may choose to implement this method, but it is not necessary, as the # base implementation delegates to #to_positive_boolean_phrase. # # ==== Returns # # String:: Boolean phrase for restriction in the negative # def to_negative_boolean_phrase "-#{to_positive_boolean_phrase}" end protected # # Whether this restriction should be negated from its original meaning # def negative? !!@negative end # # Return escaped Solr API representation of given value # # ==== Parameters # # value<Object>:: # value to convert to Solr representation (default: @value) # # ==== Returns # # String:: Solr API representation of given value # def solr_value(value = @value) Solr::Util.query_parser_escape(@field.to_indexed(value)) end end # # Results must have field with value equal to given value. If the value # is nil, results must have no value for the given field. # class EqualTo < Base def to_positive_boolean_phrase unless @value.nil? super else "-#{@field.indexed_name}:[* TO *]" end end def to_negative_boolean_phrase unless @value.nil? super else "#{@field.indexed_name}:[* TO *]" end end private def to_solr_conditional "#{solr_value}" end end # # Results must have field with value less than given value # class LessThan < Base private def to_solr_conditional "[* TO #{solr_value}]" end end # # Results must have field with value greater than given value # class GreaterThan < Base private def to_solr_conditional "[#{solr_value} TO *]" end end # # Results must have field with value in given range # class Between < Base private def to_solr_conditional "[#{solr_value(@value.first)} TO #{solr_value(@value.last)}]" end end # # Results must have field with value included in given collection # class AnyOf < Base private def to_solr_conditional "(#{@value.map { |v| solr_value v } * ' OR '})" end end # # Results must have field with values matching all values in given # collection (only makes sense for fields with multiple values) # class AllOf < Base private def to_solr_conditional "(#{@value.map { |v| solr_value v } * ' AND '})" end end # # Result must be the exact instance given (only useful when negated). # class SameAs < Base def initialize(object, negative = false) @object, @negative = object, negative end def to_positive_boolean_phrase adapter = Adapters::InstanceAdapter.adapt(@object) "id:#{Solr::Util.query_parser_escape(adapter.index_id)}" end end end end