ign-mongo_mapper 0.8.6.1
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.
- data/LICENSE +20 -0
- data/README.rdoc +33 -0
- data/UPGRADES +7 -0
- data/bin/mmconsole +60 -0
- data/examples/attr_accessible.rb +22 -0
- data/examples/attr_protected.rb +22 -0
- data/examples/cache_key.rb +24 -0
- data/examples/custom_types.rb +24 -0
- data/examples/identity_map.rb +33 -0
- data/examples/identity_map/automatic.rb +8 -0
- data/examples/keys.rb +40 -0
- data/examples/modifiers/set.rb +25 -0
- data/examples/plugins.rb +41 -0
- data/examples/querying.rb +35 -0
- data/examples/safe.rb +43 -0
- data/examples/scopes.rb +52 -0
- data/examples/validating/embedded_docs.rb +29 -0
- data/lib/mongo_mapper.rb +83 -0
- data/lib/mongo_mapper/connection.rb +83 -0
- data/lib/mongo_mapper/document.rb +41 -0
- data/lib/mongo_mapper/embedded_document.rb +31 -0
- data/lib/mongo_mapper/exceptions.rb +27 -0
- data/lib/mongo_mapper/extensions/array.rb +19 -0
- data/lib/mongo_mapper/extensions/binary.rb +22 -0
- data/lib/mongo_mapper/extensions/boolean.rb +44 -0
- data/lib/mongo_mapper/extensions/date.rb +25 -0
- data/lib/mongo_mapper/extensions/float.rb +14 -0
- data/lib/mongo_mapper/extensions/hash.rb +14 -0
- data/lib/mongo_mapper/extensions/integer.rb +19 -0
- data/lib/mongo_mapper/extensions/kernel.rb +9 -0
- data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
- data/lib/mongo_mapper/extensions/object.rb +27 -0
- data/lib/mongo_mapper/extensions/object_id.rb +30 -0
- data/lib/mongo_mapper/extensions/set.rb +20 -0
- data/lib/mongo_mapper/extensions/string.rb +18 -0
- data/lib/mongo_mapper/extensions/time.rb +29 -0
- data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
- data/lib/mongo_mapper/plugins.rb +15 -0
- data/lib/mongo_mapper/plugins/accessible.rb +44 -0
- data/lib/mongo_mapper/plugins/associations.rb +134 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +124 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +29 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +24 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +40 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +151 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +109 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +41 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +139 -0
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +243 -0
- data/lib/mongo_mapper/plugins/clone.rb +22 -0
- data/lib/mongo_mapper/plugins/descendants.rb +17 -0
- data/lib/mongo_mapper/plugins/dirty.rb +124 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +43 -0
- data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +48 -0
- data/lib/mongo_mapper/plugins/equality.rb +17 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
- data/lib/mongo_mapper/plugins/indexes.rb +12 -0
- data/lib/mongo_mapper/plugins/inspect.rb +15 -0
- data/lib/mongo_mapper/plugins/keys.rb +311 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +65 -0
- data/lib/mongo_mapper/plugins/logger.rb +18 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +112 -0
- data/lib/mongo_mapper/plugins/pagination.rb +14 -0
- data/lib/mongo_mapper/plugins/persistence.rb +69 -0
- data/lib/mongo_mapper/plugins/protected.rb +53 -0
- data/lib/mongo_mapper/plugins/querying.rb +176 -0
- data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
- data/lib/mongo_mapper/plugins/querying/plucky_methods.rb +15 -0
- data/lib/mongo_mapper/plugins/rails.rb +58 -0
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +32 -0
- data/lib/mongo_mapper/plugins/scopes.rb +21 -0
- data/lib/mongo_mapper/plugins/serialization.rb +76 -0
- data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +15 -0
- data/lib/mongo_mapper/plugins/validations.rb +50 -0
- data/lib/mongo_mapper/support/descendant_appends.rb +45 -0
- data/lib/mongo_mapper/version.rb +4 -0
- data/rails/init.rb +15 -0
- data/test/_NOTE_ON_TESTING +1 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +64 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +117 -0
- data/test/functional/associations/test_in_array_proxy.rb +349 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
- data/test/functional/associations/test_many_documents_proxy.rb +615 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
- data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
- data/test/functional/associations/test_one_proxy.rb +206 -0
- data/test/functional/test_accessible.rb +168 -0
- data/test/functional/test_associations.rb +46 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_caching.rb +76 -0
- data/test/functional/test_callbacks.rb +151 -0
- data/test/functional/test_dirty.rb +163 -0
- data/test/functional/test_document.rb +272 -0
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +210 -0
- data/test/functional/test_identity_map.rb +513 -0
- data/test/functional/test_indexes.rb +42 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +416 -0
- data/test/functional/test_pagination.rb +91 -0
- data/test/functional/test_protected.rb +175 -0
- data/test/functional/test_querying.rb +873 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +230 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_string_id_compatibility.rb +67 -0
- data/test/functional/test_timestamps.rb +62 -0
- data/test/functional/test_userstamps.rb +27 -0
- data/test/functional/test_validations.rb +342 -0
- data/test/models.rb +233 -0
- data/test/test_active_model_lint.rb +13 -0
- data/test/test_helper.rb +102 -0
- data/test/unit/associations/test_base.rb +212 -0
- data/test/unit/associations/test_proxy.rb +105 -0
- data/test/unit/serializers/test_json_serializer.rb +217 -0
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_descendant_appends.rb +71 -0
- data/test/unit/test_document.rb +208 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +639 -0
- data/test/unit/test_extensions.rb +376 -0
- data/test/unit/test_identity_map_middleware.rb +34 -0
- data/test/unit/test_inspect.rb +22 -0
- data/test/unit/test_key.rb +205 -0
- data/test/unit/test_keys.rb +89 -0
- data/test/unit/test_mongo_mapper.rb +110 -0
- data/test/unit/test_pagination.rb +11 -0
- data/test/unit/test_plugins.rb +50 -0
- data/test/unit/test_rails.rb +181 -0
- data/test/unit/test_rails_compatibility.rb +52 -0
- data/test/unit/test_serialization.rb +51 -0
- data/test/unit/test_time_zones.rb +39 -0
- data/test/unit/test_validations.rb +564 -0
- metadata +385 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Sci
|
5
|
+
module ClassMethods
|
6
|
+
def inherited(subclass)
|
7
|
+
key :_type, String unless key?(:_type)
|
8
|
+
subclass.instance_variable_set("@single_collection_inherited", true)
|
9
|
+
subclass.set_collection_name(collection_name) unless subclass.embeddable?
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def single_collection_inherited?
|
14
|
+
@single_collection_inherited == true
|
15
|
+
end
|
16
|
+
|
17
|
+
def query(options={})
|
18
|
+
super.tap do |query|
|
19
|
+
query[:_type] = name if single_collection_inherited?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module InstanceMethods
|
25
|
+
def initialize(*args)
|
26
|
+
super
|
27
|
+
write_key :_type, self.class.name if self.class.key?(:_type)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Scopes
|
5
|
+
module ClassMethods
|
6
|
+
def scope(name, scope_options={})
|
7
|
+
scopes[name] = lambda do |*args|
|
8
|
+
result = scope_options.is_a?(Proc) ? scope_options.call(*args) : scope_options
|
9
|
+
result = self.query(result) if result.is_a?(Hash)
|
10
|
+
self.query.merge(result)
|
11
|
+
end
|
12
|
+
singleton_class.send :define_method, name, &scopes[name]
|
13
|
+
end
|
14
|
+
|
15
|
+
def scopes
|
16
|
+
read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'active_support/json'
|
3
|
+
|
4
|
+
module MongoMapper
|
5
|
+
module Plugins
|
6
|
+
module Serialization
|
7
|
+
def self.configure(model)
|
8
|
+
model.class_eval { cattr_accessor :include_root_in_json, :instance_writer => true }
|
9
|
+
end
|
10
|
+
|
11
|
+
module InstanceMethods
|
12
|
+
def as_json options={}
|
13
|
+
options ||= {}
|
14
|
+
unless options[:only]
|
15
|
+
methods = [options.delete(:methods)].flatten.compact
|
16
|
+
methods << :id
|
17
|
+
options[:methods] = methods.uniq
|
18
|
+
end
|
19
|
+
|
20
|
+
except = [options.delete(:except)].flatten.compact
|
21
|
+
except << :_id
|
22
|
+
options[:except] = except
|
23
|
+
|
24
|
+
# Direct rip from Rails 3 ActiveModel Serialization (#serializable_hash)
|
25
|
+
hash = begin
|
26
|
+
options[:only] = Array.wrap(options[:only]).map { |n| n.to_s }
|
27
|
+
options[:except] = Array.wrap(options[:except]).map { |n| n.to_s }
|
28
|
+
|
29
|
+
attribute_names = attributes.keys.sort
|
30
|
+
if options[:only].any?
|
31
|
+
attribute_names &= options[:only]
|
32
|
+
elsif options[:except].any?
|
33
|
+
attribute_names -= options[:except]
|
34
|
+
end
|
35
|
+
|
36
|
+
method_names = Array.wrap(options[:methods]).inject([]) do |methods, name|
|
37
|
+
methods << name if respond_to?(name.to_s)
|
38
|
+
methods
|
39
|
+
end
|
40
|
+
|
41
|
+
(attribute_names + method_names).inject({}) { |hash, name|
|
42
|
+
hash[name] = send(name)
|
43
|
+
hash
|
44
|
+
}
|
45
|
+
end
|
46
|
+
# End rip
|
47
|
+
|
48
|
+
options.delete(:only) if options[:only].nil? or options[:only].empty?
|
49
|
+
|
50
|
+
hash.each do |key, value|
|
51
|
+
if value.is_a?(Array)
|
52
|
+
hash[key] = value.map do |item|
|
53
|
+
item.respond_to?(:as_json) ? item.as_json(options) : item
|
54
|
+
end
|
55
|
+
elsif value.is_a? BSON::ObjectId
|
56
|
+
hash[key] = value.to_s
|
57
|
+
elsif value.respond_to?(:as_json)
|
58
|
+
hash[key] = value.as_json(options)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Replicate Rails 3 naming - and also bin anytihng after : for use in our dynamic classes from unit tests
|
63
|
+
hash = { ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self.class.name)).gsub(/:.*/,'') => hash } if include_root_in_json
|
64
|
+
hash
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
module ClassMethods
|
69
|
+
def from_json(json)
|
70
|
+
self.new(ActiveSupport::JSON.decode(json))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Timestamps
|
5
|
+
module ClassMethods
|
6
|
+
def timestamps!
|
7
|
+
key :created_at, Time
|
8
|
+
key :updated_at, Time
|
9
|
+
class_eval { before_save :update_timestamps }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module InstanceMethods
|
14
|
+
def update_timestamps
|
15
|
+
now = Time.now.utc
|
16
|
+
self[:created_at] = now if new? && !created_at?
|
17
|
+
self[:updated_at] = now
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Userstamps
|
5
|
+
module ClassMethods
|
6
|
+
def userstamps!
|
7
|
+
key :creator_id, ObjectId
|
8
|
+
key :updater_id, ObjectId
|
9
|
+
belongs_to :creator, :class_name => 'User'
|
10
|
+
belongs_to :updater, :class_name => 'User'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Validations
|
5
|
+
def self.configure(model)
|
6
|
+
model.class_eval do
|
7
|
+
include Validatable
|
8
|
+
extend Validations::DocumentMacros
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module DocumentMacros
|
13
|
+
def validates_uniqueness_of(*args)
|
14
|
+
add_validations(args, Validations::ValidatesUniquenessOf)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ValidatesUniquenessOf < Validatable::ValidationBase
|
19
|
+
option :scope, :case_sensitive
|
20
|
+
default :case_sensitive => true
|
21
|
+
|
22
|
+
def valid?(instance)
|
23
|
+
value = instance[attribute]
|
24
|
+
return allow_nil if value.nil? and not allow_nil.nil?
|
25
|
+
return allow_blank if value.blank? and not allow_blank.nil?
|
26
|
+
base_conditions = case_sensitive ? {self.attribute => value} : {}
|
27
|
+
doc = instance.class.first(base_conditions.merge(scope_conditions(instance)).merge(where_conditions(instance)))
|
28
|
+
doc.nil? || instance._id == doc._id
|
29
|
+
end
|
30
|
+
|
31
|
+
def message(instance)
|
32
|
+
super || "has already been taken"
|
33
|
+
end
|
34
|
+
|
35
|
+
def scope_conditions(instance)
|
36
|
+
return {} unless scope
|
37
|
+
Array(scope).inject({}) do |conditions, key|
|
38
|
+
conditions.merge(key => instance[key])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def where_conditions(instance)
|
43
|
+
conditions = {}
|
44
|
+
conditions[attribute] = /^#{Regexp.escape(instance[attribute].to_s)}$/i unless case_sensitive
|
45
|
+
conditions
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
module MongoMapper
|
5
|
+
module Support
|
6
|
+
module DescendantAppends
|
7
|
+
def included(model)
|
8
|
+
extra_extensions.each { |extension| model.extend(extension) }
|
9
|
+
extra_inclusions.each { |inclusion| model.send(:include, inclusion) }
|
10
|
+
descendants << model
|
11
|
+
end
|
12
|
+
|
13
|
+
# @api public
|
14
|
+
def descendants
|
15
|
+
@descendants ||= Set.new
|
16
|
+
end
|
17
|
+
|
18
|
+
# @api public
|
19
|
+
def append_extensions(*extensions)
|
20
|
+
extra_extensions.concat(extensions)
|
21
|
+
descendants.each do |model|
|
22
|
+
extensions.each { |extension| model.extend(extension) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# @api public
|
27
|
+
def append_inclusions(*inclusions)
|
28
|
+
extra_inclusions.concat(inclusions)
|
29
|
+
descendants.each do |model|
|
30
|
+
inclusions.each { |inclusion| model.send(:include, inclusion) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @api private
|
35
|
+
def extra_extensions
|
36
|
+
@extra_extensions ||= []
|
37
|
+
end
|
38
|
+
|
39
|
+
# @api private
|
40
|
+
def extra_inclusions
|
41
|
+
@extra_inclusions ||= []
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# See http://groups.google.com/group/mongomapper/browse_thread/thread/68f62e8eda43b43a/4841dba76938290c
|
2
|
+
#
|
3
|
+
# to_prepare is called before each request in development mode and the first request in production.
|
4
|
+
Rails.configuration.to_prepare do
|
5
|
+
if !Rails.configuration.cache_classes
|
6
|
+
# Rails reloading was making descendants fill up and leak memory, these make sure they get cleared
|
7
|
+
MongoMapper::Document.descendants.each {|m| m.descendants.clear if m.respond_to?(:descendants) }
|
8
|
+
MongoMapper::Document.descendants.clear
|
9
|
+
MongoMapper::EmbeddedDocument.descendants.each {|m| m.descendants.clear if m.respond_to?(:descendants) }
|
10
|
+
MongoMapper::EmbeddedDocument.descendants.clear
|
11
|
+
MongoMapper::Plugins::IdentityMap.models.clear
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
config.middleware.use 'MongoMapper::Middleware::IdentityMap'
|
@@ -0,0 +1 @@
|
|
1
|
+
I am doing my best to keep unit and functional tests separate. As I see them, functional tests hit the database and should never care about internals. Unit tests do not hit the database.
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'models'
|
3
|
+
|
4
|
+
class BelongsToPolymorphicProxyTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
Status.collection.remove
|
7
|
+
Project.collection.remove
|
8
|
+
end
|
9
|
+
|
10
|
+
should "default to nil" do
|
11
|
+
status = Status.new
|
12
|
+
status.target.nil?.should be_true
|
13
|
+
status.target.inspect.should == "nil"
|
14
|
+
end
|
15
|
+
|
16
|
+
should "have boolean presence method" do
|
17
|
+
status = Status.new
|
18
|
+
status.target?.should be_false
|
19
|
+
|
20
|
+
status.target = Project.new(:name => 'mongomapper')
|
21
|
+
status.target?.should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
should "be able to replace the association" do
|
25
|
+
status = Status.new(:name => 'Foo!')
|
26
|
+
project = Project.new(:name => "mongomapper")
|
27
|
+
status.target = project
|
28
|
+
status.save.should be_true
|
29
|
+
|
30
|
+
status = status.reload
|
31
|
+
status.target.nil?.should be_false
|
32
|
+
status.target_id.should == project._id
|
33
|
+
status.target_type.should == "Project"
|
34
|
+
status.target.name.should == "mongomapper"
|
35
|
+
end
|
36
|
+
|
37
|
+
should "unset the association" do
|
38
|
+
status = Status.new(:name => 'Foo!')
|
39
|
+
project = Project.new(:name => "mongomapper")
|
40
|
+
status.target = project
|
41
|
+
status.save.should be_true
|
42
|
+
|
43
|
+
status = status.reload
|
44
|
+
status.target = nil
|
45
|
+
status.target_type.nil?.should be_true
|
46
|
+
status.target_id.nil?.should be_true
|
47
|
+
status.target.nil?.should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
context "association id set but document not found" do
|
51
|
+
setup do
|
52
|
+
@status = Status.new(:name => 'Foo!')
|
53
|
+
project = Project.new(:name => "mongomapper")
|
54
|
+
@status.target = project
|
55
|
+
@status.save.should be_true
|
56
|
+
project.destroy
|
57
|
+
@status.reload
|
58
|
+
end
|
59
|
+
|
60
|
+
should "return nil instead of raising error" do
|
61
|
+
@status.target.nil?.should be_true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'models'
|
3
|
+
|
4
|
+
class BelongsToProxyTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@post_class = Doc()
|
7
|
+
@comment_class = Doc do
|
8
|
+
key :post_id, String
|
9
|
+
end
|
10
|
+
|
11
|
+
@comment_class.belongs_to :post, :class => @post_class
|
12
|
+
end
|
13
|
+
|
14
|
+
should "default to nil" do
|
15
|
+
@comment_class.new.post.nil?.should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
should "return nil instead of a proxy" do
|
19
|
+
nil.should === @comment_class.new.post
|
20
|
+
end
|
21
|
+
|
22
|
+
should "have boolean presence method" do
|
23
|
+
comment = @comment_class.new(:name => 'Foo!')
|
24
|
+
comment.post?.should be_false
|
25
|
+
|
26
|
+
comment.post = @post_class.new(:name => 'mongomapper')
|
27
|
+
comment.post?.should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
should "be able to replace the association" do
|
31
|
+
post = @post_class.new(:name => 'mongomapper')
|
32
|
+
comment = @comment_class.new(:name => 'Foo!', :post => post)
|
33
|
+
comment.save.should be_true
|
34
|
+
|
35
|
+
comment = comment.reload
|
36
|
+
comment.post.should == post
|
37
|
+
comment.post.nil?.should be_false
|
38
|
+
end
|
39
|
+
|
40
|
+
should "generate a new proxy when replacing the association" do
|
41
|
+
post1 = @post_class.create(:name => 'post1')
|
42
|
+
post2 = @post_class.create(:name => 'post2')
|
43
|
+
|
44
|
+
comment = @comment_class.new(:name => 'Foo!', :post => post1)
|
45
|
+
comment.save.should be_true
|
46
|
+
|
47
|
+
|
48
|
+
comment = comment.reload
|
49
|
+
comment.post.should == post1
|
50
|
+
comment.post.nil?.should be_false
|
51
|
+
|
52
|
+
original_post = comment.post
|
53
|
+
original_post.name.should == 'post1'
|
54
|
+
|
55
|
+
comment.post = post2
|
56
|
+
comment.post.name.should == 'post2'
|
57
|
+
original_post.name.should == 'post1'
|
58
|
+
end
|
59
|
+
|
60
|
+
should "unset the association" do
|
61
|
+
post = @post_class.new(:name => 'mongomapper')
|
62
|
+
comment = @comment_class.new(:name => 'Foo!', :post => post)
|
63
|
+
comment.save.should be_true
|
64
|
+
|
65
|
+
comment = comment.reload
|
66
|
+
comment.post = nil
|
67
|
+
comment.post.nil?.should be_true
|
68
|
+
end
|
69
|
+
|
70
|
+
should "return nil if id set but document not found" do
|
71
|
+
id = BSON::ObjectId.new
|
72
|
+
@comment_class.new(:name => 'Foo', :post_id => id).post.nil?.should be_true
|
73
|
+
end
|
74
|
+
|
75
|
+
context ":dependent" do
|
76
|
+
setup do
|
77
|
+
# FIXME: make use of already defined models
|
78
|
+
class ::Property
|
79
|
+
include MongoMapper::Document
|
80
|
+
end
|
81
|
+
Property.collection.remove
|
82
|
+
|
83
|
+
class ::Thing
|
84
|
+
include MongoMapper::Document
|
85
|
+
key :name, String
|
86
|
+
end
|
87
|
+
Thing.collection.remove
|
88
|
+
end
|
89
|
+
|
90
|
+
teardown do
|
91
|
+
Object.send :remove_const, 'Property' if defined?(::Property)
|
92
|
+
Object.send :remove_const, 'Thing' if defined?(::Thing)
|
93
|
+
end
|
94
|
+
|
95
|
+
context "=> destroy" do
|
96
|
+
setup do
|
97
|
+
Property.key :thing_id, ObjectId
|
98
|
+
Property.belongs_to :thing, :dependent => :destroy
|
99
|
+
Thing.many :properties
|
100
|
+
|
101
|
+
@thing = Thing.create(:name => "Tree")
|
102
|
+
@property1 = Property.create
|
103
|
+
@property2 = Property.create
|
104
|
+
@property3 = Property.create
|
105
|
+
@thing.properties << @property1
|
106
|
+
@thing.properties << @property2
|
107
|
+
@thing.properties << @property3
|
108
|
+
end
|
109
|
+
|
110
|
+
should "not execute on a belongs_to association" do
|
111
|
+
Thing.count.should == 1
|
112
|
+
@property1.destroy
|
113
|
+
Thing.count.should == 1
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|