# encoding: utf-8
module Mongoid #:nodoc:
module Finders #:nodoc:
# Find +Documents+ given the conditions.
#
# Options:
#
# args: A +Hash+ with a conditions key and other options
#
# Person.all(:conditions => { :attribute => "value" })
def all(*args)
find(:all, *args)
end
# Returns a count of matching records in the database based on the
# provided arguments.
#
# Person.count(:first, :conditions => { :attribute => "value" })
def count(*args)
Criteria.translate(self, *args).count
end
# Helper to initialize a new +Criteria+ object for this class.
#
# Example:
#
# Person.criteria
def criteria
Criteria.new(self)
end
# Find a +Document+ in several different ways.
#
# If a +String+ is provided, it will be assumed that it is a
# representation of a Mongo::ObjectID and will attempt to find a single
# +Document+ based on that id. If a +Symbol+ and +Hash+ is provided then
# it will attempt to find either a single +Document+ or multiples based
# on the conditions provided and the first parameter.
#
# Person.find(:first, :conditions => { :attribute => "value" })
#
# Person.find(:all, :conditions => { :attribute => "value" })
#
# Person.find(Mongo::ObjectID.new.to_s)
def find(*args)
raise Errors::InvalidOptions.new("Calling Document#find with nil is invalid") if args[0].nil?
type = args.delete_at(0) if args[0].is_a?(Symbol)
criteria = Criteria.translate(self, *args)
case type
when :first then return criteria.one
when :last then return criteria.last
else
return criteria
end
end
# Find the first +Document+ given the conditions, or creates a new document
# with the conditions that were supplied
#
# Options:
#
# args: A +Hash+ of attributes
#
# Person.find_or_create_by(:attribute => "value")
def find_or_create_by(attrs = {})
find_or(:create, attrs)
end
# Find the first +Document+ given the conditions, or instantiates a new document
# with the conditions that were supplied
#
# Options:
#
# args: A +Hash+ of attributes
#
# Person.find_or_initialize_by(:attribute => "value")
def find_or_initialize_by(attrs = {})
find_or(:new, attrs)
end
# Find the first +Document+ given the conditions.
#
# Options:
#
# args: A +Hash+ with a conditions key and other options
#
# Person.first(:conditions => { :attribute => "value" })
def first(*args)
find(:first, *args)
end
# Find the last +Document+ given the conditions.
#
# Options:
#
# args: A +Hash+ with a conditions key and other options
#
# Person.last(:conditions => { :attribute => "value" })
def last(*args)
find(:last, *args)
end
# Convenience method for returning the max value of a field.
#
# Options:
#
# field: The field to use when calculating the max.
#
# Example:
#
# Person.max(:age)
#
# Returns: Float max value.
def max(field)
Criteria.new(self).max(field)
end
# Will execute a +Criteria+ based on the +DynamicFinder+ that gets
# generated.
#
# Options:
#
# name: The finder method name
# args: The arguments to pass to the method.
#
# Example:
#
# Person.find_all_by_title_and_age("Sir", 30)
# def method_missing(name, *args)
# dyna = DynamicFinder.new(name, *args)
# finder, conditions = dyna.finder, dyna.conditions
# results = find(finder, :conditions => conditions)
# results ? results : dyna.create(self)
# end
# Convenience method for returning the min value of a field.
#
# Options:
#
# field: The field to use when calculating the min.
#
# Example:
#
# Person.min(:age)
#
# Returns: Float min value.
def min(field)
Criteria.new(self).min(field)
end
# Find all documents in paginated fashion given the supplied arguments.
# If no parameters are passed just default to offset 0 and limit 20.
#
# Options:
#
# params: A +Hash+ of params to pass to the Criteria API.
#
# Example:
#
# Person.paginate(:conditions => { :field => "Test" }, :page => 1,
# :per_page => 20)
#
# Returns paginated array of docs.
def paginate(params = {})
Criteria.translate(self, params).paginate
end
# Entry point for creating a new criteria from a Document. This will
# instantiate a new +Criteria+ object with the supplied select criterion
# already added to it.
#
# Options:
#
# args: A list of field names to retrict the returned fields to.
#
# Example:
#
# Person.only(:field1, :field2, :field3)
#
# Returns: Criteria
def only(*args)
Criteria.new(self).only(*args)
end
# Convenience method for returning the sum of a specified field for all
# documents in the database.
#
# Options:
#
# field: The field to use when calculating the sum.
#
# Example:
#
# Person.sum(:age)
#
# Returns: Float of the sum.
def sum(field)
Criteria.new(self).sum(field)
end
# Entry point for creating a new criteria from a Document. This will
# instantiate a new +Criteria+ object with the supplied select criterion
# already added to it.
#
# Options:
#
# selector: A where criteria to initialize.
#
# Example:
#
# Person.where(:field1 => "Value")
#
# Returns: Criteria
def where(selector = nil)
Criteria.new(self).where(selector)
end
protected
# Find the first object or create/initialize it.
def find_or(method, attrs = {})
first(:conditions => attrs) || send(method, attrs)
end
end
end