# encoding: utf-8 require "uri" require "mongoid/config/database" require "mongoid/config/environment" require "mongoid/config/replset_database" require "mongoid/config/options" module Mongoid #:nodoc # This module defines all the configuration options for Mongoid, including the # database connections. # # @todo Durran: This module needs an overhaul, remove singleton, etc. module Config extend self extend Options include ActiveModel::Observing # @attribute [rw] master The master database. attr_accessor :master option :allow_dynamic_fields, :default => true option :autocreate_indexes, :default => false option :identity_map_enabled, :default => false option :include_root_in_json, :default => false option :include_type_for_serialization, :default => false option :max_retries_on_connection_failure, :default => 0 option :parameterize_keys, :default => true option :scope_overwrite_exception, :default => false option :persist_in_safe_mode, :default => false option :preload_models, :default => false option :raise_not_found_error, :default => true option :skip_version_check, :default => false option :time_zone, :default => nil option :use_utc, :default => false # Adds a new I18n locale file to the load path. # # @example Add a portuguese locale. # Mongoid::Config.add_language('pt') # # @example Add all available languages. # Mongoid::Config.add_language('*') # # @param [ String ] language_code The language to add. def add_language(language_code = nil) Dir[ File.join( File.dirname(__FILE__), "..", "config", "locales", "#{language_code}.yml" ) ].each do |file| I18n.load_path << File.expand_path(file) end end # keys to remove from self to not pass through to Mongo::Connection PRIVATE_OPTIONS = %w(uri host hosts port database databases username password logger use_activesupport_time_zone) # Get the blacklisted options from passing through to the driver. # # @example Get the blacklisted options. # Config.blacklisted_options # # @return [ Array<String> ] The blacklist. # # @since 2.4.7 def blacklisted_options PRIVATE_OPTIONS + settings.keys.map(&:to_s) end # Get any extra databases that have been configured. # # @example Get the extras. # config.databases # # @return [ Hash ] A hash of secondary databases. def databases configure_extras(@settings["databases"]) unless @databases || !@settings @databases || {} end # @todo Durran: There were no tests around the databases setter, not sure # what the exact expectation was. Set with a hash? def databases=(databases) end # Return field names that could cause destructive things to happen if # defined in a Mongoid::Document. # # @example Get the destructive fields. # config.destructive_fields # # @return [ Array<String> ] An array of bad field names. def destructive_fields Components.prohibited_methods end # Configure mongoid from a hash. This is usually called after parsing a # yaml config file such as mongoid.yml. # # @example Configure Mongoid. # config.from_hash({}) # # @param [ Hash ] options The settings to use. def from_hash(options = {}) options.except("database", "slaves", "databases").each_pair do |name, value| send("#{name}=", value) if respond_to?("#{name}=") end @master, @slaves = configure_databases(options) configure_extras(options["databases"]) end # Load the settings from a compliant mongoid.yml file. This can be used for # easy setup with frameworks other than Rails. # # @example Configure Mongoid. # Mongoid.load!("/path/to/mongoid.yml") # # @param [ String ] path The path to the file. # # @since 2.0.1 def load!(path) Environment.load_yaml(path).tap do |settings| from_hash(settings) if settings.present? end end # Returns the default logger, which is either a Rails logger of stdout logger # # @example Get the default logger # config.default_logger # # @return [ Logger ] The default Logger instance. def default_logger defined?(Rails) && Rails.respond_to?(:logger) ? Rails.logger : ::Logger.new($stdout) end # Returns the logger, or defaults to Rails logger or stdout logger. # # @example Get the logger. # config.logger # # @return [ Logger ] The configured logger or a default Logger instance. def logger @logger = default_logger unless defined?(@logger) @logger end # Sets the logger for Mongoid to use. # # @example Set the logger. # config.logger = Logger.new($stdout, :warn) # # @return [ Logger ] The newly set logger. def logger=(logger) case logger when false, nil then @logger = nil when true then @logger = default_logger else @logger = logger if logger.respond_to?(:info) end end # Purge all data in all collections, including indexes. # # @example Purge all data. # Mongoid::Config.purge! # # @since 2.0.2 def purge! master.collections.map do |collection| collection.drop if collection.name !~ /system/ end end # Sets whether the times returned from the database use the ruby or # the ActiveSupport time zone. # # @note If you omit this setting, then times will use the ruby time zone. # # @example Set the time zone config. # Config.use_activesupport_time_zone = true # # @param [ true, false ] value Whether to use Active Support time zones. # # @return [ true, false ] The supplied value or false if nil. def use_activesupport_time_zone=(value) @use_activesupport_time_zone = value || false end attr_reader :use_activesupport_time_zone alias_method :use_activesupport_time_zone?, :use_activesupport_time_zone # 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 Set the master database. # config.master = Mongo::Connection.new.db("test") # # @param [ Mongo::DB ] db The master database. # # @raise [ Errors::InvalidDatabase ] If the master isnt a valid object. # # @return [ Mongo::DB ] The master instance. def master=(db) check_database!(db) @master = db end alias :database= :master= # Returns the master database, or if none has been set it will raise an # error. # # @example Get the master database. # config.master # # @raise [ Errors::InvalidDatabase ] If the database was not set. # # @return [ Mongo::DB ] The master database. def master unless @master @master, @slaves = configure_databases(@settings) unless @settings.blank? raise Errors::InvalidDatabase.new(nil) unless @master end if @reconnect @reconnect = false reconnect! end @master end alias :database :master # Convenience method for connecting to the master database after forking a # new process. # # @example Reconnect to the master. # Mongoid.reconnect! # # @param [ true, false ] now Perform the reconnection immediately? def reconnect!(now = true) if now master.connection.connect else # We set a @reconnect flag so that #master knows to reconnect the next # time the connection is accessed. @reconnect = true end end protected # Check if the database is valid and the correct version. # # @example Check if the database is valid. # config.check_database! # # @param [ Mongo::DB ] database The db to check. # # @raise [ Errors::InvalidDatabase ] If the object is not valid. # @raise [ Errors::UnsupportedVersion ] If the db version is too old. def check_database!(database) raise Errors::InvalidDatabase.new(database) unless database.kind_of?(Mongo::DB) unless skip_version_check version = database.connection.server_version raise Errors::UnsupportedVersion.new(version) if version < Mongoid::MONGODB_VERSION end end # Get a database from settings. # # @example Configure the master and slave dbs. # config.configure_databases("database" => "mongoid") # # @param [ Hash ] options The options to use. # # @option options [ String ] :database The database name. # @option options [ String ] :host The database host. # @option options [ String ] :password The password for authentication. # @option options [ Integer ] :port The port for the database. # @option options [ Array<Hash> ] :slaves The slave db options. # @option options [ String ] :uri The uri for the database. # @option options [ String ] :username The user for authentication. # # @since 2.0.0.rc.1 def configure_databases(options) if options.has_key?('hosts') ReplsetDatabase.new(options).configure else Database.new(options).configure end end # Get the secondary databases from settings. # # @example Configure the master and slave dbs. # config.configure_extras("databases" => settings) # # @param [ Hash ] options The options to use. # # @since 2.0.0.rc.1 def configure_extras(extras) @databases = (extras || []).inject({}) do |dbs, (name, options)| dbs.tap do |extra| dbs[name], dbs["#{name}_slaves"] = configure_databases(options) end end end end end