Module: Candy::Collection

Includes:
Enumerable
Defined in:
lib/candy/collection.rb

Overview

Handles Mongo queries for cursors upon a particular Mongo collection.

Defined Under Namespace

Modules: ClassMethods

Constant Summary collapse

FIND_OPTIONS =
[:fields, :skip, :limit, :sort, :hint, :snapshot, :timeout]
UP_SORTS =
[Mongo::ASCENDING, 'ascending', 'asc', :ascending, :asc, 1, :up]
DOWN_SORTS =
[Mongo::DESCENDING, 'descending', 'desc', :descending, :desc, -1, :down]

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/candy/collection.rb', line 71

def method_missing(name, *args, &block)
  if @_candy_cursor.respond_to?(name)
    @_candy_cursor.send(name, *args, &block)
  elsif FIND_OPTIONS.include?(name)
    @_candy_options[name] = args.shift
    refresh_cursor
    self
  else
    @_candy_query[name] = args.shift
    @_candy_query.merge!(args) if args.is_a?(Hash)
    refresh_cursor
    self
  end
end

Instance Method Details

#eachObject

Makes our collection enumerable. This relies heavily on Mongo::Cursor methods – we only reimplement it so that the objects we return can be Candy objects.



89
90
91
92
93
# File 'lib/candy/collection.rb', line 89

def each
  while this = @_candy_cursor.next_document
    yield self.class._candy_piece.new(this)
  end
end

#initialize(*args, &block) ⇒ Object

Here endeth the ClassMethods module



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/candy/collection.rb', line 58

def initialize(*args, &block)
  conditions = args.pop || {}
  super
  @_candy_query = {}
  if conditions.is_a?(Hash)
    @_candy_options = {:fields => '_id'}.merge(extract_options(conditions))
    @_candy_query.merge!(conditions)
  else
    @_candy_options = {:fields => '_id'}
  end
  refresh_cursor
end

#nextObject

Get our next document as a Candy object, if there is one.



96
97
98
99
100
# File 'lib/candy/collection.rb', line 96

def next
  if this = @_candy_cursor.next_document
    self.class._candy_piece.new(this)
  end
end

#sort(*fields) ⇒ Object

Determines the sort order for this collection, with somewhat simpler semantics than the MongoDB options. Each value is either a field name (which defaults to ascending sort) or a direction (which modifies the field name immediately prior) or a two-element array of same. Direction can be :up or :down in addition to Mongo’s accepted values of :ascending, ‘asc’, 1, etc.

As an added bonus, sorts can also be chained. If you call #sort more than once then all sorts will be applied in the order in which you called them.



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/candy/collection.rb', line 110

def sort(*fields)
  @_candy_sort ||= []
  temp_sort = []
  until fields.flatten.empty?
    this = fields.pop  # We're going backwards so that we can test for modifiers
    if UP_SORTS.include?(this)
      temp_sort.unshift [fields.pop, Mongo::ASCENDING]
    elsif DOWN_SORTS.include?(this)
      temp_sort.unshift [fields.pop, Mongo::DESCENDING]
    else
      temp_sort.unshift [this, Mongo::ASCENDING]
    end
  end
  @_candy_sort += temp_sort
  @_candy_cursor.sort(@_candy_sort)
  self
end