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.
- data/LICENSE +20 -0
- data/README.rdoc +33 -0
- data/UPGRADES +26 -0
- data/bin/mmconsole +59 -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 +2 -0
- data/examples/keys.rb +40 -0
- data/examples/modifiers/set.rb +25 -0
- data/examples/plugins.rb +38 -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 +94 -0
- data/lib/mongo_mapper/connection.rb +96 -0
- data/lib/mongo_mapper/document.rb +42 -0
- data/lib/mongo_mapper/embedded_document.rb +32 -0
- data/lib/mongo_mapper/exceptions.rb +30 -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 +26 -0
- data/lib/mongo_mapper/extensions/object_id.rb +32 -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 +28 -0
- data/lib/mongo_mapper/locale/en.yml +5 -0
- data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
- data/lib/mongo_mapper/plugins.rb +22 -0
- data/lib/mongo_mapper/plugins/accessible.rb +52 -0
- data/lib/mongo_mapper/plugins/active_model.rb +18 -0
- data/lib/mongo_mapper/plugins/associations.rb +90 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +92 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +54 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +34 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +133 -0
- data/lib/mongo_mapper/plugins/associations/many_association.rb +63 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +118 -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_as_proxy.rb +22 -0
- data/lib/mongo_mapper/plugins/associations/one_association.rb +48 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +95 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +134 -0
- data/lib/mongo_mapper/plugins/associations/single_association.rb +46 -0
- data/lib/mongo_mapper/plugins/caching.rb +21 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +29 -0
- data/lib/mongo_mapper/plugins/clone.rb +22 -0
- data/lib/mongo_mapper/plugins/dirty.rb +60 -0
- data/lib/mongo_mapper/plugins/document.rb +41 -0
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +45 -0
- data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +56 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +53 -0
- data/lib/mongo_mapper/plugins/equality.rb +23 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
- data/lib/mongo_mapper/plugins/indexes.rb +13 -0
- data/lib/mongo_mapper/plugins/inspect.rb +16 -0
- data/lib/mongo_mapper/plugins/keys.rb +313 -0
- data/lib/mongo_mapper/plugins/keys/key.rb +61 -0
- data/lib/mongo_mapper/plugins/logger.rb +18 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +134 -0
- data/lib/mongo_mapper/plugins/pagination.rb +16 -0
- data/lib/mongo_mapper/plugins/persistence.rb +69 -0
- data/lib/mongo_mapper/plugins/protected.rb +45 -0
- data/lib/mongo_mapper/plugins/querying.rb +165 -0
- data/lib/mongo_mapper/plugins/querying/decorator.rb +36 -0
- data/lib/mongo_mapper/plugins/rails.rb +58 -0
- data/lib/mongo_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
- data/lib/mongo_mapper/plugins/safe.rb +28 -0
- data/lib/mongo_mapper/plugins/sci.rb +36 -0
- data/lib/mongo_mapper/plugins/scopes.rb +27 -0
- data/lib/mongo_mapper/plugins/serialization.rb +109 -0
- data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
- data/lib/mongo_mapper/plugins/touch.rb +18 -0
- data/lib/mongo_mapper/plugins/userstamps.rb +18 -0
- data/lib/mongo_mapper/plugins/validations.rb +86 -0
- data/lib/mongo_mapper/railtie.rb +48 -0
- data/lib/mongo_mapper/railtie/database.rake +65 -0
- data/lib/mongo_mapper/translation.rb +10 -0
- data/lib/mongo_mapper/version.rb +4 -0
- data/lib/rails/generators/mongo_mapper/config/config_generator.rb +24 -0
- data/lib/rails/generators/mongo_mapper/config/templates/mongo.yml +18 -0
- data/lib/rails/generators/mongo_mapper/model/model_generator.rb +23 -0
- data/lib/rails/generators/mongo_mapper/model/templates/model.rb +13 -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 +238 -0
- data/test/functional/associations/test_in_array_proxy.rb +349 -0
- data/test/functional/associations/test_many_documents_as_proxy.rb +231 -0
- data/test/functional/associations/test_many_documents_proxy.rb +866 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +239 -0
- data/test/functional/associations/test_many_embedded_proxy.rb +289 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
- data/test/functional/associations/test_one_as_proxy.rb +491 -0
- data/test/functional/associations/test_one_embedded_polymorphic_proxy.rb +208 -0
- data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
- data/test/functional/associations/test_one_proxy.rb +383 -0
- data/test/functional/test_accessible.rb +198 -0
- data/test/functional/test_associations.rb +46 -0
- data/test/functional/test_binary.rb +27 -0
- data/test/functional/test_caching.rb +77 -0
- data/test/functional/test_callbacks.rb +232 -0
- data/test/functional/test_dirty.rb +301 -0
- data/test/functional/test_document.rb +282 -0
- data/test/functional/test_dynamic_querying.rb +75 -0
- data/test/functional/test_embedded_document.rb +288 -0
- data/test/functional/test_equality.rb +20 -0
- data/test/functional/test_identity_map.rb +513 -0
- data/test/functional/test_indexes.rb +50 -0
- data/test/functional/test_logger.rb +20 -0
- data/test/functional/test_modifiers.rb +537 -0
- data/test/functional/test_pagination.rb +91 -0
- data/test/functional/test_protected.rb +201 -0
- data/test/functional/test_querying.rb +935 -0
- data/test/functional/test_safe.rb +76 -0
- data/test/functional/test_sci.rb +240 -0
- data/test/functional/test_scopes.rb +171 -0
- data/test/functional/test_timestamps.rb +62 -0
- data/test/functional/test_touch.rb +125 -0
- data/test/functional/test_userstamps.rb +44 -0
- data/test/functional/test_validations.rb +414 -0
- data/test/models.rb +261 -0
- data/test/support/railtie.rb +4 -0
- data/test/support/railtie/autoloaded.rb +2 -0
- data/test/support/railtie/not_autoloaded.rb +3 -0
- data/test/support/railtie/parent.rb +3 -0
- data/test/test_active_model_lint.rb +18 -0
- data/test/test_helper.rb +93 -0
- data/test/unit/associations/test_base.rb +146 -0
- data/test/unit/associations/test_belongs_to_association.rb +29 -0
- data/test/unit/associations/test_many_association.rb +63 -0
- data/test/unit/associations/test_one_association.rb +47 -0
- data/test/unit/associations/test_proxy.rb +100 -0
- data/test/unit/serializers/test_json_serializer.rb +216 -0
- data/test/unit/serializers/test_xml_serializer.rb +196 -0
- data/test/unit/test_clone.rb +69 -0
- data/test/unit/test_document.rb +249 -0
- data/test/unit/test_dynamic_finder.rb +125 -0
- data/test/unit/test_embedded_document.rb +682 -0
- data/test/unit/test_equality.rb +38 -0
- data/test/unit/test_exceptions.rb +12 -0
- data/test/unit/test_extensions.rb +380 -0
- data/test/unit/test_identity_map_middleware.rb +34 -0
- data/test/unit/test_inspect.rb +47 -0
- data/test/unit/test_key.rb +205 -0
- data/test/unit/test_keys.rb +65 -0
- data/test/unit/test_mongo_mapper.rb +143 -0
- data/test/unit/test_pagination.rb +11 -0
- data/test/unit/test_plugins.rb +89 -0
- data/test/unit/test_rails.rb +183 -0
- data/test/unit/test_rails_compatibility.rb +38 -0
- data/test/unit/test_rails_reflect_on_association.rb +118 -0
- data/test/unit/test_railtie.rb +66 -0
- data/test/unit/test_serialization.rb +166 -0
- data/test/unit/test_time_zones.rb +44 -0
- data/test/unit/test_translation.rb +27 -0
- data/test/unit/test_validations.rb +562 -0
- 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,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
|