mongo_mapper 0.6.10 → 0.7.0

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 (106) hide show
  1. data/README.rdoc +5 -14
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/lib/mongo_mapper.rb +48 -56
  5. data/lib/mongo_mapper/document.rb +136 -164
  6. data/lib/mongo_mapper/embedded_document.rb +29 -354
  7. data/lib/mongo_mapper/plugins.rb +31 -0
  8. data/lib/mongo_mapper/plugins/associations.rb +105 -0
  9. data/lib/mongo_mapper/plugins/associations/base.rb +123 -0
  10. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
  11. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
  12. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  13. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
  14. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
  15. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  16. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
  17. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  18. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  19. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  20. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
  21. data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
  22. data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
  23. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  24. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  25. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  26. data/lib/mongo_mapper/plugins/equality.rb +23 -0
  27. data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
  28. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  29. data/lib/mongo_mapper/plugins/keys.rb +324 -0
  30. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  31. data/lib/mongo_mapper/plugins/pagination.rb +24 -0
  32. data/lib/mongo_mapper/plugins/pagination/proxy.rb +68 -0
  33. data/lib/mongo_mapper/plugins/protected.rb +45 -0
  34. data/lib/mongo_mapper/plugins/rails.rb +45 -0
  35. data/lib/mongo_mapper/plugins/serialization.rb +105 -0
  36. data/lib/mongo_mapper/plugins/validations.rb +46 -0
  37. data/lib/mongo_mapper/query.rb +130 -0
  38. data/lib/mongo_mapper/support.rb +40 -17
  39. data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
  40. data/lib/mongo_mapper/support/find.rb +77 -0
  41. data/mongo_mapper.gemspec +55 -38
  42. data/performance/read_write.rb +52 -0
  43. data/specs.watchr +23 -2
  44. data/test/functional/associations/test_belongs_to_proxy.rb +12 -10
  45. data/test/functional/associations/test_many_documents_as_proxy.rb +4 -21
  46. data/test/functional/associations/test_many_documents_proxy.rb +2 -8
  47. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +59 -39
  48. data/test/functional/associations/test_many_embedded_proxy.rb +145 -81
  49. data/test/functional/associations/test_many_polymorphic_proxy.rb +2 -40
  50. data/test/functional/associations/test_one_proxy.rb +25 -10
  51. data/test/functional/test_binary.rb +2 -8
  52. data/test/functional/test_callbacks.rb +1 -5
  53. data/test/functional/test_dirty.rb +27 -23
  54. data/test/functional/test_document.rb +224 -165
  55. data/test/functional/test_embedded_document.rb +72 -82
  56. data/test/functional/test_identity_map.rb +508 -0
  57. data/test/functional/test_modifiers.rb +15 -5
  58. data/test/functional/test_pagination.rb +1 -3
  59. data/test/functional/test_protected.rb +155 -0
  60. data/test/functional/test_string_id_compatibility.rb +7 -12
  61. data/test/functional/test_validations.rb +26 -58
  62. data/test/models.rb +0 -39
  63. data/test/test_helper.rb +37 -3
  64. data/test/unit/associations/test_base.rb +5 -5
  65. data/test/unit/associations/test_proxy.rb +8 -6
  66. data/test/unit/test_descendant_appends.rb +71 -0
  67. data/test/unit/test_document.rb +71 -76
  68. data/test/unit/test_dynamic_finder.rb +27 -29
  69. data/test/unit/test_embedded_document.rb +555 -601
  70. data/test/unit/{test_key.rb → test_keys.rb} +2 -5
  71. data/test/unit/test_mongo_mapper.rb +69 -9
  72. data/test/unit/test_pagination.rb +40 -32
  73. data/test/unit/test_plugins.rb +50 -0
  74. data/test/unit/{test_finder_options.rb → test_query.rb} +74 -65
  75. data/test/unit/test_rails.rb +123 -0
  76. data/test/unit/{test_serializations.rb → test_serialization.rb} +1 -2
  77. data/test/unit/test_support.rb +23 -7
  78. data/test/unit/test_time_zones.rb +3 -4
  79. data/test/unit/test_validations.rb +58 -17
  80. metadata +53 -36
  81. data/lib/mongo_mapper/associations.rb +0 -78
  82. data/lib/mongo_mapper/associations/base.rb +0 -119
  83. data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
  84. data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
  85. data/lib/mongo_mapper/associations/collection.rb +0 -19
  86. data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
  87. data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
  88. data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
  89. data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
  90. data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
  91. data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
  92. data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
  93. data/lib/mongo_mapper/associations/proxy.rb +0 -116
  94. data/lib/mongo_mapper/callbacks.rb +0 -61
  95. data/lib/mongo_mapper/dirty.rb +0 -117
  96. data/lib/mongo_mapper/dynamic_finder.rb +0 -74
  97. data/lib/mongo_mapper/finder_options.rb +0 -145
  98. data/lib/mongo_mapper/key.rb +0 -36
  99. data/lib/mongo_mapper/mongo_mapper.rb +0 -125
  100. data/lib/mongo_mapper/pagination.rb +0 -66
  101. data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
  102. data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
  103. data/lib/mongo_mapper/serialization.rb +0 -54
  104. data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
  105. data/lib/mongo_mapper/validations.rb +0 -39
  106. data/test/functional/test_rails_compatibility.rb +0 -25
@@ -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,119 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class Base
4
- attr_reader :type, :name, :options, :finder_options
5
-
6
- # Options that should not be considered MongoDB query options/criteria
7
- AssociationOptions = [:as, :class, :class_name, :dependent, :extend, :foreign_key, :in, :polymorphic]
8
-
9
- def initialize(type, name, options={}, &extension)
10
- @type, @name, @options, @finder_options = type, name, {}, {}
11
- options.symbolize_keys!
12
-
13
- options[:extend] = modulized_extensions(extension, options[:extend])
14
-
15
- options.each_pair do |key, value|
16
- if AssociationOptions.include?(key)
17
- @options[key] = value
18
- else
19
- @finder_options[key] = value
20
- end
21
- end
22
- end
23
-
24
- def class_name
25
- @class_name ||= begin
26
- if cn = options[:class_name]
27
- cn
28
- elsif many?
29
- name.to_s.singularize.camelize
30
- else
31
- name.to_s.camelize
32
- end
33
- end
34
- end
35
-
36
- def klass
37
- @klass ||= options[:class] || class_name.constantize
38
- end
39
-
40
- def many?
41
- @many_type ||= @type == :many
42
- end
43
-
44
- def belongs_to?
45
- @belongs_to_type ||= @type == :belongs_to
46
- end
47
-
48
- def one?
49
- @one_type ||= @type == :one
50
- end
51
-
52
- def polymorphic?
53
- !!@options[:polymorphic]
54
- end
55
-
56
- def as?
57
- !!@options[:as]
58
- end
59
-
60
- def in_array?
61
- !!@options[:in]
62
- end
63
-
64
- def embeddable?
65
- many? && klass.embeddable?
66
- end
67
-
68
- def type_key_name
69
- @type_key_name ||= many? ? '_type' : "#{as}_type"
70
- end
71
-
72
- def as
73
- @options[:as] || self.name
74
- end
75
-
76
- def foreign_key
77
- @options[:foreign_key] || "#{name}_id"
78
- end
79
-
80
- def ivar
81
- @ivar ||= "@_#{name}"
82
- end
83
-
84
- def proxy_class
85
- @proxy_class ||= begin
86
- if many?
87
- if self.klass.embeddable?
88
- polymorphic? ? ManyEmbeddedPolymorphicProxy : ManyEmbeddedProxy
89
- else
90
- if polymorphic?
91
- ManyPolymorphicProxy
92
- elsif as?
93
- ManyDocumentsAsProxy
94
- elsif in_array?
95
- InArrayProxy
96
- else
97
- ManyDocumentsProxy
98
- end
99
- end
100
- elsif one?
101
- OneProxy
102
- else
103
- polymorphic? ? BelongsToPolymorphicProxy : BelongsToProxy
104
- end
105
- end
106
- end
107
-
108
- private
109
-
110
- # @param [Array<Module, Proc>] extensions a collection of Modules or
111
- # Procs that extend the behaviour of this association.
112
- def modulized_extensions(*extensions)
113
- extensions.flatten.compact.map do |extension|
114
- Proc === extension ? Module.new(&extension) : extension
115
- end
116
- end
117
- end
118
- end
119
- end
@@ -1,26 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class BelongsToPolymorphicProxy < Proxy
4
- def replace(doc)
5
- if doc
6
- doc.save if doc.new?
7
- id, type = doc.id, doc.class.name
8
- end
9
-
10
- owner[reflection.foreign_key] = id
11
- owner[reflection.type_key_name] = type
12
- reset
13
- end
14
-
15
- protected
16
- def find_target
17
- return nil if association_class.nil? || owner[reflection.foreign_key].nil?
18
- association_class.first(:id => owner[reflection.foreign_key])
19
- end
20
-
21
- def association_class
22
- proxy_owner[reflection.type_key_name] ? proxy_owner[reflection.type_key_name].constantize : nil
23
- end
24
- end
25
- end
26
- end
@@ -1,21 +0,0 @@
1
- module MongoMapper
2
- module Associations
3
- class BelongsToProxy < Proxy
4
- def replace(doc)
5
- if doc
6
- doc.save if doc.new?
7
- id = doc.id
8
- end
9
-
10
- owner[reflection.foreign_key] = id
11
- reset
12
- end
13
-
14
- protected
15
- def find_target
16
- return nil if owner[reflection.foreign_key].nil?
17
- klass.first(:id => owner[reflection.foreign_key])
18
- end
19
- end
20
- end
21
- end
@@ -1,19 +0,0 @@
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
@@ -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