mongo_mapper 0.10.1 → 0.11.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 (54) hide show
  1. data/UPGRADES +3 -0
  2. data/examples/plugins.rb +2 -5
  3. data/lib/mongo_mapper.rb +1 -0
  4. data/lib/mongo_mapper/connection.rb +4 -0
  5. data/lib/mongo_mapper/embedded_document.rb +1 -0
  6. data/lib/mongo_mapper/extensions/object.rb +5 -6
  7. data/lib/mongo_mapper/plugins/accessible.rb +14 -16
  8. data/lib/mongo_mapper/plugins/associations.rb +21 -23
  9. data/lib/mongo_mapper/plugins/associations/base.rb +1 -1
  10. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +4 -0
  11. data/lib/mongo_mapper/plugins/associations/many_association.rb +0 -4
  12. data/lib/mongo_mapper/plugins/associations/one_association.rb +1 -1
  13. data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
  14. data/lib/mongo_mapper/plugins/caching.rb +11 -13
  15. data/lib/mongo_mapper/plugins/callbacks.rb +12 -14
  16. data/lib/mongo_mapper/plugins/clone.rb +11 -13
  17. data/lib/mongo_mapper/plugins/dirty.rb +36 -38
  18. data/lib/mongo_mapper/plugins/document.rb +20 -22
  19. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +11 -13
  20. data/lib/mongo_mapper/plugins/embedded_document.rb +22 -24
  21. data/lib/mongo_mapper/plugins/equality.rb +6 -8
  22. data/lib/mongo_mapper/plugins/identity_map.rb +11 -13
  23. data/lib/mongo_mapper/plugins/inspect.rb +6 -8
  24. data/lib/mongo_mapper/plugins/keys.rb +109 -110
  25. data/lib/mongo_mapper/plugins/logger.rb +2 -4
  26. data/lib/mongo_mapper/plugins/modifiers.rb +32 -34
  27. data/lib/mongo_mapper/plugins/persistence.rb +5 -7
  28. data/lib/mongo_mapper/plugins/protected.rb +14 -16
  29. data/lib/mongo_mapper/plugins/querying.rb +29 -31
  30. data/lib/mongo_mapper/plugins/rails.rb +28 -22
  31. data/lib/mongo_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
  32. data/lib/mongo_mapper/plugins/safe.rb +3 -5
  33. data/lib/mongo_mapper/plugins/sci.rb +3 -5
  34. data/lib/mongo_mapper/plugins/serialization.rb +49 -52
  35. data/lib/mongo_mapper/plugins/timestamps.rb +4 -6
  36. data/lib/mongo_mapper/plugins/validations.rb +8 -10
  37. data/lib/mongo_mapper/railtie/database.rake +1 -1
  38. data/lib/mongo_mapper/version.rb +1 -1
  39. data/lib/rails/generators/mongo_mapper/model/model_generator.rb +1 -1
  40. data/lib/rails/generators/mongo_mapper/model/templates/model.rb +2 -0
  41. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +63 -0
  42. data/test/functional/associations/test_one_embedded_polymorphic_proxy.rb +208 -0
  43. data/test/functional/test_accessible.rb +5 -0
  44. data/test/functional/test_embedded_document.rb +12 -0
  45. data/test/functional/test_modifiers.rb +19 -19
  46. data/test/functional/test_protected.rb +10 -0
  47. data/test/functional/test_querying.rb +15 -1
  48. data/test/functional/test_validations.rb +33 -0
  49. data/test/models.rb +14 -0
  50. data/test/unit/associations/test_one_association.rb +11 -0
  51. data/test/unit/test_mongo_mapper.rb +9 -0
  52. data/test/unit/test_plugins.rb +2 -4
  53. data/test/unit/test_rails_reflect_on_association.rb +118 -0
  54. metadata +15 -11
@@ -57,14 +57,12 @@ module MongoMapper
57
57
  end
58
58
  end
59
59
 
60
- module InstanceMethods
61
- def collection
62
- _root_document.class.collection
63
- end
60
+ def collection
61
+ _root_document.class.collection
62
+ end
64
63
 
65
- def database
66
- _root_document.class.database
67
- end
64
+ def database
65
+ _root_document.class.database
68
66
  end
69
67
  end
70
68
  end
@@ -23,25 +23,23 @@ module MongoMapper
23
23
  end
24
24
  end
25
25
 
26
- module InstanceMethods
27
- def attributes=(attrs={})
28
- super(filter_protected_attrs(attrs))
29
- end
30
-
31
- def update_attributes(attrs={})
32
- super(filter_protected_attrs(attrs))
33
- end
26
+ def attributes=(attrs={})
27
+ super(filter_protected_attrs(attrs))
28
+ end
34
29
 
35
- def update_attributes!(attrs={})
36
- super(filter_protected_attrs(attrs))
37
- end
30
+ def update_attributes(attrs={})
31
+ super(filter_protected_attrs(attrs))
32
+ end
38
33
 
39
- protected
40
- def filter_protected_attrs(attrs)
41
- return attrs if protected_attributes.blank? || attrs.blank?
42
- attrs.dup.delete_if { |key, val| protected_attributes.include?(key.to_sym) }
43
- end
34
+ def update_attributes!(attrs={})
35
+ super(filter_protected_attrs(attrs))
44
36
  end
37
+
38
+ protected
39
+ def filter_protected_attrs(attrs)
40
+ return attrs if protected_attributes.blank? || attrs.blank?
41
+ attrs.dup.delete_if { |key, val| protected_attributes.include?(key.to_sym) }
42
+ end
45
43
  end
46
44
  end
47
45
  end
@@ -137,44 +137,42 @@ module MongoMapper
137
137
  end
138
138
  end
139
139
 
140
- module InstanceMethods
141
- def save(options={})
142
- options.assert_valid_keys(:validate, :safe)
143
- create_or_update(options)
144
- end
140
+ def save(options={})
141
+ options.assert_valid_keys(:validate, :safe)
142
+ create_or_update(options)
143
+ end
145
144
 
146
- def save!(options={})
147
- options.assert_valid_keys(:safe)
148
- save(options) || raise(DocumentNotValid.new(self))
149
- end
145
+ def save!(options={})
146
+ options.assert_valid_keys(:safe)
147
+ save(options) || raise(DocumentNotValid.new(self))
148
+ end
150
149
 
151
- def destroy
152
- delete
153
- end
150
+ def destroy
151
+ delete
152
+ end
154
153
 
155
- def delete
156
- self.class.delete(id).tap { @_destroyed = true } if persisted?
157
- end
154
+ def delete
155
+ self.class.delete(id).tap { @_destroyed = true } if persisted?
156
+ end
158
157
 
159
- private
160
- def create_or_update(options={})
161
- result = persisted? ? update(options) : create(options)
162
- result != false
163
- end
158
+ private
159
+ def create_or_update(options={})
160
+ result = persisted? ? update(options) : create(options)
161
+ result != false
162
+ end
164
163
 
165
- def create(options={})
166
- save_to_collection(options)
167
- end
164
+ def create(options={})
165
+ save_to_collection(options)
166
+ end
168
167
 
169
- def update(options={})
170
- save_to_collection(options)
171
- end
168
+ def update(options={})
169
+ save_to_collection(options)
170
+ end
172
171
 
173
- def save_to_collection(options={})
174
- @_new = false
175
- collection.save(to_mongo, :safe => options[:safe])
176
- end
177
- end
172
+ def save_to_collection(options={})
173
+ @_new = false
174
+ collection.save(to_mongo, :safe => options[:safe])
175
+ end
178
176
  end
179
177
  end
180
178
  end
@@ -2,36 +2,35 @@
2
2
  module MongoMapper
3
3
  module Plugins
4
4
  module Rails
5
+ autoload :ActiveRecordAssociationAdapter, "mongo_mapper/plugins/rails/active_record_association_adapter"
5
6
  extend ActiveSupport::Concern
6
7
 
7
- module InstanceMethods
8
- def to_param
9
- id.to_s if persisted?
10
- end
8
+ def to_param
9
+ id.to_s if persisted?
10
+ end
11
11
 
12
- def to_model
13
- self
14
- end
12
+ def to_model
13
+ self
14
+ end
15
15
 
16
- def to_key
17
- [id] if persisted?
18
- end
16
+ def to_key
17
+ [id] if persisted?
18
+ end
19
19
 
20
- def new_record?
21
- new?
22
- end
20
+ def new_record?
21
+ new?
22
+ end
23
23
 
24
- def read_attribute(name)
25
- self[name]
26
- end
24
+ def read_attribute(name)
25
+ self[name]
26
+ end
27
27
 
28
- def read_attribute_before_type_cast(name)
29
- read_key_before_type_cast(name)
30
- end
28
+ def read_attribute_before_type_cast(name)
29
+ read_key_before_type_cast(name)
30
+ end
31
31
 
32
- def write_attribute(name, value)
33
- self[name] = value
34
- end
32
+ def write_attribute(name, value)
33
+ self[name] = value
35
34
  end
36
35
 
37
36
  module ClassMethods
@@ -46,6 +45,13 @@ module MongoMapper
46
45
  def column_names
47
46
  keys.keys
48
47
  end
48
+
49
+ # Returns returns an ActiveRecordAssociationAdapter for an association. This adapter has an API that is a
50
+ # subset of ActiveRecord::Reflection::AssociationReflection. This allows MongoMapper to be used with the
51
+ # association helpers in gems like simple_form and formtastic.
52
+ def reflect_on_association(name)
53
+ ActiveRecordAssociationAdapter.for_association(associations[name]) if associations[name]
54
+ end
49
55
  end
50
56
  end
51
57
  end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Plugins
4
+ module Rails
5
+ class ActiveRecordAssociationAdapter
6
+ attr_reader :klass, :macro, :name, :options
7
+
8
+ def self.for_association(association)
9
+ macro = case association
10
+ when MongoMapper::Plugins::Associations::BelongsToAssociation
11
+ :belongs_to
12
+ when MongoMapper::Plugins::Associations::ManyAssociation
13
+ :has_many
14
+ when MongoMapper::Plugins::Associations::OneAssociation
15
+ :has_one
16
+ else
17
+ raise "no #{name} for association of type #{association.class}"
18
+ end
19
+
20
+ new(association, macro)
21
+ end
22
+
23
+ def initialize(association, macro)
24
+ @klass, @name = association.klass, association.name
25
+ # only include compatible options
26
+ @options = association.options.slice(:conditions, :order)
27
+
28
+ @macro = macro
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -19,11 +19,9 @@ module MongoMapper
19
19
  end
20
20
  end
21
21
 
22
- module InstanceMethods
23
- def save_to_collection(options={})
24
- options[:safe] = self.class.safe? unless options.key?(:safe)
25
- super
26
- end
22
+ def save_to_collection(options={})
23
+ options[:safe] = self.class.safe? unless options.key?(:safe)
24
+ super
27
25
  end
28
26
  end
29
27
  end
@@ -27,11 +27,9 @@ module MongoMapper
27
27
  end
28
28
  end
29
29
 
30
- module InstanceMethods
31
- def initialize(*args)
32
- super
33
- write_key :_type, self.class.name if self.class.key?(:_type)
34
- end
30
+ def initialize(*args)
31
+ super
32
+ write_key :_type, self.class.name if self.class.key?(:_type)
35
33
  end
36
34
  end
37
35
  end
@@ -13,77 +13,74 @@ module MongoMapper
13
13
  self.include_root_in_json = false
14
14
  end
15
15
 
16
- module InstanceMethods
17
- def serializable_attributes
18
- attributes.keys.map { |k| k.to_s } + ['id'] - ['_id']
19
- end
20
-
21
- def serializable_hash(options = nil)
22
- options ||= {}
16
+ def serializable_attributes
17
+ attributes.keys.map { |k| k.to_s } + ['id'] - ['_id']
18
+ end
23
19
 
24
- options[:only] = Array.wrap(options[:only]).map { |k| k.to_s }
25
- options[:except] = Array.wrap(options[:except]).map { |k| k.to_s }
20
+ def serializable_hash(options = nil)
21
+ options ||= {}
26
22
 
27
- attribute_names = serializable_attributes
23
+ options[:only] = Array.wrap(options[:only]).map { |k| k.to_s }
24
+ options[:except] = Array.wrap(options[:except]).map { |k| k.to_s }
28
25
 
29
- if options[:only].any?
30
- attribute_names &= options[:only]
31
- elsif options[:except].any?
32
- attribute_names -= options[:except]
33
- end
26
+ attribute_names = serializable_attributes
34
27
 
35
- attribute_names += Array.wrap(options[:methods]).map { |m| m.to_s }.select do |method|
36
- respond_to?(method)
37
- end
28
+ if options[:only].any?
29
+ attribute_names &= options[:only]
30
+ elsif options[:except].any?
31
+ attribute_names -= options[:except]
32
+ end
38
33
 
39
- hash = attribute_names.sort.inject({}) do |hash, name|
40
- value = send(name)
41
- hash[name] = if value.is_a?(Array)
42
- value.map {|v| v.respond_to?(:serializable_hash) ? v.serializable_hash : v }
43
- elsif value.respond_to?(:serializable_hash)
44
- value.serializable_hash
45
- else
46
- value
47
- end
48
- hash
49
- end
34
+ attribute_names += Array.wrap(options[:methods]).map { |m| m.to_s }.select do |method|
35
+ respond_to?(method)
36
+ end
50
37
 
51
- serializable_add_includes(options) do |association, records, opts|
52
- hash[association.to_s] = records.is_a?(Array) ?
53
- records.map { |r| r.serializable_hash(opts) } :
54
- records.serializable_hash(opts)
38
+ hash = attribute_names.sort.inject({}) do |hash, name|
39
+ value = send(name)
40
+ hash[name] = if value.is_a?(Array)
41
+ value.map {|v| v.respond_to?(:serializable_hash) ? v.serializable_hash : v }
42
+ elsif value.respond_to?(:serializable_hash)
43
+ value.serializable_hash
44
+ else
45
+ value
55
46
  end
56
-
57
47
  hash
58
48
  end
59
49
 
60
- def to_xml(options = {}, &block)
61
- XmlSerializer.new(self, options).serialize(&block)
50
+ serializable_add_includes(options) do |association, records, opts|
51
+ hash[association.to_s] = records.is_a?(Array) ?
52
+ records.map { |r| r.serializable_hash(opts) } :
53
+ records.serializable_hash(opts)
62
54
  end
63
55
 
64
- private
56
+ hash
57
+ end
65
58
 
66
- def serializable_add_includes(options = {})
67
- return unless include_associations = options.delete(:include)
59
+ def to_xml(options = {}, &block)
60
+ XmlSerializer.new(self, options).serialize(&block)
61
+ end
68
62
 
69
- base_only_or_except = { :except => options[:except],
70
- :only => options[:only] }
63
+ private
71
64
 
72
- include_has_options = include_associations.is_a?(Hash)
73
- associations = include_has_options ? include_associations.keys : Array.wrap(include_associations)
65
+ def serializable_add_includes(options = {})
66
+ return unless include_associations = options.delete(:include)
74
67
 
75
- associations.each do |association|
76
- records = get_proxy(self.class.associations[association])
77
- unless records.nil?
78
- association_options = include_has_options ? include_associations[association] : base_only_or_except
79
- opts = options.merge(association_options)
80
- yield(association, records, opts)
81
- end
82
- end
68
+ base_only_or_except = { :except => options[:except],
69
+ :only => options[:only] }
70
+
71
+ include_has_options = include_associations.is_a?(Hash)
72
+ associations = include_has_options ? include_associations.keys : Array.wrap(include_associations)
83
73
 
84
- options[:include] = include_associations
74
+ associations.each do |association|
75
+ records = get_proxy(self.class.associations[association])
76
+ unless records.nil?
77
+ association_options = include_has_options ? include_associations[association] : base_only_or_except
78
+ opts = options.merge(association_options)
79
+ yield(association, records, opts)
80
+ end
85
81
  end
86
82
 
83
+ options[:include] = include_associations
87
84
  end
88
85
 
89
86
  module ClassMethods
@@ -12,12 +12,10 @@ module MongoMapper
12
12
  end
13
13
  end
14
14
 
15
- module InstanceMethods
16
- def update_timestamps
17
- now = Time.now.utc
18
- self[:created_at] = now if !persisted? && !created_at?
19
- self[:updated_at] = now
20
- end
15
+ def update_timestamps
16
+ now = Time.now.utc
17
+ self[:created_at] = now if !persisted? && !created_at?
18
+ self[:updated_at] = now
21
19
  end
22
20
  end
23
21
  end
@@ -17,16 +17,14 @@ module MongoMapper
17
17
  end
18
18
  end
19
19
 
20
- module InstanceMethods
21
- def save(options = {})
22
- options.reverse_merge!(:validate => true)
23
- !options[:validate] || valid? ? super : false
24
- end
20
+ def save(options = {})
21
+ options.reverse_merge!(:validate => true)
22
+ !options[:validate] || valid? ? super : false
23
+ end
25
24
 
26
- def valid?(context = nil)
27
- context ||= (new_record? ? :create : :update)
28
- super(context)
29
- end
25
+ def valid?(context = nil)
26
+ context ||= (new_record? ? :create : :update)
27
+ super(context)
30
28
  end
31
29
 
32
30
  class UniquenessValidator < ::ActiveModel::EachValidator
@@ -68,7 +66,7 @@ module MongoMapper
68
66
 
69
67
  class AssociatedValidator < ::ActiveModel::EachValidator
70
68
  def validate_each(record, attribute, value)
71
- if !Array.wrap(value).all? { |c| c.nil? || c.valid? }
69
+ if !Array.wrap(value).all? { |c| c.nil? || c.valid?(options[:context]) }
72
70
  record.errors.add(attribute, :invalid, :message => options[:message], :value => value)
73
71
  end
74
72
  end