在初始化程序中获取rake任务名称

时间:2016-02-10 14:50:59

标签: ruby-on-rails ruby

我想知道,如果应用实例是由rake启动的,那么我尝试在rake中捕获initializers任务名称。例如,如果我运行rake db:migrate,我想要db:migrate或类似的东西。 我试过了;

[7] pry(main)> $0
=> "spring app    | bilet18 | started 3 secs ago | development mode"
[8] pry(main)> ARGV
=> []
[9] pry(main)> Rake.application.top_level_tasks
=> []

但一切都是空的。

我能做什么?请帮忙。

更新

如果添加Rakefile行,如

ENV["RAKE_CURRENT_TASKS"] = Rake.application.top_level_tasks.join(' ')

然后将来你能够抓住它。 但这个解决方案对我不好,我需要提前抓住rake任务名称

3 个答案:

答案 0 :(得分:3)

除非您停止使用Spring ,否则此处提供的其他答案都不会起作用,因为Spring会更改rake任务的显式调用方式。

使用Spring时,正在运行的命令使用UNIX套接字移交给Spring服务器进程,不幸的是Spring服务器在初始化rails环境后读取此套接字以获取命令及其参数。因此,在rails初始化期间,似乎没有办法在使用Spring时获取命令及其参数(例如rake任务名称),因为Spring本身还不知道!即使是Spring提供的after_fork挂钩也无济于事,因为在 rails初始化后它也会运行

可以在Spring源代码中看到证据。它是serve method,其中Spring获取从套接字运行的命令的ARGV,自行分叉并运行命令。该方法的相关部分如下:

def serve(client)
  # ... getting standard input / output streams from the client socket

  # this is where rails initialization occurs
  preload unless preloaded?

  # this is where Spring gets the command name and it's ARGV and environment
  args, env = JSON.load(client.read(client.gets.to_i)).values_at("args", "env")
  command   = Spring.command(args.shift)

  # ...

  # fork and run the command
  pid = fork {
    # ...       
    # run the command
    ARGV.replace(args)
    $0 = command.exec_name
    # ...

    # run the after_fork hook
    invoke_after_fork_callbacks

    command.call
  }

  # ...
end

preload方法中,rails初始值设定项为run,在>从套接字读取命令名称之前运行。初始化后,$0ARGV变量也会在fork块中设置。

所以,除非你明显地修补了Spring(用你自己的serve方法替换了,但是你需要自己处理套接字),你需要停止调用你的rake任务在Spring环境中。如果rake命令是RAILS_ROOT/bin/目录中的binstub,则需要使用spring binstup --remove rake删除binstub。

只有这样,我相信,您可以在其他答案中使用其中一种解决方案。

答案 1 :(得分:0)

您是否在任务中加入了=> :environment? E.g。

task :sometask => :environment do
    ...
end

否则,当您运行rake任务时,初始化程序不会运行

答案 2 :(得分:0)

有两种方法可以达到你想要的效果,

1.不使用spring,只需运行:

spring binstub --remove --all

然后运行您的佣金任务。

2.使用春天:

创建一个spring.rb文件config/spring.rb并使用after_fork

Spring.after_fork do
  # run your code here
  # you have access to ARGV
  binding.pry
end