How to pass command line arguments to a rake task

2018-12-31 14:56发布

I have a rake task that needs to insert a value into multiple databases.

I'd like to pass this value into the rake task from the command line, or from another rake task.

How can I do this?

17条回答
君临天下
2楼-- · 2018-12-31 14:59
desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
    puts args[:arg1]
end
查看更多
孤独寂梦人
3楼-- · 2018-12-31 15:00

options and dependencies need to be inside arrays:

namespace :thing do
  desc "it does a thing"
  task :work, [:option, :foo, :bar] do |task, args|
    puts "work", args
  end

  task :another, [:option, :foo, :bar] do |task, args|
    puts "another #{args}"
    Rake::Task["thing:work"].invoke(args[:option], args[:foo], args[:bar])
    # or splat the args
    # Rake::Task["thing:work"].invoke(*args)
  end

end

Then

rake thing:work[1,2,3]
=> work: {:option=>"1", :foo=>"2", :bar=>"3"}

rake thing:another[1,2,3]
=> another {:option=>"1", :foo=>"2", :bar=>"3"}
=> work: {:option=>"1", :foo=>"2", :bar=>"3"}

NOTE: variable task is the the task object, not very helpful unless you know/care about Rake internals.

RAILS NOTE:

If running the task from rails, its best to preload the environment by adding => [:environment] which is a way to setup dependent tasks.

  task :work, [:option, :foo, :bar] => [:environment] do |task, args|
    puts "work", args
  end
查看更多
几人难应
4楼-- · 2018-12-31 15:00

I use a regular ruby argument in the rake file:

DB = ARGV[1]

then I stub out the rake tasks at the bottom of the file (since rake will look for a task based on that argument name).

task :database_name1
task :database_name2

command line:

rake mytask db_name

this feels cleaner to me than the var=foo ENV var and the task args[blah, blah2] solutions.
the stub is a little jenky, but not too bad if you just have a few environments that are a one-time setup

查看更多
宁负流年不负卿
5楼-- · 2018-12-31 15:03

In addition to answer by kch (I didn't find how to leave a comment to that, sorry):

You don't have to specify variables as ENV variables before the rake command. You can just set them as usual command line parameters like that:

rake mytask var=foo

and access those from your rake file as ENV variables like such:

p ENV['var'] # => "foo"
查看更多
明月照影归
6楼-- · 2018-12-31 15:05

If you want to pass named arguments (e.g. with standard OptionParser) you could use something like this:

$ rake user:create -- --user test@example.com --pass 123

note the --, that's necessary for bypassing standard Rake arguments. Should work with Rake 0.9.x, <= 10.3.x.

Newer Rake has changed its parsing of --, and now you have to make sure it's not passed to the OptionParser#parse method, for example with parser.parse!(ARGV[2..-1])

require 'rake'
require 'optparse'
# Rake task for creating an account

namespace :user do |args|
  desc 'Creates user account with given credentials: rake user:create'
  # environment is required to have access to Rails models
  task :create do
    options = {}
    OptionParser.new(args) do |opts|
      opts.banner = "Usage: rake user:create [options]"
      opts.on("-u", "--user {username}","User's email address", String) do |user|
        options[:user] = user
      end
      opts.on("-p", "--pass {password}","User's password", String) do |pass|
        options[:pass] = pass
      end
    end.parse!

    puts "creating user account..."
    u = Hash.new
    u[:email] = options[:user]
    u[:password] = options[:pass]
    # with some DB layer like ActiveRecord:
    # user = User.new(u); user.save!
    puts "user: " + u.to_s
    puts "account created."
    exit 0
  end
end

exit at the end will make sure that the extra arguments won't be interpreted as Rake task.

Also the shortcut for arguments should work:

 rake user:create -- -u test@example.com -p 123

When rake scripts look like this, maybe it's time to look for another tool that would allow this just out of box.

查看更多
泛滥B
7楼-- · 2018-12-31 15:08

I couldn't figure out how to pass args and also the :environment until I worked this out:

namespace :db do
  desc 'Export product data'
  task :export, [:file_token, :file_path] => :environment do |t, args|
    args.with_defaults(:file_token => "products", :file_path => "./lib/data/")

       #do stuff [...]

  end
end

And then I call like this:

rake db:export['foo, /tmp/']
查看更多
登录 后发表回答