Skip to content

Commit

Permalink
Let actions to detect accepted mime type and to return the correct fo…
Browse files Browse the repository at this point in the history
…rmat symbol. Configuration can now register mime types
  • Loading branch information
jodosha committed Jun 18, 2014
1 parent 26e35be commit 32b3483
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 11 deletions.
10 changes: 6 additions & 4 deletions lib/lotus/action/mime.rb
Expand Up @@ -118,7 +118,7 @@ def format=(format)
end

def format
@format || default_format
@format || detect_format
end

# The content type that will be automatically set in the response.
Expand Down Expand Up @@ -199,12 +199,14 @@ def accepts
end
end

def default_format
::Rack::Mime::MIME_TYPES.key(content_type).gsub(/\A\./, '').to_sym
def detect_format
configuration.format_for(content_type) ||
::Rack::Mime::MIME_TYPES.key(content_type).gsub(/\A\./, '').to_sym
end

def format_to_mime_type(format)
::Rack::Mime.mime_type(".#{format}")
# FIXME lookup configuration first, then fallback to Rack::Mime
::Rack::Mime.mime_type(".#{ format }")
end
end
end
Expand Down
21 changes: 21 additions & 0 deletions lib/lotus/controller/configuration.rb
Expand Up @@ -25,6 +25,16 @@ class Configuration
# @api private
DEFAULT_ERROR_CODE = 500

# Default Mime type to format mapping
#
# @since 0.2.0
# @api private
DEFAULT_FORMATS = {
'*/*' => :all,
'application/octet-stream' => :all,
'text/html' => :html
}.freeze

# Return a copy of the configuration of the framework instance associated
# with the given class.
#
Expand Down Expand Up @@ -323,6 +333,14 @@ def modules(&blk)
end
end

def format(symbol, mime_type)
@formats.merge! mime_type => symbol
end

def format_for(mime_type)
@formats[mime_type]
end

# Duplicate by copying the settings in a new instance.
#
# @return [Lotus::Controller::Configuration] a copy of the configuration
Expand All @@ -335,6 +353,7 @@ def duplicate
c.handled_exceptions = handled_exceptions.dup
c.action_module = action_module
c.modules = modules.dup
c.formats = formats.dup
end
end

Expand All @@ -346,6 +365,7 @@ def reset!
@handle_exceptions = true
@handled_exceptions = {}
@modules = []
@formats = DEFAULT_FORMATS.dup
@action_module = ::Lotus::Action
end

Expand All @@ -361,6 +381,7 @@ def load!(base)

protected
attr_accessor :handled_exceptions
attr_accessor :formats
attr_writer :action_module
attr_writer :modules
end
Expand Down
6 changes: 3 additions & 3 deletions test/action/format_test.rb
Expand Up @@ -27,7 +27,7 @@ def call(params)

it 'lookup to #content_type if was not explicitly set (default: application/octet-stream)' do
@action.call({})
@action.send(:format).must_equal :a
@action.send(:format).must_equal :all
end
end

Expand Down Expand Up @@ -64,7 +64,7 @@ def call(params)
end
end

describe 'json' do
describe 'xml' do
before do
@action.call({ format: :xml })
end
Expand Down Expand Up @@ -106,4 +106,4 @@ def call(params)
end
end
end
end
end
33 changes: 29 additions & 4 deletions test/configuration_test.rb
Expand Up @@ -150,10 +150,29 @@ def status
end
end

describe '#register_format' do
before do
@configuration.format :custom, 'custom/format'
end

it 'registers the given format' do
@configuration.format_for('custom/format').must_equal :custom
end
end

describe 'default formats' do
it 'declares default formats' do
@configuration.format_for('*/*').must_equal :all
@configuration.format_for('application/octet-stream').must_equal :all
@configuration.format_for('text/html').must_equal :html
end
end

describe 'duplicate' do
before do
@configuration.reset!
@configuration.modules { include Kernel }
@configuration.format :custom, 'custom/format'
@config = @configuration.duplicate
end

Expand All @@ -162,23 +181,27 @@ def status
@config.handled_exceptions.must_equal @configuration.handled_exceptions
@config.action_module.must_equal @configuration.action_module
@config.modules.must_equal @configuration.modules
@config.send(:formats).must_equal @configuration.send(:formats)
end

it "doesn't affect the original configuration" do
@config.handle_exceptions = false
@config.handle_exception ArgumentError => 400
@config.action_module CustomAction
@config.modules { include Comparable }
@config.format :another, 'another/format'

@config.handle_exceptions.must_equal false
@config.handled_exceptions.must_equal Hash[ArgumentError => 400]
@config.action_module.must_equal CustomAction
@config.modules.size.must_equal 2
@config.handle_exceptions.must_equal false
@config.handled_exceptions.must_equal Hash[ArgumentError => 400]
@config.action_module.must_equal CustomAction
@config.modules.size.must_equal 2
@config.format_for('another/format').must_equal :another

@configuration.handle_exceptions.must_equal true
@configuration.handled_exceptions.must_equal Hash[]
@configuration.action_module.must_equal ::Lotus::Action
@configuration.modules.size.must_equal 1
@configuration.format_for('another/format').must_be_nil
end
end

Expand All @@ -188,6 +211,7 @@ def status
@configuration.handle_exception ArgumentError => 400
@configuration.action_module CustomAction
@configuration.modules { include Kernel }
@configuration.format :another, 'another/format'

@configuration.reset!
end
Expand All @@ -197,6 +221,7 @@ def status
@configuration.handled_exceptions.must_equal({})
@configuration.action_module.must_equal(::Lotus::Action)
@configuration.modules.must_equal([])
@configuration.send(:formats).must_equal(Lotus::Controller::Configuration::DEFAULT_FORMATS)
end
end
end
12 changes: 12 additions & 0 deletions test/integration/mime_type_test.rb
Expand Up @@ -13,12 +13,14 @@ class MimesController

action 'Default' do
def call(params)
self.body = format
end
end

action 'Custom' do
def call(params)
self.format = :xml
self.body = format
end
end

Expand All @@ -28,6 +30,8 @@ def call(params)
self.headers.merge!({'X-AcceptHtml' => accept?('text/html').to_s })
self.headers.merge!({'X-AcceptXml' => accept?('application/xml').to_s })
self.headers.merge!({'X-AcceptJson' => accept?('text/json').to_s })

self.body = format
end
end

Expand All @@ -47,11 +51,13 @@ def call(params)
it 'fallbacks to the default "Content-Type" header when the request is lacking of this information' do
response = @app.get('/')
response.headers['Content-Type'].must_equal 'application/octet-stream'
response.body.must_equal 'all'
end

it 'returns the specified "Content-Type" header' do
response = @app.get('/custom')
response.headers['Content-Type'].must_equal 'application/xml'
response.body.must_equal 'xml'
end

describe 'when Accept is sent' do
Expand All @@ -63,11 +69,13 @@ def call(params)
it 'sets "Content-Type" header according to "Accept"' do
response = @app.get('/', 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')
response.headers['Content-Type'].must_equal 'text/html'
response.body.must_equal 'html'
end

it 'sets "Content-Type" header according to "Accept" quality scale' do
response = @app.get('/', 'HTTP_ACCEPT' => 'application/json;q=0.6,application/xml;q=0.9,*/*;q=0.8')
response.headers['Content-Type'].must_equal 'application/xml'
response.body.must_equal 'xml'
end
end
end
Expand All @@ -86,6 +94,7 @@ def call(params)
@response.headers['X-AcceptHtml'].must_equal 'true'
@response.headers['X-AcceptXml'].must_equal 'true'
@response.headers['X-AcceptJson'].must_equal 'true'
@response.body.must_equal 'all'
end
end

Expand All @@ -98,6 +107,7 @@ def call(params)
@response.headers['X-AcceptHtml'].must_equal 'true'
@response.headers['X-AcceptXml'].must_equal 'true'
@response.headers['X-AcceptJson'].must_equal 'true'
@response.body.must_equal 'all'
end
end

Expand All @@ -109,6 +119,7 @@ def call(params)
@response.headers['X-AcceptHtml'].must_equal 'true'
@response.headers['X-AcceptXml'].must_equal 'false'
@response.headers['X-AcceptJson'].must_equal 'false'
@response.body.must_equal 'html'
end
end

Expand All @@ -120,6 +131,7 @@ def call(params)
@response.headers['X-AcceptHtml'].must_equal 'true'
@response.headers['X-AcceptXml'].must_equal 'true'
@response.headers['X-AcceptJson'].must_equal 'false'
@response.body.must_equal 'html'
end
end
end
Expand Down

0 comments on commit 32b3483

Please sign in to comment.