mongo_mapper 0.10.1 → 0.11.0

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