# encoding: utf-8 module Mongoid #:nodoc: module Criterion #:nodoc: module Optional # Adds fields to be sorted in ascending order. Will add them in the order # they were passed into the method. # # Example: # # criteria.ascending(:title, :dob) def ascending(*fields) clone.tap do |crit| crit.options[:sort] = [] unless options[:sort] || fields.first.nil? fields.flatten.each { |field| crit.options[:sort] << [ field, :asc ] } end end alias :asc :ascending # Tells the criteria that the cursor that gets returned needs to be # cached. This is so multiple iterations don't hit the database multiple # times, however this is not advisable when working with large data sets # as the entire results will get stored in memory. # # Example: # # criteria.cache def cache clone.tap { |crit| crit.options.merge!(:cache => true) } end # Will return true if the cache option has been set. # # Example: # # criteria.cached? def cached? options[:cache] == true end # Adds fields to be sorted in descending order. Will add them in the order # they were passed into the method. # # Example: # # criteria.descending(:title, :dob) def descending(*fields) clone.tap do |crit| crit.options[:sort] = [] unless options[:sort] || fields.first.nil? fields.flatten.each { |field| crit.options[:sort] << [ field, :desc ] } end end alias :desc :descending # Flags the criteria to execute against a read-only slave in the pool # instead of master. # # Example: # # criteria.enslave def enslave clone.tap { |crit| crit.options.merge!(:enslave => true) } end # Will return true if the criteria is enslaved. # # Example: # # criteria.enslaved? def enslaved? options[:enslave] == true end # Adds a criterion to the +Criteria+ that specifies additional options # to be passed to the Ruby driver, in the exact format for the driver. # # Options: # # extras: A +Hash+ that gets set to the driver options. # # Example: # # criteria.extras(:limit => 20, :skip => 40) # # Returns: self def extras(extras) clone.tap do |crit| crit.options.merge!(extras) crit.filter_options end end # Adds a criterion to the +Criteria+ that specifies an id that must be matched. # # Options: # # object_id: A single id or an array of ids in +String+ or BSON::ObjectId format # # Example: # # criteria.for_ids("4ab2bc4b8ad548971900005c") # criteria.for_ids(["4ab2bc4b8ad548971900005c", "4c454e7ebf4b98032d000001"]) # # Returns: self def for_ids(*ids) ids.flatten! if ids.size > 1 any_in( :_id => ::BSON::ObjectId.convert(klass, ids) ) else clone.tap do |crit| crit.selector[:_id] = ::BSON::ObjectId.convert(klass, ids.first) end end end # Adds a criterion to the +Criteria+ that specifies the maximum number of # results to return. This is mostly used in conjunction with skip() # to handle paginated results. # # Options: # # value: An +Integer+ specifying the max number of results. Defaults to 20. # # Example: # # criteria.limit(100) # # Returns: self def limit(value = 20) clone.tap { |crit| crit.options[:limit] = value } end # Returns the offset option. If a per_page option is in the list then it # will replace it with a skip parameter and return the same value. Defaults # to 20 if nothing was provided. def offset(*args) args.size > 0 ? skip(args.first) : options[:skip] end # Adds a criterion to the +Criteria+ that specifies the sort order of # the returned documents in the database. Similar to a SQL "ORDER BY". # # Options: # # params: An +Array+ of [field, direction] sorting pairs. # # Example: # # criteria.order_by([[:field1, :asc], [:field2, :desc]]) # # Returns: self def order_by(*args) clone.tap do |crit| crit.options[:sort] = [] unless options[:sort] || args.first.nil? arguments = args.first case arguments when Hash arguments.each do |field, direction| crit.options[:sort] << [ field, direction ] end when Array crit.options[:sort].concat(arguments) when Complex args.flatten.each do |complex| crit.options[:sort] << [ complex.key, complex.operator.to_sym ] end end end end alias :order :order_by # Adds a criterion to the +Criteria+ that specifies how many results to skip # when returning Documents. This is mostly used in conjunction with # limit() to handle paginated results, and is similar to the # traditional "offset" parameter. # # Options: # # value: An +Integer+ specifying the number of results to skip. Defaults to 0. # # Example: # # criteria.skip(20) # # Returns: self def skip(value = 0) clone.tap { |crit| crit.options[:skip] = value } end # Adds a criterion to the +Criteria+ that specifies a type or an Array of # type that must be matched. # # Options: # # types : An +Array+ of types of a +String+ representing the Type of you search # # Example: # # criteria.type('Browser') # criteria.type(['Firefox', 'Browser']) # # Returns: self def type(types) types = [types] unless types.is_a?(Array) any_in(:_type => types) end end end end