class ROM::Command
Abstract command class
Provides a constructor accepting relation with options and basic behavior for calling, currying and composing commands.
Typically command subclasses should inherit from specialized Create/Update/Delete, not this one.
@abstract
@api public
Base command class with factory class-level interface and setup-related logic
@private
Constants
- CommandType
- Result
Public Instance Methods
Return a new command with appended after hooks
@param [Array<Hash>] hooks A list of after hooks configurations
@return [Command]
@api public
# File lib/rom/command.rb, line 359 def after(*hooks) self.class.new(relation, **options, after: after_hooks + hooks) end
List of after hooks
@return [Array]
@api public
# File lib/rom/command.rb, line 377 def after_hooks options[:after] end
Return a new command with appended before hooks
@param [Array<Hash>] hooks A list of before hooks configurations
@return [Command]
@api public
# File lib/rom/command.rb, line 348 def before(*hooks) self.class.new(relation, **options, before: before_hooks + hooks) end
List of before hooks
@return [Array]
@api public
# File lib/rom/command.rb, line 368 def before_hooks options[:before] end
Call the command and return one or many tuples
This method will apply before/after hooks automatically
@api public
# File lib/rom/command.rb, line 270 def call(*args, &block) tuples = if hooks? prepared = if curried? apply_hooks(before_hooks, *(curry_args + args)) else apply_hooks(before_hooks, *args) end result = prepared ? execute(prepared, &block) : execute(&block) if curried? if !args.empty? apply_hooks(after_hooks, result, *args) elsif curry_args.size > 1 apply_hooks(after_hooks, result, curry_args[1]) else apply_hooks(after_hooks, result) end else apply_hooks(after_hooks, result, *args[1..args.size - 1]) end else execute(*(curry_args + args), &block) end if one? tuples.first else tuples end end
Compose this command with other commands
Composed commands can handle nested input
@return [Command::Graph]
@api public
# File lib/rom/command.rb, line 328 def combine(*others) Graph.new(self, others) end
Check if this command is curried
@return [TrueClass, FalseClass]
@api public
# File lib/rom/command.rb, line 337 def curried? !curry_args.empty? end
Curry this command with provided args
Curried command can be called without args. If argument is a graph input processor, lazy command will be returned, which is used for handling nested input hashes.
@return [Command, Lazy]
@api public
# File lib/rom/command.rb, line 313 def curry(*args) if curry_args.empty? && args.first.is_a?(Graph::InputEvaluator) Lazy[self].new(self, *args) else self.class.build(relation, **options, curry_args: args) end end
Execute the command
@abstract
@return [Array] an array with inserted tuples
@api private
# File lib/rom/command.rb, line 258 def execute(*) raise( NotImplementedError, "#{self.class}##{__method__} must be implemented" ) end
Return gateway of this command's relation
@return [Symbol]
@api public
# File lib/rom/command.rb, line 247 def gateway relation.gateway end
Check if this command is a graph
@return [false]
@api private
# File lib/rom/command.rb, line 413 def graph? false end
Check if this command has any hooks
@api private
# File lib/rom/command.rb, line 395 def hooks? !before_hooks.empty? || !after_hooks.empty? end
Check if this command is lazy
@return [false]
@api private
# File lib/rom/command.rb, line 404 def lazy? false end
Check if this command returns many tuples
@return [TrueClass,FalseClass]
@api private
# File lib/rom/command.rb, line 431 def many? result.equal?(:many) end
Yields tuples for insertion or return an enumerator
@api private
# File lib/rom/command.rb, line 447 def map_input_tuples(tuples, &mapper) return enum_for(:with_input_tuples, tuples) unless mapper if tuples.respond_to? :merge mapper[tuples] else tuples.map(&mapper) end end
Return name of this command's relation
@return [ROM::Relation::Name]
@api public
# File lib/rom/command.rb, line 238 def name relation.name end
Return a new command with other source relation
This can be used to restrict command with a specific relation
@return [Command]
@api public
# File lib/rom/command.rb, line 388 def new(new_relation) self.class.build(new_relation, **options, source: relation) end
Check if this command returns a single tuple
@return [TrueClass,FalseClass]
@api private
# File lib/rom/command.rb, line 422 def one? result.equal?(:one) end
Check if this command is restrictible through relation
@return [TrueClass,FalseClass]
@api private
# File lib/rom/command.rb, line 440 def restrictible? self.class.restrictable.equal?(true) end
Private Instance Methods
Apply provided hooks
Used by call
@return [Array<Hash>]
@api private
# File lib/rom/command.rb, line 475 def apply_hooks(hooks, tuples, *args) hooks.reduce(tuples) do |a, e| if e.is_a?(Hash) hook_meth, hook_args = e.to_a.flatten(1) __send__(hook_meth, a, *args, **hook_args) else __send__(e, a, *args) end end end
Hook called by Pipeline
to get composite class for commands
@return [Class]
@api private
# File lib/rom/command.rb, line 464 def composite_class Command::Composite end
Pipes a dataset through command's relation
@return [Array]
@api private
# File lib/rom/command.rb, line 491 def wrap_dataset(dataset) if relation.is_a?(Relation::Composite) relation.new(dataset).to_a else dataset end end