How to pass command line arguments to a rake task

后端 未结 19 1934
走了就别回头了
走了就别回头了 2020-11-22 10:13

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

相关标签:
19条回答
  • 2020-11-22 10:50

    One thing I don't see here is how to handle arbitrary arguments. If you pass arguments that are not listed in the task definition, they are still accessible under args.extras:

    task :thing, [:foo] do |task, args|
      puts args[:foo]     # named argument
      puts args.extras    # any additional arguments that were passed
    end
    
    0 讨论(0)
  • 2020-11-22 10:50

    While passing parameters, it is better option is an input file, can this be a excel a json or whatever you need and from there read the data structure and variables you need from that including the variable name as is the need. To read a file can have the following structure.

      namespace :name_sapace_task do
        desc "Description task...."
          task :name_task  => :environment do
            data =  ActiveSupport::JSON.decode(File.read(Rails.root+"public/file.json")) if defined?(data)
        # and work whit yoour data, example is data["user_id"]
    
        end
      end
    

    Example json

    {
      "name_task": "I'm a task",
      "user_id": 389,
      "users_assigned": [389,672,524],
      "task_id": 3
    }
    

    Execution

    rake :name_task 
    
    0 讨论(0)
  • 2020-11-22 10:52

    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

    0 讨论(0)
  • 2020-11-22 10:53

    I've found the answer from these two websites: Net Maniac and Aimred.

    You need to have version > 0.8 of rake to use this technique

    The normal rake task description is this:

    desc 'Task Description'
    task :task_name => [:depends_on_taskA, :depends_on_taskB] do
      #interesting things
    end
    

    To pass arguments, do three things:

    1. Add the argument names after the task name, separated by commas.
    2. Put the dependencies at the end using :needs => [...]
    3. Place |t, args| after the do. (t is the object for this task)

    To access the arguments in the script, use args.arg_name

    desc 'Takes arguments task'
    task :task_name, :display_value, :display_times, :needs => [:depends_on_taskA, :depends_on_taskB] do |t, args|
      args.display_times.to_i.times do
        puts args.display_value
      end
    end
    

    To call this task from the command line, pass it the arguments in []s

    rake task_name['Hello',4]
    

    will output

    Hello
    Hello
    Hello
    Hello
    

    and if you want to call this task from another task, and pass it arguments, use invoke

    task :caller do
      puts 'In Caller'
      Rake::Task[:task_name].invoke('hi',2)
    end
    

    then the command

    rake caller
    

    will output

    In Caller
    hi
    hi
    

    I haven't found a way to pass arguments as part of a dependency, as the following code breaks:

    task :caller => :task_name['hi',2]' do
       puts 'In Caller'
    end
    
    0 讨论(0)
  • 2020-11-22 10:54

    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.

    0 讨论(0)
  • 2020-11-22 10:54

    If you can't be bothered to remember what argument position is for what and you want do something like a ruby argument hash. You can use one argument to pass in a string and then regex that string into an options hash.

    namespace :dummy_data do
      desc "Tests options hash like arguments"
      task :test, [:options] => :environment do |t, args|
        arg_options = args[:options] || '' # nil catch incase no options are provided
        two_d_array = arg_options.scan(/\W*(\w*): (\w*)\W*/)
        puts two_d_array.to_s + ' # options are regexed into a 2d array'
        string_key_hash = two_d_array.to_h
        puts string_key_hash.to_s + ' # options are in a hash with keys as strings'
        options = two_d_array.map {|p| [p[0].to_sym, p[1]]}.to_h
        puts options.to_s + ' # options are in a hash with symbols'
        default_options = {users: '50', friends: '25', colour: 'red', name: 'tom'}
        options = default_options.merge(options)
        puts options.to_s + ' # default option values are merged into options'
      end
    end
    

    And on the command line you get.

    $ rake dummy_data:test["users: 100 friends: 50 colour: red"]
    [["users", "100"], ["friends", "50"], ["colour", "red"]] # options are regexed into a 2d array
    {"users"=>"100", "friends"=>"50", "colour"=>"red"} # options are in a hash with keys as strings
    {:users=>"100", :friends=>"50", :colour=>"red"} # options are in a hash with symbols
    {:users=>"100", :friends=>"50", :colour=>"red", :name=>"tom"} # default option values are merged into options
    
    0 讨论(0)
提交回复
热议问题