From bda787e9b10141c841ba3d86146d42b8c1e62a1b Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sun, 11 Jan 2009 15:57:44 +0000 Subject: Initial draft of the rack guide --- railties/doc/guides/html/rails_on_rack.html | 554 ++++++++++++++++++++++++++++ 1 file changed, 554 insertions(+) create mode 100644 railties/doc/guides/html/rails_on_rack.html (limited to 'railties/doc/guides/html/rails_on_rack.html') diff --git a/railties/doc/guides/html/rails_on_rack.html b/railties/doc/guides/html/rails_on_rack.html new file mode 100644 index 0000000000..bf444e28e1 --- /dev/null +++ b/railties/doc/guides/html/rails_on_rack.html @@ -0,0 +1,554 @@ + + + + + Rails on Rack + + + + + + + + + +
+ + + +
+

Rails on Rack

+
+
+

This guide covers Rails integration with Rack and interfacing with other Rack components. By referring to this guide, you will be able to:

+
    +
  • +

    +Create Rails Metal applications +

    +
  • +
  • +

    +Use Rack Middlewares in your Rails applications +

    +
  • +
  • +

    +Understand Action Pack’s internal Middleware stack +

    +
  • +
  • +

    +Define custom internal Middleware stack +

    +
  • +
  • +

    +Understand the best practices for developing a middleware aimed at Rails applications +

    +
  • +
+
+ + + +
+Note +This guide assumes a working knowledge of Rack protocol and Rack concepts such as middlewares
+
+
+
+

1. Introduction to Rack

+
+
+
+

Explaining Rack is not really in the scope of this guide. In case you are not familiar with Rack’s basics, you should check out the following links:

+ +
+

2. Rails on Rack

+
+

2.1. ActionController::Dispatcher.new

+

ActionController::Dispatcher.new is the primary Rack application object of a Rails application. It responds to call method with a single env argument and returns a Rack response. Any Rack compliant web server should be using ActionController::Dispatcher.new object to serve a Rails application.

+

2.2. script/server

+

script/server does the basic job of creating a Rack::Builder object and starting the webserver. This is Rails equivalent of Rack’s rackup script.

+

Here’s how script/server creates an instance of Rack::Builder

+
+
+
app = Rack::Builder.new {
+  use Rails::Rack::LogTailer unless options[:detach]
+  use Rails::Rack::Static
+  use Rails::Rack::Debugger if options[:debugger]
+  run ActionController::Dispatcher.new
+}.to_app
+

Middlewares used in the code above are most useful in development envrionment. The following table explains their usage:

+
+ +++ + + + + + + + + + + + + + + + + + + + +
Middleware Purpose

Rails::Rack::LogTailer

Appends log file output to console

Rails::Rack::Static

Serves static files inside RAILS_ROOT/public directory

Rails::Rack::Debugger

Starts Debugger

+
+

2.3. rackup

+

To use rackup instead of Rails' script/server, you can put the following inside config.ru of your Rails application’s root directory:

+
+
+
# RAILS_ROOT/config.ru
+require "config/environment"
+
+use Rails::Rack::LogTailer
+use Rails::Rack::Static
+run ActionController::Dispatcher.new
+

And start the server:

+
+
+
[lifo@null application]$ rackup
+

To find out more about different rackup options:

+
+
+
[lifo@null application]$ rackup --help
+
+

3. Action Controller Middleware Stack

+
+

Many of Action Controller’s internal components are implemented as Rack middlewares. ActionController::Dispatcher uses ActionController::MiddlewareStack to combine various internal and external middlewares to form a complete Rails Rack application.

+
+ + + +
+Note + +
What is ActionController::MiddlewareStack ?
ActionController::MiddlewareStack is Rails equivalent of Rack::Builder, but built for better flexibility and more features to meet Rails' requirements.
+
+

3.1. Adding Middlewares

+

Rails provides a very simple configuration interface for adding generic Rack middlewares to a Rails applications.

+

Here’s how you can add middlewares via environment.rb

+
+
+
# environment.rb
+
+config.middleware.use Rack::BounceFavicon
+

3.2. Internal Middleware Stack

+
+
+
use "ActionController::Lock", :if => lambda {
+  !ActionController::Base.allow_concurrency
+}
+
+use "ActionController::Failsafe"
+
+use "ActiveRecord::QueryCache", :if => lambda { defined?(ActiveRecord) }
+
+["ActionController::Session::CookieStore",
+ "ActionController::Session::MemCacheStore",
+ "ActiveRecord::SessionStore"].each do |store|
+   use(store, ActionController::Base.session_options,
+      :if => lambda {
+        if session_store = ActionController::Base.session_store
+          session_store.name == store
+        end
+      }
+    )
+end
+
+use ActionController::VerbPiggybacking
+
+ +++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Middleware Purpose

ActionController::Lock

Mutex

ActionController::Failsafe

Never fail

ActiveRecord::QueryCache

Query caching

ActionController::Session::CookieStore

Query caching

ActionController::Session::MemCacheStore

Query caching

ActiveRecord::SessionStore

Query caching

ActionController::VerbPiggybacking

_method hax

+
+

3.3. Custom Internal Middleware Stack

+

VERIFY THIS WORKS. Just a code dump at the moment.

+

Put the following in an initializer.

+
+
+
ActionController::Dispatcher.middleware = ActionController::MiddlewareStack.new do |m|
+  m.use ActionController::Lock
+  m.use ActionController::Failsafe
+  m.use ActiveRecord::QueryCache
+  m.use ActionController::Session::CookieStore
+  m.use ActionController::VerbPiggybacking
+end
+
+

4. Rails Metal Applications

+
+

Rails Metal applications are minimal Rack applications specially designed for integrating with a typical Rails applications. As Rails Metal Applications skip all of the Action Controller stack, serving a request has no overhead from the Rails framework itself. This is especially useful for infrequent cases where the performance of the full stack Rails framework is an issue.

+

4.1. Generating a Metal Application

+

Rails provides a generator called performance_test for creating new performance tests:

+
+
+
script/generate metal poller
+

This generates poller.rb in the app/metal directory:

+
+
+
# Allow the metal piece to run in isolation
+require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails)
+
+class Poller
+  def self.call(env)
+    if env["PATH_INFO"] =~ /^\/poller/
+      [200, {"Content-Type" => "text/html"}, ["Hello, World!"]]
+    else
+      [404, {"Content-Type" => "text/html"}, ["Not Found"]]
+    end
+  end
+end
+

Metal applications are an optimization. You should make sure to understand the related performance implications before using it.

+
+

5. Changelog

+
+ +
    +
  • +

    +January 11, 2009: First version by Pratik +

    +
  • +
+
+ +
+
+ + -- cgit v1.2.3