mongo_mapper_ign 0.7.4

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 (105) hide show
  1. data/.gitignore +10 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +35 -0
  4. data/Rakefile +37 -0
  5. data/bin/mmconsole +60 -0
  6. data/lib/mongo_mapper.rb +116 -0
  7. data/lib/mongo_mapper/document.rb +313 -0
  8. data/lib/mongo_mapper/embedded_document.rb +70 -0
  9. data/lib/mongo_mapper/plugins.rb +35 -0
  10. data/lib/mongo_mapper/plugins/associations.rb +114 -0
  11. data/lib/mongo_mapper/plugins/associations/base.rb +123 -0
  12. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
  13. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
  14. data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
  15. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +39 -0
  16. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +144 -0
  17. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  18. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +129 -0
  19. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
  20. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
  21. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
  22. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +41 -0
  23. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +69 -0
  24. data/lib/mongo_mapper/plugins/associations/proxy.rb +124 -0
  25. data/lib/mongo_mapper/plugins/callbacks.rb +240 -0
  26. data/lib/mongo_mapper/plugins/clone.rb +13 -0
  27. data/lib/mongo_mapper/plugins/descendants.rb +16 -0
  28. data/lib/mongo_mapper/plugins/dirty.rb +119 -0
  29. data/lib/mongo_mapper/plugins/equality.rb +23 -0
  30. data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
  31. data/lib/mongo_mapper/plugins/inspect.rb +14 -0
  32. data/lib/mongo_mapper/plugins/keys.rb +345 -0
  33. data/lib/mongo_mapper/plugins/logger.rb +17 -0
  34. data/lib/mongo_mapper/plugins/modifiers.rb +107 -0
  35. data/lib/mongo_mapper/plugins/pagination.rb +24 -0
  36. data/lib/mongo_mapper/plugins/pagination/proxy.rb +72 -0
  37. data/lib/mongo_mapper/plugins/persistence.rb +68 -0
  38. data/lib/mongo_mapper/plugins/protected.rb +45 -0
  39. data/lib/mongo_mapper/plugins/rails.rb +57 -0
  40. data/lib/mongo_mapper/plugins/serialization.rb +91 -0
  41. data/lib/mongo_mapper/plugins/serialization/array.rb +56 -0
  42. data/lib/mongo_mapper/plugins/serialization/xml_serializer.rb +240 -0
  43. data/lib/mongo_mapper/plugins/timestamps.rb +21 -0
  44. data/lib/mongo_mapper/plugins/userstamps.rb +14 -0
  45. data/lib/mongo_mapper/plugins/validations.rb +46 -0
  46. data/lib/mongo_mapper/query.rb +143 -0
  47. data/lib/mongo_mapper/support.rb +218 -0
  48. data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
  49. data/lib/mongo_mapper/support/find.rb +77 -0
  50. data/lib/mongo_mapper/version.rb +3 -0
  51. data/mongo_mapper.gemspec +214 -0
  52. data/mongo_mapper_ign.gemspec +217 -0
  53. data/performance/read_write.rb +52 -0
  54. data/specs.watchr +51 -0
  55. data/test/NOTE_ON_TESTING +1 -0
  56. data/test/active_model_lint_test.rb +13 -0
  57. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
  58. data/test/functional/associations/test_belongs_to_proxy.rb +101 -0
  59. data/test/functional/associations/test_in_array_proxy.rb +325 -0
  60. data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
  61. data/test/functional/associations/test_many_documents_proxy.rb +536 -0
  62. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
  63. data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
  64. data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
  65. data/test/functional/associations/test_one_embedded_proxy.rb +68 -0
  66. data/test/functional/associations/test_one_proxy.rb +196 -0
  67. data/test/functional/test_associations.rb +44 -0
  68. data/test/functional/test_binary.rb +27 -0
  69. data/test/functional/test_callbacks.rb +151 -0
  70. data/test/functional/test_dirty.rb +163 -0
  71. data/test/functional/test_document.rb +1219 -0
  72. data/test/functional/test_embedded_document.rb +210 -0
  73. data/test/functional/test_identity_map.rb +507 -0
  74. data/test/functional/test_indexing.rb +44 -0
  75. data/test/functional/test_logger.rb +20 -0
  76. data/test/functional/test_modifiers.rb +394 -0
  77. data/test/functional/test_pagination.rb +93 -0
  78. data/test/functional/test_protected.rb +163 -0
  79. data/test/functional/test_string_id_compatibility.rb +67 -0
  80. data/test/functional/test_timestamps.rb +64 -0
  81. data/test/functional/test_userstamps.rb +28 -0
  82. data/test/functional/test_validations.rb +342 -0
  83. data/test/models.rb +227 -0
  84. data/test/support/custom_matchers.rb +37 -0
  85. data/test/support/timing.rb +16 -0
  86. data/test/test_helper.rb +64 -0
  87. data/test/unit/associations/test_base.rb +212 -0
  88. data/test/unit/associations/test_proxy.rb +105 -0
  89. data/test/unit/serializers/test_json_serializer.rb +202 -0
  90. data/test/unit/test_descendant_appends.rb +71 -0
  91. data/test/unit/test_document.rb +225 -0
  92. data/test/unit/test_dynamic_finder.rb +123 -0
  93. data/test/unit/test_embedded_document.rb +657 -0
  94. data/test/unit/test_keys.rb +185 -0
  95. data/test/unit/test_mongo_mapper.rb +118 -0
  96. data/test/unit/test_pagination.rb +160 -0
  97. data/test/unit/test_plugins.rb +50 -0
  98. data/test/unit/test_query.rb +374 -0
  99. data/test/unit/test_rails.rb +181 -0
  100. data/test/unit/test_rails_compatibility.rb +52 -0
  101. data/test/unit/test_serialization.rb +51 -0
  102. data/test/unit/test_support.rb +382 -0
  103. data/test/unit/test_time_zones.rb +39 -0
  104. data/test/unit/test_validations.rb +544 -0
  105. metadata +327 -0
@@ -0,0 +1,124 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ module Associations
4
+ class Proxy
5
+ alias :proxy_respond_to? :respond_to?
6
+ alias :proxy_extend :extend
7
+
8
+ instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ }
9
+
10
+ attr_reader :owner, :association, :target
11
+
12
+ alias :proxy_owner :owner
13
+ alias :proxy_target :target
14
+ alias :proxy_association :association
15
+
16
+ delegate :klass, :to => :proxy_association
17
+ delegate :options, :to => :proxy_association
18
+ delegate :collection, :to => :klass
19
+
20
+ def initialize(owner, association)
21
+ @owner, @association, @loaded = owner, association, false
22
+ Array(association.options[:extend]).each { |ext| proxy_extend(ext) }
23
+ reset
24
+ end
25
+
26
+ def inspect
27
+ load_target
28
+ target.inspect
29
+ end
30
+
31
+ def loaded?
32
+ @loaded
33
+ end
34
+
35
+ def loaded
36
+ @loaded = true
37
+ end
38
+
39
+ def nil?
40
+ load_target
41
+ target.nil?
42
+ end
43
+
44
+ def blank?
45
+ load_target
46
+ target.blank?
47
+ end
48
+
49
+ def present?
50
+ load_target
51
+ target.present?
52
+ end
53
+
54
+ def reload
55
+ reset
56
+ load_target
57
+ self unless target.nil?
58
+ end
59
+
60
+ def replace(v)
61
+ raise NotImplementedError
62
+ end
63
+
64
+ def reset
65
+ @loaded = false
66
+ @target = nil
67
+ end
68
+
69
+ def respond_to?(*args)
70
+ proxy_respond_to?(*args) || (load_target && target.respond_to?(*args))
71
+ end
72
+
73
+ def send(method, *args)
74
+ if proxy_respond_to?(method)
75
+ super
76
+ else
77
+ load_target
78
+ target.send(method, *args)
79
+ end
80
+ end
81
+
82
+ def ===(other)
83
+ load_target
84
+ other === target
85
+ end
86
+
87
+ protected
88
+ def method_missing(method, *args, &block)
89
+ if load_target
90
+ if block_given?
91
+ target.send(method, *args) { |*block_args| block.call(*block_args) }
92
+ else
93
+ target.send(method, *args)
94
+ end
95
+ end
96
+ end
97
+
98
+ def load_target
99
+ unless loaded?
100
+ if @target.is_a?(Array) && @target.any?
101
+ @target = find_target + @target.find_all { |record| record.new? }
102
+ else
103
+ @target = find_target
104
+ end
105
+ loaded
106
+ end
107
+ @target
108
+ rescue MongoMapper::DocumentNotFound
109
+ reset
110
+ end
111
+
112
+ def find_target
113
+ raise NotImplementedError
114
+ end
115
+
116
+ def flatten_deeper(array)
117
+ array.collect do |element|
118
+ (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element
119
+ end.flatten
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,240 @@
1
+ # Almost all of this callback stuff is pulled directly from ActiveSupport
2
+ # in the interest of support rails 2 and 3 at the same time and is the
3
+ # same copyright as rails.
4
+ module MongoMapper
5
+ module Plugins
6
+ module Callbacks
7
+ def self.configure(model)
8
+ model.class_eval do
9
+ define_callbacks(
10
+ :before_save, :after_save,
11
+ :before_create, :after_create,
12
+ :before_update, :after_update,
13
+ :before_validation, :after_validation,
14
+ :before_validation_on_create, :after_validation_on_create,
15
+ :before_validation_on_update, :after_validation_on_update,
16
+ :before_destroy, :after_destroy,
17
+ :validate_on_create, :validate_on_update,
18
+ :validate
19
+ )
20
+ end
21
+ end
22
+
23
+ module ClassMethods
24
+ def define_callbacks(*callbacks)
25
+ callbacks.each do |callback|
26
+ class_eval <<-"end_eval"
27
+ def self.#{callback}(*methods, &block)
28
+ callbacks = CallbackChain.build(:#{callback}, *methods, &block)
29
+ @#{callback}_callbacks ||= CallbackChain.new
30
+ @#{callback}_callbacks.concat callbacks
31
+ end
32
+
33
+ def self.#{callback}_callback_chain
34
+ @#{callback}_callbacks ||= CallbackChain.new
35
+
36
+ if superclass.respond_to?(:#{callback}_callback_chain)
37
+ CallbackChain.new(
38
+ superclass.#{callback}_callback_chain +
39
+ @#{callback}_callbacks
40
+ )
41
+ else
42
+ @#{callback}_callbacks
43
+ end
44
+ end
45
+ end_eval
46
+ end
47
+ end
48
+ end
49
+
50
+ module InstanceMethods
51
+ def valid?
52
+ action = new? ? 'create' : 'update'
53
+ run_callbacks(:before_validation)
54
+ run_callbacks("before_validation_on_#{action}".to_sym)
55
+ result = super
56
+ run_callbacks("after_validation_on_#{action}".to_sym)
57
+ run_callbacks(:after_validation)
58
+ result
59
+ end
60
+
61
+ # Overriding validatable's valid_for_group? to integrate validation callbacks
62
+ def valid_for_group?(group) #:nodoc:
63
+ errors.clear
64
+ run_before_validations
65
+ run_callbacks(:validate)
66
+ new? ? run_callbacks(:validate_on_create) : run_callbacks(:validate_on_update)
67
+ self.class.validate_children(self, group)
68
+ self.validate_group(group)
69
+ errors.empty?
70
+ end
71
+
72
+ def destroy
73
+ run_callbacks(:before_destroy)
74
+ result = super
75
+ run_callbacks(:after_destroy)
76
+ result
77
+ end
78
+
79
+ def run_callbacks(kind, options = {}, &block)
80
+ callback_chain_method = "#{kind}_callback_chain"
81
+ return unless self.class.respond_to?(callback_chain_method)
82
+ self.class.send(callback_chain_method).run(self, options, &block)
83
+ self.embedded_associations.each do |association|
84
+ if association.one?
85
+ self.send(association.name).run_callbacks(kind, options, &block)
86
+ else
87
+ self.send(association.name).each do |document|
88
+ document.run_callbacks(kind, options, &block)
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ private
95
+ def create_or_update(*args)
96
+ run_callbacks(:before_save)
97
+ if result = super
98
+ run_callbacks(:after_save)
99
+ end
100
+ result
101
+ end
102
+
103
+ def create(*args)
104
+ run_callbacks(:before_create)
105
+ result = super
106
+ run_callbacks(:after_create)
107
+ result
108
+ end
109
+
110
+ def update(*args)
111
+ run_callbacks(:before_update)
112
+ result = super
113
+ run_callbacks(:after_update)
114
+ result
115
+ end
116
+ end
117
+
118
+ class CallbackChain < Array
119
+ def self.build(kind, *methods, &block)
120
+ methods, options = extract_options(*methods, &block)
121
+ methods.map! { |method| Callback.new(kind, method, options) }
122
+ new(methods)
123
+ end
124
+
125
+ def run(object, options = {}, &terminator)
126
+ enumerator = options[:enumerator] || :each
127
+
128
+ unless block_given?
129
+ send(enumerator) { |callback| callback.call(object) }
130
+ else
131
+ send(enumerator) do |callback|
132
+ result = callback.call(object)
133
+ break result if terminator.call(result, object)
134
+ end
135
+ end
136
+ end
137
+
138
+ # TODO: Decompose into more Array like behavior
139
+ def replace_or_append!(chain)
140
+ if index = index(chain)
141
+ self[index] = chain
142
+ else
143
+ self << chain
144
+ end
145
+ self
146
+ end
147
+
148
+ def find(callback, &block)
149
+ select { |c| c == callback && (!block_given? || yield(c)) }.first
150
+ end
151
+
152
+ def delete(callback)
153
+ super(callback.is_a?(Callback) ? callback : find(callback))
154
+ end
155
+
156
+ private
157
+ def self.extract_options(*methods, &block)
158
+ methods.flatten!
159
+ options = methods.extract_options!
160
+ methods << block if block_given?
161
+ return methods, options
162
+ end
163
+
164
+ def extract_options(*methods, &block)
165
+ self.class.extract_options(*methods, &block)
166
+ end
167
+ end
168
+
169
+ class Callback
170
+ attr_reader :kind, :method, :identifier, :options
171
+
172
+ def initialize(kind, method, options = {})
173
+ @kind = kind
174
+ @method = method
175
+ @identifier = options[:identifier]
176
+ @options = options
177
+ end
178
+
179
+ def ==(other)
180
+ case other
181
+ when Callback
182
+ (self.identifier && self.identifier == other.identifier) || self.method == other.method
183
+ else
184
+ (self.identifier && self.identifier == other) || self.method == other
185
+ end
186
+ end
187
+
188
+ def eql?(other)
189
+ self == other
190
+ end
191
+
192
+ def dup
193
+ self.class.new(@kind, @method, @options.dup)
194
+ end
195
+
196
+ def hash
197
+ if @identifier
198
+ @identifier.hash
199
+ else
200
+ @method.hash
201
+ end
202
+ end
203
+
204
+ def call(*args, &block)
205
+ evaluate_method(method, *args, &block) if should_run_callback?(*args)
206
+ rescue LocalJumpError
207
+ raise ArgumentError,
208
+ "Cannot yield from a Proc type filter. The Proc must take two " +
209
+ "arguments and execute #call on the second argument."
210
+ end
211
+
212
+ private
213
+ def evaluate_method(method, *args, &block)
214
+ case method
215
+ when Symbol
216
+ object = args.shift
217
+ object.send(method, *args, &block)
218
+ when String
219
+ eval(method, args.first.instance_eval { binding })
220
+ when Proc, Method
221
+ method.call(*args, &block)
222
+ else
223
+ if method.respond_to?(kind)
224
+ method.send(kind, *args, &block)
225
+ else
226
+ raise ArgumentError,
227
+ "Callbacks must be a symbol denoting the method to call, a string to be evaluated, " +
228
+ "a block to be invoked, or an object responding to the callback method."
229
+ end
230
+ end
231
+ end
232
+
233
+ def should_run_callback?(*args)
234
+ [options[:if]].flatten.compact.all? { |a| evaluate_method(a, *args) } &&
235
+ ![options[:unless]].flatten.compact.any? { |a| evaluate_method(a, *args) }
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,13 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ module Clone
4
+ module InstanceMethods
5
+ def clone
6
+ clone_attributes = self.attributes
7
+ clone_attributes.delete("_id")
8
+ self.class.new(clone_attributes)
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ module Descendants
4
+ module ClassMethods
5
+ def inherited(descendant)
6
+ descendants << descendant
7
+ super
8
+ end
9
+
10
+ def descendants
11
+ @descendants ||= []
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,119 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ module Dirty
4
+ module InstanceMethods
5
+ def method_missing(method, *args, &block)
6
+ if method.to_s =~ /(_changed\?|_change|_will_change!|_was)$/
7
+ method_suffix = $1
8
+ key = method.to_s.gsub(method_suffix, '')
9
+
10
+ if key_names.include?(key)
11
+ case method_suffix
12
+ when '_changed?'
13
+ key_changed?(key)
14
+ when '_change'
15
+ key_change(key)
16
+ when '_will_change!'
17
+ key_will_change!(key)
18
+ when '_was'
19
+ key_was(key)
20
+ end
21
+ else
22
+ super
23
+ end
24
+ else
25
+ super
26
+ end
27
+ end
28
+
29
+ def changed?
30
+ !changed_keys.empty?
31
+ end
32
+
33
+ def changed
34
+ changed_keys.keys
35
+ end
36
+
37
+ def changes
38
+ changed.inject({}) { |h, key| h[key] = key_change(key); h }
39
+ end
40
+
41
+ def initialize(*args)
42
+ super
43
+ changed_keys.clear if args.first.blank? || !new?
44
+ end
45
+
46
+ def save(*args)
47
+ if status = super
48
+ changed_keys.clear
49
+ end
50
+ status
51
+ end
52
+
53
+ def save!(*args)
54
+ status = super
55
+ changed_keys.clear
56
+ status
57
+ end
58
+
59
+ def reload(*args)
60
+ document = super
61
+ changed_keys.clear
62
+ document
63
+ end
64
+
65
+ private
66
+ def clone_key_value(key)
67
+ value = read_key(key)
68
+ value.duplicable? ? value.clone : value
69
+ rescue TypeError, NoMethodError
70
+ value
71
+ end
72
+
73
+ def changed_keys
74
+ @changed_keys ||= {}
75
+ end
76
+
77
+ def key_changed?(key)
78
+ changed_keys.include?(key)
79
+ end
80
+
81
+ def key_change(key)
82
+ [changed_keys[key], __send__(key)] if key_changed?(key)
83
+ end
84
+
85
+ def key_was(key)
86
+ key_changed?(key) ? changed_keys[key] : __send__(key)
87
+ end
88
+
89
+ def key_will_change!(key)
90
+ changed_keys[key] = clone_key_value(key)
91
+ end
92
+
93
+ def write_key(key, value)
94
+ key = key.to_s
95
+
96
+ if changed_keys.include?(key)
97
+ old = changed_keys[key]
98
+ changed_keys.delete(key) unless value_changed?(key, old, value)
99
+ else
100
+ old = clone_key_value(key)
101
+ changed_keys[key] = old if value_changed?(key, old, value)
102
+ end
103
+
104
+ super(key, value)
105
+ end
106
+
107
+ def value_changed?(key_name, old, value)
108
+ key = keys[key_name]
109
+
110
+ if key.number? && value.blank?
111
+ value = nil
112
+ end
113
+
114
+ old != value
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end