forked from mongodb/mongoid
/
finders.rb
167 lines (153 loc) · 4.7 KB
/
finders.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# encoding: utf-8
module Mongoid
# This module defines the finder methods that hang off the document at the
# class level.
module Finders
extend Origin::Forwardable
select_with :with_default_scope
# These are methods defined on the criteria that should also be accessible
# directly from the the class level.
delegate \
:aggregates,
:avg,
:each,
:each_with_index,
:extras,
:find_and_modify,
:first_or_create,
:first_or_create!,
:first_or_initialize,
:for_js,
:includes,
:map_reduce,
:max,
:min,
:pluck,
:sum,
:update,
:update_all, to: :with_default_scope
# Returns a count of records in the database.
# If you want to specify conditions use where.
#
# @example Get the count of matching documents.
# Person.count
# Person.where(title: "Sir").count
#
# @return [ Integer ] The number of matching documents.
def count
with_default_scope.count
end
# Returns true if count is zero
#
# @example Are there no saved documents for this model?
# Person.empty?
#
# @return [ true, false ] If the collection is empty.
def empty?
count == 0
end
# Returns true if there are on document in database based on the
# provided arguments.
#
# @example Do any documents exist for the conditions?
# Person.exists?
#
# @param [ Array ] args The conditions.
def exists?
with_default_scope.exists?
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.
#
# @example Find a single document by an id.
# Person.find(Moped::BSON::ObjectId)
#
# @param [ Array ] args An assortment of finder options.
#
# @return [ Document, nil, Criteria ] A document or matching documents.
def find(*args)
with_default_scope.find(*args)
end
# Find the first +Document+ given the conditions, or creates a new document
# with the conditions that were supplied.
#
# @example Find or create the document.
# Person.find_or_create_by(:attribute => "value")
#
# @param [ Hash ] attrs The attributes to check.
#
# @return [ Document ] A matching or newly created document.
def find_or_create_by(attrs = {}, &block)
find_or(:create, attrs, &block)
end
# Find the first +Document+ given the conditions, or initializes a new document
# with the conditions that were supplied.
#
# @example Find or initialize the document.
# Person.find_or_initialize_by(:attribute => "value")
#
# @param [ Hash ] attrs The attributes to check.
#
# @return [ Document ] A matching or newly initialized document.
def find_or_initialize_by(attrs = {}, &block)
find_or(:new, attrs, &block)
end
# Find the first +Document+ given the conditions, or raises
# Mongoid::Errors::DocumentNotFound
#
# @example Find the document by attribute other than id
# Person.find_by(:username => "superuser")
#
# @param [ Hash ] attrs The attributes to check.
#
# @raise [ Errors::DocumentNotFound ] If no document found.
#
# @return [ Document ] A matching document.
#
# @since 3.0.0
def find_by(attrs = {})
result = where(attrs).first
if result.nil? && Mongoid.raise_not_found_error
raise(Errors::DocumentNotFound.new(self, attrs))
end
yield(result) if result && block_given?
result
end
# Find the first +Document+ given the conditions.
#
# @example Find the first document.
# Person.first
#
# @return [ Document ] The first matching document.
def first
with_default_scope.first
end
# Find the last +Document+ given the conditions.
#
# @example Find the last document.
# Person.last
#
# @return [ Document ] The last matching document.
def last
with_default_scope.last
end
protected
# Find the first object or create/initialize it.
#
# @example Find or perform an action.
# Person.find_or(:create, :name => "Dev")
#
# @param [ Symbol ] method The method to invoke.
# @param [ Hash ] attrs The attributes to query or set.
#
# @return [ Document ] The first or new document.
def find_or(method, attrs = {}, &block)
where(attrs).first || send(method, attrs, &block)
end
end
end