How to pass command line arguments to a rake task

后端 未结 19 1967
走了就别回头了
走了就别回头了 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:38

    Most of the methods described above did not work for me, maybe they are deprecated in the newer versions. The up-to-date guide can be found here: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks

    a copy-and-paste ans from the guide is here:

    task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
      # You can use args from here
    end
    

    Invoke it like this

    bin/rake "task_name[value 1]" # entire argument string should be quoted
    
    0 讨论(0)
  • 2020-11-22 10:41

    Another commonly used option is to pass environment variables. In your code you read them via ENV['VAR'], and can pass them right before the rake command, like

    $ VAR=foo rake mytask
    
    0 讨论(0)
  • 2020-11-22 10:45

    You can specify formal arguments in rake by adding symbol arguments to the task call. For example:

    require 'rake'
    
    task :my_task, [:arg1, :arg2] do |t, args|
      puts "Args were: #{args} of class #{args.class}"
      puts "arg1 was: '#{args[:arg1]}' of class #{args[:arg1].class}"
      puts "arg2 was: '#{args[:arg2]}' of class #{args[:arg2].class}"
    end
    
    task :invoke_my_task do
      Rake.application.invoke_task("my_task[1, 2]")
    end
    
    # or if you prefer this syntax...
    task :invoke_my_task_2 do
      Rake::Task[:my_task].invoke(3, 4)
    end
    
    # a task with prerequisites passes its 
    # arguments to it prerequisites
    task :with_prerequisite, [:arg1, :arg2] => :my_task #<- name of prerequisite task
    
    # to specify default values, 
    # we take advantage of args being a Rake::TaskArguments object
    task :with_defaults, :arg1, :arg2 do |t, args|
      args.with_defaults(:arg1 => :default_1, :arg2 => :default_2)
      puts "Args with defaults were: #{args}"
    end
    

    Then, from the command line:

    > rake my_task[1,false]
    Args were: {:arg1=>"1", :arg2=>"false"} of class Rake::TaskArguments
    arg1 was: '1' of class String
    arg2 was: 'false' of class String
    
    > rake "my_task[1, 2]"
    Args were: {:arg1=>"1", :arg2=>"2"}
    
    > rake invoke_my_task
    Args were: {:arg1=>"1", :arg2=>"2"}
    
    > rake invoke_my_task_2
    Args were: {:arg1=>3, :arg2=>4}
    
    > rake with_prerequisite[5,6]
    Args were: {:arg1=>"5", :arg2=>"6"}
    
    > rake with_defaults
    Args with defaults were: {:arg1=>:default_1, :arg2=>:default_2}
    
    > rake with_defaults['x','y']
    Args with defaults were: {:arg1=>"x", :arg2=>"y"}
    

    As demonstrated in the second example, if you want to use spaces, the quotes around the target name are necessary to keep the shell from splitting up the arguments at the space.

    Looking at the code in rake.rb, it appears that rake does not parse task strings to extract arguments for prerequisites, so you can't do task :t1 => "dep[1,2]". The only way to specify different arguments for a prerequisite would be to invoke it explicitly within the dependent task action, as in :invoke_my_task and :invoke_my_task_2.

    Note that some shells (like zsh) require you to escape the brackets: rake my_task\['arg1'\]

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

    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"
    
    0 讨论(0)
  • 2020-11-22 10:50

    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 task object, not very helpful unless you know/care about Rake internals.

    RAILS NOTE:

    If running the task from Rails, it's 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
    
    0 讨论(0)
  • 2020-11-22 10:50

    I just wanted to be able to run:

    $ rake some:task arg1 arg2
    

    Simple, right? (Nope!)

    Rake interprets arg1 and arg2 as tasks, and tries to run them. So we just abort before it does.

    namespace :some do
      task task: :environment do
        arg1, arg2 = ARGV
    
        # your task...
    
        exit
      end
    end
    

    Take that, brackets!

    Disclaimer: I wanted to be able to do this in a pretty small pet project. Not intended for "real world" usage since you lose the ability to chain rake tasks (i.e. rake task1 task2 task3). IMO not worth it. Just use the ugly rake task[arg1,arg2].

    0 讨论(0)
提交回复
热议问题