lookout-mongo_mapper 0.11.3
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/LICENSE +20 -0
- data/README.rdoc +33 -0
- data/UPGRADES +26 -0
- data/bin/mmconsole +59 -0
- data/examples/attr_accessible.rb +22 -0
- data/examples/attr_protected.rb +22 -0
- data/examples/cache_key.rb +24 -0
- data/examples/custom_types.rb +24 -0
- data/examples/identity_map.rb +33 -0
- data/examples/identity_map/automatic.rb +2 -0
- data/examples/keys.rb +40 -0
- data/examples/modifiers/set.rb +25 -0
- data/examples/plugins.rb +38 -0
- data/examples/querying.rb +35 -0
- data/examples/safe.rb +43 -0
- data/examples/scopes.rb +52 -0
- data/examples/validating/embedded_docs.rb +29 -0
- data/lib/mongo_mapper.rb +94 -0
- data/lib/mongo_mapper/connection.rb +96 -0
- data/lib/mongo_mapper/document.rb +42 -0
- data/lib/mongo_mapper/embedded_document.rb +32 -0
- 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 +26 -0
- data/lib/mongo_mapper/extensions/object_id.rb +32 -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 +28 -0
- data/lib/mongo_mapper/locale/en.yml +5 -0
- data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
- data/lib/mongo_mapper/plugins.rb +22 -0
- data/lib/mongo_mapper/plugins/accessible.rb +52 -0
- data/lib/mongo_mapper/plugins/active_model.rb +18 -0
- data/lib/mongo_mapper/plugins/associations.rb +90 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +92 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +54 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +34 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +133 -0
- data/lib/mongo_mapper/plugins/associations/many_association.rb +63 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +118 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
- data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +22 -0
- data/lib/mongo_mapper/plugins/associations/one_association.rb +48 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +95 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +134 -0
- data/lib/mongo_mapper/plugins/associations/single_association.rb +46 -0
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +29 -0
- data/lib/mongo_mapper/plugins/clone.rb +22 -0
- data/lib/mongo_mapper/plugins/dirty.rb +60 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +45 -0
- data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +56 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +53 -0
- data/lib/mongo_mapper/plugins/equality.rb +23 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
- data/lib/mongo_mapper/plugins/indexes.rb +13 -0
- data/lib/mongo_mapper/plugins/inspect.rb +16 -0
- data/lib/mongo_mapper/plugins/keys.rb +313 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +61 -0
- data/lib/mongo_mapper/plugins/logger.rb +18 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +134 -0
- data/lib/mongo_mapper/plugins/pagination.rb +16 -0
- data/lib/mongo_mapper/plugins/persistence.rb +69 -0
- data/lib/mongo_mapper/plugins/protected.rb +45 -0
- data/lib/mongo_mapper/plugins/querying.rb +165 -0
- data/lib/mongo_mapper/plugins/querying/decorator.rb +36 -0
- data/lib/mongo_mapper/plugins/rails.rb +58 -0
- data/lib/mongo_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +36 -0
- data/lib/mongo_mapper/plugins/scopes.rb +27 -0
- data/lib/mongo_mapper/plugins/serialization.rb +109 -0
- data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
- data/lib/mongo_mapper/plugins/touch.rb +18 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +18 -0
- data/lib/mongo_mapper/plugins/validations.rb +86 -0
- data/lib/mongo_mapper/railtie.rb +48 -0
- data/lib/mongo_mapper/railtie/database.rake +65 -0
- data/lib/mongo_mapper/translation.rb +10 -0
- data/lib/mongo_mapper/version.rb +4 -0
- data/lib/rails/generators/mongo_mapper/config/config_generator.rb +24 -0
- data/lib/rails/generators/mongo_mapper/config/templates/mongo.yml +18 -0
- data/lib/rails/generators/mongo_mapper/model/model_generator.rb +23 -0
- data/lib/rails/generators/mongo_mapper/model/templates/model.rb +13 -0
- data/test/_NOTE_ON_TESTING +1 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +64 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +238 -0
- data/test/functional/associations/test_in_array_proxy.rb +349 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +231 -0
- data/test/functional/associations/test_many_documents_proxy.rb +866 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +239 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +289 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
- data/test/functional/associations/test_one_as_proxy.rb +491 -0
- data/test/functional/associations/test_one_embedded_polymorphic_proxy.rb +208 -0
- data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
- data/test/functional/associations/test_one_proxy.rb +383 -0
- data/test/functional/test_accessible.rb +198 -0
- data/test/functional/test_associations.rb +46 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_caching.rb +77 -0
- data/test/functional/test_callbacks.rb +232 -0
- data/test/functional/test_dirty.rb +301 -0
- data/test/functional/test_document.rb +282 -0
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +288 -0
- data/test/functional/test_equality.rb +20 -0
- data/test/functional/test_identity_map.rb +513 -0
- data/test/functional/test_indexes.rb +50 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +537 -0
- data/test/functional/test_pagination.rb +91 -0
- data/test/functional/test_protected.rb +201 -0
- data/test/functional/test_querying.rb +935 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +240 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_timestamps.rb +62 -0
- data/test/functional/test_touch.rb +125 -0
- data/test/functional/test_userstamps.rb +44 -0
- data/test/functional/test_validations.rb +414 -0
- data/test/models.rb +261 -0
- data/test/support/railtie.rb +4 -0
- data/test/support/railtie/autoloaded.rb +2 -0
- data/test/support/railtie/not_autoloaded.rb +3 -0
- data/test/support/railtie/parent.rb +3 -0
- data/test/test_active_model_lint.rb +18 -0
- data/test/test_helper.rb +93 -0
- data/test/unit/associations/test_base.rb +146 -0
- data/test/unit/associations/test_belongs_to_association.rb +29 -0
- data/test/unit/associations/test_many_association.rb +63 -0
- data/test/unit/associations/test_one_association.rb +47 -0
- data/test/unit/associations/test_proxy.rb +100 -0
- data/test/unit/serializers/test_json_serializer.rb +216 -0
- data/test/unit/serializers/test_xml_serializer.rb +196 -0
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_document.rb +249 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +682 -0
- data/test/unit/test_equality.rb +38 -0
- data/test/unit/test_exceptions.rb +12 -0
- data/test/unit/test_extensions.rb +380 -0
- data/test/unit/test_identity_map_middleware.rb +34 -0
- data/test/unit/test_inspect.rb +47 -0
- data/test/unit/test_key.rb +205 -0
- data/test/unit/test_keys.rb +65 -0
- data/test/unit/test_mongo_mapper.rb +143 -0
- data/test/unit/test_pagination.rb +11 -0
- data/test/unit/test_plugins.rb +89 -0
- data/test/unit/test_rails.rb +183 -0
- data/test/unit/test_rails_compatibility.rb +38 -0
- data/test/unit/test_rails_reflect_on_association.rb +118 -0
- data/test/unit/test_railtie.rb +66 -0
- data/test/unit/test_serialization.rb +166 -0
- data/test/unit/test_time_zones.rb +44 -0
- data/test/unit/test_translation.rb +27 -0
- data/test/unit/test_validations.rb +562 -0
- metadata +285 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Keys
|
|
5
|
+
class Key
|
|
6
|
+
attr_accessor :name, :type, :options, :default_value
|
|
7
|
+
|
|
8
|
+
def initialize(*args)
|
|
9
|
+
options = args.extract_options!
|
|
10
|
+
@name, @type = args.shift.to_s, args.shift
|
|
11
|
+
self.options = (options || {}).symbolize_keys
|
|
12
|
+
self.default_value = self.options[:default]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def ==(other)
|
|
16
|
+
@name == other.name && @type == other.type
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def embeddable?
|
|
20
|
+
return false unless type.respond_to?(:embeddable?)
|
|
21
|
+
type.embeddable?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def number?
|
|
25
|
+
type == Integer || type == Float
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def get(value)
|
|
29
|
+
if value.nil? && !default_value.nil?
|
|
30
|
+
if default_value.respond_to?(:call)
|
|
31
|
+
return default_value.call
|
|
32
|
+
else
|
|
33
|
+
# Using Marshal is easiest way to get a copy of mutable objects
|
|
34
|
+
# without getting an error on immutable objects
|
|
35
|
+
return Marshal.load(Marshal.dump(default_value))
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if options[:typecast].present?
|
|
40
|
+
type.from_mongo(value).map! { |v| typecast_class.from_mongo(v) }
|
|
41
|
+
else
|
|
42
|
+
type.from_mongo(value)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def set(value)
|
|
47
|
+
type.to_mongo(value).tap do |values|
|
|
48
|
+
if options[:typecast].present?
|
|
49
|
+
values.map! { |v| typecast_class.to_mongo(v) }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
def typecast_class
|
|
56
|
+
@typecast_class ||= options[:typecast].constantize
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Modifiers
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def increment(*args)
|
|
9
|
+
modifier_update('$inc', args)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def decrement(*args)
|
|
13
|
+
criteria, keys, options = criteria_and_keys_from_args(args)
|
|
14
|
+
values, to_decrement = keys.values, {}
|
|
15
|
+
keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
|
|
16
|
+
collection.update(criteria, {'$inc' => to_decrement}, :multi => true)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def set(*args)
|
|
20
|
+
criteria, updates, options = criteria_and_keys_from_args(args)
|
|
21
|
+
updates.each do |key, value|
|
|
22
|
+
updates[key] = keys[key.to_s].set(value) if key?(key)
|
|
23
|
+
end
|
|
24
|
+
modifier_update('$set', [criteria, updates, options])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def unset(*args)
|
|
28
|
+
if args[0].is_a?(Hash)
|
|
29
|
+
criteria, keys = args.shift, args
|
|
30
|
+
options = keys.last.is_a?(Hash) ? keys.pop : {}
|
|
31
|
+
else
|
|
32
|
+
keys, ids = args.partition { |arg| arg.is_a?(Symbol) }
|
|
33
|
+
options = ids.last.is_a?(Hash) ? ids.pop : {}
|
|
34
|
+
criteria = {:id => ids}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
criteria = criteria_hash(criteria).to_hash
|
|
38
|
+
updates = keys.inject({}) { |hash, key| hash[key] = 1; hash }
|
|
39
|
+
modifier_update('$unset', [criteria, updates, options])
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def push(*args)
|
|
43
|
+
modifier_update('$push', args)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def push_all(*args)
|
|
47
|
+
modifier_update('$pushAll', args)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def add_to_set(*args)
|
|
51
|
+
modifier_update('$addToSet', args)
|
|
52
|
+
end
|
|
53
|
+
alias push_uniq add_to_set
|
|
54
|
+
|
|
55
|
+
def pull(*args)
|
|
56
|
+
modifier_update('$pull', args)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def pull_all(*args)
|
|
60
|
+
modifier_update('$pullAll', args)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def pop(*args)
|
|
64
|
+
modifier_update('$pop', args)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
def modifier_update(modifier, args)
|
|
69
|
+
criteria, updates, options = criteria_and_keys_from_args(args)
|
|
70
|
+
if options
|
|
71
|
+
collection.update(criteria, {modifier => updates}, options.merge(:multi => true))
|
|
72
|
+
else
|
|
73
|
+
collection.update(criteria, {modifier => updates}, :multi => true)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def criteria_and_keys_from_args(args)
|
|
78
|
+
if args[0].is_a?(Hash)
|
|
79
|
+
criteria = args[0]
|
|
80
|
+
updates = args[1]
|
|
81
|
+
options = args[2]
|
|
82
|
+
else
|
|
83
|
+
split_args = args.partition{|a| a.is_a?(BSON::ObjectId)}
|
|
84
|
+
criteria = {:id => split_args[0]}
|
|
85
|
+
updates = split_args[1].first
|
|
86
|
+
options = split_args[1].last
|
|
87
|
+
end
|
|
88
|
+
[criteria_hash(criteria).to_hash, updates, options]
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def unset(*args)
|
|
93
|
+
self.class.unset(id, *args)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def increment(hash, options=nil)
|
|
97
|
+
self.class.increment(id, hash, options)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def decrement(hash, options=nil)
|
|
101
|
+
self.class.decrement(id, hash, options)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def set(hash, options=nil)
|
|
105
|
+
self.class.set(id, hash, options)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def push(hash, options=nil)
|
|
109
|
+
self.class.push(id, hash, options)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def push_all(hash, options=nil)
|
|
113
|
+
self.class.push_all(id, hash, options)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def pull(hash, options=nil)
|
|
117
|
+
self.class.pull(id, hash, options)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def pull_all(hash, options=nil)
|
|
121
|
+
self.class.pull_all(id, hash, options)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def add_to_set(hash, options=nil)
|
|
125
|
+
self.class.push_uniq(id, hash, options)
|
|
126
|
+
end
|
|
127
|
+
alias push_uniq add_to_set
|
|
128
|
+
|
|
129
|
+
def pop(hash, options=nil)
|
|
130
|
+
self.class.pop(id, hash, options)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Pagination
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def per_page; 25 end
|
|
9
|
+
|
|
10
|
+
def paginate(opts={})
|
|
11
|
+
query.paginate({:per_page => per_page}.merge(opts))
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
module MongoMapper
|
|
3
|
+
module Plugins
|
|
4
|
+
module Persistence
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
module ClassMethods
|
|
8
|
+
def connection(mongo_connection=nil)
|
|
9
|
+
assert_supported
|
|
10
|
+
if mongo_connection.nil?
|
|
11
|
+
@connection ||= MongoMapper.connection
|
|
12
|
+
else
|
|
13
|
+
@connection = mongo_connection
|
|
14
|
+
end
|
|
15
|
+
@connection
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def set_database_name(name)
|
|
19
|
+
assert_supported
|
|
20
|
+
@database_name = name
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def database_name
|
|
24
|
+
assert_supported
|
|
25
|
+
@database_name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def database
|
|
29
|
+
assert_supported
|
|
30
|
+
if database_name.nil?
|
|
31
|
+
MongoMapper.database
|
|
32
|
+
else
|
|
33
|
+
connection.db(database_name)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def set_collection_name(name)
|
|
38
|
+
assert_supported
|
|
39
|
+
@collection_name = name
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def collection_name
|
|
43
|
+
assert_supported
|
|
44
|
+
@collection_name ||= self.to_s.tableize.gsub(/\//, '.')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def collection
|
|
48
|
+
assert_supported
|
|
49
|
+
database.collection(collection_name)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
def assert_supported
|
|
54
|
+
if embeddable?
|
|
55
|
+
raise NotSupported.new('This is not supported for embeddable documents at this time.')
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def collection
|
|
61
|
+
_root_document.class.collection
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def database
|
|
65
|
+
_root_document.class.database
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'set'
|
|
3
|
+
|
|
4
|
+
module MongoMapper
|
|
5
|
+
module Plugins
|
|
6
|
+
module Protected
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
class_attribute :protected_attributes
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module ClassMethods
|
|
14
|
+
def attr_protected(*attrs)
|
|
15
|
+
raise AccessibleOrProtected.new(name) if try(:accessible_attributes?)
|
|
16
|
+
self.protected_attributes = Set.new(attrs) + (protected_attributes || [])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def key(*args)
|
|
20
|
+
key = super
|
|
21
|
+
attr_protected key.name.to_sym if key.options[:protected]
|
|
22
|
+
key
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def attributes=(attrs={})
|
|
27
|
+
super(filter_protected_attrs(attrs))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def update_attributes(attrs={})
|
|
31
|
+
super(filter_protected_attrs(attrs))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def update_attributes!(attrs={})
|
|
35
|
+
super(filter_protected_attrs(attrs))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
protected
|
|
39
|
+
def filter_protected_attrs(attrs)
|
|
40
|
+
return attrs if protected_attributes.blank? || attrs.blank?
|
|
41
|
+
attrs.dup.delete_if { |key, val| protected_attributes.include?(key.to_sym) }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
require 'mongo_mapper/plugins/querying/decorator'
|
|
3
|
+
|
|
4
|
+
module MongoMapper
|
|
5
|
+
module Plugins
|
|
6
|
+
module Querying
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
extend Forwardable
|
|
11
|
+
|
|
12
|
+
def_delegators :query, *Querying::Methods
|
|
13
|
+
|
|
14
|
+
def find_by_id(id)
|
|
15
|
+
find_one(:_id => id)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def first_or_create(args)
|
|
19
|
+
first(args) || create(args.reject { |key, value| !key?(key) })
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def first_or_new(args)
|
|
23
|
+
first(args) || new(args.reject { |key, value| !key?(key) })
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def create(*docs)
|
|
27
|
+
initialize_each(*docs) { |doc| doc.save }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def create!(*docs)
|
|
31
|
+
initialize_each(*docs) { |doc| doc.save! }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def update(*args)
|
|
35
|
+
if args.length == 1
|
|
36
|
+
update_multiple(args[0])
|
|
37
|
+
else
|
|
38
|
+
id, attributes = args
|
|
39
|
+
update_single(id, attributes)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def delete(*ids)
|
|
44
|
+
query(:_id => ids.flatten).remove
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def delete_all(options={})
|
|
48
|
+
query(options).remove
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def destroy(*ids)
|
|
52
|
+
find_some!(ids.flatten).each { |doc| doc.destroy }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def destroy_all(options={})
|
|
56
|
+
find_each(options) { |document| document.destroy }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @api private for now
|
|
60
|
+
def query(options={})
|
|
61
|
+
query = Plucky::Query.new(collection, :transformer => transformer)
|
|
62
|
+
query.extend(Decorator)
|
|
63
|
+
query.object_ids(object_id_keys)
|
|
64
|
+
query.amend(options)
|
|
65
|
+
query.model(self)
|
|
66
|
+
query
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @api private for now
|
|
70
|
+
def criteria_hash(criteria={})
|
|
71
|
+
Plucky::CriteriaHash.new(criteria, :object_ids => object_id_keys)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
def transformer
|
|
76
|
+
@transformer ||= lambda { |doc| load(doc) }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def find_some(ids, options={})
|
|
80
|
+
query = query(options).amend(:_id => ids.flatten.compact.uniq)
|
|
81
|
+
query.all
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def find_some!(ids, options={})
|
|
85
|
+
ids = ids.flatten.compact.uniq
|
|
86
|
+
docs = find_some(ids, options)
|
|
87
|
+
|
|
88
|
+
if ids.size != docs.size
|
|
89
|
+
raise DocumentNotFound, "Couldn't find all of the ids (#{ids.to_sentence}). Found #{docs.size}, but was expecting #{ids.size}"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
docs
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def initialize_each(*docs)
|
|
96
|
+
instances = []
|
|
97
|
+
docs = [{}] if docs.blank?
|
|
98
|
+
docs.flatten.each do |attrs|
|
|
99
|
+
doc = new(attrs)
|
|
100
|
+
yield(doc)
|
|
101
|
+
instances << doc
|
|
102
|
+
end
|
|
103
|
+
instances.size == 1 ? instances[0] : instances
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def update_single(id, attrs)
|
|
107
|
+
if id.blank? || attrs.blank? || !attrs.is_a?(Hash)
|
|
108
|
+
raise ArgumentError, "Updating a single document requires an id and a hash of attributes"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
find(id).tap do |doc|
|
|
112
|
+
doc.update_attributes(attrs)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def update_multiple(docs)
|
|
117
|
+
unless docs.is_a?(Hash)
|
|
118
|
+
raise ArgumentError, "Updating multiple documents takes 1 argument and it must be hash"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
instances = []
|
|
122
|
+
docs.each_pair { |id, attrs| instances << update(id, attrs) }
|
|
123
|
+
instances
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def save(options={})
|
|
128
|
+
options.assert_valid_keys(:validate, :safe)
|
|
129
|
+
create_or_update(options)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def save!(options={})
|
|
133
|
+
options.assert_valid_keys(:safe)
|
|
134
|
+
save(options) || raise(DocumentNotValid.new(self))
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def destroy
|
|
138
|
+
delete
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def delete
|
|
142
|
+
self.class.delete(id).tap { @_destroyed = true } if persisted?
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
private
|
|
146
|
+
def create_or_update(options={})
|
|
147
|
+
result = persisted? ? update(options) : create(options)
|
|
148
|
+
result != false
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def create(options={})
|
|
152
|
+
save_to_collection(options)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def update(options={})
|
|
156
|
+
save_to_collection(options)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def save_to_collection(options={})
|
|
160
|
+
@_new = false
|
|
161
|
+
collection.save(to_mongo, :safe => options[:safe])
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|