mongo_mapper 0.7.6 → 0.8.0

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