# encoding: utf-8 require "uri" module Mongoid #:nodoc class Config #:nodoc include Singleton attr_accessor \ :allow_dynamic_fields, :reconnect_time, :parameterize_keys, :persist_in_safe_mode, :raise_not_found_error, :autocreate_indexes, :skip_version_check # Initializes the configuration with default settings. def initialize reset end # Sets whether the times returned from the database are in UTC or local time. # If you omit this setting, then times will be returned in # the local time zone. # # Example: # # Config.use_utc = true # # Returns: # # A boolean def use_utc=(value) @use_utc = value || false end # Returns whether times are return from the database in UTC. If # this setting is false, then times will be returned in the local time zone. # # Example: # # Config.use_utc # # Returns: # # A boolean attr_reader :use_utc alias_method :use_utc?, :use_utc # Sets the Mongo::DB master database to be used. If the object trying to be # set is not a valid +Mongo::DB+, then an error will be raised. # # Example: # # Config.master = Mongo::Connection.db("test") # # Returns: # # The master +Mongo::DB+ instance. def master=(db) check_database!(db) @master = db end # Returns the master database, or if none has been set it will raise an # error. # # Example: # # Config.master # # Returns: # # The master +Mongo::DB+ def master raise Errors::InvalidDatabase.new(nil) unless @master if @reconnect @reconnect = false reconnect! end @master end alias :database :master alias :database= :master= # Sets the Mongo::DB slave databases to be used. If the objects provided # are not valid +Mongo::DBs+ an error will be raised. # # Example: # # Config.slaves = [ Mongo::Connection.db("test") ] # # Returns: # # The slave DB instances. def slaves=(dbs) return unless dbs dbs.each do |db| check_database!(db) end @slaves = dbs end # Returns the slave databases or nil if none have been set. # # Example: # # Config.slaves # # Returns: # # The slave +Mongo::DBs+ def slaves @slaves end # Returns the logger, or defaults to Rails logger or stdout logger. # # Example: # # Config.logger def logger return @logger if defined?(@logger) @logger = defined?(Rails) ? Rails.logger : ::Logger.new($stdout) end # Sets the logger for Mongoid to use. # # Example: # # Config.logger = Logger.new($stdout, :warn) def logger=(logger) @logger = logger end # Return field names that could cause destructive things to happen if # defined in a Mongoid::Document # # Example: # # Config.destructive_fields # # Returns: # # An array of bad field names. def destructive_fields @destructive_fields ||= lambda { klass = Class.new do include Mongoid::Document end klass.instance_methods(true).collect { |method| method.to_s } }.call end # Configure mongoid from a hash. This is usually called after parsing a # yaml config file such as mongoid.yml. # # Example: # # Mongoid::Config.instance.from_hash({}) def from_hash(settings) _master(settings) _slaves(settings) settings.except("database", "slaves").each_pair do |name, value| send("#{name}=", value) if respond_to?(name) end end # Convenience method for connecting to the master database after forking a # new process. # # Example: # # Mongoid.reconnect! def reconnect!(now = true) if now master.connection.connect_to_master else # We set a @reconnect flag so that #master knows to reconnect the next # time the connection is accessed. @reconnect = true end end # Reset the configuration options to the defaults. # # Example: # # config.reset def reset @allow_dynamic_fields = true @parameterize_keys = true @persist_in_safe_mode = false @raise_not_found_error = true @reconnect_time = 3 @autocreate_indexes = false @skip_version_check = false @time_zone = nil end protected # Check if the database is valid and the correct version. # # Example: # # config.check_database! def check_database!(database) raise Errors::InvalidDatabase.new(database) unless database.kind_of?(Mongo::DB) unless Mongoid.skip_version_check version = database.connection.server_version raise Errors::UnsupportedVersion.new(version) if version < Mongoid::MONGODB_VERSION end end # Get a master database from settings. # # TODO: Durran: This code's a bit hairy, refactor. # # Example: # # config._master({}, "test") def _master(settings) mongo_uri = settings["uri"].present? ? URI.parse(settings["uri"]) : OpenStruct.new name = settings["database"] || mongo_uri.path.to_s.sub("/", "") host = settings["host"] || mongo_uri.host || "localhost" port = settings["port"] || mongo_uri.port || 27017 pool_size = settings["pool_size"] || 1 username = settings["username"] || mongo_uri.user password = settings["password"] || mongo_uri.password connection = Mongo::Connection.new(host, port, :logger => Mongoid::Logger.new, :pool_size => pool_size) if username || password connection.add_auth(name, username, password) connection.apply_saved_authentication end self.master = connection.db(name) end # Get a bunch-o-slaves from settings and names. # # TODO: Durran: This code's a bit hairy, refactor. # # Example: # # config._slaves({}, "test") def _slaves(settings) mongo_uri = settings["uri"].present? ? URI.parse(settings["uri"]) : OpenStruct.new name = settings["database"] || mongo_uri.path.to_s.sub("/", "") self.slaves = [] slaves = settings["slaves"] slaves.to_a.each do |slave| slave_uri = slave["uri"].present? ? URI.parse(slave["uri"]) : OpenStruct.new slave_username = slave["username"] || slave_uri.user slave_password = slave["password"] || slave_uri.password slave_connection = Mongo::Connection.new( slave["host"] || slave_uri.host || "localhost", slave["port"] || slave_uri.port, :slave_ok => true ) if slave_username || slave_password slave_connection.add_auth(name, slave_username, slave_password) slave_connection.apply_saved_authentication end self.slaves << slave_connection.db(name) end end end end