lookout-mongo_mapper 0.11.3

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 (176) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +33 -0
  3. data/UPGRADES +26 -0
  4. data/bin/mmconsole +59 -0
  5. data/examples/attr_accessible.rb +22 -0
  6. data/examples/attr_protected.rb +22 -0
  7. data/examples/cache_key.rb +24 -0
  8. data/examples/custom_types.rb +24 -0
  9. data/examples/identity_map.rb +33 -0
  10. data/examples/identity_map/automatic.rb +2 -0
  11. data/examples/keys.rb +40 -0
  12. data/examples/modifiers/set.rb +25 -0
  13. data/examples/plugins.rb +38 -0
  14. data/examples/querying.rb +35 -0
  15. data/examples/safe.rb +43 -0
  16. data/examples/scopes.rb +52 -0
  17. data/examples/validating/embedded_docs.rb +29 -0
  18. data/lib/mongo_mapper.rb +94 -0
  19. data/lib/mongo_mapper/connection.rb +96 -0
  20. data/lib/mongo_mapper/document.rb +42 -0
  21. data/lib/mongo_mapper/embedded_document.rb +32 -0
  22. data/lib/mongo_mapper/exceptions.rb +30 -0
  23. data/lib/mongo_mapper/extensions/array.rb +19 -0
  24. data/lib/mongo_mapper/extensions/binary.rb +22 -0
  25. data/lib/mongo_mapper/extensions/boolean.rb +44 -0
  26. data/lib/mongo_mapper/extensions/date.rb +25 -0
  27. data/lib/mongo_mapper/extensions/float.rb +14 -0
  28. data/lib/mongo_mapper/extensions/hash.rb +14 -0
  29. data/lib/mongo_mapper/extensions/integer.rb +19 -0
  30. data/lib/mongo_mapper/extensions/kernel.rb +9 -0
  31. data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
  32. data/lib/mongo_mapper/extensions/object.rb +26 -0
  33. data/lib/mongo_mapper/extensions/object_id.rb +32 -0
  34. data/lib/mongo_mapper/extensions/set.rb +20 -0
  35. data/lib/mongo_mapper/extensions/string.rb +18 -0
  36. data/lib/mongo_mapper/extensions/time.rb +28 -0
  37. data/lib/mongo_mapper/locale/en.yml +5 -0
  38. data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
  39. data/lib/mongo_mapper/plugins.rb +22 -0
  40. data/lib/mongo_mapper/plugins/accessible.rb +52 -0
  41. data/lib/mongo_mapper/plugins/active_model.rb +18 -0
  42. data/lib/mongo_mapper/plugins/associations.rb +90 -0
  43. data/lib/mongo_mapper/plugins/associations/base.rb +92 -0
  44. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +54 -0
  45. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +34 -0
  46. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
  47. data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
  48. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +44 -0
  49. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +133 -0
  50. data/lib/mongo_mapper/plugins/associations/many_association.rb +63 -0
  51. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  52. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +118 -0
  53. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
  54. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
  55. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
  56. data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +22 -0
  57. data/lib/mongo_mapper/plugins/associations/one_association.rb +48 -0
  58. data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
  59. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
  60. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +95 -0
  61. data/lib/mongo_mapper/plugins/associations/proxy.rb +134 -0
  62. data/lib/mongo_mapper/plugins/associations/single_association.rb +46 -0
  63. data/lib/mongo_mapper/plugins/caching.rb +21 -0
  64. data/lib/mongo_mapper/plugins/callbacks.rb +29 -0
  65. data/lib/mongo_mapper/plugins/clone.rb +22 -0
  66. data/lib/mongo_mapper/plugins/dirty.rb +60 -0
  67. data/lib/mongo_mapper/plugins/document.rb +41 -0
  68. data/lib/mongo_mapper/plugins/dynamic_querying.rb +45 -0
  69. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
  70. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +56 -0
  71. data/lib/mongo_mapper/plugins/embedded_document.rb +53 -0
  72. data/lib/mongo_mapper/plugins/equality.rb +23 -0
  73. data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
  74. data/lib/mongo_mapper/plugins/indexes.rb +13 -0
  75. data/lib/mongo_mapper/plugins/inspect.rb +16 -0
  76. data/lib/mongo_mapper/plugins/keys.rb +313 -0
  77. data/lib/mongo_mapper/plugins/keys/key.rb +61 -0
  78. data/lib/mongo_mapper/plugins/logger.rb +18 -0
  79. data/lib/mongo_mapper/plugins/modifiers.rb +134 -0
  80. data/lib/mongo_mapper/plugins/pagination.rb +16 -0
  81. data/lib/mongo_mapper/plugins/persistence.rb +69 -0
  82. data/lib/mongo_mapper/plugins/protected.rb +45 -0
  83. data/lib/mongo_mapper/plugins/querying.rb +165 -0
  84. data/lib/mongo_mapper/plugins/querying/decorator.rb +36 -0
  85. data/lib/mongo_mapper/plugins/rails.rb +58 -0
  86. data/lib/mongo_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
  87. data/lib/mongo_mapper/plugins/safe.rb +28 -0
  88. data/lib/mongo_mapper/plugins/sci.rb +36 -0
  89. data/lib/mongo_mapper/plugins/scopes.rb +27 -0
  90. data/lib/mongo_mapper/plugins/serialization.rb +109 -0
  91. data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
  92. data/lib/mongo_mapper/plugins/touch.rb +18 -0
  93. data/lib/mongo_mapper/plugins/userstamps.rb +18 -0
  94. data/lib/mongo_mapper/plugins/validations.rb +86 -0
  95. data/lib/mongo_mapper/railtie.rb +48 -0
  96. data/lib/mongo_mapper/railtie/database.rake +65 -0
  97. data/lib/mongo_mapper/translation.rb +10 -0
  98. data/lib/mongo_mapper/version.rb +4 -0
  99. data/lib/rails/generators/mongo_mapper/config/config_generator.rb +24 -0
  100. data/lib/rails/generators/mongo_mapper/config/templates/mongo.yml +18 -0
  101. data/lib/rails/generators/mongo_mapper/model/model_generator.rb +23 -0
  102. data/lib/rails/generators/mongo_mapper/model/templates/model.rb +13 -0
  103. data/test/_NOTE_ON_TESTING +1 -0
  104. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +64 -0
  105. data/test/functional/associations/test_belongs_to_proxy.rb +238 -0
  106. data/test/functional/associations/test_in_array_proxy.rb +349 -0
  107. data/test/functional/associations/test_many_documents_as_proxy.rb +231 -0
  108. data/test/functional/associations/test_many_documents_proxy.rb +866 -0
  109. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +239 -0
  110. data/test/functional/associations/test_many_embedded_proxy.rb +289 -0
  111. data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
  112. data/test/functional/associations/test_one_as_proxy.rb +491 -0
  113. data/test/functional/associations/test_one_embedded_polymorphic_proxy.rb +208 -0
  114. data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
  115. data/test/functional/associations/test_one_proxy.rb +383 -0
  116. data/test/functional/test_accessible.rb +198 -0
  117. data/test/functional/test_associations.rb +46 -0
  118. data/test/functional/test_binary.rb +27 -0
  119. data/test/functional/test_caching.rb +77 -0
  120. data/test/functional/test_callbacks.rb +232 -0
  121. data/test/functional/test_dirty.rb +301 -0
  122. data/test/functional/test_document.rb +282 -0
  123. data/test/functional/test_dynamic_querying.rb +75 -0
  124. data/test/functional/test_embedded_document.rb +288 -0
  125. data/test/functional/test_equality.rb +20 -0
  126. data/test/functional/test_identity_map.rb +513 -0
  127. data/test/functional/test_indexes.rb +50 -0
  128. data/test/functional/test_logger.rb +20 -0
  129. data/test/functional/test_modifiers.rb +537 -0
  130. data/test/functional/test_pagination.rb +91 -0
  131. data/test/functional/test_protected.rb +201 -0
  132. data/test/functional/test_querying.rb +935 -0
  133. data/test/functional/test_safe.rb +76 -0
  134. data/test/functional/test_sci.rb +240 -0
  135. data/test/functional/test_scopes.rb +171 -0
  136. data/test/functional/test_timestamps.rb +62 -0
  137. data/test/functional/test_touch.rb +125 -0
  138. data/test/functional/test_userstamps.rb +44 -0
  139. data/test/functional/test_validations.rb +414 -0
  140. data/test/models.rb +261 -0
  141. data/test/support/railtie.rb +4 -0
  142. data/test/support/railtie/autoloaded.rb +2 -0
  143. data/test/support/railtie/not_autoloaded.rb +3 -0
  144. data/test/support/railtie/parent.rb +3 -0
  145. data/test/test_active_model_lint.rb +18 -0
  146. data/test/test_helper.rb +93 -0
  147. data/test/unit/associations/test_base.rb +146 -0
  148. data/test/unit/associations/test_belongs_to_association.rb +29 -0
  149. data/test/unit/associations/test_many_association.rb +63 -0
  150. data/test/unit/associations/test_one_association.rb +47 -0
  151. data/test/unit/associations/test_proxy.rb +100 -0
  152. data/test/unit/serializers/test_json_serializer.rb +216 -0
  153. data/test/unit/serializers/test_xml_serializer.rb +196 -0
  154. data/test/unit/test_clone.rb +69 -0
  155. data/test/unit/test_document.rb +249 -0
  156. data/test/unit/test_dynamic_finder.rb +125 -0
  157. data/test/unit/test_embedded_document.rb +682 -0
  158. data/test/unit/test_equality.rb +38 -0
  159. data/test/unit/test_exceptions.rb +12 -0
  160. data/test/unit/test_extensions.rb +380 -0
  161. data/test/unit/test_identity_map_middleware.rb +34 -0
  162. data/test/unit/test_inspect.rb +47 -0
  163. data/test/unit/test_key.rb +205 -0
  164. data/test/unit/test_keys.rb +65 -0
  165. data/test/unit/test_mongo_mapper.rb +143 -0
  166. data/test/unit/test_pagination.rb +11 -0
  167. data/test/unit/test_plugins.rb +89 -0
  168. data/test/unit/test_rails.rb +183 -0
  169. data/test/unit/test_rails_compatibility.rb +38 -0
  170. data/test/unit/test_rails_reflect_on_association.rb +118 -0
  171. data/test/unit/test_railtie.rb +66 -0
  172. data/test/unit/test_serialization.rb +166 -0
  173. data/test/unit/test_time_zones.rb +44 -0
  174. data/test/unit/test_translation.rb +27 -0
  175. data/test/unit/test_validations.rb +562 -0
  176. metadata +285 -0
@@ -0,0 +1,48 @@
1
+ require "mongo_mapper"
2
+ require "rails"
3
+ require "active_model/railtie"
4
+
5
+ module MongoMapper
6
+ # = MongoMapper Railtie
7
+ class Railtie < Rails::Railtie
8
+
9
+ config.mongo_mapper = ActiveSupport::OrderedOptions.new
10
+
11
+ rake_tasks do
12
+ load "mongo_mapper/railtie/database.rake"
13
+ end
14
+
15
+ initializer "mongo_mapper.set_configs" do |app|
16
+ ActiveSupport.on_load(:mongo_mapper) do
17
+ app.config.mongo_mapper.each do |k,v|
18
+ send "#{k}=", v
19
+ end
20
+ end
21
+ end
22
+
23
+ # This sets the database configuration and establishes the connection.
24
+ initializer "mongo_mapper.initialize_database" do |app|
25
+ config_file = Rails.root.join('config/mongo.yml')
26
+ if config_file.file?
27
+ config = YAML.load(ERB.new(config_file.read).result)
28
+ MongoMapper.setup(config, Rails.env, :logger => Rails.logger)
29
+ end
30
+ end
31
+
32
+ # Clear the identity map after each request
33
+ initializer "mongo_mapper.clear_identity_map" do |app|
34
+ app.config.middleware.use 'MongoMapper::Middleware::IdentityMap'
35
+ end
36
+
37
+ initializer "mongo_mapper.prepare_dispatcher" do |app|
38
+ # See http://groups.google.com/group/mongomapper/browse_thread/thread/68f62e8eda43b43a/4841dba76938290c
39
+ # to_prepare is called before each request in development mode and the first request in production.
40
+
41
+ ActionDispatch::Callbacks.to_prepare do
42
+ unless app.config.cache_classes
43
+ MongoMapper::Plugins::IdentityMap.models.clear
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,65 @@
1
+ namespace :db do
2
+ unless Rake::Task.task_defined?("db:drop")
3
+ desc 'Drops all the collections for the database for the current Rails.env'
4
+ task :drop => :environment do
5
+ MongoMapper.database.collections.select {|c| c.name !~ /system/ }.each(&:drop)
6
+ end
7
+ end
8
+
9
+ unless Rake::Task.task_defined?("db:seed")
10
+ # if another ORM has defined db:seed, don't run it twice.
11
+ desc 'Load the seed data from db/seeds.rb'
12
+ task :seed => :environment do
13
+ seed_file = File.join(Rails.root, 'db', 'seeds.rb')
14
+ load(seed_file) if File.exist?(seed_file)
15
+ end
16
+ end
17
+
18
+ unless Rake::Task.task_defined?("db:setup")
19
+ desc 'Create the database, and initialize with the seed data'
20
+ task :setup => [ 'db:create', 'db:seed' ]
21
+ end
22
+
23
+ unless Rake::Task.task_defined?("db:reseed")
24
+ desc 'Delete data and seed'
25
+ task :reseed => [ 'db:drop', 'db:seed' ]
26
+ end
27
+
28
+ unless Rake::Task.task_defined?("db:create")
29
+ task :create => :environment do
30
+ # noop
31
+ end
32
+ end
33
+
34
+ unless Rake::Task.task_defined?("db:migrate")
35
+ task :migrate => :environment do
36
+ # noop
37
+ end
38
+ end
39
+
40
+ unless Rake::Task.task_defined?("db:schema:load")
41
+ namespace :schema do
42
+ task :load do
43
+ # noop
44
+ end
45
+ end
46
+ end
47
+
48
+ unless Rake::Task.task_defined?("db:test:prepare")
49
+ namespace :test do
50
+ task :prepare => :environment do
51
+ MongoMapper.connect('test')
52
+ MongoMapper.database.collections.select {|c| c.name !~ /system/ }.each(&:drop)
53
+ MongoMapper.connect(Rails.env)
54
+ end
55
+ end
56
+ end
57
+
58
+ desc 'Load indexes from db/indexes.rb'
59
+ task :index => :environment do
60
+ indexes = File.join(Rails.root, 'db', 'indexes.rb')
61
+ load(indexes) if File.exist?(indexes)
62
+ end
63
+ end
64
+
65
+ task 'test:prepare' => 'db:test:prepare'
@@ -0,0 +1,10 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ module Translation
4
+ include ActiveModel::Translation
5
+
6
+ def i18n_scope
7
+ :mongo_mapper
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ # encoding: UTF-8
2
+ module MongoMapper
3
+ Version = '0.11.3'
4
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ module MongoMapper
4
+ module Generators
5
+ class ConfigGenerator < Rails::Generators::Base
6
+ desc "creates the MongoMapper configuration at config/mongo.yml"
7
+
8
+ argument :database_name, :type => :string, :optional => true
9
+
10
+ def self.source_root
11
+ @source_root ||= File.expand_path("../templates", __FILE__)
12
+ end
13
+
14
+ def app_name
15
+ Rails::Application.subclasses.first.parent.to_s.underscore
16
+ end
17
+
18
+ def create_config_file
19
+ template 'mongo.yml', File.join('config', "mongo.yml")
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ defaults: &defaults
2
+ host: 127.0.0.1
3
+ port: 27017
4
+
5
+ development:
6
+ <<: *defaults
7
+ database: <%= database_name || app_name %>_development
8
+
9
+ test:
10
+ <<: *defaults
11
+ database: <%= database_name || app_name %>_test
12
+
13
+ # set these environment variables on your prod server
14
+ production:
15
+ <<: *defaults
16
+ database: <%= database_name || app_name %>
17
+ username: <%%= ENV['MONGO_USERNAME'] %>
18
+ password: <%%= ENV['MONGO_PASSWORD'] %>
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ module MongoMapper
4
+ module Generators
5
+ class ModelGenerator < Rails::Generators::NamedBase
6
+ desc 'Creates a mongomapper model'
7
+ argument :name, :type => :string
8
+ argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
9
+ class_option :timestamps, :type => :boolean
10
+ check_class_collision
11
+
12
+ def self.source_root
13
+ @source_root ||= File.expand_path("../templates", __FILE__)
14
+ end
15
+
16
+ def create_model_file
17
+ template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
18
+ end
19
+
20
+ hook_for :test_framework
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>
3
+ include MongoMapper::Document
4
+
5
+ <% attributes.each do |attribute| -%>
6
+ key :<%= attribute.name %>, <%= attribute.type.to_s.camelcase %>
7
+ <% end -%>
8
+ <% if options[:timestamps] %>
9
+ timestamps!
10
+ <% end -%>
11
+
12
+ end
13
+ <% end -%>
@@ -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,238 @@
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, ObjectId
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 "allow overriding association methods" do
31
+ @comment_class.class_eval do
32
+ def post?
33
+ super
34
+ end
35
+ end
36
+
37
+ instance = @comment_class.new
38
+ instance.post?.should be_false
39
+ instance.post = @post_class.new
40
+ instance.post?.should be_true
41
+ end
42
+
43
+ should "be able to replace the association" do
44
+ post = @post_class.new(:name => 'mongomapper')
45
+ comment = @comment_class.new(:name => 'Foo!', :post => post)
46
+ comment.save.should be_true
47
+
48
+ comment = comment.reload
49
+ comment.post.should == post
50
+ comment.post.nil?.should be_false
51
+ end
52
+
53
+ should "not reload the association when replacing" do
54
+ post = @post_class.new(:name => 'mongomapper')
55
+ comment = @comment_class.new(:name => 'Foo!', :post => post)
56
+ comment.post.proxy_target.object_id.should == post.object_id
57
+ end
58
+
59
+ should "properly assign the associated object when assigning the association with create" do
60
+ child_class = Doc('Child')
61
+ parent_class = Doc('Parent')
62
+
63
+ parent_class.one :child, :class => child_class
64
+ child_class.belongs_to :parent, :class => parent_class
65
+
66
+ child = child_class.create(:parent => parent_class.create)
67
+ child.parent.child.should == child
68
+ end
69
+
70
+ should "generate a new proxy when replacing the association" do
71
+ post1 = @post_class.create(:name => 'post1')
72
+ post2 = @post_class.create(:name => 'post2')
73
+
74
+ comment = @comment_class.new(:name => 'Foo!', :post => post1)
75
+ comment.save.should be_true
76
+
77
+
78
+ comment = comment.reload
79
+ comment.post.should == post1
80
+ comment.post.nil?.should be_false
81
+
82
+ original_post = comment.post
83
+ original_post.name.should == 'post1'
84
+
85
+ comment.post = post2
86
+ comment.post.name.should == 'post2'
87
+ original_post.name.should == 'post1'
88
+ end
89
+
90
+ should "unset the association" do
91
+ post = @post_class.new(:name => 'mongomapper')
92
+ comment = @comment_class.new(:name => 'Foo!', :post => post)
93
+ comment.save.should be_true
94
+
95
+ comment = comment.reload
96
+ comment.post = nil
97
+ comment.post.nil?.should be_true
98
+ end
99
+
100
+ should "return nil if id set but document not found" do
101
+ id = BSON::ObjectId.new
102
+ @comment_class.new(:name => 'Foo', :post_id => id).post.nil?.should be_true
103
+ end
104
+
105
+ should "define foreign key if it doesn't exist" do
106
+ @category_class = Doc()
107
+ @post_class.belongs_to :category, :class => @category_class
108
+
109
+ @post_class.key?(:category_id).should be_true
110
+ end
111
+
112
+ should "not define foreign key if it already exists" do
113
+ @category_class = Doc()
114
+ @post_class.key :category_id, String
115
+ @post_class.belongs_to :category, :class => @category_class
116
+
117
+ @post_class.keys['category_id'].type.should == String
118
+ end
119
+
120
+ context ":dependent" do
121
+ setup do
122
+ # FIXME: make use of already defined models
123
+ class ::Property
124
+ include MongoMapper::Document
125
+ end
126
+ Property.collection.remove
127
+
128
+ class ::Thing
129
+ include MongoMapper::Document
130
+ key :name, String
131
+ end
132
+ Thing.collection.remove
133
+ end
134
+
135
+ teardown do
136
+ Object.send :remove_const, 'Property' if defined?(::Property)
137
+ Object.send :remove_const, 'Thing' if defined?(::Thing)
138
+ end
139
+
140
+ context "=> destroy" do
141
+ setup do
142
+ Property.key :thing_id, ObjectId
143
+ Property.belongs_to :thing, :dependent => :destroy
144
+ Thing.many :properties
145
+
146
+ @thing = Thing.create(:name => "Tree")
147
+ @property1 = Property.create
148
+ @property2 = Property.create
149
+ @property3 = Property.create
150
+ @thing.properties << @property1
151
+ @thing.properties << @property2
152
+ @thing.properties << @property3
153
+ end
154
+
155
+ should "not execute on a belongs_to association" do
156
+ Thing.count.should == 1
157
+ @property1.destroy
158
+ Thing.count.should == 1
159
+ end
160
+ end
161
+ end
162
+
163
+ should "be able to build" do
164
+ @comment_class.belongs_to :post, :class => @post_class
165
+
166
+ comment = @comment_class.create
167
+ post = comment.build_post(:title => 'Hello, world!')
168
+ comment.post.should be_instance_of(@post_class)
169
+ comment.post.should be_new
170
+ comment.post.title.should == 'Hello, world!'
171
+ comment.post.should == post
172
+ comment.post_id.should == post.id
173
+ end
174
+
175
+ should "be able to create" do
176
+ @comment_class.belongs_to :post, :class => @post_class
177
+
178
+ comment = @comment_class.create
179
+ post = comment.create_post(:title => 'Hello, world!')
180
+ comment.post.should be_instance_of(@post_class)
181
+ comment.post.should_not be_new
182
+ comment.post.title.should == 'Hello, world!'
183
+ comment.post.should == post
184
+ comment.post_id.should == post.id
185
+ end
186
+
187
+ context "#create!" do
188
+ setup do
189
+ @post_class.key :title, String, :required => true
190
+ @comment_class.belongs_to :post, :class => @post_class
191
+ end
192
+
193
+ should "raise exception if invalid" do
194
+ comment = @comment_class.create
195
+ assert_raises(MongoMapper::DocumentNotValid) do
196
+ comment.create_post!
197
+ end
198
+ end
199
+
200
+ should "work if valid" do
201
+ comment = @comment_class.create
202
+ post = comment.create_post!(:title => 'Hello, world!')
203
+ comment.post.should be_instance_of(@post_class)
204
+ comment.post.should_not be_new
205
+ comment.post.title.should == 'Hello, world!'
206
+ comment.post.should == post
207
+ comment.post_id.should == post.id
208
+ end
209
+ end
210
+
211
+ context 'autosave' do
212
+ should 'not be true by default' do
213
+ @comment_class.associations[:post].options[:autosave].should_not be_true
214
+ end
215
+
216
+ should 'save parent changes when true' do
217
+ @comment_class.associations[:post].options[:autosave] = true
218
+
219
+ comment = @comment_class.create
220
+ post = comment.create_post(:title => 'Hello, world!')
221
+
222
+ comment.post.attributes = {:title => 'Hi, world.'}
223
+ comment.save
224
+
225
+ post.reload.title.should == 'Hi, world.'
226
+ end
227
+
228
+ should 'not save parent changes when false' do
229
+ comment = @comment_class.create
230
+ post = comment.create_post(:title => 'Hello, world!')
231
+
232
+ comment.post.attributes = {:title => 'Hi, world.'}
233
+ comment.save
234
+
235
+ post.reload.title.should == 'Hello, world!'
236
+ end
237
+ end
238
+ end