mongo_mapper-unstable 2010.3.8 → 2010.06.23
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/README.rdoc +4 -8
- data/bin/mmconsole +1 -1
- data/examples/keys.rb +37 -0
- data/examples/plugins.rb +41 -0
- data/examples/querying.rb +35 -0
- data/examples/scopes.rb +52 -0
- data/lib/mongo_mapper/connection.rb +83 -0
- data/lib/mongo_mapper/document.rb +11 -329
- data/lib/mongo_mapper/embedded_document.rb +9 -38
- data/lib/mongo_mapper/exceptions.rb +30 -0
- data/lib/mongo_mapper/extensions/array.rb +19 -0
- data/lib/mongo_mapper/extensions/binary.rb +22 -0
- data/lib/mongo_mapper/extensions/boolean.rb +44 -0
- data/lib/mongo_mapper/extensions/date.rb +25 -0
- data/lib/mongo_mapper/extensions/float.rb +14 -0
- data/lib/mongo_mapper/extensions/hash.rb +14 -0
- data/lib/mongo_mapper/extensions/integer.rb +19 -0
- data/lib/mongo_mapper/extensions/kernel.rb +9 -0
- data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
- data/lib/mongo_mapper/extensions/object.rb +27 -0
- data/lib/mongo_mapper/extensions/object_id.rb +30 -0
- data/lib/mongo_mapper/extensions/set.rb +20 -0
- data/lib/mongo_mapper/extensions/string.rb +18 -0
- data/lib/mongo_mapper/extensions/time.rb +29 -0
- data/lib/mongo_mapper/plugins/accessible.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +7 -6
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +5 -6
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +5 -6
- data/lib/mongo_mapper/plugins/associations/collection.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +2 -1
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +25 -39
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +4 -4
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +36 -46
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +5 -4
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +1 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +40 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +7 -7
- data/lib/mongo_mapper/plugins/associations/proxy.rb +16 -8
- data/lib/mongo_mapper/plugins/associations.rb +14 -22
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +17 -5
- data/lib/mongo_mapper/plugins/clone.rb +10 -4
- data/lib/mongo_mapper/plugins/descendants.rb +3 -2
- data/lib/mongo_mapper/plugins/dirty.rb +1 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/{support/find.rb → plugins/dynamic_querying/dynamic_finder.rb} +3 -36
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +43 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +49 -0
- data/lib/mongo_mapper/plugins/equality.rb +4 -10
- data/lib/mongo_mapper/plugins/identity_map.rb +29 -23
- data/lib/mongo_mapper/plugins/indexes.rb +12 -0
- data/lib/mongo_mapper/plugins/inspect.rb +1 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +55 -0
- data/lib/mongo_mapper/plugins/keys.rb +85 -110
- data/lib/mongo_mapper/plugins/logger.rb +1 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +41 -16
- data/lib/mongo_mapper/plugins/pagination.rb +5 -15
- data/lib/mongo_mapper/plugins/persistence.rb +69 -0
- data/lib/mongo_mapper/plugins/protected.rb +9 -1
- data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
- data/lib/mongo_mapper/plugins/querying/plucky_methods.rb +15 -0
- data/lib/mongo_mapper/plugins/querying.rb +176 -0
- data/lib/mongo_mapper/plugins/rails.rb +6 -1
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +32 -0
- data/lib/mongo_mapper/plugins/scopes.rb +21 -0
- data/lib/mongo_mapper/plugins/serialization.rb +5 -4
- data/lib/mongo_mapper/plugins/timestamps.rb +2 -1
- data/lib/mongo_mapper/plugins/userstamps.rb +1 -0
- data/lib/mongo_mapper/plugins/validations.rb +9 -5
- data/lib/mongo_mapper/plugins.rb +1 -20
- data/lib/mongo_mapper/support/descendant_appends.rb +5 -6
- data/lib/mongo_mapper/version.rb +4 -0
- data/lib/mongo_mapper.rb +71 -128
- data/test/{NOTE_ON_TESTING → _NOTE_ON_TESTING} +0 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +5 -5
- data/test/functional/associations/test_belongs_to_proxy.rb +13 -21
- data/test/functional/associations/test_in_array_proxy.rb +7 -9
- data/test/functional/associations/test_many_documents_as_proxy.rb +5 -5
- data/test/functional/associations/test_many_documents_proxy.rb +186 -64
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +22 -22
- data/test/functional/associations/test_many_embedded_proxy.rb +32 -32
- data/test/functional/associations/test_many_polymorphic_proxy.rb +47 -47
- data/test/functional/associations/test_one_embedded_proxy.rb +67 -0
- data/test/functional/associations/test_one_proxy.rb +70 -49
- data/test/functional/test_accessible.rb +168 -0
- data/test/functional/test_associations.rb +11 -11
- data/test/functional/test_binary.rb +5 -5
- data/test/functional/test_caching.rb +76 -0
- data/test/functional/test_callbacks.rb +104 -34
- data/test/functional/test_dirty.rb +16 -16
- data/test/functional/test_document.rb +12 -924
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +88 -8
- data/test/functional/test_identity_map.rb +41 -43
- data/test/functional/{test_indexing.rb → test_indexes.rb} +3 -5
- data/test/functional/test_logger.rb +1 -1
- data/test/functional/test_modifiers.rb +275 -181
- data/test/functional/test_pagination.rb +13 -15
- data/test/functional/test_protected.rb +25 -11
- data/test/functional/test_querying.rb +873 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +230 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_string_id_compatibility.rb +11 -11
- data/test/functional/test_timestamps.rb +0 -2
- data/test/functional/test_userstamps.rb +0 -1
- data/test/functional/test_validations.rb +44 -31
- data/test/models.rb +18 -17
- data/test/{active_model_lint_test.rb → test_active_model_lint.rb} +3 -1
- data/test/test_helper.rb +59 -16
- data/test/unit/associations/test_base.rb +47 -42
- data/test/unit/associations/test_proxy.rb +15 -15
- data/test/unit/serializers/test_json_serializer.rb +29 -29
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_descendant_appends.rb +3 -3
- data/test/unit/test_document.rb +49 -67
- data/test/unit/test_dynamic_finder.rb +53 -51
- data/test/unit/test_embedded_document.rb +19 -38
- data/test/unit/{test_support.rb → test_extensions.rb} +136 -122
- data/test/unit/test_key.rb +185 -0
- data/test/unit/test_keys.rb +29 -147
- data/test/unit/test_mongo_mapper.rb +3 -48
- data/test/unit/test_pagination.rb +1 -150
- data/test/unit/test_rails.rb +77 -19
- data/test/unit/test_rails_compatibility.rb +12 -12
- data/test/unit/test_serialization.rb +5 -5
- data/test/unit/test_time_zones.rb +9 -9
- data/test/unit/test_validations.rb +46 -46
- metadata +157 -155
- data/.gitignore +0 -10
- data/Rakefile +0 -55
- data/VERSION +0 -1
- data/lib/mongo_mapper/plugins/pagination/proxy.rb +0 -72
- data/lib/mongo_mapper/query.rb +0 -130
- data/lib/mongo_mapper/support.rb +0 -215
- data/mongo_mapper.gemspec +0 -196
- data/performance/read_write.rb +0 -52
- data/specs.watchr +0 -51
- data/test/support/custom_matchers.rb +0 -55
- data/test/support/timing.rb +0 -16
- data/test/unit/test_query.rb +0 -340
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
module MongoMapper
|
2
3
|
module Plugins
|
3
4
|
module Modifiers
|
@@ -14,7 +15,24 @@ module MongoMapper
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def set(*args)
|
17
|
-
|
18
|
+
criteria, updates = criteria_and_keys_from_args(args)
|
19
|
+
updates.each do |key, value|
|
20
|
+
updates[key] = keys[key].set(value) if key?(key)
|
21
|
+
end
|
22
|
+
collection.update(criteria, {'$set' => updates}, :multi => true)
|
23
|
+
end
|
24
|
+
|
25
|
+
def unset(*args)
|
26
|
+
if args[0].is_a?(Hash)
|
27
|
+
criteria, keys = args.shift, args
|
28
|
+
else
|
29
|
+
keys, ids = args.partition { |arg| arg.is_a?(Symbol) }
|
30
|
+
criteria = {:id => ids}
|
31
|
+
end
|
32
|
+
|
33
|
+
criteria = criteria_hash(criteria).to_hash
|
34
|
+
modifiers = keys.inject({}) { |hash, key| hash[key] = 1; hash }
|
35
|
+
collection.update(criteria, {'$unset' => modifiers}, :multi => true)
|
18
36
|
end
|
19
37
|
|
20
38
|
def push(*args)
|
@@ -25,11 +43,10 @@ module MongoMapper
|
|
25
43
|
modifier_update('$pushAll', args)
|
26
44
|
end
|
27
45
|
|
28
|
-
def
|
29
|
-
|
30
|
-
keys.each { |key, value | criteria[key] = {'$ne' => value} }
|
31
|
-
collection.update(criteria, {'$push' => keys}, :multi => true)
|
46
|
+
def add_to_set(*args)
|
47
|
+
modifier_update('$addToSet', args)
|
32
48
|
end
|
49
|
+
alias push_uniq add_to_set
|
33
50
|
|
34
51
|
def pull(*args)
|
35
52
|
modifier_update('$pull', args)
|
@@ -45,41 +62,49 @@ module MongoMapper
|
|
45
62
|
|
46
63
|
private
|
47
64
|
def modifier_update(modifier, args)
|
48
|
-
criteria,
|
49
|
-
|
50
|
-
collection.update(criteria, modifiers, :multi => true)
|
65
|
+
criteria, updates = criteria_and_keys_from_args(args)
|
66
|
+
collection.update(criteria, {modifier => updates}, :multi => true)
|
51
67
|
end
|
52
68
|
|
53
69
|
def criteria_and_keys_from_args(args)
|
54
70
|
keys = args.pop
|
55
71
|
criteria = args[0].is_a?(Hash) ? args[0] : {:id => args}
|
56
|
-
[
|
72
|
+
[criteria_hash(criteria).to_hash, keys]
|
57
73
|
end
|
58
74
|
end
|
59
75
|
|
60
76
|
module InstanceMethods
|
77
|
+
def unset(*keys)
|
78
|
+
self.class.unset(id, *keys)
|
79
|
+
end
|
80
|
+
|
61
81
|
def increment(hash)
|
62
|
-
self.class.increment(
|
82
|
+
self.class.increment(id, hash)
|
63
83
|
end
|
64
84
|
|
65
85
|
def decrement(hash)
|
66
|
-
self.class.decrement(
|
86
|
+
self.class.decrement(id, hash)
|
67
87
|
end
|
68
88
|
|
69
89
|
def set(hash)
|
70
|
-
self.class.set(
|
90
|
+
self.class.set(id, hash)
|
71
91
|
end
|
72
92
|
|
73
93
|
def push(hash)
|
74
|
-
self.class.push(
|
94
|
+
self.class.push(id, hash)
|
75
95
|
end
|
76
96
|
|
77
97
|
def pull(hash)
|
78
|
-
self.class.pull(
|
98
|
+
self.class.pull(id, hash)
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_to_set(hash)
|
102
|
+
self.class.push_uniq(id, hash)
|
79
103
|
end
|
104
|
+
alias push_uniq add_to_set
|
80
105
|
|
81
|
-
def
|
82
|
-
self.class.
|
106
|
+
def pop(hash)
|
107
|
+
self.class.pop(id, hash)
|
83
108
|
end
|
84
109
|
end
|
85
110
|
end
|
@@ -1,24 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
module MongoMapper
|
2
3
|
module Plugins
|
3
4
|
module Pagination
|
4
5
|
module ClassMethods
|
5
|
-
def per_page
|
6
|
-
25
|
7
|
-
end
|
8
|
-
|
9
|
-
def paginate(options)
|
10
|
-
per_page = options.delete(:per_page) || self.per_page
|
11
|
-
page = options.delete(:page)
|
12
|
-
total_entries = count(options)
|
13
|
-
pagination = Pagination::Proxy.new(total_entries, page, per_page)
|
6
|
+
def per_page; 25 end
|
14
7
|
|
15
|
-
|
16
|
-
|
17
|
-
pagination
|
8
|
+
def paginate(opts={})
|
9
|
+
query.paginate({:per_page => per_page}.merge(opts))
|
18
10
|
end
|
19
11
|
end
|
20
12
|
end
|
21
13
|
end
|
22
|
-
end
|
23
|
-
|
24
|
-
require 'mongo_mapper/plugins/pagination/proxy'
|
14
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Persistence
|
5
|
+
module ClassMethods
|
6
|
+
def connection(mongo_connection=nil)
|
7
|
+
assert_supported
|
8
|
+
if mongo_connection.nil?
|
9
|
+
@connection ||= MongoMapper.connection
|
10
|
+
else
|
11
|
+
@connection = mongo_connection
|
12
|
+
end
|
13
|
+
@connection
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_database_name(name)
|
17
|
+
assert_supported
|
18
|
+
@database_name = name
|
19
|
+
end
|
20
|
+
|
21
|
+
def database_name
|
22
|
+
assert_supported
|
23
|
+
@database_name
|
24
|
+
end
|
25
|
+
|
26
|
+
def database
|
27
|
+
assert_supported
|
28
|
+
if database_name.nil?
|
29
|
+
MongoMapper.database
|
30
|
+
else
|
31
|
+
connection.db(database_name)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_collection_name(name)
|
36
|
+
assert_supported
|
37
|
+
@collection_name = name
|
38
|
+
end
|
39
|
+
|
40
|
+
def collection_name
|
41
|
+
assert_supported
|
42
|
+
@collection_name ||= self.to_s.tableize.gsub(/\//, '.')
|
43
|
+
end
|
44
|
+
|
45
|
+
def collection
|
46
|
+
assert_supported
|
47
|
+
database.collection(collection_name)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
def assert_supported
|
52
|
+
if embeddable?
|
53
|
+
raise NotSupported.new('This is not supported for embeddable documents at this time.')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
module InstanceMethods
|
59
|
+
def collection
|
60
|
+
_root_document.class.collection
|
61
|
+
end
|
62
|
+
|
63
|
+
def database
|
64
|
+
_root_document.class.database
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -1,8 +1,12 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'set'
|
3
|
+
|
1
4
|
module MongoMapper
|
2
5
|
module Plugins
|
3
6
|
module Protected
|
4
7
|
module ClassMethods
|
5
8
|
def attr_protected(*attrs)
|
9
|
+
raise AccessibleOrProtected.new(name) if try(:accessible_attributes?)
|
6
10
|
self.write_inheritable_attribute(:attr_protected, Set.new(attrs) + (protected_attributes || []))
|
7
11
|
end
|
8
12
|
|
@@ -10,6 +14,10 @@ module MongoMapper
|
|
10
14
|
self.read_inheritable_attribute(:attr_protected)
|
11
15
|
end
|
12
16
|
|
17
|
+
def protected_attributes?
|
18
|
+
!protected_attributes.nil?
|
19
|
+
end
|
20
|
+
|
13
21
|
def key(*args)
|
14
22
|
key = super
|
15
23
|
attr_protected key.name.to_sym if key.options[:protected]
|
@@ -36,7 +44,7 @@ module MongoMapper
|
|
36
44
|
|
37
45
|
protected
|
38
46
|
def filter_protected_attrs(attrs)
|
39
|
-
return attrs if protected_attributes.blank?
|
47
|
+
return attrs if protected_attributes.blank? || attrs.blank?
|
40
48
|
attrs.dup.delete_if { |key, val| protected_attributes.include?(key.to_sym) }
|
41
49
|
end
|
42
50
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Querying
|
5
|
+
module Decorator
|
6
|
+
include DynamicQuerying::ClassMethods
|
7
|
+
|
8
|
+
def model(model=nil)
|
9
|
+
return @model if model.nil?
|
10
|
+
@model = model
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def find!(*ids)
|
15
|
+
raise DocumentNotFound, "Couldn't find without an ID" if ids.size == 0
|
16
|
+
|
17
|
+
find(*ids).tap do |result|
|
18
|
+
if result.nil? || ids.size != Array(result).size
|
19
|
+
raise DocumentNotFound, "Couldn't find all of the ids (#{ids.join(',')}). Found #{Array(result).size}, but was expecting #{ids.size}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def all(opts={})
|
25
|
+
super.map { |doc| model.load(doc) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def first(opts={})
|
29
|
+
model.load(super)
|
30
|
+
end
|
31
|
+
|
32
|
+
def last(opts={})
|
33
|
+
model.load(super)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def method_missing(method, *args, &block)
|
38
|
+
return super unless model.respond_to?(method)
|
39
|
+
result = model.send(method, *args, &block)
|
40
|
+
return super unless result.is_a?(Plucky::Query)
|
41
|
+
merge(result)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module MongoMapper
|
5
|
+
module Plugins
|
6
|
+
module Querying
|
7
|
+
module PluckyMethods
|
8
|
+
extend Forwardable
|
9
|
+
def_delegators :query, :where, :fields, :limit, :skip, :sort,
|
10
|
+
:count, :last, :first, :all, :paginate,
|
11
|
+
:find, :find!, :exists?, :exist?, :find_each
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'mongo_mapper/plugins/querying/decorator'
|
3
|
+
require 'mongo_mapper/plugins/querying/plucky_methods'
|
4
|
+
|
5
|
+
module MongoMapper
|
6
|
+
module Plugins
|
7
|
+
module Querying
|
8
|
+
module ClassMethods
|
9
|
+
include PluckyMethods
|
10
|
+
|
11
|
+
def find_each(opts={})
|
12
|
+
super(opts).each { |doc| yield load(doc) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_by_id(id)
|
16
|
+
find_one(:_id => id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def first_or_create(args)
|
20
|
+
first(args) || create(args.reject { |key, value| !key?(key) })
|
21
|
+
end
|
22
|
+
|
23
|
+
def first_or_new(args)
|
24
|
+
first(args) || new(args.reject { |key, value| !key?(key) })
|
25
|
+
end
|
26
|
+
|
27
|
+
def create(*docs)
|
28
|
+
initialize_each(*docs) { |doc| doc.save }
|
29
|
+
end
|
30
|
+
|
31
|
+
def create!(*docs)
|
32
|
+
initialize_each(*docs) { |doc| doc.save! }
|
33
|
+
end
|
34
|
+
|
35
|
+
def update(*args)
|
36
|
+
if args.length == 1
|
37
|
+
update_multiple(args[0])
|
38
|
+
else
|
39
|
+
id, attributes = args
|
40
|
+
update_single(id, attributes)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def delete(*ids)
|
45
|
+
query(:_id => ids.flatten).remove
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete_all(options={})
|
49
|
+
query(options).remove
|
50
|
+
end
|
51
|
+
|
52
|
+
def destroy(*ids)
|
53
|
+
find_some!(ids.flatten).each(&:destroy)
|
54
|
+
end
|
55
|
+
|
56
|
+
def destroy_all(options={})
|
57
|
+
find_each(options) { |document| document.destroy }
|
58
|
+
end
|
59
|
+
|
60
|
+
# @api private for now
|
61
|
+
def query(options={})
|
62
|
+
Plucky::Query.new(collection).tap do |query|
|
63
|
+
query.extend(Decorator)
|
64
|
+
query.object_ids(object_id_keys)
|
65
|
+
query.update(options)
|
66
|
+
query.model(self)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# @api private for now
|
71
|
+
def criteria_hash(criteria={})
|
72
|
+
Plucky::CriteriaHash.new(criteria, :object_ids => object_id_keys)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def find_some(ids, options={})
|
77
|
+
query = query(options).update(:_id => ids.flatten.compact.uniq)
|
78
|
+
find_many(query.to_hash).compact
|
79
|
+
end
|
80
|
+
|
81
|
+
def find_some!(ids, options={})
|
82
|
+
ids = ids.flatten.compact.uniq
|
83
|
+
docs = find_some(ids, options)
|
84
|
+
|
85
|
+
if ids.size != docs.size
|
86
|
+
raise DocumentNotFound, "Couldn't find all of the ids (#{ids.to_sentence}). Found #{docs.size}, but was expecting #{ids.size}"
|
87
|
+
end
|
88
|
+
|
89
|
+
docs
|
90
|
+
end
|
91
|
+
|
92
|
+
# All query methods that load documents pass through find_one or find_many
|
93
|
+
def find_one(options={})
|
94
|
+
query(options).first
|
95
|
+
end
|
96
|
+
|
97
|
+
# All query methods that load documents pass through find_one or find_many
|
98
|
+
def find_many(options)
|
99
|
+
query(options).all
|
100
|
+
end
|
101
|
+
|
102
|
+
def initialize_each(*docs)
|
103
|
+
instances = []
|
104
|
+
docs = [{}] if docs.blank?
|
105
|
+
docs.flatten.each do |attrs|
|
106
|
+
doc = new(attrs)
|
107
|
+
yield(doc)
|
108
|
+
instances << doc
|
109
|
+
end
|
110
|
+
instances.size == 1 ? instances[0] : instances
|
111
|
+
end
|
112
|
+
|
113
|
+
def update_single(id, attrs)
|
114
|
+
if id.blank? || attrs.blank? || !attrs.is_a?(Hash)
|
115
|
+
raise ArgumentError, "Updating a single document requires an id and a hash of attributes"
|
116
|
+
end
|
117
|
+
|
118
|
+
find(id).tap do |doc|
|
119
|
+
doc.update_attributes(attrs)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def update_multiple(docs)
|
124
|
+
unless docs.is_a?(Hash)
|
125
|
+
raise ArgumentError, "Updating multiple documents takes 1 argument and it must be hash"
|
126
|
+
end
|
127
|
+
|
128
|
+
instances = []
|
129
|
+
docs.each_pair { |id, attrs| instances << update(id, attrs) }
|
130
|
+
instances
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
module InstanceMethods
|
135
|
+
def save(options={})
|
136
|
+
options.assert_valid_keys(:validate, :safe)
|
137
|
+
options.reverse_merge!(:validate => true)
|
138
|
+
!options[:validate] || valid? ? create_or_update(options) : false
|
139
|
+
end
|
140
|
+
|
141
|
+
def save!(options={})
|
142
|
+
options.assert_valid_keys(:safe)
|
143
|
+
save(options) || raise(DocumentNotValid.new(self))
|
144
|
+
end
|
145
|
+
|
146
|
+
def destroy
|
147
|
+
delete
|
148
|
+
end
|
149
|
+
|
150
|
+
def delete
|
151
|
+
@_destroyed = true
|
152
|
+
self.class.delete(id) unless new?
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
def create_or_update(options={})
|
157
|
+
result = new? ? create(options) : update(options)
|
158
|
+
result != false
|
159
|
+
end
|
160
|
+
|
161
|
+
def create(options={})
|
162
|
+
save_to_collection(options)
|
163
|
+
end
|
164
|
+
|
165
|
+
def update(options={})
|
166
|
+
save_to_collection(options)
|
167
|
+
end
|
168
|
+
|
169
|
+
def save_to_collection(options={})
|
170
|
+
@_new = false
|
171
|
+
collection.save(to_mongo, :safe => options[:safe])
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
module MongoMapper
|
2
3
|
module Plugins
|
3
4
|
module Rails
|
@@ -7,13 +8,17 @@ module MongoMapper
|
|
7
8
|
|
8
9
|
module InstanceMethods
|
9
10
|
def to_param
|
10
|
-
id.to_s
|
11
|
+
id.to_s if persisted?
|
11
12
|
end
|
12
13
|
|
13
14
|
def to_model
|
14
15
|
self
|
15
16
|
end
|
16
17
|
|
18
|
+
def to_key
|
19
|
+
[id] if persisted?
|
20
|
+
end
|
21
|
+
|
17
22
|
def new_record?
|
18
23
|
new?
|
19
24
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Safe
|
5
|
+
module ClassMethods
|
6
|
+
def inherited(subclass)
|
7
|
+
super
|
8
|
+
subclass.safe if safe?
|
9
|
+
end
|
10
|
+
|
11
|
+
def safe
|
12
|
+
@safe = true
|
13
|
+
end
|
14
|
+
|
15
|
+
def safe?
|
16
|
+
@safe == true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module InstanceMethods
|
21
|
+
def save_to_collection(options={})
|
22
|
+
options[:safe] = self.class.safe? unless options.key?(:safe)
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Sci
|
5
|
+
module ClassMethods
|
6
|
+
def inherited(subclass)
|
7
|
+
key :_type, String unless key?(:_type)
|
8
|
+
subclass.instance_variable_set("@single_collection_inherited", true)
|
9
|
+
subclass.set_collection_name(collection_name) unless subclass.embeddable?
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def single_collection_inherited?
|
14
|
+
@single_collection_inherited == true
|
15
|
+
end
|
16
|
+
|
17
|
+
def query(options={})
|
18
|
+
super.tap do |query|
|
19
|
+
query[:_type] = name if single_collection_inherited?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module InstanceMethods
|
25
|
+
def initialize(*args)
|
26
|
+
super
|
27
|
+
write_key :_type, self.class.name if self.class.key?(:_type)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Scopes
|
5
|
+
module ClassMethods
|
6
|
+
def scope(name, scope_options={})
|
7
|
+
scopes[name] = lambda do |*args|
|
8
|
+
result = scope_options.is_a?(Proc) ? scope_options.call(*args) : scope_options
|
9
|
+
result = self.query(result) if result.is_a?(Hash)
|
10
|
+
self.query.merge(result)
|
11
|
+
end
|
12
|
+
singleton_class.send :define_method, name, &scopes[name]
|
13
|
+
end
|
14
|
+
|
15
|
+
def scopes
|
16
|
+
read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
require 'active_support/json'
|
2
3
|
|
3
4
|
module MongoMapper
|
@@ -6,7 +7,7 @@ module MongoMapper
|
|
6
7
|
def self.configure(model)
|
7
8
|
model.class_eval { cattr_accessor :include_root_in_json, :instance_writer => true }
|
8
9
|
end
|
9
|
-
|
10
|
+
|
10
11
|
module InstanceMethods
|
11
12
|
def as_json options={}
|
12
13
|
options ||= {}
|
@@ -43,7 +44,7 @@ module MongoMapper
|
|
43
44
|
}
|
44
45
|
end
|
45
46
|
# End rip
|
46
|
-
|
47
|
+
|
47
48
|
options.delete(:only) if options[:only].nil? or options[:only].empty?
|
48
49
|
|
49
50
|
hash.each do |key, value|
|
@@ -51,13 +52,13 @@ module MongoMapper
|
|
51
52
|
hash[key] = value.map do |item|
|
52
53
|
item.respond_to?(:as_json) ? item.as_json(options) : item
|
53
54
|
end
|
54
|
-
elsif value.is_a?
|
55
|
+
elsif value.is_a? BSON::ObjectID
|
55
56
|
hash[key] = value.to_s
|
56
57
|
elsif value.respond_to?(:as_json)
|
57
58
|
hash[key] = value.as_json(options)
|
58
59
|
end
|
59
60
|
end
|
60
|
-
|
61
|
+
|
61
62
|
# Replicate Rails 3 naming - and also bin anytihng after : for use in our dynamic classes from unit tests
|
62
63
|
hash = { ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self)).gsub(/:.*/,'') => hash } if include_root_in_json
|
63
64
|
hash
|
@@ -1,16 +1,20 @@
|
|
1
|
+
# encoding: UTF-8
|
1
2
|
module MongoMapper
|
2
3
|
module Plugins
|
3
4
|
module Validations
|
4
5
|
def self.configure(model)
|
5
|
-
model.class_eval
|
6
|
+
model.class_eval do
|
7
|
+
include Validatable
|
8
|
+
extend Validations::DocumentMacros
|
9
|
+
end
|
6
10
|
end
|
7
|
-
|
11
|
+
|
8
12
|
module DocumentMacros
|
9
13
|
def validates_uniqueness_of(*args)
|
10
|
-
add_validations(args,
|
14
|
+
add_validations(args, Validations::ValidatesUniquenessOf)
|
11
15
|
end
|
12
16
|
end
|
13
|
-
|
17
|
+
|
14
18
|
class ValidatesUniquenessOf < Validatable::ValidationBase
|
15
19
|
option :scope, :case_sensitive
|
16
20
|
default :case_sensitive => true
|
@@ -37,7 +41,7 @@ module MongoMapper
|
|
37
41
|
|
38
42
|
def where_conditions(instance)
|
39
43
|
conditions = {}
|
40
|
-
conditions[attribute] =
|
44
|
+
conditions[attribute] = /^#{Regexp.escape(instance[attribute].to_s)}$/i unless case_sensitive
|
41
45
|
conditions
|
42
46
|
end
|
43
47
|
end
|