mongo_mapper-rails3 0.7.0.1 → 0.7.2

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.
Files changed (94) hide show
  1. data/README.rdoc +8 -37
  2. metadata +16 -284
  3. data/.gitignore +0 -10
  4. data/Gemfile +0 -15
  5. data/LICENSE +0 -20
  6. data/Rakefile +0 -58
  7. data/VERSION +0 -1
  8. data/bin/mmconsole +0 -60
  9. data/lib/mongo_mapper.rb +0 -131
  10. data/lib/mongo_mapper/document.rb +0 -439
  11. data/lib/mongo_mapper/embedded_document.rb +0 -68
  12. data/lib/mongo_mapper/plugins.rb +0 -30
  13. data/lib/mongo_mapper/plugins/associations.rb +0 -106
  14. data/lib/mongo_mapper/plugins/associations/base.rb +0 -123
  15. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +0 -30
  16. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +0 -25
  17. data/lib/mongo_mapper/plugins/associations/collection.rb +0 -21
  18. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +0 -50
  19. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +0 -141
  20. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +0 -28
  21. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +0 -120
  22. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +0 -31
  23. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +0 -23
  24. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +0 -13
  25. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +0 -68
  26. data/lib/mongo_mapper/plugins/associations/proxy.rb +0 -119
  27. data/lib/mongo_mapper/plugins/callbacks.rb +0 -87
  28. data/lib/mongo_mapper/plugins/clone.rb +0 -14
  29. data/lib/mongo_mapper/plugins/descendants.rb +0 -17
  30. data/lib/mongo_mapper/plugins/dirty.rb +0 -120
  31. data/lib/mongo_mapper/plugins/equality.rb +0 -24
  32. data/lib/mongo_mapper/plugins/identity_map.rb +0 -124
  33. data/lib/mongo_mapper/plugins/inspect.rb +0 -15
  34. data/lib/mongo_mapper/plugins/keys.rb +0 -310
  35. data/lib/mongo_mapper/plugins/logger.rb +0 -19
  36. data/lib/mongo_mapper/plugins/pagination.rb +0 -26
  37. data/lib/mongo_mapper/plugins/pagination/proxy.rb +0 -72
  38. data/lib/mongo_mapper/plugins/protected.rb +0 -46
  39. data/lib/mongo_mapper/plugins/rails.rb +0 -46
  40. data/lib/mongo_mapper/plugins/serialization.rb +0 -50
  41. data/lib/mongo_mapper/plugins/validations.rb +0 -88
  42. data/lib/mongo_mapper/query.rb +0 -130
  43. data/lib/mongo_mapper/support.rb +0 -217
  44. data/lib/mongo_mapper/support/descendant_appends.rb +0 -46
  45. data/lib/mongo_mapper/support/find.rb +0 -77
  46. data/mongo_mapper-rails3.gemspec +0 -208
  47. data/performance/read_write.rb +0 -52
  48. data/specs.watchr +0 -51
  49. data/test/NOTE_ON_TESTING +0 -1
  50. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +0 -63
  51. data/test/functional/associations/test_belongs_to_proxy.rb +0 -101
  52. data/test/functional/associations/test_in_array_proxy.rb +0 -321
  53. data/test/functional/associations/test_many_documents_as_proxy.rb +0 -229
  54. data/test/functional/associations/test_many_documents_proxy.rb +0 -453
  55. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +0 -176
  56. data/test/functional/associations/test_many_embedded_proxy.rb +0 -256
  57. data/test/functional/associations/test_many_polymorphic_proxy.rb +0 -302
  58. data/test/functional/associations/test_one_proxy.rb +0 -161
  59. data/test/functional/test_associations.rb +0 -44
  60. data/test/functional/test_binary.rb +0 -27
  61. data/test/functional/test_callbacks.rb +0 -81
  62. data/test/functional/test_dirty.rb +0 -163
  63. data/test/functional/test_document.rb +0 -1244
  64. data/test/functional/test_embedded_document.rb +0 -125
  65. data/test/functional/test_identity_map.rb +0 -508
  66. data/test/functional/test_logger.rb +0 -20
  67. data/test/functional/test_modifiers.rb +0 -252
  68. data/test/functional/test_pagination.rb +0 -93
  69. data/test/functional/test_protected.rb +0 -161
  70. data/test/functional/test_string_id_compatibility.rb +0 -67
  71. data/test/functional/test_validations.rb +0 -329
  72. data/test/models.rb +0 -232
  73. data/test/support/custom_matchers.rb +0 -55
  74. data/test/support/timing.rb +0 -16
  75. data/test/test_helper.rb +0 -59
  76. data/test/unit/associations/test_base.rb +0 -207
  77. data/test/unit/associations/test_proxy.rb +0 -105
  78. data/test/unit/serializers/test_json_serializer.rb +0 -189
  79. data/test/unit/test_descendant_appends.rb +0 -71
  80. data/test/unit/test_document.rb +0 -231
  81. data/test/unit/test_dynamic_finder.rb +0 -123
  82. data/test/unit/test_embedded_document.rb +0 -663
  83. data/test/unit/test_keys.rb +0 -169
  84. data/test/unit/test_lint.rb +0 -8
  85. data/test/unit/test_mongo_mapper.rb +0 -125
  86. data/test/unit/test_pagination.rb +0 -160
  87. data/test/unit/test_plugins.rb +0 -51
  88. data/test/unit/test_query.rb +0 -334
  89. data/test/unit/test_rails.rb +0 -123
  90. data/test/unit/test_rails_compatibility.rb +0 -57
  91. data/test/unit/test_serialization.rb +0 -51
  92. data/test/unit/test_support.rb +0 -362
  93. data/test/unit/test_time_zones.rb +0 -39
  94. data/test/unit/test_validations.rb +0 -557
data/Rakefile DELETED
@@ -1,58 +0,0 @@
1
- require 'rubygems'
2
- require 'rake'
3
- require 'jeweler'
4
- require 'yard'
5
- require 'yard/rake/yardoc_task'
6
-
7
- Jeweler::Tasks.new do |gem|
8
- gem.name = "mongo_mapper-rails3"
9
- gem.summary = %Q{Rails3 / ActiveModel compatible fork of MongoMapper.}
10
- gem.email = "merbjedi@gmail.com"
11
- gem.homepage = "http://github.com/merbjedi/mongomapper"
12
- gem.authors = ["Mike Harris", "Paul Bowsher", "Jacques Crocker", "John Nunemaker"]
13
-
14
- gem.add_dependency('activesupport', '>= 3.0.0.beta')
15
- gem.add_dependency('activemodel', '>= 3.0.0.beta')
16
- gem.add_dependency('bundler', '>= 0.9.7')
17
- gem.add_dependency('mongo', '>= 0.18.3')
18
-
19
- gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
20
- gem.add_development_dependency('shoulda', '2.10.2')
21
- gem.add_development_dependency('timecop', '0.3.1')
22
- gem.add_development_dependency('mocha', '0.9.8')
23
- gem.add_development_dependency('yard', '>= 0.5.3')
24
- gem.add_development_dependency('jeweler', '>= 1.4.0')
25
- end
26
-
27
- Jeweler::GemcutterTasks.new
28
-
29
- require 'rake/testtask'
30
- Rake::TestTask.new(:test) do |test|
31
- test.libs << 'test'
32
- test.ruby_opts << '-rubygems'
33
- test.pattern = 'test/**/test_*.rb'
34
- test.verbose = true
35
- end
36
-
37
- namespace :test do
38
- Rake::TestTask.new(:units) do |test|
39
- test.libs << 'test'
40
- test.ruby_opts << '-rubygems'
41
- test.pattern = 'test/unit/**/test_*.rb'
42
- test.verbose = true
43
- end
44
-
45
- Rake::TestTask.new(:functionals) do |test|
46
- test.libs << 'test'
47
- test.ruby_opts << '-rubygems'
48
- test.pattern = 'test/functional/**/test_*.rb'
49
- test.verbose = true
50
- end
51
- end
52
-
53
- task :default => :test
54
- task :test => :check_dependencies
55
-
56
- YARD::Rake::YardocTask.new(:doc) do |t|
57
- t.options = ["--legacy"] if RUBY_VERSION < "1.9.0"
58
- end
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.7.0.1
@@ -1,60 +0,0 @@
1
- #!/usr/bin/env ruby
2
- $:.unshift(File.dirname(__FILE__) + '/../lib')
3
-
4
- begin
5
- require 'mongo_mapper'
6
- require 'irb'
7
- rescue LoadError
8
- require 'rubygems'
9
- retry
10
- end
11
-
12
- IRB.setup(nil)
13
- irb = IRB::Irb.new
14
-
15
- IRB.conf[:MAIN_CONTEXT] = irb.context
16
-
17
- irb.context.evaluate("require 'irb/completion'", 0)
18
- irb.context.evaluate(%@
19
- include MongoMapper
20
-
21
- MongoMapper.database = "mmtest"
22
- $db = MongoMapper.database
23
-
24
- @, 0)
25
-
26
- puts %@
27
- Welcome to the MongoMapper Console!
28
-
29
- Example 1:
30
- things = $db.collection("things")
31
- things.insert("name" => "Raw Thing")
32
- things.insert("name" => "Another Thing", "date" => Time.now)
33
-
34
- cursor = things.find("name" => "Raw Thing")
35
- puts cursor.next_object.inspect
36
-
37
- Example 2:
38
- class Thing
39
- include MongoMapper::Document
40
- key :name, String, :required => true
41
- key :date, Time
42
- end
43
-
44
- thing = Thing.new
45
- thing.name = "My thing"
46
- thing.date = Time.now
47
- thing.save
48
-
49
- all_things = Thing.all
50
- puts all_things.map { |object| object.name }.inspect
51
- @
52
-
53
- trap("SIGINT") do
54
- irb.signal_handle
55
- end
56
-
57
- catch(:IRB_EXIT) do
58
- irb.eval_input
59
- end
60
-
@@ -1,131 +0,0 @@
1
- require 'set'
2
-
3
- begin
4
- # Require the preresolved locked set of gems.
5
- require File.expand_path('../.bundle/environment', __FILE__)
6
- rescue LoadError
7
- # Fallback on doing the resolve at runtime.
8
- require "rubygems"
9
- require "bundler"
10
- Bundler.setup
11
- end
12
-
13
- require "active_model"
14
- require "active_model/callbacks"
15
- require "active_model/conversion"
16
- require "active_model/deprecated_error_methods"
17
- require "active_model/errors"
18
- require "active_model/naming"
19
- require "active_model/serialization"
20
- require "active_model/translation"
21
- require "active_model/validator"
22
- require "active_model/validations"
23
- require 'active_support/core_ext/hash/indifferent_access'
24
- require 'active_support/core_ext/hash'
25
- require 'active_support/core_ext/object/try'
26
- require 'active_support/core_ext/module'
27
-
28
- require 'mongo'
29
-
30
- module MongoMapper
31
- # generic MM error
32
- class MongoMapperError < StandardError; end
33
-
34
- # raised when key expected to exist but not found
35
- class KeyNotFound < MongoMapperError; end
36
-
37
- # raised when document expected but not found
38
- class DocumentNotFound < MongoMapperError; end
39
-
40
- # raised when document not valid and using !
41
- class DocumentNotValid < MongoMapperError
42
- def initialize(document)
43
- super("Validation failed: #{document.errors.full_messages.join(", ")}")
44
- end
45
- end
46
-
47
- # @api public
48
- def self.connection
49
- @@connection ||= Mongo::Connection.new
50
- end
51
-
52
- # @api public
53
- def self.connection=(new_connection)
54
- @@connection = new_connection
55
- end
56
-
57
- # @api public
58
- def self.logger
59
- connection.logger
60
- end
61
-
62
- # @api public
63
- def self.database=(name)
64
- @@database = nil
65
- @@database_name = name
66
- end
67
-
68
- # @api public
69
- def self.database
70
- if @@database_name.blank?
71
- raise 'You forgot to set the default database name: MongoMapper.database = "foobar"'
72
- end
73
-
74
- @@database ||= MongoMapper.connection.db(@@database_name)
75
- end
76
-
77
- def self.config=(hash)
78
- @@config = hash
79
- end
80
-
81
- def self.config
82
- raise 'Set config before connecting. MongoMapper.config = {...}' unless defined?(@@config)
83
- @@config
84
- end
85
-
86
- def self.connect(environment, options={})
87
- raise 'Set config before connecting. MongoMapper.config = {...}' if config.blank?
88
- MongoMapper.connection = Mongo::Connection.new(config[environment]['host'], config[environment]['port'], options)
89
- MongoMapper.database = config[environment]['database']
90
- if config[environment]['username'].present? && config[environment]['password'].present?
91
- MongoMapper.database.authenticate(config[environment]['username'], config[environment]['password'])
92
- end
93
- end
94
-
95
- def self.setup(config, environment, options={})
96
- using_passenger = options.delete(:passenger)
97
- handle_passenger_forking if using_passenger
98
- self.config = config
99
- connect(environment, options)
100
- end
101
-
102
- def self.handle_passenger_forking
103
- if defined?(PhusionPassenger)
104
- PhusionPassenger.on_event(:starting_worker_process) do |forked|
105
- connection.connect_to_master if forked
106
- end
107
- end
108
- end
109
-
110
- # @api private
111
- def self.use_time_zone?
112
- Time.respond_to?(:zone) && Time.zone ? true : false
113
- end
114
-
115
- # @api private
116
- def self.time_class
117
- use_time_zone? ? Time.zone : Time
118
- end
119
-
120
- # @api private
121
- def self.normalize_object_id(value)
122
- value.is_a?(String) ? Mongo::ObjectID.from_string(value) : value
123
- end
124
-
125
- autoload :Query, 'mongo_mapper/query'
126
- autoload :Document, 'mongo_mapper/document'
127
- autoload :EmbeddedDocument, 'mongo_mapper/embedded_document'
128
- end
129
-
130
- require 'mongo_mapper/support'
131
- require 'mongo_mapper/plugins'
@@ -1,439 +0,0 @@
1
- module MongoMapper
2
- module Document
3
- extend Support::DescendantAppends
4
- extend ActiveSupport::Concern
5
-
6
- included do
7
- include InstanceMethods
8
- include ActiveModel::Conversion
9
- extend Support::Find
10
- extend ClassMethods
11
- extend Plugins
12
-
13
- plugin Plugins::Associations
14
- plugin Plugins::Clone
15
- plugin Plugins::Descendants
16
- plugin Plugins::Equality
17
- plugin Plugins::Inspect
18
- plugin Plugins::Keys
19
- plugin Plugins::Dirty # for now dirty needs to be after keys
20
- plugin Plugins::Logger
21
- plugin Plugins::Pagination
22
- plugin Plugins::Protected
23
- plugin Plugins::Rails
24
- plugin Plugins::Serialization
25
- plugin Plugins::Validations
26
- plugin Plugins::Callbacks
27
-
28
- extend Plugins::Validations::DocumentMacros
29
- end
30
-
31
- module ClassMethods
32
- def inherited(subclass)
33
- subclass.set_collection_name(collection_name)
34
- super
35
- end
36
-
37
- def ensure_index(name_or_array, options={})
38
- keys_to_index = if name_or_array.is_a?(Array)
39
- name_or_array.map { |pair| [pair[0], pair[1]] }
40
- else
41
- name_or_array
42
- end
43
-
44
- collection.create_index(keys_to_index, options[:unique])
45
- end
46
-
47
- def find(*args)
48
- assert_no_first_last_or_all(args)
49
- options = args.extract_options!
50
- return nil if args.size == 0
51
-
52
- if args.first.is_a?(Array) || args.size > 1
53
- find_some(args, options)
54
- else
55
- find_one(options.merge({:_id => args[0]}))
56
- end
57
- end
58
-
59
- def find!(*args)
60
- assert_no_first_last_or_all(args)
61
- options = args.extract_options!
62
- raise DocumentNotFound, "Couldn't find without an ID" if args.size == 0
63
-
64
- if args.first.is_a?(Array) || args.size > 1
65
- find_some!(args, options)
66
- else
67
- find_one(options.merge({:_id => args[0]})) || raise(DocumentNotFound, "Document match #{options.inspect} does not exist in #{collection.name} collection")
68
- end
69
- end
70
-
71
- def find_each(options={})
72
- criteria, options = to_query(options)
73
- collection.find(criteria, options).each do |doc|
74
- yield load(doc)
75
- end
76
- end
77
-
78
- def find_by_id(id)
79
- find(id)
80
- end
81
-
82
- def first_or_create(arg)
83
- first(arg) || create(arg)
84
- end
85
-
86
- def first_or_new(arg)
87
- first(arg) || new(arg)
88
- end
89
-
90
- def first(options={})
91
- find_one(options)
92
- end
93
-
94
- def last(options={})
95
- raise ':order option must be provided when using last' if options[:order].blank?
96
- find_one(options.merge(:order => invert_order_clause(options[:order])))
97
- end
98
-
99
- def all(options={})
100
- find_many(options)
101
- end
102
-
103
- def count(options={})
104
- collection.find(to_criteria(options)).count
105
- end
106
-
107
- def exists?(options={})
108
- !count(options).zero?
109
- end
110
-
111
- def create(*docs)
112
- initialize_each(*docs) { |doc| doc.save }
113
- end
114
-
115
- def create!(*docs)
116
- initialize_each(*docs) { |doc| doc.save! }
117
- end
118
-
119
- def update(*args)
120
- if args.length == 1
121
- update_multiple(args[0])
122
- else
123
- id, attributes = args
124
- update_single(id, attributes)
125
- end
126
- end
127
-
128
- def delete(*ids)
129
- collection.remove(to_criteria(:_id => ids.flatten))
130
- end
131
-
132
- def delete_all(options={})
133
- collection.remove(to_criteria(options))
134
- end
135
-
136
- def destroy(*ids)
137
- find_some!(ids.flatten).each(&:destroy)
138
- end
139
-
140
- def destroy_all(options={})
141
- find_each(options) { |document| document.destroy }
142
- end
143
-
144
- def increment(*args)
145
- modifier_update('$inc', args)
146
- end
147
-
148
- def decrement(*args)
149
- criteria, keys = criteria_and_keys_from_args(args)
150
- values, to_decrement = keys.values, {}
151
- keys.keys.each_with_index { |k, i| to_decrement[k] = -values[i].abs }
152
- collection.update(criteria, {'$inc' => to_decrement}, :multi => true)
153
- end
154
-
155
- def set(*args)
156
- modifier_update('$set', args)
157
- end
158
-
159
- def push(*args)
160
- modifier_update('$push', args)
161
- end
162
-
163
- def push_all(*args)
164
- modifier_update('$pushAll', args)
165
- end
166
-
167
- def push_uniq(*args)
168
- criteria, keys = criteria_and_keys_from_args(args)
169
- keys.each { |key, value | criteria[key] = {'$ne' => value} }
170
- collection.update(criteria, {'$push' => keys}, :multi => true)
171
- end
172
-
173
- def pull(*args)
174
- modifier_update('$pull', args)
175
- end
176
-
177
- def pull_all(*args)
178
- modifier_update('$pullAll', args)
179
- end
180
-
181
- def pop(*args)
182
- modifier_update('$pop', args)
183
- end
184
-
185
- def embeddable?
186
- false
187
- end
188
-
189
- def connection(mongo_connection=nil)
190
- if mongo_connection.nil?
191
- @connection ||= MongoMapper.connection
192
- else
193
- @connection = mongo_connection
194
- end
195
- @connection
196
- end
197
-
198
- def set_database_name(name)
199
- @database_name = name
200
- end
201
-
202
- def database_name
203
- @database_name
204
- end
205
-
206
- def database
207
- if database_name.nil?
208
- MongoMapper.database
209
- else
210
- connection.db(database_name)
211
- end
212
- end
213
-
214
- def set_collection_name(name)
215
- @collection_name = name
216
- end
217
-
218
- def collection_name
219
- @collection_name ||= self.to_s.tableize.gsub(/\//, '.')
220
- end
221
-
222
- def collection
223
- database.collection(collection_name)
224
- end
225
-
226
- def timestamps!
227
- key :created_at, Time
228
- key :updated_at, Time
229
- class_eval { before_save :update_timestamps }
230
- end
231
-
232
- def userstamps!
233
- key :creator_id, ObjectId
234
- key :updater_id, ObjectId
235
- belongs_to :creator, :class_name => 'User'
236
- belongs_to :updater, :class_name => 'User'
237
- end
238
-
239
- def single_collection_inherited?
240
- keys.key?(:_type) && single_collection_inherited_superclass?
241
- end
242
-
243
- def single_collection_inherited_superclass?
244
- superclass.respond_to?(:keys) && superclass.keys.key?(:_type)
245
- end
246
-
247
- private
248
- def initialize_each(*docs)
249
- instances = []
250
- docs = [{}] if docs.blank?
251
- docs.flatten.each do |attrs|
252
- doc = new(attrs)
253
- yield(doc)
254
- instances << doc
255
- end
256
- instances.size == 1 ? instances[0] : instances
257
- end
258
-
259
- def modifier_update(modifier, args)
260
- criteria, keys = criteria_and_keys_from_args(args)
261
- modifiers = {modifier => keys}
262
- collection.update(criteria, modifiers, :multi => true)
263
- end
264
-
265
- def criteria_and_keys_from_args(args)
266
- keys = args.pop
267
- criteria = args[0].is_a?(Hash) ? args[0] : {:id => args}
268
- [to_criteria(criteria), keys]
269
- end
270
-
271
- def assert_no_first_last_or_all(args)
272
- if args[0] == :first || args[0] == :last || args[0] == :all
273
- raise ArgumentError, "#{self}.find(:#{args}) is no longer supported, use #{self}.#{args} instead."
274
- end
275
- end
276
-
277
- def find_some(ids, options={})
278
- ids = ids.flatten.compact.uniq
279
- find_many(options.merge(:_id => ids)).compact
280
- end
281
-
282
- def find_some!(ids, options={})
283
- ids = ids.flatten.compact.uniq
284
- documents = find_some(ids, options)
285
-
286
- if ids.size == documents.size
287
- documents
288
- else
289
- raise DocumentNotFound, "Couldn't find all of the ids (#{ids.to_sentence}). Found #{documents.size}, but was expecting #{ids.size}"
290
- end
291
- end
292
-
293
- # All query methods that load documents pass through find_one or find_many
294
- def find_one(options={})
295
- criteria, options = to_query(options)
296
- if doc = collection.find_one(criteria, options)
297
- load(doc)
298
- end
299
- end
300
-
301
- # All query methods that load documents pass through find_one or find_many
302
- def find_many(options)
303
- criteria, options = to_query(options)
304
- collection.find(criteria, options).to_a.map do |doc|
305
- load(doc)
306
- end
307
- end
308
-
309
- def invert_order_clause(order)
310
- order.split(',').map do |order_segment|
311
- if order_segment =~ /\sasc/i
312
- order_segment.sub /\sasc/i, ' desc'
313
- elsif order_segment =~ /\sdesc/i
314
- order_segment.sub /\sdesc/i, ' asc'
315
- else
316
- "#{order_segment.strip} desc"
317
- end
318
- end.join(',')
319
- end
320
-
321
- def update_single(id, attrs)
322
- if id.blank? || attrs.blank? || !attrs.is_a?(Hash)
323
- raise ArgumentError, "Updating a single document requires an id and a hash of attributes"
324
- end
325
-
326
- doc = find(id)
327
- doc.update_attributes(attrs)
328
- doc
329
- end
330
-
331
- def update_multiple(docs)
332
- unless docs.is_a?(Hash)
333
- raise ArgumentError, "Updating multiple documents takes 1 argument and it must be hash"
334
- end
335
-
336
- instances = []
337
- docs.each_pair { |id, attrs| instances << update(id, attrs) }
338
- instances
339
- end
340
-
341
- def to_criteria(options={})
342
- Query.new(self, options).criteria
343
- end
344
-
345
- def to_query(options={})
346
- Query.new(self, options).to_a
347
- end
348
- end
349
-
350
- module InstanceMethods
351
- def initialize(attrs={}, from_database=false)
352
- unless attrs.nil?
353
- provided_keys = attrs.keys.map { |k| k.to_s }
354
- unless provided_keys.include?('_id') || provided_keys.include?('id')
355
- write_key :_id, Mongo::ObjectID.new
356
- end
357
- end
358
-
359
- #here for ActiveModel compatibility, should do something real with this
360
- def destroyed?
361
- false
362
- end
363
-
364
- assign_type_if_present
365
-
366
- if from_database
367
- @new = false
368
- self.attributes = attrs
369
- else
370
- @new = true
371
- assign(attrs)
372
- end
373
- end
374
-
375
- def collection
376
- self.class.collection
377
- end
378
-
379
- def database
380
- self.class.database
381
- end
382
-
383
- def save(options={})
384
- options.assert_valid_keys(:validate, :safe)
385
- options.reverse_merge!(:validate => true)
386
- !options[:validate] || valid? ? create_or_update(options) : false
387
- end
388
-
389
- def save!(options={})
390
- options.assert_valid_keys(:safe)
391
- save(options) || raise(DocumentNotValid.new(self))
392
- end
393
-
394
- def destroy
395
- delete
396
- end
397
-
398
- def delete
399
- self.class.delete(id) unless new?
400
- end
401
-
402
- def reload
403
- if attrs = collection.find_one({:_id => _id})
404
- self.class.associations.each { |name, assoc| send(name).reset if respond_to?(name) }
405
- self.attributes = attrs
406
- self
407
- else
408
- raise DocumentNotFound, "Document match #{_id.inspect} does not exist in #{collection.name} collection"
409
- end
410
- end
411
-
412
- private
413
- def create_or_update(options={})
414
- result = new? ? create(options) : update(options)
415
- result != false
416
- end
417
-
418
- def create(options={})
419
- save_to_collection(options)
420
- end
421
-
422
- def update(options={})
423
- save_to_collection(options)
424
- end
425
-
426
- def save_to_collection(options={})
427
- safe = options[:safe] || false
428
- @new = false
429
- collection.save(to_mongo, :safe => safe)
430
- end
431
-
432
- def update_timestamps
433
- now = Time.now.utc
434
- self[:created_at] = now if new? && !created_at?
435
- self[:updated_at] = now
436
- end
437
- end
438
- end # Document
439
- end # MongoMapper