我想知道,如果应用实例是由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任务名称
答案 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,在>>从套接字读取命令名称之前运行。初始化后,$0
和ARGV
变量也会在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