rack/rack — pull request #570 by graysonwright (2013-06-03 07:33:54+00:00)
Title: Extract several methods from Rack::File#serving

## Extracted methods:

- mime_type
- filesize
- response_body

## Motivation

1. The method is [somewhat complicated](codeclimate)
2. Extracting pieces of the method into their own functions really improves your ability to extend the class to customize it.

## Example of Customization

Let's say you have a basic Rack::Directory setup.

```ruby
run Rack::Directory.new(".")
```

But you have a lot of markdown files in the directory, and you want to compile and render them on the fly. That requires modifying the mime type, the response body, and the filesize.

By extracting the methods out of `Rack::File#serving`, you only have to overwrite two methods (file_size is calculated based on the new `response_body`

The `config.ru` would look something like this:

```ruby
require 'redcarpet'
require 'rack/mime'

def markdown_compiler
Redcarpet::Markdown.new(Redcarpet::Render::HTML.new)
end

class Rack::File
# Overwrite
def mime_type
@mime ||= Rack::Mime.mime_type(F.extname(@path), @default_mime)
markdown? ? 'text/html' : @mime
end

# Overwrite
def response_body
if markdown?
@response_body ||= markdown_compiler.render(F.read(@path))
else
nil
end
end

def markdown?
F.extname(@path) == '.md'
end
end

run Rack::Directory.new(".")
```

## Other stuff

This doesn't change the behavior of Rack, it just makes it easier to customize and to work on in the future. Because of that, I didn't write any tests. Let me know if I should.

[codeclimate]: https://codeclimate.com/github/rack/rack/Rack::File#method-complexity