Как определить, запущен ли Rails из CLI, консоли или как сервер?

У меня есть промежуточное ПО для объявления моего приложения в приложении локальной сети с использованием Bonjour, но оно также объявляет сервис, когда Rails вызывается из rake или через консоль.

Я хотел бы исключить эти случаи и использовать промежуточное программное обеспечение Bonjour, только когда Rails работает как сервер.

Конфигурация промежуточного программного обеспечения принимает процедуру исключения промежуточного программного обеспечения при определенных условиях с использованием proc:

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

Но как мне определить, был ли Rails вызван из CLI, консоли или как сервер?

8 ответов

Решение

Подглядывать за Rails Модуль, использующий pry, показывает, что вызовы консоли могут быть обнаружены следующим образом:

Rails.const_defined? 'Console'

И серверные вызовы как это:

Rails.const_defined? 'Server'

Краткое описание среды для каждой команды.

Я обнаружил, что существующие ответы являются неполными, избыточными или не исчерпывающими. Итак, вот формат таблицы каждой команды и как выглядит итоговая среда.

Rails 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, а также добавлять любые дополнительные команды, которые нужно "перехватить".

Супер полезно. Спасибо @crishoj.

Я хотел исследовать объект консоли более подробно на предмет другой проблемы, над которой я работаю, и обнаружил, что константа консоли может быть достигнута с помощью Rails::Console, так что другой вариант для проверки будет использовать:

defined? Rails::Console
defined? Rails::Server

Используя Rails 5 с или без сервера приложений, такого как Puma/Passenger, вот три способа определить, как работает ваше приложение:

# 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'}}

"Сервер" не определен, когда Rails 5 работает под Passenger.

Лучшее решение, которое я нашел, - вариант этого ответа:

if %w(rails rake).include?(File.basename($0))
   <console or runner>
else
   <server>       
end

В нашем проекте я должен был определить режим консоли в boot.rb, для этого я использовал:

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

Не надежное решение, но достаточно хорошее для нашего варианта использования.

Вот моя версия, которая обнаруживает sidekiq или работающий сервер на пассажирском /puma. Учитывая предыдущие ответы, он не уверен на 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

Для Падрино:

Консольная проверка:

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

Проверка сервера:

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

Другие вопросы по тегам