Skip to content

Commit 6c1fedd

Browse files
author
Michael Bleigh
committed
Merge branch 'master' of https://github.com/spraints/grape
2 parents d33bfae + 535d43d commit 6c1fedd

File tree

2 files changed

+66
-11
lines changed

2 files changed

+66
-11
lines changed

lib/grape/middleware/formatter.rb

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,26 @@ class Formatter < Base
1111
:rss => 'application/rss+xml',
1212
:txt => 'text/plain'
1313
}
14+
FORMATTERS = {
15+
:json => :encode_json,
16+
:txt => :encode_txt,
17+
}
1418

1519
def default_options
1620
{
1721
:default_format => :txt,
22+
:formatters => {},
1823
:content_types => {}
1924
}
2025
end
2126

2227
def content_types
2328
CONTENT_TYPES.merge(options[:content_types])
2429
end
30+
31+
def formatters
32+
FORMATTERS.merge(options[:formatters])
33+
end
2534

2635
def mime_types
2736
content_types.invert
@@ -75,18 +84,25 @@ def mime_array
7584

7685
def after
7786
status, headers, bodies = *@app_response
78-
bodymap = []
79-
bodies.each do |body|
80-
bodymap << case env['api.format']
81-
when :json
82-
encode_json(body)
83-
when :txt
84-
encode_txt(body)
85-
end
87+
formatter = formatter_for env['api.format']
88+
bodymap = bodies.collect do |body|
89+
formatter.call(body)
8690
end
87-
headers['Content-Type'] = 'application/json'
91+
headers['Content-Type'] = content_types[env['api.format']]
8892
Rack::Response.new(bodymap, status, headers).to_a
8993
end
94+
95+
def formatter_for(api_format)
96+
spec = formatters[api_format]
97+
case spec
98+
when nil
99+
lambda { |obj| obj }
100+
when Symbol
101+
method(spec)
102+
else
103+
spec
104+
end
105+
end
90106

91107
def encode_json(object)
92108
if object.respond_to? :serializable_hash
@@ -103,4 +119,4 @@ def encode_txt(object)
103119
end
104120
end
105121
end
106-
end
122+
end

spec/grape/middleware/formatter_spec.rb

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,43 @@ def serializable_hash
8484
subject.env['api.format'].should == :json
8585
end
8686
end
87-
end
87+
88+
context 'Content-type' do
89+
it 'should be set for json' do
90+
_, headers, _ = subject.call({'PATH_INFO' => '/info.json'})
91+
headers['Content-type'].should == 'application/json'
92+
end
93+
it 'should be set for xml' do
94+
_, headers, _ = subject.call({'PATH_INFO' => '/info.xml'})
95+
headers['Content-type'].should == 'application/xml'
96+
end
97+
it 'should be set for txt' do
98+
_, headers, _ = subject.call({'PATH_INFO' => '/info.txt'})
99+
headers['Content-type'].should == 'text/plain'
100+
end
101+
it 'should be set for custom' do
102+
subject.options[:content_types][:custom] = 'application/x-custom'
103+
_, headers, _ = subject.call({'PATH_INFO' => '/info.custom'})
104+
headers['Content-type'].should == 'application/x-custom'
105+
end
106+
end
107+
108+
context 'Format' do
109+
it 'should use custom formatter' do
110+
subject.options[:content_types][:custom] = "don't care"
111+
subject.options[:formatters][:custom] = lambda { |obj| 'CUSTOM FORMAT' }
112+
_, _, body = subject.call({'PATH_INFO' => '/info.custom'})
113+
body.body.should == ['CUSTOM FORMAT']
114+
end
115+
it 'should use default json formatter' do
116+
@body = 'blah'
117+
_, _, body = subject.call({'PATH_INFO' => '/info.json'})
118+
body.body.should == ['"blah"']
119+
end
120+
it 'should use custom json formatter' do
121+
subject.options[:formatters][:json] = lambda { |obj| 'CUSTOM JSON FORMAT' }
122+
_, _, body = subject.call({'PATH_INFO' => '/info.json'})
123+
body.body.should == ['CUSTOM JSON FORMAT']
124+
end
125+
end
126+
end

0 commit comments

Comments
 (0)