How do I pass args from command line to rake then rspec - ruby

I'm trying to pass a couple of variables through the command line to rake to be used in rspec.
From what i gather i can do this to pass args into my rake task:
task :my_task, :arg1, :arg2 do |t, args|
puts "Args were: #{args}"
end
but I'm using rspec so my rake task looks like this:
RSpec::Core::RakeTask.new(:my_task), :arg1, :arg2 do |t, args|
puts args.arg1
puts args.arg2
end
which doesn't work.
also I havent figured out how to pass it to my rspec spec file

How do you call rake?
For your example you have to call:
rake mytask[val1,val2]
I'm not sure about your 2nd code example.
args should be a hash with keys :arg1 and :arg2.
So you may use
puts args[:arg1]
I'm in doubt if args.arg1 will work.

It's been a while since the original question, but I had to solve a similar problem. You don't have to change much of your initial idea:
RSpec::Core::RakeTask.new(:my_task, [:arg1, :arg2]) do |t, args|
puts args.arg1
puts args.arg2
end
Then call it e.g. via:
rake my_task["hello","world"]

Related

Confused with the second variable of task : some_random_name1, [:some_random_name2] => :environment in rake?

I am new to ruby and rake, and currently confused with some ruby syntax.
task :some_random_name1, [:some_random_name2] => :environment do |task, args|
end
What does [:some_random_name2] here mean? I know some_random_name1 is a task that depends on another task :environment, and task and args in |task, args| are arguments from command line. Thanks in advance.
[:some_random_name2] is referring to arguments that you can pass into your rake task. May I suggest checking out this article which can explain in more depth passing arguments to a rake task.
When you call rake -T from the command line, you should see:
rake example: some_random_name1[some_random_name2]
(assuming your namespace is 'example')

Testing rake tasks with rspec doesn't seem to work

I'm trying to test a very simple rake task with rspec, but I'm finding it very difficult and whatever change I do my tests don't seem to fail...
This is the task I'm trying to test:
desc 'Outputs the current version of Rivendell'
task version: :environment do
puts Rivendell::VERSION
end
As you can see, it's a very basic task.
This is my test:
describe 'Rakefile' do
before :each do
Rake.application.rake_require File.expand_path(
'../../Rakefile', File.dirname(__FILE__))
Rake::Task.define_task :environment
end
describe 'rivendell::version' do
let :run_rake_task do
Rake::Task["rivendell::version"].reenable
Rake.application.invoke_task "rivendell::version"
end
it 'should display the right version' do
Rivendell.should_receive('VERSION')
run_rake_task
end
end
All tests for some reason pass, but if I change the should_receive call to
Rivendell.should_receive('DOESNTEXIST')
All tests pass in any case.
What am I doing wrong here?

Thor Executable - Ignore Task Name

The thor wiki page, Making an Exectable, shows you how to create a thor powered CLI command that looks something like this:
bash
./mythorcommand foo
This requires you to pass in the thor task foo as the first argument.
I can also run a thor executable without any arguments using thor's default_method:
bash
./mythorcommand
However, I'd like to pass in a variable string as the first argument:
bash
./mythorcommand "somevalue"
This doesn't work because thor commands expect the first argument to the be a task name. Is there a way to ignore the task name and send the first argument to a default method?
If this functionality doesn't exist, I think it would be very useful to add a method that would pass all commandline arguments into one task/method:
class MyThorCommand < Thor
only_method :default
def default(*args)
puts args.inpsect
end
end
MyThorCommand.start
You should extend from Thor::Group and that call start method
class Test < Thor::Group
desc "Act description"
def act
puts "do smth"
end
end
Test.start
I found a rather 'strange' solution for this problem that is working quite well with me.
You add a default task to Thor. Than you add the method_missing so that you can trick Thor into passing the default method as an argument if there are parameters to your application.
Taking from your example, the solution would look like this:
class MyThorCommand < Thor
default_task :my_default
desc "my_default", "A simple default"
def my_default(*args)
puts args.inspect
end
def method_missing(method, *args)
args = ["my_default", method.to_s] + args
MyThorCommand.start(args)
end
end
MyThorCommand.start(ARGV)
If this is in the file "my_thor.rb" an execution "ruby my_thor.rb foo bar" would show '["foo", "bar"]' as a result.
Hope it helps.
Though this does not exactly solve your problem, one alternative might be using Thor.map to invoke a command by only giving an option flag:
map '-F' => 'foo'
Now you can also pass parameters
mythorcommand -F bar # => invokes foo("bar")

Namespaces in Ruby Rake Tasks

Are the following equivalent?
namespace :resque do
task setup: :environment do
end
end
task "resque:setup" => :environment do
end
In short: yes. When running rake resque:setup both of these tasks will be invoked.
Rake will merge these tasks. You can test this by doing the following:
p Rake.application.tasks
Which in this case would return something like
[<Rake::Task resque:setup => [environment]>]
Which is simply an Array holding a single Rake::Task object. You can also check the scope or list of namespaces for a task by doing:
p Rake.application.tasks.first.scope
#=> ["resque"]
If you want to learn a little more on how the internals of Rake work, check out Rake::Task and Rake::TaskManager

How do I run Rake tasks within a Ruby script?

I have a Rakefile with a Rake task that I would normally call from the command line:
rake blog:post Title
I'd like to write a Ruby script that calls that Rake task multiple times, but the only solution I see is shelling out using `` (backticks) or system.
What's the right way to do this?
from timocracy.com:
require 'rake'
def capture_stdout
s = StringIO.new
oldstdout = $stdout
$stdout = s
yield
s.string
ensure
$stdout = oldstdout
end
Rake.application.rake_require 'metric_fetcher', ['../../lib/tasks']
results = capture_stdout {Rake.application['metric_fetcher'].invoke}
This works with Rake version 10.0.3:
require 'rake'
app = Rake.application
app.init
# do this as many times as needed
app.add_import 'some/other/file.rake'
# this loads the Rakefile and other imports
app.load_rakefile
app['sometask'].invoke
As knut said, use reenable if you want to invoke multiple times.
You can use invoke and reenable to execute the task a second time.
Your example call rake blog:post Title seems to have a parameter. This parameter can be used as a parameter in invoke:
Example:
require 'rake'
task 'mytask', :title do |tsk, args|
p "called #{tsk} (#{args[:title]})"
end
Rake.application['mytask'].invoke('one')
Rake.application['mytask'].reenable
Rake.application['mytask'].invoke('two')
Please replace mytask with blog:post and instead the task definition you can require your rakefile.
This solution will write the result to stdout - but you did not mention, that you want to suppress output.
Interesting experiment:
You can call the reenable also inside the task definition. This allows a task to reenable himself.
Example:
require 'rake'
task 'mytask', :title do |tsk, args|
p "called #{tsk} (#{args[:title]})"
tsk.reenable #<-- HERE
end
Rake.application['mytask'].invoke('one')
Rake.application['mytask'].invoke('two')
The result (tested with rake 10.4.2):
"called mytask (one)"
"called mytask (two)"
In a script with Rails loaded (e.g. rails runner script.rb)
def rake(*tasks)
tasks.each do |task|
Rake.application[task].tap(&:invoke).tap(&:reenable)
end
end
rake('db:migrate', 'cache:clear', 'cache:warmup')

Resources