mongo_mapper-unstable 2010.1.6 → 2010.1.12

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 (86) hide show
  1. data/VERSION +1 -1
  2. data/lib/mongo_mapper/descendant_appends.rb +44 -0
  3. data/lib/mongo_mapper/document.rb +54 -98
  4. data/lib/mongo_mapper/embedded_document.rb +28 -348
  5. data/lib/mongo_mapper/finder_options.rb +15 -33
  6. data/lib/mongo_mapper/plugins/associations/base.rb +121 -0
  7. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +28 -0
  8. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +23 -0
  9. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  10. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +49 -0
  11. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
  12. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  13. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
  14. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  15. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  16. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  17. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +66 -0
  18. data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
  19. data/lib/mongo_mapper/plugins/associations.rb +104 -0
  20. data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
  21. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  22. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  23. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  24. data/lib/mongo_mapper/plugins/equality.rb +11 -0
  25. data/lib/mongo_mapper/plugins/identity_map.rb +66 -0
  26. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  27. data/lib/mongo_mapper/plugins/keys.rb +295 -0
  28. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  29. data/lib/mongo_mapper/plugins/pagination.rb +85 -0
  30. data/lib/mongo_mapper/plugins/rails.rb +45 -0
  31. data/lib/mongo_mapper/plugins/serialization.rb +109 -0
  32. data/lib/mongo_mapper/plugins/validations.rb +48 -0
  33. data/lib/mongo_mapper/plugins.rb +19 -0
  34. data/lib/mongo_mapper/support.rb +36 -15
  35. data/lib/mongo_mapper.rb +23 -22
  36. data/performance/read_write.rb +52 -0
  37. data/specs.watchr +23 -2
  38. data/test/functional/associations/test_belongs_to_proxy.rb +1 -1
  39. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +58 -39
  40. data/test/functional/associations/test_many_embedded_proxy.rb +103 -69
  41. data/test/functional/test_dirty.rb +1 -1
  42. data/test/functional/test_document.rb +25 -25
  43. data/test/functional/test_embedded_document.rb +66 -63
  44. data/test/functional/test_identity_map.rb +233 -0
  45. data/test/functional/test_modifiers.rb +14 -0
  46. data/test/functional/test_string_id_compatibility.rb +4 -4
  47. data/test/functional/test_validations.rb +13 -0
  48. data/test/models.rb +0 -39
  49. data/test/test_helper.rb +8 -2
  50. data/test/unit/associations/test_base.rb +1 -1
  51. data/test/unit/associations/test_proxy.rb +3 -3
  52. data/test/unit/test_descendant_appends.rb +71 -0
  53. data/test/unit/test_document.rb +35 -46
  54. data/test/unit/test_embedded_document.rb +218 -271
  55. data/test/unit/{test_key.rb → test_keys.rb} +0 -0
  56. data/test/unit/test_pagination.rb +10 -2
  57. data/test/unit/test_plugins.rb +42 -0
  58. data/test/unit/test_rails.rb +123 -0
  59. data/test/unit/{test_serializations.rb → test_serialization.rb} +0 -0
  60. data/test/unit/test_support.rb +10 -6
  61. data/test/unit/test_time_zones.rb +2 -2
  62. metadata +44 -31
  63. data/lib/mongo_mapper/associations/base.rb +0 -119
  64. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
  65. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
  66. data/lib/mongo_mapper/associations/collection.rb +0 -19
  67. data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
  68. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
  69. data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
  70. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
  71. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
  72. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
  73. data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
  74. data/lib/mongo_mapper/associations/proxy.rb +0 -116
  75. data/lib/mongo_mapper/associations.rb +0 -78
  76. data/lib/mongo_mapper/callbacks.rb +0 -61
  77. data/lib/mongo_mapper/dirty.rb +0 -117
  78. data/lib/mongo_mapper/key.rb +0 -36
  79. data/lib/mongo_mapper/mongo_mapper.rb +0 -125
  80. data/lib/mongo_mapper/pagination.rb +0 -66
  81. data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
  82. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
  83. data/lib/mongo_mapper/serialization.rb +0 -54
  84. data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
  85. data/lib/mongo_mapper/validations.rb +0 -39
  86. data/test/functional/test_rails_compatibility.rb +0 -25
@@ -1,137 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class InArrayProxy < Collection
4
- include ::MongoMapper::Finders
5
-
6
- def find(*args)
7
- options = args.extract_options!
8
-
9
- case args.first
10
- when :first
11
- first(options)
12
- when :last
13
- last(options)
14
- when :all
15
- all(options)
16
- else
17
- klass.find(*scoped_ids(args) << scoped_options(options))
18
- end
19
- end
20
-
21
- def find!(*args)
22
- options = args.extract_options!
23
-
24
- case args.first
25
- when :first
26
- first(options)
27
- when :last
28
- last(options)
29
- when :all
30
- all(options)
31
- else
32
- klass.find!(*scoped_ids(args) << scoped_options(options))
33
- end
34
- end
35
-
36
- def paginate(options)
37
- klass.paginate(scoped_options(options))
38
- end
39
-
40
- def all(options={})
41
- klass.all(scoped_options(options))
42
- end
43
-
44
- def first(options={})
45
- klass.first(scoped_options(options))
46
- end
47
-
48
- def last(options={})
49
- klass.last(scoped_options(options))
50
- end
51
-
52
- def count(options={})
53
- options.blank? ? ids.size : klass.count(scoped_options(options))
54
- end
55
-
56
- def destroy_all(options={})
57
- all(options).each do |doc|
58
- ids.delete(doc.id)
59
- doc.destroy
60
- end
61
- reset
62
- end
63
-
64
- def delete_all(options={})
65
- docs = all(options.merge(:select => ['_id']))
66
- docs.each { |doc| ids.delete(doc.id) }
67
- klass.delete(docs.map(&:id))
68
- reset
69
- end
70
-
71
- def nullify
72
- replace([])
73
- reset
74
- end
75
-
76
- def create(attrs={})
77
- doc = klass.create(attrs)
78
- unless doc.new?
79
- ids << doc.id
80
- owner.save
81
- end
82
- doc
83
- end
84
-
85
- def create!(attrs={})
86
- doc = klass.create!(attrs)
87
- unless doc.new?
88
- ids << doc.id
89
- owner.save
90
- end
91
- doc
92
- end
93
-
94
- def <<(*docs)
95
- flatten_deeper(docs).each do |doc|
96
- doc.save if doc.new?
97
- unless ids.include?(doc.id)
98
- ids << doc.id
99
- end
100
- end
101
- reset
102
- end
103
- alias_method :push, :<<
104
- alias_method :concat, :<<
105
-
106
- def replace(docs)
107
- doc_ids = docs.map do |doc|
108
- doc.save if doc.new?
109
- doc.id
110
- end
111
- ids.replace(doc_ids.uniq)
112
- reset
113
- end
114
-
115
- private
116
- def scoped_conditions
117
- {:_id => ids}
118
- end
119
-
120
- def scoped_options(options)
121
- reflection.finder_options.merge(options).merge(scoped_conditions)
122
- end
123
-
124
- def scoped_ids(args)
125
- args.flatten.reject { |id| !ids.include?(id) }
126
- end
127
-
128
- def find_target
129
- ids.blank? ? [] : all
130
- end
131
-
132
- def ids
133
- owner[options[:in]]
134
- end
135
- end
136
- end
137
- end
@@ -1,26 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class ManyDocumentsAsProxy < ManyDocumentsProxy
4
- protected
5
- def scoped_conditions
6
- {type_key_name => owner.class.name, id_key_name => owner.id}
7
- end
8
-
9
- def apply_scope(doc)
10
- ensure_owner_saved
11
- doc[type_key_name] = owner.class.name
12
- doc[id_key_name] = owner.id
13
- doc
14
- end
15
-
16
- private
17
- def type_key_name
18
- "#{options[:as]}_type"
19
- end
20
-
21
- def id_key_name
22
- "#{options[:as]}_id"
23
- end
24
- end
25
- end
26
- end
@@ -1,115 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class ManyDocumentsProxy < Collection
4
- include ::MongoMapper::Finders
5
-
6
- def find(*args)
7
- options = args.extract_options!
8
- klass.find(*args << scoped_options(options))
9
- end
10
-
11
- def find!(*args)
12
- options = args.extract_options!
13
- klass.find!(*args << scoped_options(options))
14
- end
15
-
16
- def paginate(options)
17
- klass.paginate(scoped_options(options))
18
- end
19
-
20
- def all(options={})
21
- klass.all(scoped_options(options))
22
- end
23
-
24
- def first(options={})
25
- klass.first(scoped_options(options))
26
- end
27
-
28
- def last(options={})
29
- klass.last(scoped_options(options))
30
- end
31
-
32
- def count(options={})
33
- klass.count(scoped_options(options))
34
- end
35
-
36
- def replace(docs)
37
- load_target
38
- target.map(&:destroy)
39
- docs.each { |doc| apply_scope(doc).save }
40
- reset
41
- end
42
-
43
- def <<(*docs)
44
- ensure_owner_saved
45
- flatten_deeper(docs).each { |doc| apply_scope(doc).save }
46
- reset
47
- end
48
- alias_method :push, :<<
49
- alias_method :concat, :<<
50
-
51
- def build(attrs={})
52
- doc = klass.new(attrs)
53
- apply_scope(doc)
54
- doc
55
- end
56
-
57
- def create(attrs={})
58
- doc = klass.new(attrs)
59
- apply_scope(doc).save
60
- doc
61
- end
62
-
63
- def create!(attrs={})
64
- doc = klass.new(attrs)
65
- apply_scope(doc).save!
66
- doc
67
- end
68
-
69
- def destroy_all(options={})
70
- all(options).map(&:destroy)
71
- reset
72
- end
73
-
74
- def delete_all(options={})
75
- klass.delete_all(options.merge(scoped_conditions))
76
- reset
77
- end
78
-
79
- def nullify
80
- criteria = FinderOptions.new(klass, scoped_conditions).criteria
81
- all(criteria).each do |doc|
82
- doc.update_attributes(self.foreign_key => nil)
83
- end
84
- reset
85
- end
86
-
87
- protected
88
- def scoped_conditions
89
- {self.foreign_key => owner.id}
90
- end
91
-
92
- def scoped_options(options)
93
- reflection.finder_options.merge(options).merge(scoped_conditions)
94
- end
95
-
96
- def find_target
97
- all
98
- end
99
-
100
- def ensure_owner_saved
101
- owner.save if owner.new?
102
- end
103
-
104
- def apply_scope(doc)
105
- ensure_owner_saved
106
- doc[foreign_key] = owner.id
107
- doc
108
- end
109
-
110
- def foreign_key
111
- options[:foreign_key] || owner.class.name.underscore.gsub("/", "_") + "_id"
112
- end
113
- end
114
- end
115
- end
@@ -1,31 +0,0 @@
1
- module MongoMapper
2
- module Associations
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)
8
- else
9
- v
10
- end
11
- end
12
- reset
13
- end
14
-
15
- protected
16
- def find_target
17
- (@_values || []).map do |hash|
18
- polymorphic_class(hash).new(hash)
19
- end
20
- end
21
-
22
- def polymorphic_class(doc)
23
- if class_name = doc[reflection.type_key_name]
24
- class_name.constantize
25
- else
26
- klass
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,54 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class ManyEmbeddedProxy < Collection
4
- def replace(values)
5
- @_values = values.map do |v|
6
- v.kind_of?(EmbeddedDocument) ? v.attributes : v
7
- end
8
- reset
9
- end
10
-
11
- def build(attributes={})
12
- doc = klass.new(attributes)
13
- assign_root_document(doc)
14
- self << doc
15
- doc
16
- end
17
-
18
- # TODO: test that both string and oid version work
19
- def find(id)
20
- load_target
21
- target.detect { |item| item.id.to_s == id || item.id == id }
22
- end
23
-
24
- def <<(*docs)
25
- load_target
26
- docs.each do |doc|
27
- assign_root_document(doc)
28
- target << doc
29
- end
30
- end
31
- alias_method :push, :<<
32
- alias_method :concat, :<<
33
-
34
- private
35
- def find_target
36
- (@_values || []).map do |v|
37
- child = klass.new(v)
38
- assign_root_document(child)
39
- child
40
- end
41
- end
42
-
43
- def root_document
44
- owner._root_document || owner
45
- end
46
-
47
- def assign_root_document(*docs)
48
- docs.each do |doc|
49
- doc._root_document = root_document
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,11 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class ManyPolymorphicProxy < ManyDocumentsProxy
4
- private
5
- def apply_scope(doc)
6
- doc[reflection.type_key_name] = doc.class.name
7
- super
8
- end
9
- end
10
- end
11
- end
@@ -1,64 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class OneProxy < Proxy
4
- def build(attrs={})
5
- instantiate_target(:new, attrs)
6
- end
7
-
8
- def create(attrs={})
9
- instantiate_target(:create, attrs)
10
- end
11
-
12
- def create!(attrs={})
13
- instantiate_target(:create!, attrs)
14
- end
15
-
16
- def replace(doc)
17
- load_target
18
-
19
- if !target.nil? && target != doc
20
- if options[:dependent] && !target.new?
21
- case options[:dependent]
22
- when :delete
23
- target.delete
24
- when :destroy
25
- target.destroy
26
- when :nullify
27
- target[foreign_key] = nil
28
- target.save
29
- end
30
- end
31
- end
32
-
33
- reset
34
-
35
- unless doc.nil?
36
- owner.save if owner.new?
37
- doc[foreign_key] = owner.id
38
- doc.save if doc.new?
39
- loaded
40
- @target = doc
41
- end
42
- end
43
-
44
- protected
45
- def find_target
46
- target_class.first(reflection.finder_options.merge(foreign_key => owner.id))
47
- end
48
-
49
- def instantiate_target(instantiator, attrs={})
50
- @target = target_class.send(instantiator, attrs.update(foreign_key => owner.id))
51
- loaded
52
- @target
53
- end
54
-
55
- def target_class
56
- @target_class ||= options[:class] || (options[:class_name] || reflection.name.to_s.camelize).constantize
57
- end
58
-
59
- def foreign_key
60
- options[:foreign_key] || owner.class.name.foreign_key
61
- end
62
- end
63
- end
64
- end
@@ -1,116 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class Proxy
4
- alias :proxy_respond_to? :respond_to?
5
- alias :proxy_extend :extend
6
-
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, @loaded = owner, reflection, false
21
- Array(reflection.options[:extend]).each { |ext| proxy_extend(ext) }
22
- reset
23
- end
24
-
25
- def inspect
26
- load_target
27
- target.inspect
28
- end
29
-
30
- def loaded?
31
- @loaded
32
- end
33
-
34
- def loaded
35
- @loaded = true
36
- end
37
-
38
- def nil?
39
- load_target
40
- target.nil?
41
- end
42
-
43
- def blank?
44
- load_target
45
- target.blank?
46
- end
47
-
48
- def present?
49
- load_target
50
- target.present?
51
- end
52
-
53
- def reload
54
- reset
55
- load_target
56
- self unless target.nil?
57
- end
58
-
59
- def replace(v)
60
- raise NotImplementedError
61
- end
62
-
63
- def reset
64
- @loaded = false
65
- @target = nil
66
- end
67
-
68
- def respond_to?(*args)
69
- proxy_respond_to?(*args) || (load_target && target.respond_to?(*args))
70
- end
71
-
72
- def send(method, *args)
73
- if proxy_respond_to?(method)
74
- super
75
- else
76
- load_target
77
- target.send(method, *args)
78
- end
79
- end
80
-
81
- def ===(other)
82
- load_target
83
- other === target
84
- end
85
-
86
- protected
87
- def method_missing(method, *args, &block)
88
- if load_target
89
- if block_given?
90
- target.send(method, *args) { |*block_args| block.call(*block_args) }
91
- else
92
- target.send(method, *args)
93
- end
94
- end
95
- end
96
-
97
- def load_target
98
- @target = find_target unless loaded?
99
- loaded
100
- @target
101
- rescue MongoMapper::DocumentNotFound
102
- reset
103
- end
104
-
105
- def find_target
106
- raise NotImplementedError
107
- end
108
-
109
- def flatten_deeper(array)
110
- array.collect do |element|
111
- (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element
112
- end.flatten
113
- end
114
- end
115
- end
116
- end
@@ -1,78 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- module ClassMethods
4
- def belongs_to(association_id, options={}, &extension)
5
- create_association(:belongs_to, association_id, options, &extension)
6
- end
7
-
8
- def many(association_id, options={}, &extension)
9
- create_association(:many, association_id, options, &extension)
10
- end
11
-
12
- def one(association_id, options={}, &extension)
13
- create_association(:one, association_id, options, &extension)
14
- end
15
-
16
- def associations
17
- @associations ||= HashWithIndifferentAccess.new
18
- end
19
-
20
- def associations=(hash)
21
- @associations = hash
22
- end
23
-
24
- def inherited(subclass)
25
- subclass.associations = associations.dup
26
- super
27
- end
28
-
29
- private
30
- def create_association(type, name, options, &extension)
31
- association = Associations::Base.new(type, name, options, &extension)
32
- associations[association.name] = association
33
-
34
- define_method(association.name) do
35
- get_proxy(association)
36
- end
37
-
38
- define_method("#{association.name}=") do |value|
39
- get_proxy(association).replace(value)
40
- value
41
- end
42
-
43
- if association.one? || association.belongs_to?
44
- define_method("#{association.name}?") do
45
- get_proxy(association).present?
46
- end
47
- end
48
-
49
- if association.options[:dependent] && association.many? && !association.embeddable?
50
- after_destroy do |doc|
51
- case association.options[:dependent]
52
- when :destroy
53
- doc.get_proxy(association).destroy_all
54
- when :delete_all
55
- doc.get_proxy(association).delete_all
56
- when :nullify
57
- doc.get_proxy(association).nullify
58
- end
59
- end
60
- end
61
- end
62
- end
63
-
64
- module InstanceMethods
65
- def associations
66
- self.class.associations
67
- end
68
-
69
- def get_proxy(association)
70
- unless proxy = self.instance_variable_get(association.ivar)
71
- proxy = association.proxy_class.new(self, association)
72
- self.instance_variable_set(association.ivar, proxy)
73
- end
74
- proxy
75
- end
76
- end
77
- end
78
- end
@@ -1,61 +0,0 @@
1
- module MongoMapper
2
- module Callbacks
3
- def self.included(model)
4
- model.class_eval do
5
- include ActiveSupport::Callbacks
6
-
7
- define_callbacks(
8
- :before_save, :after_save,
9
- :before_create, :after_create,
10
- :before_update, :after_update,
11
- :before_validation, :after_validation,
12
- :before_validation_on_create, :after_validation_on_create,
13
- :before_validation_on_update, :after_validation_on_update,
14
- :before_destroy, :after_destroy
15
- )
16
- end
17
- end
18
-
19
- def valid?
20
- action = new? ? 'create' : 'update'
21
-
22
- run_callbacks(:before_validation)
23
- run_callbacks("before_validation_on_#{action}".to_sym)
24
- result = super
25
- run_callbacks("after_validation_on_#{action}".to_sym)
26
- run_callbacks(:after_validation)
27
-
28
- result
29
- end
30
-
31
- def destroy
32
- run_callbacks(:before_destroy)
33
- result = super
34
- run_callbacks(:after_destroy)
35
- result
36
- end
37
-
38
- private
39
- def create_or_update(*args)
40
- run_callbacks(:before_save)
41
- if result = super
42
- run_callbacks(:after_save)
43
- end
44
- result
45
- end
46
-
47
- def create(*args)
48
- run_callbacks(:before_create)
49
- result = super
50
- run_callbacks(:after_create)
51
- result
52
- end
53
-
54
- def update(*args)
55
- run_callbacks(:before_update)
56
- result = super
57
- run_callbacks(:after_update)
58
- result
59
- end
60
- end
61
- end