38

我有一个中间件,用于使用 Bonjour 在本地网络应用程序上宣布我的应用程序,但是当从 rake 或通过控制台调用 Rails 时,它也会宣布服务。

我想排除这些情况,只在 Rails 作为服务器运行时使用 Bonjour 中间件。

中间件配置接受 proc 在某些条件下使用 proc 排除中间件proc

config.middleware.insert_before ActionDispatch::Static, Rack::SSL, :exclude => proc { |env| 
  env['HTTPS'] != 'on' 
}

但是如何确定 Rails 是从 CLI、控制台还是作为服务器调用的呢?

4

8 回答 8

48

使用pry查看Rails模块显示可以像这样检测控制台调用:

Rails.const_defined? 'Console'

和这样的服务器调用:

Rails.const_defined? 'Server'
于 2012-11-23T09:15:39.120 回答
16

超级有帮助。谢谢@crishoj。

我想更仔细地检查 Console 对象以解决我正在处理的另一个问题,发现可以使用 来访问 Console 常量Rails::Console,因此另一个检查选项是使用:

defined? Rails::Console
defined? Rails::Server
于 2014-12-04T17:57:28.280 回答
11

在有或没有像 Puma/Passenger 这样的应用服务器的情况下使用 Rails 5,这里有三种方法可以确定你的应用程序是如何运行的:

# We are running in a CLI console
defined?(Rails::Console)

# We are running as a Rack application (including Rails)
caller.any?{|l| l =~ %r{/config.ru/}}

# We are running as a CLI console
caller.any?{|l| l =~ %r{/lib/rake/task.rb:\d+:in `execute'}}
于 2018-04-01T12:59:22.430 回答
9

每个命令的环境摘要。

我发现现有的答案要么不完整,要么多余,要么不详尽。所以这里是每个命令的表格格式以及生成的环境是什么样的。

导轨 4.2

| Command                            |  Rails.const_defined?( "Console" )  |  Rails.const_defined?( "Server" )  |               ARGV              |
|------------------------------------|-------------------------------------|------------------------------------|---------------------------------|
| `rake db:migrate:status`           |  false                              |  true                              |  ["db:migrate:status"]          |
| `rails console`                    |  true                               |  true                              |  []                             |
| `rails server`                     |  false                              |  true                              |  []                             |
| `rails g migration new_migration`  |  false                              |  true                              |  ["migration", "new_migration"] |
| `rails r "puts 'Hi'"`              |  false                              |  true                              |  []                             |

您可以看到,仅检查定义为Rails常量的“服务器”不会捕获生成器,例如rails g migration. 你需要检查ARGV来做到这一点。

我希望这有帮助。我只能立即访问 Rails 4.2,但可以随意添加其他 Rails 版本的部分,以及添加任何需要“捕获”的附加命令。

于 2018-12-28T19:44:02.470 回答
3

Rails 5 在Passenger 下运行时未定义“服务器”。

我发现的最佳解决方案是这个答案的变体:

if %w(rails rake).include?(File.basename($0))
   <console or runner>
else
   <server>       
end
于 2017-03-06T06:48:06.543 回答
1

在我们的项目中,我必须在boot.rb中检测控制台模式,为此我使用了:

in_console = (ARGV & ['c', 'console']).any?

这不是一个万无一失的解决方案,但对于我们的用例来说已经足够了。

于 2018-12-03T03:59:32.320 回答
0

这是我在乘客/美洲狮上检测 sidekiq 或运行服务器的版本。鉴于前面的答案,不能 100% 确定它在所有情况下都能正常工作(我还没有测试过运行 rails runner 或 rake 任务时的情况)

@running_app = begin
  if defined?(Rails::Console)
    'Console'
  elsif Sidekiq.server?
    'Worker'
  elsif defined?(::PhusionPassenger) || defined?(Rails::Server) 
    'Server'
  else
    nil # unknown
  end
end
于 2021-10-27T08:20:52.320 回答
-7

对于帕德里诺:

控制台检查:

if Padrino::constants.include? :Cli
    #your code
end

服务器检查:

if !Padrino::constants.include? :Cli
    #your code
end
于 2018-11-18T18:04:24.043 回答