Browse files

Adding first round of convenience methods for connecting from Rails. …

…Can now be something like this:

  MongoMapper.setup(YAML.load(Rails.root.join('config', 'database.yml')), Rails.env, {
    :logger    => Rails.logger),
    :passenger => true,
  })

Instead of the much more verbose:

  config = YAML.load_file(Rails.root + 'config' + 'database.yml')[Rails.env]

  MongoMapper.connection = Mongo::Connection.new(config['host'], config['port'], :logger => Rails.logger)
  MongoMapper.database = config['database']

  if config['username'].present?
    MongoMapper.database.authenticate(config['username'], config['password'])
  end

  if defined?(PhusionPassenger)
    PhusionPassenger.on_event(:starting_worker_process) do |forked|
      MongoMapper.connection.connect_to_master if forked
    end
  end
  • Loading branch information...
1 parent d35d17a commit efad5c7ba2ba648c55e49a400423c43857a2f77a @jnunemaker jnunemaker committed with Karl Feb 9, 2010
Showing with 118 additions and 25 deletions.
  1. +49 −16 lib/mongo_mapper.rb
  2. +69 −9 test/unit/test_mongo_mapper.rb
View
65 lib/mongo_mapper.rb
@@ -17,83 +17,116 @@
module MongoMapper
# generic MM error
class MongoMapperError < StandardError; end
-
+
# raised when key expected to exist but not found
class KeyNotFound < MongoMapperError; end
-
+
# raised when document expected but not found
class DocumentNotFound < MongoMapperError; end
-
+
# raised when document not valid and using !
class DocumentNotValid < MongoMapperError
def initialize(document)
super("Validation failed: #{document.errors.full_messages.join(", ")}")
end
end
-
+
# @api public
def self.connection
@@connection ||= Mongo::Connection.new
end
-
+
# @api public
def self.connection=(new_connection)
@@connection = new_connection
end
-
+
# @api public
def self.logger
connection.logger
end
-
+
# @api public
def self.database=(name)
@@database = nil
@@database_name = name
end
-
+
# @api public
def self.database
if @@database_name.blank?
raise 'You forgot to set the default database name: MongoMapper.database = "foobar"'
end
-
+
@@database ||= MongoMapper.connection.db(@@database_name)
end
-
+
+ def self.config=(hash)
+ @@config = hash
+ end
+
+ def self.config
+ raise 'Set config before connecting. MongoMapper.config = {...}' unless defined?(@@config)
+ @@config
+ end
+
+ def self.connect(environment, options={})
+ raise 'Set config before connecting. MongoMapper.config = {...}' if config.blank?
+ MongoMapper.connection = Mongo::Connection.new(config[environment]['host'], config[environment]['port'], options)
+ MongoMapper.database = config[environment]['database']
+ if config[environment]['username'].present? && config[environment]['password'].present?
+ MongoMapper.database.authenticate(config[environment]['username'], config[environment]['password'])
+ end
+ end
+
+ def self.setup(config, environment, options={})
+ using_passenger = options.delete(:passenger)
+ handle_passenger_forking if using_passenger
+ self.config = config
+ connect(environment, options)
+ end
+
+ def self.handle_passenger_forking
+ if defined?(PhusionPassenger)
+ PhusionPassenger.on_event(:starting_worker_process) do |forked|
+ connection.connect_to_master if forked
+ end
+ end
+ end
+
# @api private
def self.ensured_indexes
@@ensured_indexes ||= []
end
-
+
# @api private
def self.ensured_indexes=(value)
@@ensured_indexes = value
end
-
+
# @api private
def self.ensure_index(klass, keys, options={})
ensured_indexes << {:klass => klass, :keys => keys, :options => options}
end
-
+
# @api public
def self.ensure_indexes!
ensured_indexes.each do |index|
unique = index[:options].delete(:unique)
index[:klass].collection.create_index(index[:keys], unique)
end
end
-
+
# @api private
def self.use_time_zone?
Time.respond_to?(:zone) && Time.zone ? true : false
end
-
+
# @api private
def self.time_class
use_time_zone? ? Time.zone : Time
end
-
+
# @api private
def self.normalize_object_id(value)
value.is_a?(String) ? Mongo::ObjectID.from_string(value) : value
View
78 test/unit/test_mongo_mapper.rb
@@ -8,58 +8,118 @@ class MongoMapperTest < Test::Unit::TestCase
MongoMapper.connection = conn
MongoMapper.connection.should == conn
end
-
+
should "default connection to new mongo ruby driver" do
MongoMapper.connection = nil
MongoMapper.connection.should be_instance_of(Mongo::Connection)
end
-
+
should "be able to write and read default database" do
MongoMapper.database = 'test'
MongoMapper.database.should be_instance_of(Mongo::DB)
MongoMapper.database.name.should == 'test'
end
-
+
should "have document not found error" do
lambda {
MongoMapper::DocumentNotFound
}.should_not raise_error
end
+
+ should "be able to read/write config" do
+ config = {
+ 'development' => {'host' => '127.0.0.1', 'port' => 27017, 'database' => 'test'},
+ 'production' => {'host' => '127.0.0.1', 'port' => 27017, 'database' => 'test-prod'}
+ }
+
+ MongoMapper.config = config
+ MongoMapper.config.should == config
+ end
+
+ context "connecting to environment from config" do
+ should "work without authentication" do
+ MongoMapper.config = {
+ 'development' => {'host' => '127.0.0.1', 'port' => 27017, 'database' => 'test'}
+ }
+
+ Mongo::Connection.expects(:new).with('127.0.0.1', 27017, {})
+ MongoMapper.expects(:database=).with('test')
+ Mongo::DB.any_instance.expects(:authenticate).never
+ MongoMapper.connect('development')
+ end
+
+ should "work with options" do
+ MongoMapper.config = {
+ 'development' => {'host' => '127.0.0.1', 'port' => 27017, 'database' => 'test'}
+ }
+
+ connection, logger = mock('connection'), mock('logger')
+ Mongo::Connection.expects(:new).with('127.0.0.1', 27017, :logger => logger)
+ MongoMapper.connect('development', :logger => logger)
+ end
+
+ should "work with authentication" do
+ MongoMapper.config = {
+ 'development' => {'host' => '127.0.0.1', 'port' => 27017, 'database' => 'test', 'username' => 'john', 'password' => 'secret'}
+ }
+
+ Mongo::DB.any_instance.expects(:authenticate).with('john', 'secret')
+ MongoMapper.connect('development')
+ end
+ end
+
+ context "setup" do
+ should "work as shortcut for setting config, environment and options" do
+ config, logger = mock('config'), mock('logger')
+ MongoMapper.expects(:config=).with(config)
+ MongoMapper.expects(:connect).with('development', :logger => logger)
+ MongoMapper.expects(:handle_passenger_forking).never
+ MongoMapper.setup(config, 'development', :logger => logger)
+ end
+
+ should "handle passenger if option present" do
+ config, logger = mock('config'), mock('logger')
+ MongoMapper.expects(:config=).with(config)
+ MongoMapper.expects(:connect).with('development', :logger => logger)
+ MongoMapper.expects(:handle_passenger_forking)
+ MongoMapper.setup(config, 'development', :logger => logger, :passenger => true)
+ end
+ end
+
context "use_time_zone?" do
should "be true if Time.zone set" do
Time.zone = 'Hawaii'
MongoMapper.use_time_zone?.should be_true
Time.zone = nil
end
-
+
should "be false if Time.zone not set" do
MongoMapper.use_time_zone?.should be_false
end
end
-
+
context "time_class" do
should "be Time.zone if using time zones" do
Time.zone = 'Hawaii'
MongoMapper.time_class.should == Time.zone
Time.zone = nil
end
-
+
should "be Time if not using time zones" do
MongoMapper.time_class.should == Time
end
end
-
+
context "normalize_object_id" do
should "turn string into object id" do
id = Mongo::ObjectID.new
MongoMapper.normalize_object_id(id.to_s).should == id
end
-
+
should "leave object id alone" do
id = Mongo::ObjectID.new
MongoMapper.normalize_object_id(id).should == id
end
end
-
end

0 comments on commit efad5c7

Please sign in to comment.