[英]Get rake task name in initializer
I want to know, if the app instance is started by rake
, so I tried out catching rake
task name in initializers
. 我想知道,如果app实例是由
rake
启动的,那么我尝试在initializers
捕获rake
任务名称。 For example, if I run rake db:migrate
I want get db:migrate
or something like this. 例如,如果我运行
rake db:migrate
我想要获取db:migrate
或类似的东西。 I tried this; 我试过这个;
[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
=> []
but everything is empty. 但一切都是空的。
What can I do that? 我能做什么? please help.
请帮忙。
UPDATE UPDATE
if add in Rakefile line like 如果添加Rakefile行就好
ENV["RAKE_CURRENT_TASKS"] = Rake.application.top_level_tasks.join(' ')
then in future you'll be able to catch it in. but this solution is not good for me, I need to catch rake task name earlier 然后在将来你将能够抓住它。但这个解决方案对我不好,我需要更早地抓住rake任务名称
None of the other answers presented here will work unless you stop using Spring , because Spring changes the way rake tasks are called significantly. 除非你停止使用Spring , 否则这里提出的其他答案都不会有效,因为Spring会改变rake任务被大量调用的方式。
When using Spring, the command being run is handed over to the Spring server process using a UNIX socket and unfortunately Spring server reads this socket to get the command and its arguments after initializing the rails environment . 使用Spring时,正在运行的命令将使用UNIX套接字移交给Spring服务器进程,不幸的是,Spring服务器在初始化rails环境后读取此套接字以获取命令及其参数。 Thus, during rails initialization, there seems to be no way of getting the command and its arguments (eg the rake task name) when using Spring, as Spring itself does not know yet!
因此,在rails初始化期间,使用Spring时似乎无法获取命令及其参数(例如rake任务名称),因为Spring本身还不知道! Even the
after_fork
hook that Spring provides won't help, because it is being also run after rails initialization. 即使是Spring提供的
after_fork
钩子也无济于事,因为它也是在 rails初始化之后运行的。
A proof can be seen in the Spring source code. 可以在Spring源代码中看到证据。 It is the
serve
method in which Spring gets the ARGV
of the command being run from the socket, forks itself and runs the command. 它是一个
serve
方法 ,Spring从套接字中获取命令的ARGV
,自行分叉并运行命令。 The relevant parts of the method are these: 该方法的相关部分如下:
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
The rails initializers are run in the preload
method which is run before the command name is read from the socket. rails初始化程序在
preload
方法中运行 ,该方法在从套接字读取命令名之前运行。 The $0
and ARGV
variables are also set after initialization, in the fork
block. 在初始化之后,在
fork
块中也设置$0
和ARGV
变量。
So, unless you monkey-patched Spring significantly (replaced the serve
method with your own, but you'd need to handle working with the socket yourself), you need to stop calling your rake tasks inside the Spring environment . 因此,除非你明显地修补了Spring(用你自己的方法替换了
serve
方法,但是你需要自己处理套接字), 你需要停止在Spring环境中调用你的rake任务 。 If the rake
command is a binstub in the RAILS_ROOT/bin/
directory, you need to remove the binstub with spring binstup --remove rake
. 如果
rake
命令是RAILS_ROOT/bin/
目录中的binstub,则需要使用spring binstup --remove rake
删除binstub。
Only then, I believe, you can use one of the solutions in the other answers. 只有这样,我相信,您可以在其他答案中使用其中一种解决方案。
Did you include the => :environment
in your task? 您是否在任务中包含了
=> :environment
? Eg 例如
task :sometask => :environment do
...
end
Otherwise the initializers wont run when you run a rake task 否则,在运行rake任务时,初始化程序不会运行
There is two ways to achieve what you want, 有两种方法可以达到你想要的效果,
1 .Not using spring
, just run: 1,不使用
spring
,只需运行:
spring binstub --remove --all
and then run your rake task. 然后运行你的rake任务。
2 .Using spring: 2,使用弹簧:
create a spring.rb file config/spring.rb
and use after_fork
创建一个spring.rb文件
config/spring.rb
after_fork
并使用after_fork
Spring.after_fork do
# run your code here
# you have access to ARGV
binding.pry
end
I believe this answers your needs. 我相信这可以满足您的需求。 Task name should include also the namespace.
任务名称还应包括命名空间。
config/initializers/rake.rb 配置/初始化/ rake.rb
module Rake
class Application
attr_accessor :current_task
end
class Task
alias :old_execute :execute
def execute(args=nil)
Rake.application.current_task = @name
old_execute(args)
end
end #class Task
end #module Rake
models/something.rb: 车型/ something.rb:
class Something < ActiveRecord::Base
puts Rake.application.current_task
end
lib/tasks/some_task.rake: LIB /任务/ some_task.rake:
require 'rake'
namespace :ns do
task :some_task => :environment do
Something.all.to_a
end
end
console: 安慰:
rake ns:some_task
ns:some_task
also works: 也有效:
bundle exec rake ns:some_task
ns:some_task
You could redefine tasks using Rake::Task#enhance
to create a variable before invoking the original task, but that seems a bit messy and you'll have to worry about what to do with tasks like :environment
and :default
. 您可以使用
Rake::Task#enhance
来重新定义任务,以便在调用原始任务之前创建变量,但这看起来有点混乱,您将不得不担心如何处理以下任务:environment
和:default
。
I think the easiest way is probably to just extend the Rake::Task#invoke
method to add a global variable which you could then access in initializers, or from wherever else you want. 我认为最简单的方法可能是扩展
Rake::Task#invoke
方法以添加一个全局变量,然后可以在初始化程序中或从您想要的任何地方访问该变量。
Here's a really quick an dirty example which you could do in the Rakefile
: 这是一个非常快速的脏例子,你可以在
Rakefile
做:
module RakeTaskName
def invoke(*args)
$rake_task_name = name
super *args
end
end
Rake::Task.send :prepend, RakeTaskName
Then, in an initializer, you can do: 然后,在初始化程序中,您可以执行以下操作:
if defined? $rake_task_name
puts "Running from rake task: #{$rake_task_name}"
end
Edit 编辑
Here's a new rails project with this code & 1 migration. 这是一个带有此代码和1迁移的新rails项目 。 The output looks like this:
输出如下所示:
Running from rake task: db:migrate
== 20160411150810 CreateFoo: migrating ========================================
-- create_table(:foos)
-> 0.0010s
== 20160411150810 CreateFoo: migrated (0.0011s) ===============================
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.