lib/mongoid/clients/options.rb in mongoid-5.4.1 vs lib/mongoid/clients/options.rb in mongoid-6.0.0.beta

- old
+ new

@@ -2,301 +2,106 @@ module Mongoid module Clients module Options extend ActiveSupport::Concern - # Tell the next persistence operation to store in a specific collection, - # database or client. + # Change the persistence context for this object during the block. # # @example Save the current document to a different collection. - # model.with(collection: "secondary").save + # model.with(collection: "secondary") do |m| + # m.save + # end # - # @example Save the current document to a different database. - # model.with(database: "secondary").save + # @param [ Hash, Mongoid::PersistenceContext ] options_or_context + # The storage options or a persistence context. # - # @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 + # @since 6.0.0 + def with(options_or_context, &block) + original_cluster = persistence_context.cluster + set_persistence_context(options_or_context) + yield self + ensure + clear_persistence_context(original_cluster) end - def persistence_options - @persistence_options + def collection(parent = nil) + persistence_context.collection(parent) end + def collection_name + persistence_context.collection_name + end + def mongo_client - tmp = persistence_options - if (opts = tmp && !tmp.empty? && tmp.dup) - if opts[:client] - client = Clients.with_name(opts[:client]) - else - client = Clients.with_name(self.class.client_name) - client = client.use(self.class.database_name) - end - client.with(opts.reject{ |k, v| k == :collection || k == :client }) - end + persistence_context.client end - def collection_name - if persistence_options && v = persistence_options[:collection] - return v.to_sym - end + def persistence_context + PersistenceContext.get(self) || + PersistenceContext.get(self.class) || + PersistenceContext.new(self.class) end - module Threaded + private - # 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 + def set_persistence_context(options_or_context) + PersistenceContext.set(self, options_or_context) + end - # Get the client with special options for the current thread. - # - # @example Get the client with options. - # Threaded.client_with_options(Band) - # - # @param [ Class ] klass The model class. - # - # @return [ Mongo::Client ] The client. - # - # @since 5.1.0 - def client_with_options(klass = self) - Thread.current["[mongoid][#{klass}]:mongo-client"] - end - - private - # Set the persistence options on the current thread. - # - # @api private - # - # @example Set the persistence options. - # Threaded.set_persistence_options(Band, { write: { w: 3 }}) - # - # @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 - - # Unset the persistence options on the current thread. - # - # @api private - # - # @example Unset the persistence options. - # Threaded.unset_persistence_options(Band) - # - # @param [ Class ] klass The model class. - # - # @return [ nil ] nil. - # - # @since 5.1.0 - def unset_persistence_options(klass) - Thread.current["[mongoid][#{klass}]:persistence-options"] = nil - end - - # Set the persistence options and client with those options on the current thread. - # Note that a client will only be set if its cluster differs from the cluster of the - # original client. - # - # @api private - # - # @example Set the persistence options and client with those options on the current thread. - # Threaded.set_options(Band, { write: { w: 3 }}) - # - # @param [ Class ] klass The model class. - # @param [ Mongo::Client ] options The options. - # - # @return [ Mongo::Client, nil ] The client or nil if the cluster does not change. - # - # @since 5.1.0 - def set_options(klass, options) - original_cluster = mongo_client.cluster - set_persistence_options(klass, options) - m = mongo_client - set_client_with_options(klass, m) unless m.cluster.equal?(original_cluster) - end - - # Set the client with special options on the current thread. - # - # @api private - # - # @example Set the client with options. - # Threaded.set_client_with_options(Band, client) - # - # @param [ Class ] klass The model class. - # @param [ Mongo::Client ] client The client with options. - # - # @return [ Mongo::Client ] The client. - # - # @since 5.1.0 - def set_client_with_options(klass, client) - Thread.current["[mongoid][#{klass}]:mongo-client"] = client - end - - # Unset the client with special options on the current thread. - # - # @api private - # - # @example Unset the client with options. - # Threaded.unset_client_with_options(Band) - # - # @param [ Class ] klass The model class. - # - # @return [ nil ] nil. - # - # @since 5.1.0 - def unset_client_with_options(klass) - if client = Thread.current["[mongoid][#{klass}]:mongo-client"] - client.close - Thread.current["[mongoid][#{klass}]:mongo-client"] = nil - end - end - - # Unset the persistence options and client with special options on the current thread. - # - # @api private - # - # @example Unset the persistence options and client with options. - # Threaded.unset_options(Band) - # - # @param [ Class ] klass The model class. - # - # @return [ nil ] nil. - # - # @since 5.1.0 - def unset_options(klass) - unset_persistence_options(klass) - unset_client_with_options(klass) - end + def clear_persistence_context(original_cluster = nil) + PersistenceContext.clear(self, original_cluster) end module ClassMethods - include Threaded def client_name - if persistence_options && v = persistence_options[:client] - return v.to_sym - end - super + persistence_context.client_name end def collection_name - if persistence_options && v = persistence_options[:collection] - return v.to_sym - end - super + persistence_context.collection_name end def database_name - if persistence_options && v = persistence_options[:database] - return v.to_sym - end - super + persistence_context.database_name end - # Tell the next persistence operation to store in a specific collection, - # database or client. + def collection + persistence_context.collection + end + + def mongo_client + persistence_context.client + end + + # Change the persistence context for this class during the block. # - # @example Create a document in a different collection. - # Model.with(collection: "secondary").create(name: "test") + # @example Save the current document to a different collection. + # Model.with(collection: "secondary") do |m| + # m.create + # end # - # @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) - if block_given? - set_options(self, options) - result = yield self - unset_options(self) - result - else - Proxy.new(self, (persistence_options || {}).merge(options)) - end - 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 + # @since 6.0.0 + def with(options, &block) + original_cluster = persistence_context.cluster + PersistenceContext.set(self, options) + yield self ensure - unset_persistence_options(@target) + PersistenceContext.clear(self, original_cluster) end - def send(symbol, *args) - __send__(symbol, *args) - end - - def self.const_missing(name) - ::Object.const_get(name) + def persistence_context + PersistenceContext.get(self) || PersistenceContext.new(self) end end end end end