27.02.2013 Views

Rails%203%20In%20Action

Rails%203%20In%20Action

Rails%203%20In%20Action

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Middleware<br />

def call(env)<br />

path = env['PATH_INFO'].chomp('/')<br />

method = env['REQUEST_METHOD']<br />

if FILE_METHODS.include?(method)<br />

The env variable here is the same sort of style as the env variable that you used back in<br />

your Rack application. Rack middleware and Rack applications are actually designed<br />

almost identically. You saw the env["PATH_INFO"] key before—that’s the one that contains<br />

the path of the request, something such as /images/rails.png. By calling chomp<br />

on this, it strips off any trailing forward-slashes on the end of this URL.<br />

The env["REQUEST_METHOD"] key contains the HTTP request method used in this<br />

request. If this method is either GET or HEAD, then the code inside the if runs here.<br />

The next line after this one checks for the presence of a file:<br />

if file_exist?(path)<br />

This method is defined further down in this file, like this:<br />

def file_exist?(path)<br />

full_path = File.join(@file_server.root, ::Rack::Utils.unescape(path))<br />

File.file?(full_path) && File.readable?(full_path)<br />

end<br />

This method uses the root method, which returns the fill path to the public directory<br />

of your application. This method then uses File.join to join the path to the public<br />

directory and the unescaped name of the file that’s being requested. Finally, this<br />

method uses the File.file? and File.readable? methods to determine if the path<br />

specified is actually a file and if that file is readable. If it is indeed a file and is indeed<br />

readable, then this line is executed:<br />

return @file_server.call(env)<br />

This calls the call method on the Rack::File instance, which then (after some additional<br />

processing) serves the file.<br />

So far, this has been the process this piece of middleware uses for an existing file. If<br />

the file doesn’t exist, then it goes into the else for the if File.exists? line, which<br />

results in the following code being run:<br />

cached_path = directory_exist?(path) ? "#{path}/index" : path<br />

cached_path += ::ActionController::Base.page_cache_extension<br />

if file_exist?(cached_path)<br />

env['PATH_INFO'] = cached_path<br />

return @file_server.call(env)<br />

end<br />

The first line here checks for a directory with the same name as the path you’ve<br />

requested. Imagine your request is now /projects and you have a public/projects directory.<br />

This directory_exists? method would then return true because this directory<br />

exists. The directory_exists? method is defined like this:<br />

537

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!