mongo_mapper-unstable 2010.1.6 → 2010.1.12

Sign up to get free protection for your applications and to get access to all the features.
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