mongo_mapper 0.7.6 → 0.8.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 (134) hide show
  1. data/README.rdoc +4 -8
  2. data/bin/mmconsole +1 -1
  3. data/examples/keys.rb +37 -0
  4. data/examples/plugins.rb +41 -0
  5. data/examples/querying.rb +35 -0
  6. data/examples/scopes.rb +52 -0
  7. data/lib/mongo_mapper.rb +77 -97
  8. data/lib/mongo_mapper/connection.rb +83 -0
  9. data/lib/mongo_mapper/document.rb +10 -252
  10. data/lib/mongo_mapper/embedded_document.rb +7 -46
  11. data/lib/mongo_mapper/exceptions.rb +30 -0
  12. data/lib/mongo_mapper/extensions/array.rb +19 -0
  13. data/lib/mongo_mapper/extensions/binary.rb +22 -0
  14. data/lib/mongo_mapper/extensions/boolean.rb +44 -0
  15. data/lib/mongo_mapper/extensions/date.rb +25 -0
  16. data/lib/mongo_mapper/extensions/float.rb +14 -0
  17. data/lib/mongo_mapper/extensions/hash.rb +14 -0
  18. data/lib/mongo_mapper/extensions/integer.rb +19 -0
  19. data/lib/mongo_mapper/extensions/kernel.rb +9 -0
  20. data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
  21. data/lib/mongo_mapper/extensions/object.rb +27 -0
  22. data/lib/mongo_mapper/extensions/object_id.rb +30 -0
  23. data/lib/mongo_mapper/extensions/set.rb +20 -0
  24. data/lib/mongo_mapper/extensions/string.rb +18 -0
  25. data/lib/mongo_mapper/extensions/time.rb +29 -0
  26. data/lib/mongo_mapper/plugins.rb +1 -21
  27. data/lib/mongo_mapper/plugins/accessible.rb +44 -0
  28. data/lib/mongo_mapper/plugins/associations.rb +7 -24
  29. data/lib/mongo_mapper/plugins/associations/base.rb +1 -0
  30. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +5 -6
  31. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +5 -6
  32. data/lib/mongo_mapper/plugins/associations/collection.rb +1 -0
  33. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +2 -1
  34. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +22 -39
  35. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +4 -4
  36. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +22 -23
  37. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +1 -0
  38. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +1 -0
  39. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +1 -0
  40. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +2 -3
  41. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +6 -7
  42. data/lib/mongo_mapper/plugins/associations/proxy.rb +8 -6
  43. data/lib/mongo_mapper/plugins/caching.rb +21 -0
  44. data/lib/mongo_mapper/plugins/callbacks.rb +4 -3
  45. data/lib/mongo_mapper/plugins/clone.rb +10 -4
  46. data/lib/mongo_mapper/plugins/descendants.rb +1 -0
  47. data/lib/mongo_mapper/plugins/dirty.rb +1 -0
  48. data/lib/mongo_mapper/plugins/document.rb +41 -0
  49. data/lib/mongo_mapper/plugins/dynamic_querying.rb +41 -0
  50. data/lib/mongo_mapper/{support/find.rb → plugins/dynamic_querying/dynamic_finder.rb} +3 -36
  51. data/lib/mongo_mapper/plugins/embedded_document.rb +49 -0
  52. data/lib/mongo_mapper/plugins/equality.rb +3 -9
  53. data/lib/mongo_mapper/plugins/identity_map.rb +8 -10
  54. data/lib/mongo_mapper/plugins/indexes.rb +12 -0
  55. data/lib/mongo_mapper/plugins/inspect.rb +1 -0
  56. data/lib/mongo_mapper/plugins/keys.rb +15 -27
  57. data/lib/mongo_mapper/plugins/keys/key.rb +14 -3
  58. data/lib/mongo_mapper/plugins/logger.rb +1 -0
  59. data/lib/mongo_mapper/plugins/modifiers.rb +3 -2
  60. data/lib/mongo_mapper/plugins/pagination.rb +5 -15
  61. data/lib/mongo_mapper/plugins/persistence.rb +12 -11
  62. data/lib/mongo_mapper/plugins/protected.rb +8 -0
  63. data/lib/mongo_mapper/plugins/querying.rb +236 -0
  64. data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
  65. data/lib/mongo_mapper/plugins/rails.rb +1 -0
  66. data/lib/mongo_mapper/plugins/safe.rb +28 -0
  67. data/lib/mongo_mapper/plugins/sci.rb +32 -0
  68. data/lib/mongo_mapper/plugins/scopes.rb +21 -0
  69. data/lib/mongo_mapper/plugins/serialization.rb +1 -0
  70. data/lib/mongo_mapper/plugins/timestamps.rb +1 -0
  71. data/lib/mongo_mapper/plugins/userstamps.rb +1 -0
  72. data/lib/mongo_mapper/plugins/validations.rb +5 -1
  73. data/lib/mongo_mapper/support/descendant_appends.rb +5 -6
  74. data/lib/mongo_mapper/version.rb +2 -1
  75. data/test/NOTE_ON_TESTING +1 -0
  76. data/test/active_model_lint_test.rb +13 -0
  77. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
  78. data/test/functional/associations/test_belongs_to_proxy.rb +93 -0
  79. data/test/functional/associations/test_in_array_proxy.rb +319 -0
  80. data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
  81. data/test/functional/associations/test_many_documents_proxy.rb +536 -0
  82. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
  83. data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
  84. data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
  85. data/test/functional/associations/test_one_embedded_proxy.rb +58 -0
  86. data/test/functional/associations/test_one_proxy.rb +182 -0
  87. data/test/functional/test_accessible.rb +168 -0
  88. data/test/functional/test_associations.rb +44 -0
  89. data/test/functional/test_binary.rb +27 -0
  90. data/test/functional/test_caching.rb +76 -0
  91. data/test/functional/test_callbacks.rb +151 -0
  92. data/test/functional/test_dirty.rb +163 -0
  93. data/test/functional/test_document.rb +253 -0
  94. data/test/functional/test_dynamic_querying.rb +75 -0
  95. data/test/functional/test_embedded_document.rb +210 -0
  96. data/test/functional/test_identity_map.rb +506 -0
  97. data/test/functional/test_indexes.rb +42 -0
  98. data/test/functional/test_logger.rb +20 -0
  99. data/test/functional/test_modifiers.rb +416 -0
  100. data/test/functional/test_pagination.rb +91 -0
  101. data/test/functional/test_protected.rb +175 -0
  102. data/test/functional/test_querying.rb +873 -0
  103. data/test/functional/test_safe.rb +76 -0
  104. data/test/functional/test_sci.rb +230 -0
  105. data/test/functional/test_scopes.rb +171 -0
  106. data/test/functional/test_string_id_compatibility.rb +67 -0
  107. data/test/functional/test_timestamps.rb +62 -0
  108. data/test/functional/test_userstamps.rb +27 -0
  109. data/test/functional/test_validations.rb +342 -0
  110. data/test/models.rb +227 -0
  111. data/test/test_helper.rb +98 -0
  112. data/test/unit/associations/test_base.rb +212 -0
  113. data/test/unit/associations/test_proxy.rb +105 -0
  114. data/test/unit/serializers/test_json_serializer.rb +202 -0
  115. data/test/unit/test_clone.rb +69 -0
  116. data/test/unit/test_descendant_appends.rb +71 -0
  117. data/test/unit/test_document.rb +213 -0
  118. data/test/unit/test_dynamic_finder.rb +125 -0
  119. data/test/unit/test_embedded_document.rb +644 -0
  120. data/test/unit/test_extensions.rb +380 -0
  121. data/test/unit/test_key.rb +185 -0
  122. data/test/unit/test_keys.rb +55 -0
  123. data/test/unit/test_mongo_mapper.rb +110 -0
  124. data/test/unit/test_pagination.rb +11 -0
  125. data/test/unit/test_plugins.rb +50 -0
  126. data/test/unit/test_rails.rb +181 -0
  127. data/test/unit/test_rails_compatibility.rb +52 -0
  128. data/test/unit/test_serialization.rb +51 -0
  129. data/test/unit/test_time_zones.rb +39 -0
  130. data/test/unit/test_validations.rb +544 -0
  131. metadata +113 -44
  132. data/lib/mongo_mapper/plugins/pagination/proxy.rb +0 -72
  133. data/lib/mongo_mapper/query.rb +0 -23
  134. data/lib/mongo_mapper/support.rb +0 -196
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Extensions
4
+ module Date
5
+ def to_mongo(value)
6
+ if value.nil? || value == ''
7
+ nil
8
+ else
9
+ date = value.is_a?(::Date) || value.is_a?(::Time) ? value : ::Date.parse(value.to_s)
10
+ ::Time.utc(date.year, date.month, date.day)
11
+ end
12
+ rescue
13
+ nil
14
+ end
15
+
16
+ def from_mongo(value)
17
+ value.to_date if value.present?
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ class Date
24
+ extend MongoMapper::Extensions::Date
25
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Extensions
4
+ module Float
5
+ def to_mongo(value)
6
+ value.nil? ? nil : value.to_f
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ class Float
13
+ extend MongoMapper::Extensions::Float
14
+ end
@@ -0,0 +1,14 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Extensions
4
+ module Hash
5
+ def from_mongo(value)
6
+ HashWithIndifferentAccess.new(value || {})
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ class Hash
13
+ extend MongoMapper::Extensions::Hash
14
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Extensions
4
+ module Integer
5
+ def to_mongo(value)
6
+ value_to_i = value.to_i
7
+ if value_to_i == 0 && value != value_to_i
8
+ value.to_s =~ /^(0x|0b)?0+/ ? 0 : nil
9
+ else
10
+ value_to_i
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ class Integer
18
+ extend MongoMapper::Extensions::Integer
19
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: UTF-8
2
+ module Kernel
3
+ # Returns the object's singleton class.
4
+ def singleton_class
5
+ class << self
6
+ self
7
+ end
8
+ end unless respond_to?(:singleton_class) # exists in 1.9.2
9
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Extensions
4
+ module NilClass
5
+ def to_mongo(value)
6
+ value
7
+ end
8
+
9
+ def from_mongo(value)
10
+ value
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ class NilClass
17
+ include MongoMapper::Extensions::NilClass
18
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Extensions
4
+ module Object
5
+ module ClassMethods
6
+ def to_mongo(value)
7
+ value
8
+ end
9
+
10
+ def from_mongo(value)
11
+ value
12
+ end
13
+ end
14
+
15
+ module InstanceMethods
16
+ def to_mongo
17
+ self.class.to_mongo(self)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ class Object
25
+ extend MongoMapper::Extensions::Object::ClassMethods
26
+ include MongoMapper::Extensions::Object::InstanceMethods
27
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Extensions
4
+ module ObjectId
5
+ def to_mongo(value)
6
+ Plucky.to_object_id(value)
7
+ end
8
+
9
+ def from_mongo(value)
10
+ value
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ class ObjectId
17
+ extend MongoMapper::Extensions::ObjectId
18
+ end
19
+
20
+ class BSON::ObjectID
21
+ alias_method :original_to_json, :to_json
22
+
23
+ def as_json(options=nil)
24
+ to_s
25
+ end
26
+
27
+ def to_json(options = nil)
28
+ as_json.to_json
29
+ end
30
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+ require 'set'
3
+
4
+ module MongoMapper
5
+ module Extensions
6
+ module Set
7
+ def to_mongo(value)
8
+ value.to_a
9
+ end
10
+
11
+ def from_mongo(value)
12
+ (value || []).to_set
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ class Set
19
+ extend MongoMapper::Extensions::Set
20
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Extensions
4
+ module String
5
+ def to_mongo(value)
6
+ value.nil? ? nil : value.to_s
7
+ end
8
+
9
+ def from_mongo(value)
10
+ value.nil? ? nil : value.to_s
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ class String
17
+ extend MongoMapper::Extensions::String
18
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Extensions
4
+ module Time
5
+ def to_mongo(value)
6
+ if value.nil? || value == ''
7
+ nil
8
+ else
9
+ time_class = ::Time.try(:zone).present? ? ::Time.zone : ::Time
10
+ time = value.is_a?(::Time) ? value : time_class.parse(value.to_s)
11
+ # strip milliseconds as Ruby does micro and bson does milli and rounding rounded wrong
12
+ at(time.to_i).utc if time
13
+ end
14
+ end
15
+
16
+ def from_mongo(value)
17
+ if ::Time.try(:zone).present? && value.present?
18
+ value.in_time_zone(::Time.zone)
19
+ else
20
+ value
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ class Time
28
+ extend MongoMapper::Extensions::Time
29
+ end
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module MongoMapper
2
3
  module Plugins
3
4
  def plugins
@@ -10,26 +11,5 @@ module MongoMapper
10
11
  mod.configure(self) if mod.respond_to?(:configure)
11
12
  plugins << mod
12
13
  end
13
-
14
- autoload :Callbacks, 'mongo_mapper/plugins/callbacks'
15
- autoload :Clone, 'mongo_mapper/plugins/clone'
16
- autoload :Descendants, 'mongo_mapper/plugins/descendants'
17
- autoload :Dirty, 'mongo_mapper/plugins/dirty'
18
- autoload :Equality, 'mongo_mapper/plugins/equality'
19
- autoload :IdentityMap, 'mongo_mapper/plugins/identity_map'
20
- autoload :Inspect, 'mongo_mapper/plugins/inspect'
21
- autoload :Keys, 'mongo_mapper/plugins/keys'
22
- autoload :Logger, 'mongo_mapper/plugins/logger'
23
- autoload :Modifiers, 'mongo_mapper/plugins/modifiers'
24
- autoload :Persistence, 'mongo_mapper/plugins/persistence'
25
- autoload :Protected, 'mongo_mapper/plugins/protected'
26
- autoload :Rails, 'mongo_mapper/plugins/rails'
27
- autoload :Serialization, 'mongo_mapper/plugins/serialization'
28
- autoload :Timestamps, 'mongo_mapper/plugins/timestamps'
29
- autoload :Userstamps, 'mongo_mapper/plugins/userstamps'
30
- autoload :Validations, 'mongo_mapper/plugins/validations'
31
14
  end
32
15
  end
33
-
34
- require 'mongo_mapper/plugins/associations'
35
- require 'mongo_mapper/plugins/pagination'
@@ -0,0 +1,44 @@
1
+ module MongoMapper
2
+ module Plugins
3
+ module Accessible
4
+ module ClassMethods
5
+ def attr_accessible(*attrs)
6
+ raise AccessibleOrProtected.new(name) if try(:protected_attributes?)
7
+ self.write_inheritable_attribute(:attr_accessible, Set.new(attrs) + (accessible_attributes || []))
8
+ end
9
+
10
+ def accessible_attributes?
11
+ !accessible_attributes.nil?
12
+ end
13
+
14
+ def accessible_attributes
15
+ self.read_inheritable_attribute(:attr_accessible)
16
+ end
17
+ end
18
+
19
+ module InstanceMethods
20
+ def assign(attrs={})
21
+ super(filter_inaccessible_attrs(attrs))
22
+ end
23
+
24
+ def update_attributes(attrs={})
25
+ super(filter_inaccessible_attrs(attrs))
26
+ end
27
+
28
+ def update_attributes!(attrs={})
29
+ super(filter_inaccessible_attrs(attrs))
30
+ end
31
+
32
+ def accessible_attributes
33
+ self.class.accessible_attributes
34
+ end
35
+
36
+ protected
37
+ def filter_inaccessible_attrs(attrs)
38
+ return attrs if accessible_attributes.blank? || attrs.blank?
39
+ attrs.dup.delete_if { |key, val| !accessible_attributes.include?(key.to_sym) }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,7 +1,13 @@
1
+ # encoding: UTF-8
1
2
  module MongoMapper
2
3
  module Plugins
3
4
  module Associations
4
5
  module ClassMethods
6
+ def inherited(subclass)
7
+ subclass.associations = associations.dup
8
+ super
9
+ end
10
+
5
11
  def belongs_to(association_id, options={}, &extension)
6
12
  create_association(:belongs_to, association_id, options, &extension)
7
13
  end
@@ -22,11 +28,6 @@ module MongoMapper
22
28
  @associations = hash
23
29
  end
24
30
 
25
- def inherited(subclass)
26
- subclass.associations = associations.dup
27
- super
28
- end
29
-
30
31
  private
31
32
  def create_association(type, name, options, &extension)
32
33
  association = Associations::Base.new(type, name, options, &extension)
@@ -67,7 +68,6 @@ module MongoMapper
67
68
  self.class.associations
68
69
  end
69
70
 
70
- # @api private?
71
71
  def embedded_associations
72
72
  associations.select do |name, association|
73
73
  association.embeddable?
@@ -81,11 +81,10 @@ module MongoMapper
81
81
  proxy = association.proxy_class.new(self, association)
82
82
  self.instance_variable_set(association.ivar, proxy)
83
83
  end
84
-
85
84
  proxy
86
85
  end
87
86
 
88
- def save_to_collection(options = {})
87
+ def save_to_collection(options={})
89
88
  super
90
89
  associations.each do |association_name, association|
91
90
  proxy = get_proxy(association)
@@ -93,22 +92,6 @@ module MongoMapper
93
92
  end
94
93
  end
95
94
  end
96
-
97
- autoload :Base, 'mongo_mapper/plugins/associations/base'
98
- autoload :Collection, 'mongo_mapper/plugins/associations/collection'
99
- autoload :EmbeddedCollection, 'mongo_mapper/plugins/associations/embedded_collection'
100
- autoload :ManyDocumentsProxy, 'mongo_mapper/plugins/associations/many_documents_proxy'
101
- autoload :BelongsToProxy, 'mongo_mapper/plugins/associations/belongs_to_proxy'
102
- autoload :BelongsToPolymorphicProxy, 'mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy'
103
- autoload :ManyPolymorphicProxy, 'mongo_mapper/plugins/associations/many_polymorphic_proxy'
104
- autoload :ManyEmbeddedProxy, 'mongo_mapper/plugins/associations/many_embedded_proxy'
105
- autoload :ManyEmbeddedPolymorphicProxy, 'mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy'
106
- autoload :ManyDocumentsAsProxy, 'mongo_mapper/plugins/associations/many_documents_as_proxy'
107
- autoload :OneProxy, 'mongo_mapper/plugins/associations/one_proxy'
108
- autoload :OneEmbeddedProxy, 'mongo_mapper/plugins/associations/one_embedded_proxy'
109
- autoload :InArrayProxy, 'mongo_mapper/plugins/associations/in_array_proxy'
110
95
  end
111
96
  end
112
97
  end
113
-
114
- require 'mongo_mapper/plugins/associations/proxy'
@@ -1,3 +1,4 @@
1
+ # encoding: UTF-8
1
2
  module MongoMapper
2
3
  module Plugins
3
4
  module Associations
@@ -1,24 +1,23 @@
1
+ # encoding: UTF-8
1
2
  module MongoMapper
2
3
  module Plugins
3
4
  module Associations
4
5
  class BelongsToPolymorphicProxy < Proxy
5
- undef_method :object_id
6
-
7
6
  def replace(doc)
8
7
  if doc
9
8
  doc.save if doc.new?
10
9
  id, type = doc.id, doc.class.name
11
10
  end
12
11
 
13
- owner[association.foreign_key] = id
14
- owner[association.type_key_name] = type
12
+ proxy_owner[association.foreign_key] = id
13
+ proxy_owner[association.type_key_name] = type
15
14
  reset
16
15
  end
17
16
 
18
17
  protected
19
18
  def find_target
20
- return nil if association_class.nil? || owner[association.foreign_key].nil?
21
- association_class.find_by_id(owner[association.foreign_key])
19
+ return nil if association_class.nil? || proxy_owner[association.foreign_key].nil?
20
+ association_class.find_by_id(proxy_owner[association.foreign_key])
22
21
  end
23
22
 
24
23
  def association_class
@@ -1,23 +1,22 @@
1
+ # encoding: UTF-8
1
2
  module MongoMapper
2
3
  module Plugins
3
4
  module Associations
4
5
  class BelongsToProxy < Proxy
5
- undef_method :object_id
6
-
7
6
  def replace(doc)
8
7
  if doc
9
8
  doc.save if doc.new?
10
9
  id = doc.id
11
10
  end
12
11
 
13
- owner[association.foreign_key] = id
14
- reset
12
+ proxy_owner[association.foreign_key] = id
13
+ reload
15
14
  end
16
15
 
17
16
  protected
18
17
  def find_target
19
- return nil if owner[association.foreign_key].nil?
20
- klass.find_by_id(owner[association.foreign_key])
18
+ return nil if proxy_owner[association.foreign_key].nil?
19
+ klass.find_by_id(proxy_owner[association.foreign_key])
21
20
  end
22
21
  end
23
22
  end