diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown index 68f0a81d05..5c40e869e3 100644 --- a/CHANGELOG.markdown +++ b/CHANGELOG.markdown @@ -3,7 +3,8 @@ * [#265](https://github.com/intridea/grape/issues/264): Fix: Moved `ValidationError` into `Grape::Exceptions` - [@thepumpkin1979](https://github.com/thepumpkin1979). * [#269](https://github.com/intridea/grape/pull/269): Fix: `LocalJumpError` will not be raised when using explict return in API methods - [@simulacre](https://github.com/simulacre). -* [#86] (https://github.com/intridea/grape/issues/275): Fix Path-based versioning not recognizing '/' route - [@walski](https://github.com/walski). +* [#86](https://github.com/intridea/grape/issues/275): Fix Path-based versioning not recognizing '/' route - [@walski](https://github.com/walski). +* [#277](https://github.com/intridea/grape/pull/277): Added a DSL to declare `formatter` in API settings - [@tim-vandecasteele](https://github.com/tim-vandecasteele). * Your contribution here. 0.2.2 diff --git a/README.markdown b/README.markdown index 24d6e87d4c..3df24088e2 100644 --- a/README.markdown +++ b/README.markdown @@ -589,9 +589,12 @@ Serialization takes place automatically. Your API can declare additional types to support. Response format is determined by the request's extension, an explicit `format` parameter in the query string, or `Accept` header. +Custom formatters for additional types can be defined with a proc or by method pointer. + ``` ruby class Twitter::API < Grape::API content_type :xls, "application/vnd.ms-excel" + formatter :xls, lambda { |object| object.to_fancy_xls } end ``` diff --git a/lib/grape/api.rb b/lib/grape/api.rb index 782ac491a1..527978dc63 100644 --- a/lib/grape/api.rb +++ b/lib/grape/api.rb @@ -130,6 +130,10 @@ def format(new_format = nil) new_format ? set(:format, new_format.to_sym) : settings[:format] end + def formatter(content_type, new_formatter) + settings.imbue(:formatters, content_type.to_sym => new_formatter) + end + # Specify the format for error messages. # May be `:json` or `:txt` (default). def error_format(new_format = nil) diff --git a/lib/grape/endpoint.rb b/lib/grape/endpoint.rb index 62222a296d..6765a730cf 100644 --- a/lib/grape/endpoint.rb +++ b/lib/grape/endpoint.rb @@ -395,7 +395,8 @@ def build_middleware b.use Grape::Middleware::Formatter, :format => settings[:format], :default_format => settings[:default_format] || :txt, - :content_types => settings[:content_types] + :content_types => settings[:content_types], + :formatters => settings[:formatters] aggregate_setting(:middleware).each do |m| m = m.dup diff --git a/spec/grape/api_spec.rb b/spec/grape/api_spec.rb index 48f0ce314d..eb83e9c44c 100644 --- a/spec/grape/api_spec.rb +++ b/spec/grape/api_spec.rb @@ -946,6 +946,26 @@ class CommunicationError < RuntimeError; end end end + describe ".formatter" do + context "multiple formatters" do + before :each do + subject.formatter :json, lambda { |object| "{\"custom_formatter\":\"#{object[:some]}\"}" } + subject.formatter :txt, lambda { |object| "custom_formatter: #{object[:some]}" } + subject.get :simple do + {:some => 'hash'} + end + end + it 'sets one formatter' do + get '/simple.json' + last_response.body.should eql '{"custom_formatter":"hash"}' + end + it 'sets another formatter' do + get '/simple.txt' + last_response.body.should eql 'custom_formatter: hash' + end + end + end + describe ".default_error_status" do it 'should allow setting default_error_status' do subject.rescue_from :all