mongo_mapper-unstable 2009.12.4 → 2009.12.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. data/VERSION +1 -1
  2. data/lib/mongo_mapper/associations/base.rb +1 -1
  3. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +7 -15
  4. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +5 -6
  5. data/lib/mongo_mapper/associations/collection.rb +19 -0
  6. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +10 -9
  7. data/lib/mongo_mapper/associations/many_documents_proxy.rb +9 -21
  8. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +8 -10
  9. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +14 -13
  10. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +1 -1
  11. data/lib/mongo_mapper/associations/proxy.rb +69 -36
  12. data/lib/mongo_mapper/document.rb +5 -14
  13. data/lib/mongo_mapper/dynamic_finder.rb +40 -1
  14. data/lib/mongo_mapper/embedded_document.rb +5 -0
  15. data/lib/mongo_mapper/pagination.rb +3 -1
  16. data/lib/mongo_mapper/support.rb +1 -5
  17. data/lib/mongo_mapper/validations.rb +1 -1
  18. data/lib/mongo_mapper.rb +12 -36
  19. data/mongo_mapper.gemspec +9 -7
  20. data/test/functional/associations/{test_many_proxy.rb → test_many_documents_proxy.rb} +14 -11
  21. data/test/functional/associations/test_many_embedded_proxy.rb +11 -15
  22. data/test/functional/test_associations.rb +1 -1
  23. data/test/functional/test_document.rb +52 -6
  24. data/test/functional/test_embedded_document.rb +10 -0
  25. data/test/functional/test_validations.rb +19 -10
  26. data/test/unit/{test_association_base.rb → associations/test_base.rb} +2 -2
  27. data/test/unit/associations/test_proxy.rb +91 -0
  28. data/test/unit/test_support.rb +1 -1
  29. metadata +9 -7
  30. data/lib/mongo_mapper/associations/many_proxy.rb +0 -6
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2009.12.04
1
+ 2009.12.14
@@ -87,7 +87,7 @@ module MongoMapper
87
87
  elsif as?
88
88
  ManyDocumentsAsProxy
89
89
  else
90
- ManyProxy
90
+ ManyDocumentsProxy
91
91
  end
92
92
  end
93
93
  else
@@ -4,30 +4,22 @@ module MongoMapper
4
4
  def replace(doc)
5
5
  if doc
6
6
  doc.save if doc.new?
7
- id, type = doc._id, doc.class.name
7
+ id, type = doc.id, doc.class.name
8
8
  end
9
9
 
10
- @owner.send("#{@association.foreign_key}=", id)
11
- @owner.send("#{@association.type_key_name}=", type)
10
+ owner[reflection.foreign_key] = id
11
+ owner[reflection.type_key_name] = type
12
12
  reset
13
13
  end
14
14
 
15
15
  protected
16
16
  def find_target
17
- if proxy_id && proxy_class
18
- proxy_class.find_by_id(proxy_id)
19
- end
17
+ return nil if association_class.nil? || owner[reflection.foreign_key].nil?
18
+ association_class.first(:id => owner[reflection.foreign_key])
20
19
  end
21
20
 
22
- def proxy_id
23
- @proxy_id ||= @owner.send(@association.foreign_key)
24
- end
25
-
26
- def proxy_class
27
- @proxy_class ||= begin
28
- klass = @owner.send(@association.type_key_name)
29
- klass && klass.constantize
30
- end
21
+ def association_class
22
+ proxy_owner[reflection.type_key_name] ? proxy_owner[reflection.type_key_name].constantize : nil
31
23
  end
32
24
  end
33
25
  end
@@ -4,18 +4,17 @@ module MongoMapper
4
4
  def replace(doc)
5
5
  if doc
6
6
  doc.save if doc.new?
7
- id = doc._id
7
+ id = doc.id
8
8
  end
9
-
10
- @owner.send("#{@association.foreign_key}=", id)
9
+
10
+ owner[reflection.foreign_key] = id
11
11
  reset
12
12
  end
13
13
 
14
14
  protected
15
15
  def find_target
16
- if association_id = @owner.send(@association.foreign_key)
17
- @association.klass.find_by_id(association_id)
18
- end
16
+ return nil if owner[reflection.foreign_key].nil?
17
+ klass.first(:id => owner[reflection.foreign_key])
19
18
  end
20
19
  end
21
20
  end
@@ -0,0 +1,19 @@
1
+ module MongoMapper
2
+ module Associations
3
+ class Collection < Proxy
4
+ def to_ary
5
+ load_target
6
+ if target.is_a?(Array)
7
+ target.to_ary
8
+ else
9
+ Array(target)
10
+ end
11
+ end
12
+
13
+ def reset
14
+ super
15
+ target = []
16
+ end
17
+ end
18
+ end
19
+ end
@@ -3,22 +3,23 @@ module MongoMapper
3
3
  class ManyDocumentsAsProxy < ManyDocumentsProxy
4
4
  protected
5
5
  def scoped_conditions
6
- {as_type_name => @owner.class.name, as_id_name => @owner._id}
6
+ {type_key_name => owner.class.name, id_key_name => owner.id}
7
7
  end
8
8
 
9
9
  def apply_scope(doc)
10
10
  ensure_owner_saved
11
- doc.send("#{as_type_name}=", @owner.class.name)
12
- doc.send("#{as_id_name}=", @owner._id)
11
+ doc[type_key_name] = owner.class.name
12
+ doc[id_key_name] = owner.id
13
13
  doc
14
14
  end
15
-
16
- def as_type_name
17
- @as_type_name ||= @association.options[:as].to_s + "_type"
15
+
16
+ private
17
+ def type_key_name
18
+ "#{options[:as]}_type"
18
19
  end
19
-
20
- def as_id_name
21
- @as_id_name ||= @association.options[:as].to_s + "_id"
20
+
21
+ def id_key_name
22
+ "#{options[:as]}_id"
22
23
  end
23
24
  end
24
25
  end
@@ -1,9 +1,6 @@
1
1
  module MongoMapper
2
2
  module Associations
3
- class ManyDocumentsProxy < Proxy
4
- delegate :klass, :to => :@association
5
- delegate :collection, :to => :klass
6
-
3
+ class ManyDocumentsProxy < Collection
7
4
  include ::MongoMapper::Finders
8
5
 
9
6
  def find(*args)
@@ -37,7 +34,8 @@ module MongoMapper
37
34
  end
38
35
 
39
36
  def replace(docs)
40
- @target.map(&:destroy) if load_target
37
+ load_target
38
+ target.map(&:destroy)
41
39
  docs.each { |doc| apply_scope(doc).save }
42
40
  reset
43
41
  end
@@ -85,24 +83,14 @@ module MongoMapper
85
83
  end
86
84
  reset
87
85
  end
88
-
89
- def method_missing(method, *args)
90
- finder = DynamicFinder.new(method)
91
-
92
- if finder.found?
93
- dynamic_find(finder, args)
94
- else
95
- super
96
- end
97
- end
98
-
86
+
99
87
  protected
100
88
  def scoped_conditions
101
- {self.foreign_key => @owner._id}
89
+ {self.foreign_key => owner.id}
102
90
  end
103
91
 
104
92
  def scoped_options(options)
105
- @association.finder_options.merge(options).merge(scoped_conditions)
93
+ reflection.finder_options.merge(options).merge(scoped_conditions)
106
94
  end
107
95
 
108
96
  def find_target
@@ -110,17 +98,17 @@ module MongoMapper
110
98
  end
111
99
 
112
100
  def ensure_owner_saved
113
- @owner.save if @owner.new?
101
+ owner.save if owner.new?
114
102
  end
115
103
 
116
104
  def apply_scope(doc)
117
105
  ensure_owner_saved
118
- doc.send("#{self.foreign_key}=", @owner._id)
106
+ doc[foreign_key] = owner.id
119
107
  doc
120
108
  end
121
109
 
122
110
  def foreign_key
123
- @association.options[:foreign_key] || @owner.class.name.underscore.gsub("/", "_") + "_id"
111
+ options[:foreign_key] || owner.class.name.underscore.gsub("/", "_") + "_id"
124
112
  end
125
113
  end
126
114
  end
@@ -1,16 +1,14 @@
1
1
  module MongoMapper
2
2
  module Associations
3
- class ManyEmbeddedPolymorphicProxy < Proxy
4
- def replace(v)
5
- @_values = v.map do |doc_or_hash|
6
- if doc_or_hash.kind_of?(EmbeddedDocument)
7
- doc = doc_or_hash
8
- {@association.type_key_name => doc.class.name}.merge(doc.attributes)
3
+ class ManyEmbeddedPolymorphicProxy < Collection
4
+ def replace(values)
5
+ @_values = values.map do |v|
6
+ if v.kind_of?(EmbeddedDocument)
7
+ v.attributes.merge(reflection.type_key_name => v.class.name)
9
8
  else
10
- doc_or_hash
9
+ v
11
10
  end
12
11
  end
13
-
14
12
  reset
15
13
  end
16
14
 
@@ -22,10 +20,10 @@ module MongoMapper
22
20
  end
23
21
 
24
22
  def polymorphic_class(doc)
25
- if class_name = doc[@association.type_key_name]
23
+ if class_name = doc[reflection.type_key_name]
26
24
  class_name.constantize
27
25
  else
28
- @association.klass
26
+ klass
29
27
  end
30
28
  end
31
29
  end
@@ -1,13 +1,15 @@
1
1
  module MongoMapper
2
2
  module Associations
3
- class ManyEmbeddedProxy < Proxy
4
- def replace(v)
5
- @_values = v.map { |e| e.kind_of?(EmbeddedDocument) ? e.attributes : e }
3
+ class ManyEmbeddedProxy < Collection
4
+ def replace(values)
5
+ @_values = values.map do |v|
6
+ v.kind_of?(EmbeddedDocument) ? v.attributes : v
7
+ end
6
8
  reset
7
9
  end
8
10
 
9
11
  def build(attributes={})
10
- doc = @association.klass.new(attributes)
12
+ doc = klass.new(attributes)
11
13
  assign_root_document(doc)
12
14
  self << doc
13
15
  doc
@@ -16,15 +18,14 @@ module MongoMapper
16
18
  # TODO: test that both string and oid version work
17
19
  def find(id)
18
20
  load_target
19
- @target.detect { |item| item.id.to_s == id || item.id == id }
21
+ target.detect { |item| item.id.to_s == id || item.id == id }
20
22
  end
21
23
 
22
24
  def <<(*docs)
23
- if load_target
24
- docs.each do |doc|
25
- assign_root_document(doc)
26
- @target << doc
27
- end
25
+ load_target
26
+ docs.each do |doc|
27
+ assign_root_document(doc)
28
+ target << doc
28
29
  end
29
30
  end
30
31
  alias_method :push, :<<
@@ -32,15 +33,15 @@ module MongoMapper
32
33
 
33
34
  private
34
35
  def find_target
35
- (@_values || []).map do |e|
36
- child = @association.klass.new(e)
36
+ (@_values || []).map do |v|
37
+ child = klass.new(v)
37
38
  assign_root_document(child)
38
39
  child
39
40
  end
40
41
  end
41
42
 
42
43
  def root_document
43
- @owner._root_document || @owner
44
+ owner._root_document || owner
44
45
  end
45
46
 
46
47
  def assign_root_document(*docs)
@@ -3,7 +3,7 @@ module MongoMapper
3
3
  class ManyPolymorphicProxy < ManyDocumentsProxy
4
4
  private
5
5
  def apply_scope(doc)
6
- doc.send("#{@association.type_key_name}=", doc.class.name)
6
+ doc[reflection.type_key_name] = doc.class.name
7
7
  super
8
8
  end
9
9
  end
@@ -1,67 +1,100 @@
1
1
  module MongoMapper
2
2
  module Associations
3
- class Proxy < BasicObject
4
- attr_reader :owner, :association
3
+ class Proxy
4
+ alias :proxy_respond_to? :respond_to?
5
+ alias :proxy_extend :extend
5
6
 
6
- def initialize(owner, association)
7
- @owner = owner
8
- @association = association
9
- @association.options[:extend].each { |ext| class << self; self; end.instance_eval { include ext } }
7
+ instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ }
8
+
9
+ attr_reader :owner, :reflection, :target
10
+
11
+ alias :proxy_owner :owner
12
+ alias :proxy_target :target
13
+ alias :proxy_reflection :reflection
14
+
15
+ delegate :klass, :to => :proxy_reflection
16
+ delegate :options, :to => :proxy_reflection
17
+ delegate :collection, :to => :klass
18
+
19
+ def initialize(owner, reflection)
20
+ @owner, @reflection = owner, reflection
21
+ Array(reflection.options[:extend]).each { |ext| proxy_extend(ext) }
10
22
  reset
11
23
  end
12
-
13
- def respond_to?(*methods)
14
- (load_target && @target.respond_to?(*methods))
24
+
25
+ def inspect
26
+ load_target
27
+ target.inspect
15
28
  end
16
-
17
- def reset
18
- @target = nil
29
+
30
+ def loaded?
31
+ @loaded
19
32
  end
20
-
21
- def reload_target
22
- reset
33
+
34
+ def loaded
35
+ @loaded = true
36
+ end
37
+
38
+ def nil?
23
39
  load_target
24
- self
40
+ target.nil?
25
41
  end
26
-
27
- def send(method, *args)
28
- metaclass_instance_methods = class << self; self; end.instance_methods
29
-
30
- if metaclass_instance_methods.any? { |m| m.to_s == method.to_s }
31
- return __send__(method, *args)
32
- end
33
-
42
+
43
+ def blank?
34
44
  load_target
35
- @target.send(method, *args)
45
+ target.blank?
36
46
  end
37
-
47
+
48
+ def reload
49
+ reset
50
+ load_target
51
+ self unless target.nil?
52
+ end
53
+
38
54
  def replace(v)
39
55
  raise NotImplementedError
40
56
  end
41
-
42
- def inspect
43
- load_target
44
- @target.inspect
57
+
58
+ def reset
59
+ @loaded = false
60
+ target = nil
61
+ end
62
+
63
+ def respond_to?(*args)
64
+ proxy_respond_to?(*args) || (load_target && target.respond_to?(*args))
65
+ end
66
+
67
+ def send(method, *args)
68
+ if proxy_respond_to?(method)
69
+ super
70
+ else
71
+ load_target
72
+ target.send(method, *args)
73
+ end
45
74
  end
46
75
 
47
- def nil?
76
+ def ===(other)
48
77
  load_target
49
- @target.nil?
78
+ other === target
50
79
  end
51
80
 
52
81
  protected
53
82
  def method_missing(method, *args, &block)
54
83
  if load_target
55
- if block.nil?
56
- @target.send(method, *args)
84
+ if block_given?
85
+ target.send(method, *args) { |*block_args| block.call(*block_args) }
57
86
  else
58
- @target.send(method, *args) { |*block_args| block.call(*block_args) }
87
+ target.send(method, *args)
59
88
  end
60
89
  end
61
90
  end
62
91
 
63
92
  def load_target
64
- @target ||= find_target
93
+ @target = find_target unless loaded?
94
+ loaded
95
+ @target
96
+ rescue MongoMapper::DocumentNotFound
97
+ reset
65
98
  end
66
99
 
67
100
  def find_target
@@ -316,18 +316,6 @@ module MongoMapper
316
316
  superclass.respond_to?(:keys) && superclass.keys.has_key?('_type')
317
317
  end
318
318
 
319
- protected
320
- def method_missing(method, *args)
321
- finder = DynamicFinder.new(method)
322
-
323
- if finder.found?
324
- meta_def(finder.method) { |*args| dynamic_find(finder, args) }
325
- send(finder.method, *args)
326
- else
327
- super
328
- end
329
- end
330
-
331
319
  private
332
320
  def create_indexes_for(key)
333
321
  ensure_index key.name if key.options[:index]
@@ -438,7 +426,10 @@ module MongoMapper
438
426
  end
439
427
 
440
428
  def reload
441
- self.class.find(_id)
429
+ doc = self.class.find(_id)
430
+ self.class.associations.each { |name, assoc| send(name).reset }
431
+ self.attributes = doc.attributes
432
+ self
442
433
  end
443
434
 
444
435
  private
@@ -469,7 +460,7 @@ module MongoMapper
469
460
 
470
461
  def update_timestamps
471
462
  now = Time.now.utc
472
- write_attribute('created_at', now) if new?
463
+ write_attribute('created_at', now) if new? && read_attribute('created_at').blank?
473
464
  write_attribute('updated_at', now)
474
465
  end
475
466
 
@@ -1,4 +1,39 @@
1
1
  module MongoMapper
2
+ # @api private
3
+ module Finders
4
+ def dynamic_find(finder, args)
5
+ attributes = {}
6
+ finder.attributes.each_with_index do |attr, index|
7
+ attributes[attr] = args[index]
8
+ end
9
+
10
+ options = args.extract_options!.merge(attributes)
11
+
12
+ if result = find(finder.finder, options)
13
+ result
14
+ else
15
+ if finder.raise?
16
+ raise DocumentNotFound, "Couldn't find Document with #{attributes.inspect} in collection named #{collection.name}"
17
+ end
18
+
19
+ if finder.instantiator
20
+ self.send(finder.instantiator, attributes)
21
+ end
22
+ end
23
+ end
24
+
25
+ protected
26
+ def method_missing(method, *args, &block)
27
+ finder = DynamicFinder.new(method)
28
+
29
+ if finder.found?
30
+ dynamic_find(finder, args)
31
+ else
32
+ super
33
+ end
34
+ end
35
+ end
36
+
2
37
  class DynamicFinder
3
38
  attr_reader :method, :attributes, :finder, :bang, :instantiator
4
39
 
@@ -6,12 +41,16 @@ module MongoMapper
6
41
  @method = method
7
42
  @finder = :first
8
43
  @bang = false
9
- match()
44
+ match
10
45
  end
11
46
 
12
47
  def found?
13
48
  @finder.present?
14
49
  end
50
+
51
+ def raise?
52
+ bang == true
53
+ end
15
54
 
16
55
  protected
17
56
  def match
@@ -333,6 +333,11 @@ module MongoMapper
333
333
  save
334
334
  end
335
335
 
336
+ def update_attributes!(attrs={})
337
+ self.attributes = attrs
338
+ save!
339
+ end
340
+
336
341
  private
337
342
  def _keys
338
343
  self.metaclass.keys
@@ -1,6 +1,8 @@
1
1
  module MongoMapper
2
2
  module Pagination
3
- class PaginationProxy < BasicObject
3
+ class PaginationProxy
4
+ instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|proxy_|^object_id$)/ }
5
+
4
6
  attr_accessor :subject
5
7
  attr_reader :total_entries, :per_page, :current_page
6
8
  alias limit per_page
@@ -1,9 +1,5 @@
1
1
  require 'set'
2
2
 
3
- class BasicObject #:nodoc:
4
- instance_methods.each { |m| undef_method m unless m =~ /(^__|instance_eval)/ }
5
- end unless defined?(BasicObject)
6
-
7
3
  class Array
8
4
  def self.to_mongo(value)
9
5
  value = value.respond_to?(:lines) ? value.lines : value
@@ -188,6 +184,6 @@ end
188
184
  # TODO: Remove when patch accepted into driver
189
185
  class Mongo::ObjectID
190
186
  def to_json(options = nil)
191
- to_s
187
+ %Q("#{to_s}")
192
188
  end
193
189
  end
@@ -32,7 +32,7 @@ module MongoMapper
32
32
  def where_conditions(instance)
33
33
  conditions = {}
34
34
  unless case_sensitive
35
- conditions.merge!({'$where' => "this.#{attribute}.toLowerCase() == '#{instance[attribute].downcase}'"})
35
+ conditions.merge!({'$where' => "this.#{attribute}.toLowerCase() == '#{instance[attribute].to_s.downcase}'"})
36
36
  end
37
37
  conditions
38
38
  end
data/lib/mongo_mapper.rb CHANGED
@@ -67,31 +67,6 @@ module MongoMapper
67
67
  end
68
68
  end
69
69
 
70
- # @api private
71
- module Finders
72
- def dynamic_find(finder, args)
73
- attributes = {}
74
- finder.attributes.each_with_index do |attr, index|
75
- attributes[attr] = args[index]
76
- end
77
-
78
- options = args.extract_options!.merge(attributes)
79
- result = find(finder.finder, options)
80
-
81
- if result.nil?
82
- if finder.bang
83
- raise DocumentNotFound, "Couldn't find Document with #{attributes.inspect} in collection named #{collection.name}"
84
- end
85
-
86
- if finder.instantiator
87
- self.send(finder.instantiator, attributes)
88
- end
89
- else
90
- result
91
- end
92
- end
93
- end
94
-
95
70
  # @api private
96
71
  def self.use_time_zone?
97
72
  Time.respond_to?(:zone) && Time.zone ? true : false
@@ -102,23 +77,13 @@ module MongoMapper
102
77
  use_time_zone? ? Time.zone : Time
103
78
  end
104
79
 
80
+ # @api private
105
81
  def self.normalize_object_id(value)
106
82
  value.is_a?(String) ? Mongo::ObjectID.from_string(value) : value
107
83
  end
108
84
  end
109
85
 
110
86
  require 'mongo_mapper/support'
111
- require 'mongo_mapper/associations'
112
- require 'mongo_mapper/associations/base'
113
- require 'mongo_mapper/associations/proxy'
114
- require 'mongo_mapper/associations/many_documents_proxy'
115
- require 'mongo_mapper/associations/belongs_to_proxy'
116
- require 'mongo_mapper/associations/belongs_to_polymorphic_proxy'
117
- require 'mongo_mapper/associations/many_proxy'
118
- require 'mongo_mapper/associations/many_polymorphic_proxy'
119
- require 'mongo_mapper/associations/many_embedded_proxy'
120
- require 'mongo_mapper/associations/many_embedded_polymorphic_proxy'
121
- require 'mongo_mapper/associations/many_documents_as_proxy'
122
87
  require 'mongo_mapper/callbacks'
123
88
  require 'mongo_mapper/finder_options'
124
89
  require 'mongo_mapper/dirty'
@@ -132,3 +97,14 @@ require 'mongo_mapper/rails_compatibility/document'
132
97
  require 'mongo_mapper/rails_compatibility/embedded_document'
133
98
  require 'mongo_mapper/embedded_document'
134
99
  require 'mongo_mapper/document'
100
+ require 'mongo_mapper/associations'
101
+ require 'mongo_mapper/associations/base'
102
+ require 'mongo_mapper/associations/proxy'
103
+ require 'mongo_mapper/associations/collection'
104
+ require 'mongo_mapper/associations/many_documents_proxy'
105
+ require 'mongo_mapper/associations/belongs_to_proxy'
106
+ require 'mongo_mapper/associations/belongs_to_polymorphic_proxy'
107
+ require 'mongo_mapper/associations/many_polymorphic_proxy'
108
+ require 'mongo_mapper/associations/many_embedded_proxy'
109
+ require 'mongo_mapper/associations/many_embedded_polymorphic_proxy'
110
+ require 'mongo_mapper/associations/many_documents_as_proxy'
data/mongo_mapper.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mongo_mapper}
8
- s.version = "0.6.5"
8
+ s.version = "0.6.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["John Nunemaker"]
12
- s.date = %q{2009-12-01}
12
+ s.date = %q{2009-12-13}
13
13
  s.default_executable = %q{mmconsole}
14
14
  s.email = %q{nunemaker@gmail.com}
15
15
  s.executables = ["mmconsole"]
@@ -29,12 +29,12 @@ Gem::Specification.new do |s|
29
29
  "lib/mongo_mapper/associations/base.rb",
30
30
  "lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb",
31
31
  "lib/mongo_mapper/associations/belongs_to_proxy.rb",
32
+ "lib/mongo_mapper/associations/collection.rb",
32
33
  "lib/mongo_mapper/associations/many_documents_as_proxy.rb",
33
34
  "lib/mongo_mapper/associations/many_documents_proxy.rb",
34
35
  "lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb",
35
36
  "lib/mongo_mapper/associations/many_embedded_proxy.rb",
36
37
  "lib/mongo_mapper/associations/many_polymorphic_proxy.rb",
37
- "lib/mongo_mapper/associations/many_proxy.rb",
38
38
  "lib/mongo_mapper/associations/proxy.rb",
39
39
  "lib/mongo_mapper/callbacks.rb",
40
40
  "lib/mongo_mapper/dirty.rb",
@@ -57,10 +57,10 @@ Gem::Specification.new do |s|
57
57
  "test/functional/associations/test_belongs_to_polymorphic_proxy.rb",
58
58
  "test/functional/associations/test_belongs_to_proxy.rb",
59
59
  "test/functional/associations/test_many_documents_as_proxy.rb",
60
+ "test/functional/associations/test_many_documents_proxy.rb",
60
61
  "test/functional/associations/test_many_embedded_polymorphic_proxy.rb",
61
62
  "test/functional/associations/test_many_embedded_proxy.rb",
62
63
  "test/functional/associations/test_many_polymorphic_proxy.rb",
63
- "test/functional/associations/test_many_proxy.rb",
64
64
  "test/functional/test_associations.rb",
65
65
  "test/functional/test_binary.rb",
66
66
  "test/functional/test_callbacks.rb",
@@ -76,8 +76,9 @@ Gem::Specification.new do |s|
76
76
  "test/support/custom_matchers.rb",
77
77
  "test/support/timing.rb",
78
78
  "test/test_helper.rb",
79
+ "test/unit/associations/test_base.rb",
80
+ "test/unit/associations/test_proxy.rb",
79
81
  "test/unit/serializers/test_json_serializer.rb",
80
- "test/unit/test_association_base.rb",
81
82
  "test/unit/test_document.rb",
82
83
  "test/unit/test_dynamic_finder.rb",
83
84
  "test/unit/test_embedded_document.rb",
@@ -101,10 +102,10 @@ Gem::Specification.new do |s|
101
102
  "test/functional/associations/test_belongs_to_polymorphic_proxy.rb",
102
103
  "test/functional/associations/test_belongs_to_proxy.rb",
103
104
  "test/functional/associations/test_many_documents_as_proxy.rb",
105
+ "test/functional/associations/test_many_documents_proxy.rb",
104
106
  "test/functional/associations/test_many_embedded_polymorphic_proxy.rb",
105
107
  "test/functional/associations/test_many_embedded_proxy.rb",
106
108
  "test/functional/associations/test_many_polymorphic_proxy.rb",
107
- "test/functional/associations/test_many_proxy.rb",
108
109
  "test/functional/test_associations.rb",
109
110
  "test/functional/test_binary.rb",
110
111
  "test/functional/test_callbacks.rb",
@@ -120,8 +121,9 @@ Gem::Specification.new do |s|
120
121
  "test/support/custom_matchers.rb",
121
122
  "test/support/timing.rb",
122
123
  "test/test_helper.rb",
124
+ "test/unit/associations/test_base.rb",
125
+ "test/unit/associations/test_proxy.rb",
123
126
  "test/unit/serializers/test_json_serializer.rb",
124
- "test/unit/test_association_base.rb",
125
127
  "test/unit/test_document.rb",
126
128
  "test/unit/test_dynamic_finder.rb",
127
129
  "test/unit/test_embedded_document.rb",
@@ -1,7 +1,7 @@
1
1
  require 'test_helper'
2
2
  require 'models'
3
3
 
4
- class ManyProxyTest < Test::Unit::TestCase
4
+ class ManyDocumentsProxyTest < Test::Unit::TestCase
5
5
  def setup
6
6
  Project.collection.remove
7
7
  Status.collection.remove
@@ -37,16 +37,16 @@ class ManyProxyTest < Test::Unit::TestCase
37
37
  project.statuses.concat Status.new(:name => 'concat')
38
38
 
39
39
  project = project.reload
40
- project.statuses[0].project_id.should == project._id
41
- project.statuses[1].project_id.should == project._id
42
- project.statuses[2].project_id.should == project._id
40
+ project.statuses[0].project_id.should == project.id
41
+ project.statuses[1].project_id.should == project.id
42
+ project.statuses[2].project_id.should == project.id
43
43
  end
44
44
 
45
45
  context "build" do
46
46
  should "assign foreign key" do
47
47
  project = Project.create
48
48
  status = project.statuses.build
49
- status.project_id.should == project._id
49
+ status.project_id.should == project.id
50
50
  end
51
51
 
52
52
  should "allow assigning attributes" do
@@ -60,7 +60,7 @@ class ManyProxyTest < Test::Unit::TestCase
60
60
  should "assign foreign key" do
61
61
  project = Project.create
62
62
  status = project.statuses.create(:name => 'Foo!')
63
- status.project_id.should == project._id
63
+ status.project_id.should == project.id
64
64
  end
65
65
 
66
66
  should "save record" do
@@ -81,7 +81,7 @@ class ManyProxyTest < Test::Unit::TestCase
81
81
  should "assign foreign key" do
82
82
  project = Project.create
83
83
  status = project.statuses.create!(:name => 'Foo!')
84
- status.project_id.should == project._id
84
+ status.project_id.should == project.id
85
85
  end
86
86
 
87
87
  should "save record" do
@@ -205,11 +205,14 @@ class ManyProxyTest < Test::Unit::TestCase
205
205
  context "dynamic finders" do
206
206
  should "work with single key" do
207
207
  @project1.statuses.find_by_name('New').should == @brand_new
208
+ @project1.statuses.find_by_name!('New').should == @brand_new
208
209
  @project2.statuses.find_by_name('In Progress').should == @in_progress
210
+ @project2.statuses.find_by_name!('In Progress').should == @in_progress
209
211
  end
210
212
 
211
213
  should "work with multiple keys" do
212
214
  @project1.statuses.find_by_name_and_position('New', 1).should == @brand_new
215
+ @project1.statuses.find_by_name_and_position!('New', 1).should == @brand_new
213
216
  @project1.statuses.find_by_name_and_position('New', 2).should be_nil
214
217
  end
215
218
 
@@ -315,25 +318,25 @@ class ManyProxyTest < Test::Unit::TestCase
315
318
 
316
319
  context "with one id" do
317
320
  should "work for id in association" do
318
- @project1.statuses.find(@complete._id).should == @complete
321
+ @project1.statuses.find(@complete.id).should == @complete
319
322
  end
320
323
 
321
324
  should "not work for id not in association" do
322
325
  lambda {
323
- @project1.statuses.find!(@archived._id)
326
+ @project1.statuses.find!(@archived.id)
324
327
  }.should raise_error(MongoMapper::DocumentNotFound)
325
328
  end
326
329
  end
327
330
 
328
331
  context "with multiple ids" do
329
332
  should "work for ids in association" do
330
- statuses = @project1.statuses.find(@brand_new._id, @complete._id)
333
+ statuses = @project1.statuses.find(@brand_new.id, @complete.id)
331
334
  statuses.should == [@brand_new, @complete]
332
335
  end
333
336
 
334
337
  should "not work for ids not in association" do
335
338
  lambda {
336
- @project1.statuses.find!(@brand_new._id, @complete._id, @archived._id)
339
+ @project1.statuses.find!(@brand_new.id, @complete.id, @archived.id)
337
340
  }.should raise_error(MongoMapper::DocumentNotFound)
338
341
  end
339
342
  end
@@ -26,7 +26,7 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
26
26
  project.addresses << chi
27
27
  project.save
28
28
 
29
- project = project.reload
29
+ project.reload
30
30
  project.addresses.size.should == 2
31
31
  project.addresses[0].should == sb
32
32
  project.addresses[1].should == chi
@@ -47,7 +47,7 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
47
47
  doc = @document.new(:person => meg)
48
48
  doc.save
49
49
 
50
- doc = doc.reload
50
+ doc.reload
51
51
  doc.person.name.should == 'Meg'
52
52
  doc.person.child.name.should == 'Steve'
53
53
  doc.person.child.child.name.should == 'Linda'
@@ -70,7 +70,7 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
70
70
  pet_lover.pets[1].species.should == "Siberian Husky"
71
71
  pet_lover.save.should be_true
72
72
 
73
- pet_lover = pet_lover.reload
73
+ pet_lover.reload
74
74
  pet_lover.name.should == "Mr. Pet Lover"
75
75
  pet_lover.pets[0].name.should == "Jimmy"
76
76
  pet_lover.pets[0].species.should == "Cocker Spainel"
@@ -89,19 +89,17 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
89
89
  end
90
90
 
91
91
  should "persist all embedded documents" do
92
- meg = Person.new(:name => "Meg")
92
+ meg = Person.new(:name => "Meg")
93
93
  sparky = Pet.new(:name => "Sparky", :species => "Dog")
94
- koda = Pet.new(:name => "Koda", :species => "Dog")
94
+ koda = Pet.new(:name => "Koda", :species => "Dog")
95
95
 
96
96
  doc = @document.new
97
-
98
97
  meg.pets << sparky
99
98
  meg.pets << koda
100
-
101
99
  doc.people << meg
102
100
  doc.save
103
101
 
104
- doc = doc.reload
102
+ doc.reload
105
103
  doc.people.first.name.should == "Meg"
106
104
  doc.people.first.pets.should_not == []
107
105
  doc.people.first.pets.first.name.should == "Sparky"
@@ -111,11 +109,9 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
111
109
  end
112
110
 
113
111
  should "create a reference to the root document for all embedded documents before save" do
114
- meg = Person.new(:name => "Meg")
112
+ meg = Person.new(:name => "Meg")
115
113
  sparky = Pet.new(:name => "Sparky", :species => "Dog")
116
-
117
- doc = @document.new
118
-
114
+ doc = @document.new
119
115
  doc.people << meg
120
116
  meg.pets << sparky
121
117
 
@@ -125,12 +121,12 @@ class ManyEmbeddedProxyTest < Test::Unit::TestCase
125
121
 
126
122
  should "create a reference to the root document for all embedded documents" do
127
123
  sparky = Pet.new(:name => "Sparky", :species => "Dog")
128
- meg = Person.new(:name => "Meg", :pets => [sparky])
129
- doc = @document.new
124
+ meg = Person.new(:name => "Meg", :pets => [sparky])
125
+ doc = @document.new
130
126
  doc.people << meg
131
127
  doc.save
132
128
 
133
- doc = doc.reload
129
+ doc.reload
134
130
  doc.people.first._root_document.should == doc
135
131
  doc.people.first.pets.first._root_document.should == doc
136
132
  end
@@ -40,5 +40,5 @@ class AssociationsTest < Test::Unit::TestCase
40
40
 
41
41
  post1 = post1.reload
42
42
  post1.tags.should == [tag1]
43
- end
43
+ end
44
44
  end
@@ -32,7 +32,9 @@ class DocumentTest < Test::Unit::TestCase
32
32
 
33
33
  should "not fail" do
34
34
  doc = @document.new(:file => nil)
35
- doc.save
35
+ lambda {
36
+ doc.save
37
+ }.should_not raise_error
36
38
  end
37
39
  end
38
40
 
@@ -1113,6 +1115,16 @@ class DocumentTest < Test::Unit::TestCase
1113
1115
  doc.created_at.should_not be(nil)
1114
1116
  doc.updated_at.should_not be(nil)
1115
1117
  end
1118
+
1119
+ should "not overwrite created_at if it already exists" do
1120
+ original_created_at = 1.month.ago
1121
+ doc = @document.new(:first_name => 'John', :age => 27, :created_at => original_created_at)
1122
+ doc.created_at.to_i.should == original_created_at.to_i
1123
+ doc.updated_at.should be_nil
1124
+ doc.save
1125
+ doc.created_at.to_i.should == original_created_at.to_i
1126
+ doc.updated_at.should_not be_nil
1127
+ end
1116
1128
 
1117
1129
  should "set updated_at on field update but leave created_at alone" do
1118
1130
  doc = @document.create(:first_name => 'John', :age => 27)
@@ -1168,13 +1180,47 @@ class DocumentTest < Test::Unit::TestCase
1168
1180
 
1169
1181
  context "reload" do
1170
1182
  setup do
1171
- @doc_instance_1 = @document.create({:first_name => 'Ryan', :last_name => 'Koopmans', :age => '37'})
1172
- @doc_instance_2 = @document.update(@doc_instance_1._id, {:age => '39'})
1183
+ @foo_class = Class.new do
1184
+ include MongoMapper::Document
1185
+ key :name
1186
+ end
1187
+ @foo_class.collection.remove
1188
+
1189
+ @bar_class = Class.new do
1190
+ include MongoMapper::EmbeddedDocument
1191
+ key :name
1192
+ end
1193
+
1194
+ @document.many :foos, :class => @foo_class
1195
+ @document.many :bars, :class => @bar_class
1196
+
1197
+ @instance = @document.create({
1198
+ :age => 39,
1199
+ :foos => [@foo_class.new(:name => '1')],
1200
+ :bars => [@bar_class.new(:name => '1')],
1201
+ })
1173
1202
  end
1174
1203
 
1175
- should "load fresh information from the database" do
1176
- @doc_instance_1.age.should == 37
1177
- @doc_instance_1.reload.age.should == 39
1204
+ should "reload keys from the database" do
1205
+ @instance.age = 37
1206
+ @instance.age.should == 37
1207
+ @instance.reload
1208
+ @instance.age.should == 39
1209
+ end
1210
+
1211
+ should "reset all associations" do
1212
+ @instance.foos.expects(:reset).at_least_once
1213
+ @instance.bars.expects(:reset).at_least_once
1214
+ @instance.reload
1215
+ end
1216
+
1217
+ should "reinstantiate embedded associations" do
1218
+ @instance.reload
1219
+ @instance.bars.first.name.should == '1'
1220
+ end
1221
+
1222
+ should "return self" do
1223
+ @instance.reload.object_id.should == @instance.object_id
1178
1224
  end
1179
1225
  end
1180
1226
  end
@@ -122,4 +122,14 @@ class EmbeddedDocumentTest < Test::Unit::TestCase
122
122
  person.pets.first.name.should == 'koda'
123
123
  end
124
124
  end
125
+
126
+ context "update_attributes!" do
127
+ should "pass the attributes to self.attributes" do
128
+ person = RealPerson.create
129
+ attributes = { :foo => 'bar' }
130
+ person.expects(:attributes=).with(attributes)
131
+ person.expects(:save!)
132
+ person.update_attributes!(attributes)
133
+ end
134
+ end
125
135
  end
@@ -246,20 +246,29 @@ class ValidationsTest < Test::Unit::TestCase
246
246
  doc2.should_not have_error_on(:name)
247
247
  end
248
248
 
249
- should "fail on entries that differ only in case if :case_sensitive => false" do
250
- document = Class.new do
251
- include MongoMapper::Document
252
- set_collection_name 'test'
249
+ context "with :case_sensitive => false" do
250
+ setup do
251
+ @document = Class.new do
252
+ include MongoMapper::Document
253
+ set_collection_name 'test'
253
254
 
254
- key :name
255
- validates_uniqueness_of :name, :case_sensitive => false
255
+ key :name
256
+ validates_uniqueness_of :name, :case_sensitive => false
257
+ end
256
258
  end
259
+
260
+ should "fail on entries that differ only in case" do
261
+ doc = @document.new("name" => "BLAMMO")
262
+ doc.save.should be_true
257
263
 
258
- doc = document.new("name" => "BLAMMO")
259
- doc.save.should be_true
264
+ doc2 = @document.new("name" => "blammo")
265
+ doc2.should have_error_on(:name)
266
+ end
260
267
 
261
- doc2 = document.new("name" => "blammo")
262
- doc2.should have_error_on(:name)
268
+ should "not raise an error if value is nil" do
269
+ doc = @document.new("name" => nil)
270
+ lambda { doc.valid? }.should_not raise_error
271
+ end
263
272
  end
264
273
 
265
274
  context "scoped by a single attribute" do
@@ -132,9 +132,9 @@ class AssociationBaseTest < Test::Unit::TestCase
132
132
  end
133
133
 
134
134
  context "proxy_class" do
135
- should "be ManyProxy for many" do
135
+ should "be ManyDocumentsProxy for many" do
136
136
  base = Base.new(:many, :statuses)
137
- base.proxy_class.should == ManyProxy
137
+ base.proxy_class.should == ManyDocumentsProxy
138
138
  end
139
139
 
140
140
  should "be ManyPolymorphicProxy for polymorphic many" do
@@ -0,0 +1,91 @@
1
+ require 'test_helper'
2
+
3
+ class FakeNilProxy < MongoMapper::Associations::Proxy
4
+ def find_target; nil end
5
+ end
6
+
7
+ class FakeBlankProxy < MongoMapper::Associations::Proxy
8
+ def find_target; '' end
9
+ end
10
+
11
+ class FakeProxy < MongoMapper::Associations::Proxy
12
+ def find_target
13
+ [1, 2]
14
+ end
15
+ end
16
+
17
+ class ProxyTest < Test::Unit::TestCase
18
+ def setup
19
+ @owner = mock('owner')
20
+ @owner.stubs(:new?).returns(false)
21
+ @association = mock('association')
22
+ @association.stubs(:options).returns({:extend => []})
23
+
24
+ @proxy = FakeProxy.new(@owner, @association)
25
+ @nil_proxy = FakeNilProxy.new(@owner, @association)
26
+ @blank_proxy = FakeBlankProxy.new(@owner, @association)
27
+ end
28
+
29
+ should 'return true for === target' do
30
+ @proxy = FakeProxy.new(@owner, @association)
31
+ @proxy.should === Array
32
+ end
33
+
34
+ should "set target to nil when reset is called" do
35
+ @proxy.reset
36
+ @proxy.target.should be_nil
37
+ end
38
+
39
+ should "be able to inspect the proxy" do
40
+ @proxy.inspect.should == '[1, 2]'
41
+ end
42
+
43
+ context "nil?" do
44
+ should "be true if nil" do
45
+ @nil_proxy.nil?.should be_true
46
+ end
47
+
48
+ should "be false if not nil" do
49
+ @proxy.nil?.should be_false
50
+ end
51
+ end
52
+
53
+ context "blank?" do
54
+ should "be true if blank" do
55
+ @blank_proxy.blank?.should be_true
56
+ end
57
+
58
+ should "be false if not blank" do
59
+ @proxy.blank?.should be_false
60
+ end
61
+ end
62
+
63
+ should "delegate respond_to? to target" do
64
+ @proxy.respond_to?(:each).should be_true
65
+ @proxy.respond_to?(:size).should be_true
66
+ @proxy.respond_to?(:gsub).should be_false
67
+ end
68
+
69
+ should "alias proxy owner to owner" do
70
+ @proxy.proxy_owner.should == @owner
71
+ end
72
+
73
+ should "alias proxy target to target" do
74
+ @proxy.proxy_target.should == @target
75
+ end
76
+
77
+ context "send" do
78
+ should "work if proxy responds to method" do
79
+ @proxy.send(:reset)
80
+ @proxy.target.should be_nil
81
+ end
82
+
83
+ should "work if the target responds to the method" do
84
+ @proxy.send(:size).should == 2
85
+ end
86
+
87
+ should "not work if neither the proxy or target respond to method" do
88
+ lambda { @proxy.send(:gsub) }.should raise_error
89
+ end
90
+ end
91
+ end
@@ -335,7 +335,7 @@ class SupportTest < Test::Unit::TestCase
335
335
  context "Mongo::ObjectID.to_json" do
336
336
  should "convert object id to string" do
337
337
  id = Mongo::ObjectID.new
338
- id.to_json.should == id.to_s
338
+ id.to_json.should == %Q("#{id}")
339
339
  end
340
340
  end
341
341
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongo_mapper-unstable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2009.12.4
4
+ version: 2009.12.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-04 00:00:00 -05:00
12
+ date: 2009-12-14 00:00:00 -05:00
13
13
  default_executable: mmconsole
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -103,12 +103,12 @@ files:
103
103
  - lib/mongo_mapper/associations/base.rb
104
104
  - lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb
105
105
  - lib/mongo_mapper/associations/belongs_to_proxy.rb
106
+ - lib/mongo_mapper/associations/collection.rb
106
107
  - lib/mongo_mapper/associations/many_documents_as_proxy.rb
107
108
  - lib/mongo_mapper/associations/many_documents_proxy.rb
108
109
  - lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb
109
110
  - lib/mongo_mapper/associations/many_embedded_proxy.rb
110
111
  - lib/mongo_mapper/associations/many_polymorphic_proxy.rb
111
- - lib/mongo_mapper/associations/many_proxy.rb
112
112
  - lib/mongo_mapper/associations/proxy.rb
113
113
  - lib/mongo_mapper/callbacks.rb
114
114
  - lib/mongo_mapper/dirty.rb
@@ -131,10 +131,10 @@ files:
131
131
  - test/functional/associations/test_belongs_to_polymorphic_proxy.rb
132
132
  - test/functional/associations/test_belongs_to_proxy.rb
133
133
  - test/functional/associations/test_many_documents_as_proxy.rb
134
+ - test/functional/associations/test_many_documents_proxy.rb
134
135
  - test/functional/associations/test_many_embedded_polymorphic_proxy.rb
135
136
  - test/functional/associations/test_many_embedded_proxy.rb
136
137
  - test/functional/associations/test_many_polymorphic_proxy.rb
137
- - test/functional/associations/test_many_proxy.rb
138
138
  - test/functional/test_associations.rb
139
139
  - test/functional/test_binary.rb
140
140
  - test/functional/test_callbacks.rb
@@ -150,8 +150,9 @@ files:
150
150
  - test/support/custom_matchers.rb
151
151
  - test/support/timing.rb
152
152
  - test/test_helper.rb
153
+ - test/unit/associations/test_base.rb
154
+ - test/unit/associations/test_proxy.rb
153
155
  - test/unit/serializers/test_json_serializer.rb
154
- - test/unit/test_association_base.rb
155
156
  - test/unit/test_document.rb
156
157
  - test/unit/test_dynamic_finder.rb
157
158
  - test/unit/test_embedded_document.rb
@@ -195,13 +196,14 @@ specification_version: 3
195
196
  summary: Awesome gem for modeling your domain and storing it in mongo
196
197
  test_files:
197
198
  - test/unit/test_embedded_document.rb
198
- - test/unit/test_association_base.rb
199
199
  - test/unit/test_serializations.rb
200
200
  - test/unit/test_key.rb
201
201
  - test/unit/test_dynamic_finder.rb
202
202
  - test/unit/serializers/test_json_serializer.rb
203
203
  - test/unit/test_support.rb
204
204
  - test/unit/test_finder_options.rb
205
+ - test/unit/associations/test_proxy.rb
206
+ - test/unit/associations/test_base.rb
205
207
  - test/unit/test_time_zones.rb
206
208
  - test/unit/test_observing.rb
207
209
  - test/unit/test_rails_compatibility.rb
@@ -216,7 +218,7 @@ test_files:
216
218
  - test/functional/test_string_id_compatibility.rb
217
219
  - test/functional/test_associations.rb
218
220
  - test/functional/associations/test_belongs_to_proxy.rb
219
- - test/functional/associations/test_many_proxy.rb
221
+ - test/functional/associations/test_many_documents_proxy.rb
220
222
  - test/functional/associations/test_many_embedded_proxy.rb
221
223
  - test/functional/associations/test_many_documents_as_proxy.rb
222
224
  - test/functional/associations/test_many_embedded_polymorphic_proxy.rb
@@ -1,6 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class ManyProxy < ManyDocumentsProxy
4
- end
5
- end
6
- end