【问题标题】:How can I pass an array as an argument to a Rake task?如何将数组作为参数传递给 Rake 任务?
【发布时间】:2012-08-21 13:25:30
【问题描述】:

我正在编写一个 Rake 任务,我想传递一个数组作为参数之一。这是我目前拥有的方式。

task :change_statuses, :ids, :current_status, :new_status do |task, args|
  puts "args were #{args.inspect}"
end

我已尝试通过以下方式运行任务:

# First argument as array
rake "change_statuses[[1,2,3], active, inactive]"

# First argument as string
rake "utility:change_account_statuses['1,2,3', foo, bar]"

我的预期输出将是:

args were {:ids=> [1,2,3], :current_status=> 2 , :new_status=> 3}

但是,我在每种情况下的实际输出是:

args were {:ids=>"[1", :current_status=>"2", :new_status=>"3]"}

如何将数组传递给 Rake 任务?

【问题讨论】:

  • 我知道我可以为此使用ENV,但我想知道是否有更惯用的方式。

标签: ruby rake


【解决方案1】:

您也可以尝试稍微改变方法,并尝试使用 arg.extras 方法获取 id。

$ rake change_statuses[foo, bar, 1, 2, 3]
task :change_statuses, [:foo, :bar] do |_task, args|
  puts args[:foo]     # => foo
  puts args[:bar]     # => bar
  puts args.extras    # => ["1","2","3"]
end

您可以在本文中找到更多信息-> https://blog.stevenocchipinti.com/2013/10/18/rake-task-with-an-arbitrary-number-of-arguments/

【讨论】:

    【解决方案2】:

    其中一个解决方案是避免在字符串中使用, 符号,因此您的命令行如下所示:

    $ rake change_statuses['1 2 3', foo, bar]
    

    然后你可以简单地拆分 ID:

    # Rakefile
    
    task :change_statuses, :ids, :current_status, :new_status do |task, args|
      ids = args[:ids].split ' '
    
      puts "args were #{args.inspect}"
      puts "ids were #{ids.inspect}"
    end
    

    或者您可以解析 ids 值以获得您的预期输出:

    args[:ids] = args[:ids].split(' ').map{ |s| s.to_i }
    

    我正在使用 rake 0.8.7

    【讨论】:

    • 请注意,使用参数调用 rake 任务时,逗号后不应有空格,否则 bash 会误解它,您会收到类似 Don't know how to build task blahblah[param,' 的错误。所以上面的例子应该是rake change_statuses['1 2 3',foo,bar]
    • 谢谢,莱纳斯!奇怪 :) 它看起来真的像一个 bash 技巧,但我记得在发布答案之前我正在测试它。解决该问题的另一种方法是将 rake 任务放入大括号中,因此示例看起来像 rake "change_statuses['1 2 3', foo, bar]"
    • 这在控制台上也可以正常工作,但是在尝试使用我们的建议在 heroku 上运行时我被咬了。 :) 最后,我不得不输入 heroku run rake "change_statuses['1 2 3',foo,bar]" 的等价物,因为外部引号被删除了!
    • 感谢 Linus 的评论!无法弄清楚为什么从带有多个参数的命令行调用任务会给我这个错误“不知道如何构建任务......”但是你指出了我正确(和简单)的方向。
    • 您实际上可以不带任何参数直接调用.split,它会默认以空格分隔 (" ")。这就是我们顺便去的。我们认为最干净的是,当值中不能有空格时,例如 id 值。
    【解决方案3】:

    实现这一点的另一种方法,也赢得了传递哈希的能力

    namespace :stackoverflow do
      desc 'How to pass an array and also a hash at the same time 8-D'
      task :awesome_task, [:attributes] do |_task, args|
        options = Rack::Utils.parse_nested_query(args[:attributes])
        puts options
      end
    end
    

    然后像这样调用 rake 任务:

    bundle exec rake "stackoverflow:awesome_task[what_a_great_key[]=I know&what_a_great_key[]=Me too\!&i_am_a_hash[and_i_am_your_key]=what_an_idiot]"
    

    那会打印出来

    {"what_a_great_key"=>["I know", "Me too!"], "i_am_a_hash"=>{"and_i_am_your_key"=>"what_an_idiot"}}
    

    【讨论】:

      【解决方案4】:
      rake "change_statuses[1 2 3, foo, bar]"
      

      这对我有用,你不应该用 ' 配额 1 2 3

      task :import_course, [:cids, :title] => :environment do |t, args|
        puts args[:cids]
      end
      

      如果您将 1 2 3 作为正确答案,则 args[:cids] 将是“'1 2 3'”,其中包括 ' char,您必须修剪 ' char,但如果您使用我的答案,args[:cids] 会是 "1 2 3",这样比较好用,只需要 args[:cids].split(" ") 就可以得到 [1, 2, 3]

      【讨论】:

      • 你已经引用了整个 rake 任务,我觉得 rake change_status['1 2 3', foo bar] 更合适。
      • 你试过了吗?请尝试,rake change_status['1 2 3', foo bar],将 '1 2 3' 作为字符串传递,但包括 ', "'1 2 3'",你必须修剪 ' char,rake change_status ['1 2 3', foo bar] 将 [1, 2, 3] 作为字符串传递,不包含' char,这样更容易使用,你只需要 split(" ") 得到数组
      【解决方案5】:

      您也可以这样做:

       task :my_task, [:values] do |_task, args|
         values = args.values.split(',')
         puts values
       end
      

      并使用

      运行任务
      rake my_task"[1\,2\,3]"
      

      【讨论】:

        猜你喜欢
        • 2012-05-18
        • 2015-02-14
        • 2011-07-02
        • 2014-08-03
        • 1970-01-01
        • 1970-01-01
        • 2010-10-23
        • 2016-04-08
        相关资源
        最近更新 更多