mongo_mapper 0.13.0 → 0.15.1

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 (137) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +61 -0
  4. data/examples/keys.rb +1 -1
  5. data/examples/modifiers/set.rb +1 -1
  6. data/examples/querying.rb +1 -1
  7. data/examples/safe.rb +2 -2
  8. data/examples/scopes.rb +1 -1
  9. data/lib/mongo_mapper.rb +7 -0
  10. data/lib/mongo_mapper/connection.rb +16 -37
  11. data/lib/mongo_mapper/document.rb +4 -0
  12. data/lib/mongo_mapper/extensions/array.rb +14 -6
  13. data/lib/mongo_mapper/extensions/hash.rb +15 -3
  14. data/lib/mongo_mapper/extensions/object.rb +4 -0
  15. data/lib/mongo_mapper/extensions/object_id.rb +5 -1
  16. data/lib/mongo_mapper/extensions/string.rb +13 -5
  17. data/lib/mongo_mapper/extensions/symbol.rb +18 -0
  18. data/lib/mongo_mapper/plugins/accessible.rb +15 -5
  19. data/lib/mongo_mapper/plugins/associations.rb +7 -6
  20. data/lib/mongo_mapper/plugins/associations/base.rb +27 -14
  21. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +10 -1
  22. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +9 -8
  23. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +12 -11
  24. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +4 -4
  25. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +60 -29
  26. data/lib/mongo_mapper/plugins/associations/in_foreign_array_proxy.rb +136 -0
  27. data/lib/mongo_mapper/plugins/associations/many_association.rb +4 -2
  28. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +18 -16
  29. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +55 -48
  30. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +14 -13
  31. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +7 -6
  32. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +7 -5
  33. data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +14 -11
  34. data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +14 -13
  35. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +9 -9
  36. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +27 -26
  37. data/lib/mongo_mapper/plugins/associations/proxy.rb +36 -29
  38. data/lib/mongo_mapper/plugins/associations/single_association.rb +5 -4
  39. data/lib/mongo_mapper/plugins/callbacks.rb +13 -0
  40. data/lib/mongo_mapper/plugins/counter_cache.rb +97 -0
  41. data/lib/mongo_mapper/plugins/dirty.rb +29 -37
  42. data/lib/mongo_mapper/plugins/document.rb +1 -1
  43. data/lib/mongo_mapper/plugins/dynamic_querying.rb +10 -9
  44. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +18 -17
  45. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +2 -1
  46. data/lib/mongo_mapper/plugins/embedded_document.rb +1 -1
  47. data/lib/mongo_mapper/plugins/identity_map.rb +4 -2
  48. data/lib/mongo_mapper/plugins/indexes.rb +14 -7
  49. data/lib/mongo_mapper/plugins/keys.rb +170 -151
  50. data/lib/mongo_mapper/plugins/keys/key.rb +27 -16
  51. data/lib/mongo_mapper/plugins/keys/static.rb +45 -0
  52. data/lib/mongo_mapper/plugins/modifiers.rb +64 -38
  53. data/lib/mongo_mapper/plugins/partial_updates.rb +86 -0
  54. data/lib/mongo_mapper/plugins/persistence.rb +13 -8
  55. data/lib/mongo_mapper/plugins/protected.rb +6 -5
  56. data/lib/mongo_mapper/plugins/querying.rb +85 -42
  57. data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +20 -15
  58. data/lib/mongo_mapper/plugins/rails.rb +1 -0
  59. data/lib/mongo_mapper/plugins/safe.rb +10 -4
  60. data/lib/mongo_mapper/plugins/sci.rb +0 -0
  61. data/lib/mongo_mapper/plugins/scopes.rb +78 -7
  62. data/lib/mongo_mapper/plugins/stats.rb +17 -0
  63. data/lib/mongo_mapper/plugins/strong_parameters.rb +26 -0
  64. data/lib/mongo_mapper/plugins/timestamps.rb +1 -0
  65. data/lib/mongo_mapper/plugins/validations.rb +1 -1
  66. data/lib/mongo_mapper/railtie.rb +4 -3
  67. data/lib/mongo_mapper/utils.rb +2 -2
  68. data/lib/mongo_mapper/version.rb +1 -1
  69. data/lib/rails/generators/mongo_mapper/config/config_generator.rb +12 -13
  70. data/lib/rails/generators/mongo_mapper/model/model_generator.rb +9 -9
  71. data/spec/examples.txt +1717 -0
  72. data/spec/functional/accessible_spec.rb +19 -13
  73. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +13 -13
  74. data/spec/functional/associations/belongs_to_proxy_spec.rb +36 -20
  75. data/spec/functional/associations/in_array_proxy_spec.rb +145 -10
  76. data/spec/functional/associations/in_foreign_array_proxy_spec.rb +321 -0
  77. data/spec/functional/associations/many_documents_as_proxy_spec.rb +6 -6
  78. data/spec/functional/associations/many_documents_proxy_spec.rb +85 -14
  79. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +13 -13
  80. data/spec/functional/associations/many_embedded_proxy_spec.rb +1 -1
  81. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +4 -4
  82. data/spec/functional/associations/one_as_proxy_spec.rb +10 -10
  83. data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +9 -9
  84. data/spec/functional/associations/one_embedded_proxy_spec.rb +3 -3
  85. data/spec/functional/associations/one_proxy_spec.rb +10 -10
  86. data/spec/functional/associations_spec.rb +3 -3
  87. data/spec/functional/binary_spec.rb +2 -2
  88. data/spec/functional/caching_spec.rb +8 -15
  89. data/spec/functional/callbacks_spec.rb +89 -2
  90. data/spec/functional/counter_cache_spec.rb +235 -0
  91. data/spec/functional/dirty_spec.rb +63 -46
  92. data/spec/functional/document_spec.rb +30 -5
  93. data/spec/functional/dumpable_spec.rb +1 -1
  94. data/spec/functional/embedded_document_spec.rb +17 -17
  95. data/spec/functional/identity_map_spec.rb +29 -16
  96. data/spec/functional/indexes_spec.rb +19 -18
  97. data/spec/functional/keys_spec.rb +86 -28
  98. data/spec/functional/logger_spec.rb +3 -3
  99. data/spec/functional/modifiers_spec.rb +81 -19
  100. data/spec/functional/partial_updates_spec.rb +577 -0
  101. data/spec/functional/protected_spec.rb +14 -14
  102. data/spec/functional/querying_spec.rb +77 -28
  103. data/spec/functional/safe_spec.rb +23 -27
  104. data/spec/functional/sci_spec.rb +9 -9
  105. data/spec/functional/scopes_spec.rb +235 -2
  106. data/spec/functional/static_keys_spec.rb +153 -0
  107. data/spec/functional/stats_spec.rb +86 -0
  108. data/spec/functional/strong_parameters_spec.rb +49 -0
  109. data/spec/functional/touch_spec.rb +1 -1
  110. data/spec/functional/validations_spec.rb +51 -57
  111. data/spec/quality_spec.rb +51 -0
  112. data/spec/spec_helper.rb +37 -9
  113. data/spec/support/matchers.rb +5 -14
  114. data/spec/unit/associations/base_spec.rb +12 -12
  115. data/spec/unit/associations/belongs_to_association_spec.rb +2 -2
  116. data/spec/unit/associations/many_association_spec.rb +2 -2
  117. data/spec/unit/associations/one_association_spec.rb +2 -2
  118. data/spec/unit/associations/proxy_spec.rb +19 -20
  119. data/spec/unit/clone_spec.rb +1 -1
  120. data/spec/unit/document_spec.rb +8 -8
  121. data/spec/unit/dynamic_finder_spec.rb +8 -8
  122. data/spec/unit/embedded_document_spec.rb +18 -19
  123. data/spec/unit/extensions_spec.rb +41 -17
  124. data/spec/unit/identity_map_middleware_spec.rb +65 -96
  125. data/spec/unit/key_spec.rb +28 -26
  126. data/spec/unit/keys_spec.rb +20 -11
  127. data/spec/unit/model_generator_spec.rb +0 -0
  128. data/spec/unit/mongo_mapper_spec.rb +38 -85
  129. data/spec/unit/rails_spec.rb +5 -0
  130. data/spec/unit/serialization_spec.rb +1 -1
  131. data/spec/unit/time_zones_spec.rb +2 -2
  132. data/spec/unit/validations_spec.rb +46 -33
  133. metadata +66 -37
  134. data/README.rdoc +0 -59
  135. data/lib/mongo_mapper/connections/10gen.rb +0 -0
  136. data/lib/mongo_mapper/connections/moped.rb +0 -0
  137. data/lib/mongo_mapper/extensions/ordered_hash.rb +0 -23
@@ -17,6 +17,8 @@ module MongoMapper
17
17
  ManyPolymorphicProxy
18
18
  elsif as?
19
19
  ManyDocumentsAsProxy
20
+ elsif in_foreign_array?
21
+ InForeignArrayProxy
20
22
  elsif in_array?
21
23
  InArrayProxy
22
24
  else
@@ -26,7 +28,7 @@ module MongoMapper
26
28
  end
27
29
 
28
30
  def setup(model)
29
- model.associations_module.module_eval <<-end_eval
31
+ model.associations_module.module_eval(<<-end_eval, __FILE__, __LINE__ + 1)
30
32
  def #{name}
31
33
  get_proxy(associations[#{name.inspect}])
32
34
  end
@@ -60,4 +62,4 @@ module MongoMapper
60
62
  end
61
63
  end
62
64
  end
63
- end
65
+ end
@@ -3,25 +3,27 @@ module MongoMapper
3
3
  module Plugins
4
4
  module Associations
5
5
  class ManyDocumentsAsProxy < ManyDocumentsProxy
6
- protected
7
- def criteria
8
- {type_key_name => proxy_owner.class.name, id_key_name => proxy_owner.id}
9
- end
6
+ protected
10
7
 
11
- def apply_scope(doc)
12
- ensure_owner_saved
13
- criteria.each { |key, value| doc[key] = value }
14
- doc
15
- end
8
+ def criteria
9
+ {type_key_name => proxy_owner.class.name, id_key_name => proxy_owner.id}
10
+ end
16
11
 
17
- private
18
- def type_key_name
19
- "#{options[:as]}_type"
20
- end
12
+ def apply_scope(doc)
13
+ ensure_owner_saved
14
+ criteria.each { |key, value| doc[key] = value }
15
+ doc
16
+ end
21
17
 
22
- def id_key_name
23
- "#{options[:as]}_id"
24
- end
18
+ private
19
+
20
+ def type_key_name
21
+ "#{options[:as]}_type"
22
+ end
23
+
24
+ def id_key_name
25
+ "#{options[:as]}_id"
26
+ end
25
27
  end
26
28
  end
27
29
  end
@@ -80,63 +80,70 @@ module MongoMapper
80
80
  load_target.each(&block)
81
81
  end
82
82
 
83
- protected
84
- def query(options={})
85
- klass.
86
- query(association.query_options).
87
- amend(options).amend(criteria)
88
- end
83
+ protected
89
84
 
90
- def method_missing(method, *args, &block)
91
- if klass.respond_to?(method)
92
- result = klass.send(method, *args, &block)
93
- case result
94
- when Plucky::Query
95
- query.merge result
96
-
97
- # If we got a single record of this classas a result, return it
98
- when klass
99
- result
100
-
101
- # If we got an array of this class as a result, return it
102
- when Array
103
- if result[0].is_a? klass
104
- result
105
- else
106
- super
107
- end
108
- else
109
- super
110
- end
111
- else
112
- super
113
- end
114
- end
85
+ def query(options={})
86
+ klass.
87
+ query(association.query_options).
88
+ amend(options).
89
+ amend(criteria)
90
+ end
115
91
 
116
- def criteria
117
- {self.foreign_key => proxy_owner.id}
118
- end
92
+ def criteria
93
+ {self.foreign_key => proxy_owner.id}
94
+ end
119
95
 
120
- def find_target
121
- all
122
- end
96
+ def find_target
97
+ all
98
+ end
123
99
 
124
- def ensure_owner_saved
125
- proxy_owner.save unless proxy_owner.persisted?
126
- end
100
+ def ensure_owner_saved
101
+ proxy_owner.save unless proxy_owner.persisted?
102
+ end
127
103
 
128
- def prepare(doc)
129
- klass === doc ? apply_scope(doc) : build(doc)
130
- end
104
+ def prepare(doc)
105
+ klass === doc ? apply_scope(doc) : build(doc)
106
+ end
131
107
 
132
- def apply_scope(doc)
133
- criteria.each { |key, value| doc[key] = value }
134
- doc
108
+ def apply_scope(doc)
109
+ criteria.each { |key, value| doc[key] = value }
110
+ doc
111
+ end
112
+
113
+ def foreign_key
114
+ options[:foreign_key] || proxy_owner.class.name.foreign_key
115
+ end
116
+
117
+ private
118
+
119
+ def method_missing(method, *args, &block)
120
+ return super unless klass.respond_to?(method)
121
+
122
+ result = nil
123
+
124
+ query.with_scope(query.criteria_hash) do
125
+ result = klass.send(method, *args, &block)
135
126
  end
136
127
 
137
- def foreign_key
138
- options[:foreign_key] || proxy_owner.class.name.foreign_key
128
+ case result
129
+ when Plucky::Query
130
+ query.merge result
131
+
132
+ # If we got a single record of this class as a result, return it
133
+ when klass
134
+ result
135
+
136
+ # If we got an array of this class as a result, return it
137
+ when Array
138
+ if result[0].is_a? klass
139
+ result
140
+ else
141
+ super
142
+ end
143
+ else
144
+ super
139
145
  end
146
+ end
140
147
  end
141
148
  end
142
149
  end
@@ -10,22 +10,23 @@ module MongoMapper
10
10
  reset
11
11
  end
12
12
 
13
- protected
14
- def find_target
15
- (@_values || []).map do |hash|
16
- child = polymorphic_class(hash).load(hash, true)
17
- assign_references(child)
18
- child
19
- end
13
+ protected
14
+
15
+ def find_target
16
+ (@_values || []).map do |hash|
17
+ child = polymorphic_class(hash).load(hash, true)
18
+ assign_references(child)
19
+ child
20
20
  end
21
+ end
21
22
 
22
- def polymorphic_class(doc)
23
- if class_name = doc[association.type_key_name]
24
- class_name.constantize
25
- else
26
- klass
27
- end
23
+ def polymorphic_class(doc)
24
+ if class_name = doc[association.type_key_name]
25
+ class_name.constantize
26
+ else
27
+ klass
28
28
  end
29
+ end
29
30
  end
30
31
  end
31
32
  end
@@ -10,14 +10,15 @@ module MongoMapper
10
10
  reset
11
11
  end
12
12
 
13
- private
14
- def find_target
15
- (@_values ||= []).map do |attrs|
16
- klass.load(attrs, true).tap do |child|
17
- assign_references(child)
18
- end
13
+ private
14
+
15
+ def find_target
16
+ (@_values ||= []).map do |attrs|
17
+ klass.load(attrs, true).tap do |child|
18
+ assign_references(child)
19
19
  end
20
20
  end
21
+ end
21
22
  end
22
23
  end
23
24
  end
@@ -3,11 +3,13 @@ module MongoMapper
3
3
  module Plugins
4
4
  module Associations
5
5
  class ManyPolymorphicProxy < ManyDocumentsProxy
6
- private
7
- def apply_scope(doc)
8
- doc[association.type_key_name] = doc.class.name
9
- super
10
- end
6
+
7
+ private
8
+
9
+ def apply_scope(doc)
10
+ doc[association.type_key_name] = doc.class.name
11
+ super
12
+ end
11
13
  end
12
14
  end
13
15
  end
@@ -3,19 +3,22 @@ module MongoMapper
3
3
  module Plugins
4
4
  module Associations
5
5
  class OneAsProxy < OneProxy
6
- protected
7
- def criteria
8
- {type_key_name => proxy_owner.class.name, id_key_name => proxy_owner.id}
9
- end
10
6
 
11
- private
12
- def type_key_name
13
- "#{options[:as]}_type"
14
- end
7
+ protected
15
8
 
16
- def id_key_name
17
- "#{options[:as]}_id"
18
- end
9
+ def criteria
10
+ {type_key_name => proxy_owner.class.name, id_key_name => proxy_owner.id}
11
+ end
12
+
13
+ private
14
+
15
+ def type_key_name
16
+ "#{options[:as]}_type"
17
+ end
18
+
19
+ def id_key_name
20
+ "#{options[:as]}_id"
21
+ end
19
22
  end
20
23
  end
21
24
  end
@@ -8,22 +8,23 @@ module MongoMapper
8
8
  reset
9
9
  end
10
10
 
11
- protected
12
- def find_target
13
- if @value
14
- child = polymorphic_class(@value).load(@value, true)
15
- assign_references(child)
16
- child
17
- end
11
+ protected
12
+
13
+ def find_target
14
+ if @value
15
+ child = polymorphic_class(@value).load(@value, true)
16
+ assign_references(child)
17
+ child
18
18
  end
19
+ end
19
20
 
20
- def polymorphic_class(doc)
21
- if class_name = doc[association.type_key_name]
22
- class_name.constantize
23
- else
24
- klass
25
- end
21
+ def polymorphic_class(doc)
22
+ if class_name = doc[association.type_key_name]
23
+ class_name.constantize
24
+ else
25
+ klass
26
26
  end
27
+ end
27
28
  end
28
29
  end
29
30
  end
@@ -25,19 +25,19 @@ module MongoMapper
25
25
  @target.persist(options) if @target
26
26
  end
27
27
 
28
- protected
28
+ protected
29
29
 
30
- def find_target
31
- if @value
32
- klass.load(@value, true).tap do |child|
33
- assign_references(child)
34
- end
30
+ def find_target
31
+ if @value
32
+ klass.load(@value, true).tap do |child|
33
+ assign_references(child)
35
34
  end
36
35
  end
36
+ end
37
37
 
38
- def assign_references(doc)
39
- doc._parent_document = proxy_owner if doc
40
- end
38
+ def assign_references(doc)
39
+ doc._parent_document = proxy_owner if doc
40
+ end
41
41
  end
42
42
  end
43
43
  end
@@ -57,38 +57,39 @@ module MongoMapper
57
57
  reset
58
58
  end
59
59
 
60
- protected
61
- def find_target
62
- target_class.first(association.query_options.merge(criteria))
63
- end
60
+ protected
64
61
 
65
- def instantiate_target(instantiator, attrs={}, &block)
66
- @target = target_class.send(instantiator, attrs.update(criteria), &block)
67
- loaded
68
- @target
69
- end
62
+ def find_target
63
+ target_class.first(association.query_options.merge(criteria))
64
+ end
70
65
 
71
- def target_class
72
- @target_class ||= options[:class] || (options[:class_name] || association.name.to_s.camelize).constantize
73
- end
66
+ def instantiate_target(instantiator, attrs={}, &block)
67
+ @target = target_class.send(instantiator, attrs.update(criteria), &block)
68
+ loaded
69
+ @target
70
+ end
74
71
 
75
- def foreign_key
76
- options[:foreign_key] || proxy_owner.class.name.foreign_key
77
- end
72
+ def target_class
73
+ @target_class ||= options[:class] || (options[:class_name] || association.name.to_s.camelize).constantize
74
+ end
78
75
 
79
- def criteria
80
- {self.foreign_key => proxy_owner.id}
81
- end
76
+ def foreign_key
77
+ options[:foreign_key] || proxy_owner.class.name.foreign_key
78
+ end
82
79
 
83
- def nullify_scope(doc)
84
- criteria.each { |key, value| doc[key] = nil }
85
- doc
86
- end
80
+ def criteria
81
+ {self.foreign_key => proxy_owner.id}
82
+ end
87
83
 
88
- def apply_scope(doc)
89
- criteria.each { |key, value| doc[key] = value }
90
- doc
91
- end
84
+ def nullify_scope(doc)
85
+ criteria.each { |key, value| doc[key] = nil }
86
+ doc
87
+ end
88
+
89
+ def apply_scope(doc)
90
+ criteria.each { |key, value| doc[key] = value }
91
+ doc
92
+ end
92
93
  end
93
94
  end
94
95
  end
@@ -13,7 +13,6 @@ module MongoMapper
13
13
 
14
14
  attr_reader :proxy_owner, :association, :target
15
15
 
16
- alias :proxy_target :target
17
16
  alias :proxy_association :association
18
17
 
19
18
  def_delegators :proxy_association, :klass, :options
@@ -91,47 +90,55 @@ module MongoMapper
91
90
  proxy_respond_to?(*args) || (load_target && target.respond_to?(*args))
92
91
  end
93
92
 
94
- def send(method, *args)
93
+ def send(method, *args, &block)
95
94
  if proxy_respond_to?(method, true)
96
95
  super
97
96
  else
98
97
  load_target
99
- target.send(method, *args)
98
+ target.send(method, *args, &block)
100
99
  end
101
100
  end
102
101
 
103
- protected
104
- def method_missing(method, *args, &block)
105
- if load_target
106
- target.send(method, *args, &block)
107
- end
108
- end
102
+ def read
103
+ load_target
104
+ @target
105
+ end
109
106
 
110
- def load_target
111
- unless loaded?
112
- if @target.is_a?(Array) && @target.any?
113
- @target = find_target + @target.find_all { |record| !record.persisted? }
114
- else
115
- @target = find_target
116
- end
117
- loaded
107
+ protected
108
+
109
+ def load_target
110
+ unless loaded?
111
+ if @target.is_a?(Array) && @target.any?
112
+ @target = find_target + @target.find_all { |record| !record.persisted? }
113
+ else
114
+ @target = find_target
118
115
  end
119
- @target
120
- rescue MongoMapper::DocumentNotFound
121
- reset
116
+ loaded
122
117
  end
118
+ @target
119
+ rescue MongoMapper::DocumentNotFound
120
+ reset
121
+ end
123
122
 
124
- # :nocov:
125
- def find_target
126
- raise NotImplementedError
127
- end
128
- # :nocov:
123
+ # :nocov:
124
+ def find_target
125
+ raise NotImplementedError
126
+ end
127
+ # :nocov:
129
128
 
130
- def flatten_deeper(array)
131
- array.collect do |element|
132
- (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element
133
- end.flatten
129
+ def flatten_deeper(array)
130
+ array.collect do |element|
131
+ (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element
132
+ end.flatten
133
+ end
134
+
135
+ private
136
+
137
+ def method_missing(method, *args, &block)
138
+ if load_target
139
+ target.send(method, *args, &block)
134
140
  end
141
+ end
135
142
  end
136
143
  end
137
144
  end