Module: Thor::Invocation
- Defined in:
- lib/thor/invocation.rb
Instance Method Summary collapse
-
#initialize(args = [], options = {}, config = {}, &block) ⇒ Object
Make initializer aware of invocations and the initializer proc.
-
#invoke(name = nil, task = nil, args = nil, opts = nil, config = nil) ⇒ Object
Receives a name and invokes it.
Instance Method Details
#initialize(args = [], options = {}, config = {}, &block) ⇒ Object
Make initializer aware of invocations and the initializer proc.
6 7 8 9 10 |
# File 'lib/thor/invocation.rb', line 6 def initialize(args=[], ={}, config={}, &block) #:nodoc: @_invocations = config[:invocations] || Hash.new { |h,k| h[k] = [] } @_initializer = [ args, , config ] super end |
#invoke(name = nil, task = nil, args = nil, opts = nil, config = nil) ⇒ Object
Receives a name and invokes it. The name can be a string (either “task” or “namespace:task”), a Thor::Task, a Class or a Thor instance. If the task cannot be guessed by name, it can also be supplied as second argument.
You can also supply the arguments, options and configuration values for the task to be invoked, if none is given, the same values used to initialize the invoker are used to initialize the invoked.
Examples
class A < Thor
def foo
invoke :bar
invoke "b:hello", ["José"]
end
def
invoke "b:hello", ["José"]
end
end
class B < Thor
def hello(name)
puts "hello #{name}"
end
end
You can notice that the method “foo” above invokes two tasks: “bar”, which belongs to the same class and “hello” which belongs to the class B.
By using an invocation system you ensure that a task is invoked only once. In the example above, invoking “foo” will invoke “b:hello” just once, even if it’s invoked later by “bar” method.
When class A invokes class B, all arguments used on A initialization are supplied to B. This allows lazy parse of options. Let’s suppose you have some rspec tasks:
class Rspec < Thor::Group
class_option :mock_framework, :type => :string, :default => :rr
def invoke_mock_framework
invoke "rspec:#{[:mock_framework]}"
end
end
As you noticed, it invokes the given mock framework, which might have its own options:
class Rspec::RR < Thor::Group
class_option :style, :type => :string, :default => :mock
end
Since it’s not rspec concern to parse mock framework options, when RR is invoked all options are parsed again, so RR can extract only the options that it’s going to use.
If you want Rspec::RR to be initialized with its own set of options, you have to do that explicitely:
invoke "rspec:rr", [], :style => :foo
Besides giving an instance, you can also give a class to invoke:
invoke Rspec::RR, [], :style => :foo
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/thor/invocation.rb', line 78 def invoke(name=nil, task=nil, args=nil, opts=nil, config=nil) task, args, opts, config = nil, task, args, opts if task.nil? || task.is_a?(Array) args, opts, config = nil, args, opts if args.is_a?(Hash) object, task = _setup_for_invoke(name, task) if object.is_a?(Class) klass = object stored_args, stored_opts, stored_config = @_initializer args ||= stored_args.dup opts ||= stored_opts.dup config ||= {} config = stored_config.merge(_shared_configuration).merge!(config) instance = klass.new(args, opts, config) else klass, instance = object.class, object end method_args = [] current = @_invocations[klass] iterator = proc do |_, task| unless current.include?(task.name) current << task.name task.run(instance, method_args) end end if task args ||= [] method_args = args[Range.new(klass.arguments.size, -1)] || [] iterator.call(nil, task) else klass.all_tasks.map(&iterator) end end |