module DataMapper module Validations # Module with validation context functionality. # # Contexts are implemented using a simple array based # stack that is thread local. The default context can be # altered by overwriting default_validation_context or # will default to :default # module Context # TODO: document # @api private def default_validation_context current_validation_context || :default end protected # Pushes given context on top of context stack and yields # given block, then pops the stack. During block execution # contexts previously pushed onto the stack have no effect. # # @api private def validation_context(context = default_validation_context) assert_valid_context(context) validation_context_stack << context begin yield ensure validation_context_stack.pop end end private # Initializes (if necessary) and returns current scope stack # @api private def validation_context_stack Thread.current[:dm_validations_context_stack] ||= [] end # Returns the current validation context or nil if none has been pushed # @api private def current_validation_context context = validation_context_stack.last valid_context?(context) ? context : :default end # Return the contexts for the model # # @return [Hash] # the hash of contexts for the model # # @api private def contexts model.validators.contexts end # Test if the context is valid for the model # # @param [Symbol] context # the context to test # # @return [Boolean] # true if the context is valid for the model # # @api private def valid_context?(context) contexts.empty? || contexts.key?(context) end # Assert that the context is valid for this model # # @param [Symbol] context # the context to test # # @raise [InvalidContextError] # raised if the context is not valid for this model # # @api private def assert_valid_context(context) unless valid_context?(context) raise InvalidContextError, "#{context} is an invalid context, known contexts are #{contexts.keys.inspect}" end end end include Context end end