mongo_doc 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.textile +174 -0
- data/Rakefile +135 -0
- data/TODO +31 -0
- data/VERSION +1 -0
- data/data/.gitignore +2 -0
- data/examples/simple_document.rb +35 -0
- data/examples/simple_object.rb +30 -0
- data/features/finders.feature +76 -0
- data/features/mongodb.yml +7 -0
- data/features/mongodoc_base.feature +128 -0
- data/features/new_record.feature +36 -0
- data/features/partial_updates.feature +105 -0
- data/features/removing_documents.feature +68 -0
- data/features/saving_an_object.feature +15 -0
- data/features/scopes.feature +66 -0
- data/features/step_definitions/collection_steps.rb +14 -0
- data/features/step_definitions/document_steps.rb +149 -0
- data/features/step_definitions/documents.rb +30 -0
- data/features/step_definitions/finder_steps.rb +15 -0
- data/features/step_definitions/json_steps.rb +9 -0
- data/features/step_definitions/object_steps.rb +50 -0
- data/features/step_definitions/objects.rb +24 -0
- data/features/step_definitions/partial_update_steps.rb +32 -0
- data/features/step_definitions/query_steps.rb +54 -0
- data/features/step_definitions/removing_documents_steps.rb +14 -0
- data/features/step_definitions/scope_steps.rb +18 -0
- data/features/step_definitions/util_steps.rb +7 -0
- data/features/support/support.rb +10 -0
- data/features/using_criteria.feature +128 -0
- data/lib/mongo_doc/associations/collection_proxy.rb +105 -0
- data/lib/mongo_doc/associations/document_proxy.rb +56 -0
- data/lib/mongo_doc/associations/hash_proxy.rb +98 -0
- data/lib/mongo_doc/associations/proxy_base.rb +53 -0
- data/lib/mongo_doc/attributes.rb +140 -0
- data/lib/mongo_doc/bson.rb +45 -0
- data/lib/mongo_doc/collection.rb +55 -0
- data/lib/mongo_doc/connection.rb +88 -0
- data/lib/mongo_doc/contexts/enumerable.rb +128 -0
- data/lib/mongo_doc/contexts/ids.rb +41 -0
- data/lib/mongo_doc/contexts/mongo.rb +232 -0
- data/lib/mongo_doc/contexts.rb +25 -0
- data/lib/mongo_doc/criteria.rb +38 -0
- data/lib/mongo_doc/cursor.rb +32 -0
- data/lib/mongo_doc/document.rb +216 -0
- data/lib/mongo_doc/ext/array.rb +5 -0
- data/lib/mongo_doc/ext/binary.rb +7 -0
- data/lib/mongo_doc/ext/boolean_class.rb +11 -0
- data/lib/mongo_doc/ext/date.rb +16 -0
- data/lib/mongo_doc/ext/date_time.rb +13 -0
- data/lib/mongo_doc/ext/dbref.rb +7 -0
- data/lib/mongo_doc/ext/hash.rb +7 -0
- data/lib/mongo_doc/ext/nil_class.rb +5 -0
- data/lib/mongo_doc/ext/numeric.rb +17 -0
- data/lib/mongo_doc/ext/object.rb +17 -0
- data/lib/mongo_doc/ext/object_id.rb +7 -0
- data/lib/mongo_doc/ext/regexp.rb +5 -0
- data/lib/mongo_doc/ext/string.rb +5 -0
- data/lib/mongo_doc/ext/symbol.rb +5 -0
- data/lib/mongo_doc/ext/time.rb +5 -0
- data/lib/mongo_doc/finders.rb +49 -0
- data/lib/mongo_doc/matchers.rb +35 -0
- data/lib/mongo_doc/query.rb +7 -0
- data/lib/mongo_doc/scope.rb +64 -0
- data/lib/mongo_doc/validations/macros.rb +11 -0
- data/lib/mongo_doc/validations/validates_embedded.rb +13 -0
- data/lib/mongo_doc.rb +19 -0
- data/lib/mongoid/contexts/paging.rb +42 -0
- data/lib/mongoid/criteria.rb +247 -0
- data/lib/mongoid/criterion/complex.rb +21 -0
- data/lib/mongoid/criterion/exclusion.rb +65 -0
- data/lib/mongoid/criterion/inclusion.rb +92 -0
- data/lib/mongoid/criterion/optional.rb +136 -0
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
- data/lib/mongoid/extensions/symbol/inflections.rb +36 -0
- data/lib/mongoid/matchers/all.rb +11 -0
- data/lib/mongoid/matchers/default.rb +26 -0
- data/lib/mongoid/matchers/exists.rb +13 -0
- data/lib/mongoid/matchers/gt.rb +11 -0
- data/lib/mongoid/matchers/gte.rb +11 -0
- data/lib/mongoid/matchers/in.rb +11 -0
- data/lib/mongoid/matchers/lt.rb +11 -0
- data/lib/mongoid/matchers/lte.rb +11 -0
- data/lib/mongoid/matchers/ne.rb +11 -0
- data/lib/mongoid/matchers/nin.rb +11 -0
- data/lib/mongoid/matchers/size.rb +11 -0
- data/mongo_doc.gemspec +205 -0
- data/mongod.example.yml +2 -0
- data/mongodb.example.yml +14 -0
- data/perf/mongo_doc_runner.rb +90 -0
- data/perf/ruby_driver_runner.rb +64 -0
- data/script/console +8 -0
- data/spec/associations/collection_proxy_spec.rb +200 -0
- data/spec/associations/document_proxy_spec.rb +42 -0
- data/spec/associations/hash_proxy_spec.rb +163 -0
- data/spec/attributes_spec.rb +273 -0
- data/spec/bson_matchers.rb +54 -0
- data/spec/bson_spec.rb +196 -0
- data/spec/collection_spec.rb +161 -0
- data/spec/connection_spec.rb +147 -0
- data/spec/contexts/enumerable_spec.rb +274 -0
- data/spec/contexts/ids_spec.rb +49 -0
- data/spec/contexts/mongo_spec.rb +198 -0
- data/spec/contexts_spec.rb +28 -0
- data/spec/criteria_spec.rb +33 -0
- data/spec/cursor_spec.rb +91 -0
- data/spec/document_ext.rb +9 -0
- data/spec/document_spec.rb +664 -0
- data/spec/embedded_save_spec.rb +109 -0
- data/spec/finders_spec.rb +73 -0
- data/spec/hash_matchers.rb +27 -0
- data/spec/matchers_spec.rb +342 -0
- data/spec/mongodb.yml +6 -0
- data/spec/mongodb_pairs.yml +8 -0
- data/spec/new_record_spec.rb +128 -0
- data/spec/query_spec.rb +12 -0
- data/spec/scope_spec.rb +79 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +13 -0
- metadata +290 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
require 'mongo_doc/bson'
|
|
2
|
+
require 'mongo_doc/query'
|
|
3
|
+
require 'mongo_doc/attributes'
|
|
4
|
+
require 'mongo_doc/criteria'
|
|
5
|
+
require 'mongo_doc/finders'
|
|
6
|
+
require 'mongo_doc/scope'
|
|
7
|
+
require 'mongo_doc/validations/macros'
|
|
8
|
+
|
|
9
|
+
module MongoDoc
|
|
10
|
+
class UnsupportedOperation < RuntimeError; end
|
|
11
|
+
class DocumentInvalidError < RuntimeError; end
|
|
12
|
+
class NotADocumentError < RuntimeError; end
|
|
13
|
+
|
|
14
|
+
module Document
|
|
15
|
+
|
|
16
|
+
def self.included(klass)
|
|
17
|
+
klass.class_eval do
|
|
18
|
+
include Attributes
|
|
19
|
+
extend ClassMethods
|
|
20
|
+
extend Criteria
|
|
21
|
+
extend Finders
|
|
22
|
+
extend Scope
|
|
23
|
+
include ::Validatable
|
|
24
|
+
extend Validations::Macros
|
|
25
|
+
|
|
26
|
+
alias :id :_id
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def initialize(attrs = {})
|
|
31
|
+
self.attributes = attrs
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def ==(other)
|
|
35
|
+
return false unless self.class === other
|
|
36
|
+
self.class._attributes.all? {|var| self.send(var) == other.send(var)}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def attributes
|
|
40
|
+
hash = {}
|
|
41
|
+
self.class._attributes.each do |attr|
|
|
42
|
+
hash[attr] = send(attr)
|
|
43
|
+
end
|
|
44
|
+
hash
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def attributes=(attrs)
|
|
48
|
+
attrs.each do |key, value|
|
|
49
|
+
send("#{key}=", value)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def new_record?
|
|
54
|
+
_id.nil?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def remove
|
|
58
|
+
raise UnsupportedOperation.new('Document#remove is not supported for embedded documents') if _root
|
|
59
|
+
remove_document
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def remove_document
|
|
63
|
+
return _root.remove_document if _root
|
|
64
|
+
_remove
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def save(validate = true)
|
|
68
|
+
return _root.save(validate) if _root
|
|
69
|
+
return _save(false) unless validate and not valid?
|
|
70
|
+
false
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def save!
|
|
74
|
+
return _root.save! if _root
|
|
75
|
+
raise DocumentInvalidError unless valid?
|
|
76
|
+
_save(true)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def to_bson(*args)
|
|
80
|
+
{MongoDoc::BSON::CLASS_KEY => self.class.name}.tap do |bson_hash|
|
|
81
|
+
bson_hash['_id'] = _id unless new_record?
|
|
82
|
+
self.class._attributes.each do |name|
|
|
83
|
+
bson_hash[name.to_s] = send(name).to_bson(args)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def to_param
|
|
89
|
+
_id.to_s
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def update_attributes(attrs)
|
|
93
|
+
strict = attrs.delete(:__strict__)
|
|
94
|
+
self.attributes = attrs
|
|
95
|
+
return save if new_record?
|
|
96
|
+
return false unless valid?
|
|
97
|
+
if strict
|
|
98
|
+
_strict_update_attributes(_path_to_root(self, attrs), false)
|
|
99
|
+
else
|
|
100
|
+
_naive_update_attributes(_path_to_root(self, attrs), false)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def update_attributes!(attrs)
|
|
105
|
+
strict = attrs.delete(:__strict__)
|
|
106
|
+
self.attributes = attrs
|
|
107
|
+
return save! if new_record?
|
|
108
|
+
raise DocumentInvalidError unless valid?
|
|
109
|
+
if strict
|
|
110
|
+
_strict_update_attributes(_path_to_root(self, attrs), true)
|
|
111
|
+
else
|
|
112
|
+
_naive_update_attributes(_path_to_root(self, attrs), true)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
module ClassMethods
|
|
117
|
+
def bson_create(bson_hash, options = {})
|
|
118
|
+
new.tap do |obj|
|
|
119
|
+
bson_hash.each do |name, value|
|
|
120
|
+
obj.send("#{name}=", MongoDoc::BSON.decode(value, options))
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def collection
|
|
126
|
+
@collection ||= MongoDoc::Collection.new(collection_name)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def collection_name
|
|
130
|
+
self.to_s.tableize.gsub('/', '.')
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def create(attrs = {})
|
|
134
|
+
instance = new(attrs)
|
|
135
|
+
instance.save(false)
|
|
136
|
+
instance
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def create!(attrs = {})
|
|
140
|
+
instance = new(attrs)
|
|
141
|
+
instance.save!(true)
|
|
142
|
+
instance
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
protected
|
|
147
|
+
|
|
148
|
+
def _collection
|
|
149
|
+
self.class.collection
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def _naive_update_attributes(attrs, safe)
|
|
153
|
+
return _root.send(:_naive_update_attributes, attrs, safe) if _root
|
|
154
|
+
_update({}, attrs, safe)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def _remove
|
|
158
|
+
_collection.remove({'_id' => _id})
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def _strict_update_attributes(attrs, safe, selector = {})
|
|
162
|
+
return _root.send(:_strict_update_attributes, attrs, safe, _path_to_root(self, '_id' => _id)) if _root
|
|
163
|
+
_update(selector, attrs, safe)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def _update(selector, data, safe)
|
|
167
|
+
_collection.update({'_id' => _id}.merge(selector), MongoDoc::Query.set_modifier(data), :safe => safe)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def _save(safe)
|
|
171
|
+
notify_before_save_observers
|
|
172
|
+
self._id = _collection.save(self, :safe => safe)
|
|
173
|
+
notify_save_success_observers
|
|
174
|
+
self._id
|
|
175
|
+
rescue Mongo::MongoDBError => e
|
|
176
|
+
notify_save_failed_observers
|
|
177
|
+
raise e
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def before_save_callback(root)
|
|
181
|
+
self._id = Mongo::ObjectID.new if new_record?
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def save_failed_callback(root)
|
|
185
|
+
self._id = nil
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def save_success_callback(root)
|
|
189
|
+
root.unregister_save_observer(self)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def save_observers
|
|
193
|
+
@save_observers ||= []
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def register_save_observer(child)
|
|
197
|
+
save_observers << child
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def unregister_save_observer(child)
|
|
201
|
+
save_observers.delete(child)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def notify_before_save_observers
|
|
205
|
+
save_observers.each {|obs| obs.before_save_callback(self) }
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def notify_save_success_observers
|
|
209
|
+
save_observers.each {|obs| obs.save_success_callback(self) }
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def notify_save_failed_observers
|
|
213
|
+
save_observers.each {|obs| obs.save_failed_callback(self) }
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Date
|
|
2
|
+
def to_bson(*args)
|
|
3
|
+
{
|
|
4
|
+
MongoDoc::BSON::CLASS_KEY => self.class.name,
|
|
5
|
+
'dt' => strftime,
|
|
6
|
+
'sg' => start
|
|
7
|
+
}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
alias start sg unless method_defined?(:start)
|
|
11
|
+
|
|
12
|
+
def self.bson_create(bson_hash, options = nil)
|
|
13
|
+
Date.parse(*bson_hash.values_at('dt', 'sg'))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class Object
|
|
2
|
+
def to_bson(*args)
|
|
3
|
+
{MongoDoc::BSON::CLASS_KEY => self.class.name}.tap do |bson_hash|
|
|
4
|
+
instance_variables.each do |name|
|
|
5
|
+
bson_hash[name[1..-1]] = instance_variable_get(name).to_bson(args)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.bson_create(bson_hash, options = {})
|
|
11
|
+
new.tap do |obj|
|
|
12
|
+
bson_hash.each do |name, value|
|
|
13
|
+
obj.instance_variable_set("@#{name}", MongoDoc::BSON.decode(value, options))
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'mongo_doc/criteria'
|
|
2
|
+
|
|
3
|
+
module MongoDoc
|
|
4
|
+
module Finders
|
|
5
|
+
def self.extended(base)
|
|
6
|
+
base.extend(Criteria) unless base === Criteria
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
%w(count first last).each do |name|
|
|
10
|
+
module_eval <<-RUBY
|
|
11
|
+
# #{name.humanize} for this +Document+ class
|
|
12
|
+
#
|
|
13
|
+
# <tt>Person.#{name}</tt>
|
|
14
|
+
def #{name}
|
|
15
|
+
criteria.#{name}
|
|
16
|
+
end
|
|
17
|
+
RUBY
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Find a +Document+ based on id (+String+ or +Mongo::ObjectID+)
|
|
21
|
+
#
|
|
22
|
+
# <tt>Person.find('1')</tt>
|
|
23
|
+
# <tt>Person.find(obj_id_1, obj_id_2)</tt>
|
|
24
|
+
def find(*args)
|
|
25
|
+
criteria.id(*args)
|
|
26
|
+
end
|
|
27
|
+
#
|
|
28
|
+
# Find all +Document+s in the collections
|
|
29
|
+
#
|
|
30
|
+
# <tt>Person.find_all</tt>
|
|
31
|
+
def find_all
|
|
32
|
+
criteria
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Find a +Document+ based on id (+String+ or +Mongo::ObjectID+)
|
|
36
|
+
# or conditions
|
|
37
|
+
#
|
|
38
|
+
# <tt>Person.find_one('1')</tt>
|
|
39
|
+
# <tt>Person.find_one(:where => {:age.gt > 25})</tt>
|
|
40
|
+
def find_one(conditions_or_id)
|
|
41
|
+
if Hash === conditions_or_id
|
|
42
|
+
Mongoid::Criteria.translate(self, conditions_or_id).one
|
|
43
|
+
else
|
|
44
|
+
Mongoid::Criteria.translate(self, conditions_or_id)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require "mongoid/matchers/default"
|
|
2
|
+
require "mongoid/matchers/all"
|
|
3
|
+
require "mongoid/matchers/exists"
|
|
4
|
+
require "mongoid/matchers/gt"
|
|
5
|
+
require "mongoid/matchers/gte"
|
|
6
|
+
require "mongoid/matchers/in"
|
|
7
|
+
require "mongoid/matchers/lt"
|
|
8
|
+
require "mongoid/matchers/lte"
|
|
9
|
+
require "mongoid/matchers/ne"
|
|
10
|
+
require "mongoid/matchers/nin"
|
|
11
|
+
require "mongoid/matchers/size"
|
|
12
|
+
|
|
13
|
+
module MongoDoc #:nodoc:
|
|
14
|
+
module Matchers
|
|
15
|
+
# Determines if this document has the attributes to match the supplied
|
|
16
|
+
# MongoDB selector. Used for matching on embedded associations.
|
|
17
|
+
def matches?(selector)
|
|
18
|
+
selector.each_pair do |key, value|
|
|
19
|
+
return false unless matcher(key, value).matches?(value)
|
|
20
|
+
end
|
|
21
|
+
true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
protected
|
|
25
|
+
# Get the matcher for the supplied key and value. Will determine the class
|
|
26
|
+
# name from the key.
|
|
27
|
+
def matcher(key, value)
|
|
28
|
+
if value.is_a?(Hash)
|
|
29
|
+
name = "Mongoid::Matchers::#{value.keys.first.gsub("$", "").camelize}"
|
|
30
|
+
return name.constantize.new(send(key))
|
|
31
|
+
end
|
|
32
|
+
Mongoid::Matchers::Default.new(send(key))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Based on ActiveRecord::NamedScope
|
|
2
|
+
module MongoDoc
|
|
3
|
+
module Scope
|
|
4
|
+
def scopes
|
|
5
|
+
read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def scope(name, *args, &block)
|
|
9
|
+
options = args.extract_options!
|
|
10
|
+
raise ArgumentError if args.size != 1
|
|
11
|
+
criteria = args.first
|
|
12
|
+
name = name.to_sym
|
|
13
|
+
scopes[name] = lambda do |parent_scope, *args|
|
|
14
|
+
CriteriaProxy.new(parent_scope, Mongoid::Criteria === criteria ? criteria : criteria.call(*args), options, &block)
|
|
15
|
+
end
|
|
16
|
+
(class << self; self; end).class_eval <<-EOT
|
|
17
|
+
def #{name}(*args)
|
|
18
|
+
scopes[:#{name}].call(self, *args)
|
|
19
|
+
end
|
|
20
|
+
EOT
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class CriteriaProxy
|
|
24
|
+
attr_accessor :criteria, :klass, :parent_scope
|
|
25
|
+
|
|
26
|
+
delegate :scopes, :to => :parent_scope
|
|
27
|
+
|
|
28
|
+
def initialize(parent_scope, criteria, options, &block)
|
|
29
|
+
[options.delete(:extend)].flatten.each { |extension| extend extension } if options.include?(:extend)
|
|
30
|
+
extend Module.new(&block) if block_given?
|
|
31
|
+
if CriteriaProxy === parent_scope
|
|
32
|
+
chained = Mongoid::Criteria.new(klass)
|
|
33
|
+
chained.merge(parent_scope)
|
|
34
|
+
chained.merge(criteria)
|
|
35
|
+
self.criteria = chained
|
|
36
|
+
self.klass = criteria.klass
|
|
37
|
+
else
|
|
38
|
+
self.criteria = criteria
|
|
39
|
+
self.klass = parent_scope
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
self.parent_scope = parent_scope
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def respond_to?(method, include_private = false)
|
|
46
|
+
return true if scopes.include?(method)
|
|
47
|
+
criteria.respond_to?(method, include_private)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def method_missing(method, *args, &block)
|
|
53
|
+
if scopes.include?(method)
|
|
54
|
+
scopes[method].call(self, *args)
|
|
55
|
+
else
|
|
56
|
+
chained = Mongoid::Criteria.new(klass)
|
|
57
|
+
chained.merge(criteria)
|
|
58
|
+
chained.send(method, *args, &block)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
data/lib/mongo_doc.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
|
|
3
|
+
gem 'mongo', '0.19'
|
|
4
|
+
gem 'mongo_ext', '0.19'
|
|
5
|
+
gem 'durran-validatable', '2.0.1'
|
|
6
|
+
gem 'leshill-will_paginate', '2.3.11'
|
|
7
|
+
|
|
8
|
+
require 'mongo'
|
|
9
|
+
require 'active_support'
|
|
10
|
+
require 'validatable'
|
|
11
|
+
require 'will_paginate/collection'
|
|
12
|
+
|
|
13
|
+
module MongoDoc
|
|
14
|
+
VERSION = '0.3.0'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require 'mongo_doc/connection'
|
|
18
|
+
require 'mongo_doc/collection'
|
|
19
|
+
require 'mongo_doc/document'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Mongoid #:nodoc:
|
|
3
|
+
module Contexts #:nodoc:
|
|
4
|
+
module Paging
|
|
5
|
+
# Paginates the documents.
|
|
6
|
+
#
|
|
7
|
+
# Example:
|
|
8
|
+
#
|
|
9
|
+
# <tt>context.paginate</tt>
|
|
10
|
+
#
|
|
11
|
+
# Returns:
|
|
12
|
+
#
|
|
13
|
+
# A collection of documents paginated.
|
|
14
|
+
def paginate
|
|
15
|
+
@collection ||= execute(true)
|
|
16
|
+
WillPaginate::Collection.create(page, per_page, count) do |pager|
|
|
17
|
+
pager.replace(@collection.to_a)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Either returns the page option and removes it from the options, or
|
|
22
|
+
# returns a default value of 1.
|
|
23
|
+
#
|
|
24
|
+
# Returns:
|
|
25
|
+
#
|
|
26
|
+
# An +Integer+ page number.
|
|
27
|
+
def page
|
|
28
|
+
skips, limits = options[:skip], options[:limit]
|
|
29
|
+
(skips && limits) ? (skips + limits) / limits : 1
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Get the number of results per page or the default of 20.
|
|
33
|
+
#
|
|
34
|
+
# Returns:
|
|
35
|
+
#
|
|
36
|
+
# The +Integer+ number of documents in each page.
|
|
37
|
+
def per_page
|
|
38
|
+
(options[:limit] || 20).to_i
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|