# encoding: utf-8 module Mongoid module Clients module Options extend ActiveSupport::Concern extend Gem::Deprecate # Tell the next persistance operation to store in a specific collection, # database or client. # # @example Save the current document to a different collection. # model.with(collection: "secondary").save # # @example Save the current document to a different database. # model.with(database: "secondary").save # # @example Save the current document to a different client. # model.with(client: "replica_set").save # # @example Save with a combination of options. # model.with(client: "sharded", database: "secondary").save # # @note This method will instantiate a new client under the covers and # can be expensive. It is also recommended that the user manually # closes the extra client after using it, otherwise an excessive amount # of connections to the server will be eventually opened. # # @param [ Hash ] options The storage options. # # @option options [ String, Symbol ] :collection The collection name. # @option options [ String, Symbol ] :database The database name. # @option options [ String, Symbol ] :client The client name. # # @return [ Document ] The current document. # # @since 3.0.0 def with(options) @persistence_options = options self end def persistence_options @persistence_options end def mongo_client if persistence_options if persistence_options[:client] client = Clients.with_name(persistence_options[:client]) else client = Clients.with_name(self.class.client_name) client.use(self.class.database_name) end client.with(persistence_options.reject{ |k, v| k == :collection || k == :client }) end end alias :mongo_session :mongo_client deprecate :mongo_session, :mongo_client, 2015, 12 def collection_name if persistence_options && v = persistence_options[:collection] return v.to_sym end end module Threaded # Get the persistence options for the current thread. # # @example Get the persistence options. # Threaded.persistence_options(Band) # # @param [ Class ] klass The model class. # # @return [ Hash ] The current persistence options. # # @since 4.0.0 def persistence_options(klass = self) Thread.current["[mongoid][#{klass}]:persistence-options"] end private # Set the persistence options on the current thread. # # @api private # # @example Set the persistence options. # Threaded.set_persistence_options(Band, { safe: { fsync: true }}) # # @param [ Class ] klass The model class. # @param [ Hash ] options The persistence options. # # @return [ Hash ] The persistence options. # # @since 4.0.0 def set_persistence_options(klass, options) Thread.current["[mongoid][#{klass}]:persistence-options"] = options end end module ClassMethods extend Gem::Deprecate include Threaded def client_name if persistence_options && v = persistence_options[:client] return v.to_sym end super end alias :session_name :client_name deprecate :session_name, :client_name, 2015, 12 def collection_name if persistence_options && v = persistence_options[:collection] return v.to_sym end super end def database_name if persistence_options && v = persistence_options[:database] return v.to_sym end super end # Tell the next persistance operation to store in a specific collection, # database or client. # # @example Create a document in a different collection. # Model.with(collection: "secondary").create(name: "test") # # @example Create a document in a different database. # Model.with(database: "secondary").create(name: "test") # # @example Create a document in a different client. # Model.with(client: "secondary").create(name: "test") # # @example Create with a combination of options. # Model.with(client: "sharded", database: "secondary").create # # @param [ Hash ] options The storage options. # # @option options [ String, Symbol ] :collection The collection name. # @option options [ String, Symbol ] :database The database name. # @option options [ String, Symbol ] :client The client name. # # @return [ Class ] The model class. # # @since 3.0.0 def with(options) Proxy.new(self, (persistence_options || {}).merge(options)) end end class Proxy < BasicObject include Threaded undef_method :== def initialize(target, options) @target = target @options = options end def persistence_options @options end def respond_to?(*args) @target.respond_to?(*args) end def method_missing(name, *args, &block) set_persistence_options(@target, @options) ret = @target.send(name, *args, &block) if Mongoid::Criteria == ret.class ret.with @options end ret ensure set_persistence_options(@target, nil) end def send(symbol, *args) __send__(symbol, *args) end def self.const_missing(name) ::Object.const_get(name) end end end end end