[英]Get rake task name in initializer
我想知道,如果app實例是由rake
啟動的,那么我嘗試在initializers
捕獲rake
任務名稱。 例如,如果我運行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
=> []
但一切都是空的。
我能做什么? 請幫忙。
UPDATE
如果添加Rakefile行就好
ENV["RAKE_CURRENT_TASKS"] = Rake.application.top_level_tasks.join(' ')
然后在將來你將能夠抓住它。但這個解決方案對我不好,我需要更早地抓住rake任務名稱
除非你停止使用Spring , 否則這里提出的其他答案都不會有效,因為Spring會改變rake任務被大量調用的方式。
使用Spring時,正在運行的命令將使用UNIX套接字移交給Spring服務器進程,不幸的是,Spring服務器在初始化rails環境后讀取此套接字以獲取命令及其參數。 因此,在rails初始化期間,使用Spring時似乎無法獲取命令及其參數(例如rake任務名稱),因為Spring本身還不知道! 即使是Spring提供的after_fork
鈎子也無濟於事,因為它也是在 rails初始化之后運行的。
可以在Spring源代碼中看到證據。 它是一個serve
方法 ,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
rails初始化程序在preload
方法中運行 ,該方法在從套接字讀取命令名之前運行。 在初始化之后,在fork
塊中也設置$0
和ARGV
變量。
因此,除非你明顯地修補了Spring(用你自己的方法替換了serve
方法,但是你需要自己處理套接字), 你需要停止在Spring環境中調用你的rake任務 。 如果rake
命令是RAILS_ROOT/bin/
目錄中的binstub,則需要使用spring binstup --remove rake
刪除binstub。
只有這樣,我相信,您可以在其他答案中使用其中一種解決方案。
您是否在任務中包含了=> :environment
? 例如
task :sometask => :environment do
...
end
否則,在運行rake任務時,初始化程序不會運行
有兩種方法可以達到你想要的效果,
1,不使用spring
,只需運行:
spring binstub --remove --all
然后運行你的rake任務。
2,使用彈簧:
創建一個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
我相信這可以滿足您的需求。 任務名稱還應包括命名空間。
配置/初始化/ 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
車型/ something.rb:
class Something < ActiveRecord::Base
puts Rake.application.current_task
end
LIB /任務/ some_task.rake:
require 'rake'
namespace :ns do
task :some_task => :environment do
Something.all.to_a
end
end
安慰:
rake ns:some_task
ns:some_task
也有效:
bundle exec rake ns:some_task
ns:some_task
您可以使用Rake::Task#enhance
來重新定義任務,以便在調用原始任務之前創建變量,但這看起來有點混亂,您將不得不擔心如何處理以下任務:environment
和:default
。
我認為最簡單的方法可能是擴展Rake::Task#invoke
方法以添加一個全局變量,然后可以在初始化程序中或從您想要的任何地方訪問該變量。
這是一個非常快速的臟例子,你可以在Rakefile
做:
module RakeTaskName
def invoke(*args)
$rake_task_name = name
super *args
end
end
Rake::Task.send :prepend, RakeTaskName
然后,在初始化程序中,您可以執行以下操作:
if defined? $rake_task_name
puts "Running from rake task: #{$rake_task_name}"
end
編輯
這是一個帶有此代碼和1遷移的新rails項目 。 輸出如下所示:
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.