Rails on Rack

Это руководство раскрывает интеграцию Rails и Rack и взаимодействие с другими компонентами Rack. Обратившись к нему, вы сможете:

Это руководство предполагает практические знания протокола Rack и такие концепции Rack, как промежуточные программы (middlewares), карты (maps) url и Rack::Builder.

Введение в Rack

Rack представляет собой минимальный, модульный и адаптивный интерфейс для разработки веб-приложений на Ruby. Оборачивая запросы и отклики HTTP как можно более простым образом, он объединил и очистил API для веб-серверов, веб-фреймворков и промежуточных программ (так называемых middleware) до единственного метода call.

- Документация Rack API

Объяснение, что такое Rack, на самом деле не является темой этого руководства. Если вы не знакомы с основами Rack, обратитесь к разделу Источники.

Rails on Rack

Объект Rack приложения Rails

ApplicationName::Application это основной объект приложения Rack в приложении Rails. Любой совместимый с Rack веб-сервер должен использовать объект ApplicationName::Application для обслуживания приложения Rails.

rails server

rails server выполняет основную работу по созданию объекта Rack::Server и запуску веб-сервера.

Вот как rails server создает экземпляр Rack::Server

Rails::Server.new.tap { |server|
  require APP_PATH
  Dir.chdir(Rails.application.root)
  server.start
}

Rails::Server унаследован от Rack::Server и вызывает метод Rack::Server#start следующим образом:

class Server < ::Rack::Server
  def start
    ...
    super
  end
end

Вот как он загружает промежуточные программы:

def middleware
  middlewares = []
  middlewares << [Rails::Rack::Debugger]  if options[:debugger]
  middlewares << [::Rack::ContentLength]
  Hash.new(middlewares)
end

Rails::Rack::Debugger в основном полезен только в окружении development. Следующая таблица объясняет назначение загружаемых промежуточных программ:

Промежуточная программа Назначение
Rails::Rack::Debugger Запускает отладчик
Rack::ContentLength Считает количество байт в отклике и устанавливает заголовок HTTP Content-Length

rackup

Для использования rackup вместо рельсового rails server, следует поместить следующее в config.ru в корневой директории приложения Rails:

# Rails.root/config.ru
require "config/environment"

use Rack::Debugger
use Rack::ContentLength
run ApplicationName::Application

И запустить сервер:

$ rackup config.ru

Узнать подробности различных опций rackup:

$ rackup --help

Стек промежуточных программ Action Dispatcher

Многие внутренние компоненты Action Dispatcher реализованы как промежуточные программы Rack. Rails::Application использует ActionDispatch::MiddlewareStack для объединения различных внутренних и внешних промежуточных программ для формирования полноценного приложения Rails Rack.

ActionDispatch::MiddlewareStack это эквивалент Rack::Builder в Rails, сделанный с большей гибкостью и приспособленностью к требованиям Rails.

Просмотр стека промежуточных программ

В Rails имеется удобный таск rake для просмотра используемого стека промежуточных программ:

$ rake middleware

Для нового приложения Rails он может выдать что-то наподобие:

use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x000000029a0838>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use ActionDispatch::Head
use Rack::ConditionalGet
use Rack::ETag
use ActionDispatch::BestStandardsSupport
run ApplicationName::Application.routes

Назначение каждой из этих промежуточных программ объясняется в разделе Внутренние промежуточные программы.

Настройка стека промежуточных программ

Rails предоставляет простой конфигурационных интерфейс config.middleware для добавления, удаления и изменения промежуточных программ в стеке промежуточных программ, из application.rb или конфигурационного файла определенной среды environments/<environment>.rb.

Добавление промежуточной программы

Добавить новую промежуточную программу в стек промежуточных программ можно с использованием следующих методов:

# config/application.rb

# Добавить Rack::BounceFavicon в конец
config.middleware.use Rack::BounceFavicon

# Добавить Lifo::Cache после ActiveRecord::QueryCache.
# Передать аргумент { :page_cache => false } в Lifo::Cache.
config.middleware.insert_after ActiveRecord::QueryCache, Lifo::Cache, :page_cache => false
Перемена местами промежуточных программ

Поменять местами существующие промежуточные программы в стеке можно с использованием config.middleware.swap.

# config/application.rb

# Поменять местами ActionDispatch::ShowExceptions с Lifo::ShowExceptions
config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
Стек промежуточных программ как Enumerable

Стек промежуточных программ ведет себя как обычный Enumerable. Можно использовать любой Enumerable метод для воздействия или получения данных из стека. Стек промежуточных программ также реализует некоторые методы Array, включая [], unshift and delete. Методы, описанные в предыдущем разделе — это всего лишь методы для удобства.

Добавьте следующие строчки в конфигурацию вашего приложения:

# config/application.rb
config.middleware.delete "Rack::Lock"

Теперь, при просмотре стека промежуточных программ, вы увидите, что Rack::Lock больше не является его частью.

$ rake middleware
(in /Users/lifo/Rails/blog)
use ActionDispatch::Static
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000001c304c8>
use Rack::Runtime
...
run Blog::Application.routes

Если хотите убрать промежуточные программы, относящиеся к сессии, сделайте следующее:

# config/application.rb
config.middleware.delete "ActionDispatch::Cookies"
config.middleware.delete "ActionDispatch::Session::CookieStore"
config.middleware.delete "ActionDispatch::Flash"

Чтобы убрать промежуточные программы, относящиеся к бразуеру,

# config/application.rb
config.middleware.delete "ActionDispatch::BestStandardsSupport"
config.middleware.delete "Rack::MethodOverride"

Стек внутренних промежуточных программ

Значительная часть функционала Action Controller реализована как промежуточные программы. Следующий перечень объясняет назначение каждой из них:

ActionDispatch::Static Rack::Lock ActiveSupport::Cache::Strategy::LocalCache::Middleware Rack::Runtime Rack::MethodOverride ActionDispatch::RequestId Rails::Rack::Logger ActionDispatch::ShowExceptions ActionDispatch::DebugExceptions ActionDispatch::RemoteIp ActionDispatch::Reloader ActionDispatch::Callbacks ActiveRecord::ConnectionAdapters::ConnectionManagement ActiveRecord::QueryCache ActionDispatch::Cookies ActionDispatch::Session::CookieStore ActionDispatch::Flash ActionDispatch::ParamsParser ActionDispatch::Head Rack::ConditionalGet Rack::ETag ActionDispatch::BestStandardsSupport

Можете использовать любые из этих промежуточных программ в своем стеке Rack.

Использование Rack Builder

Следующее показывает, как использовать Rack::Builder вместо предоставленного Rails MiddlewareStack.

Очистите существующий стек промежуточных программ Rails

# config/application.rb
config.middleware.clear


Добавьте файл config.ru в Rails.root

# config.ru
use MyOwnStackFromScratch
run ApplicationName::Application

Источники

Обучение Rack

Понимание промежуточных программ