Last active
December 11, 2015 14:08
-
-
Save sdeboer/4612099 to your computer and use it in GitHub Desktop.
A very thin abstract class for fast rails responses
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ExampleProfileController < MetalController | |
# assuming a route something like: | |
# /profile/:user_id.json | |
def show | |
prof = Profile.find params['user_id'] | |
if prof | |
respond_with prof | |
else | |
response_error 'not_found', "User id of #{params['user_id']} has not been found." | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MetalController < ActionController::Metal | |
abstract! | |
include ActionController::ParamsWrapper | |
def response_error(message, reason = nil, status = 400) | |
args = {error: message, reason: reason} | |
respond_with args, 'error', status | |
end | |
# This has the opinion that the params['format'] will tell you the | |
# contnent type and that you can use Rails standard conversion for | |
# those and that this is a successful response, that you want to compress. | |
# Each of these could be overridden by the appropriate argument. | |
# (sure we could do the rails standard extract_options approach, but this | |
# is supposed to be bare bones) | |
# | |
# The reason for compression is because in my usage this is called by a | |
# CDN caching service and it doesn't make sense for all data to be | |
# compressed so Apache/Nginx plugins for this don't make sense. | |
# | |
# There is treatment for JSONP if the request is a .js request, you | |
# should probably remove that unless you know you want it. | |
# | |
# NOTE: If you pass a type then your data must already be in the | |
# final format. | |
# | |
# NOTE: If you really don't want this thing compressed you need to | |
# set the self.headers['Content-Encoding'] before respond_with | |
def respond_with(data, js_callback = nil, status = 200, type = nil) | |
if status >= 200 and status < 300 and !Rails.env.development? | |
self.headers['ETag'] ||= %Q{"#{Digest::MD5.hexdigest(body)}"} | |
self.headers['Cache-control'] ||= "max-age=18000" | |
end | |
self.headers['Date'] ||= Time.now.httpdate | |
self.headers['Vary'] ||= 'Accept-Encoding' | |
unless type | |
format = param['format'] | |
if format.eql?('js') | |
body = data.to_json | |
type = Mime::JS | |
callback = js_callback || params['jsonp'] | |
body = %Q{#{params['jsonp'](#{data.to_json});} | |
elsif format.eql?('xml') | |
type = Mime::XML | |
body = data.to_xml | |
else | |
body = data.to_json | |
type = Mime::JSON | |
end | |
end | |
self.content_type = type | |
if self.headers['Content-Encoding'] | |
self.response_body = body | |
else | |
self.headers['Content-Encoding'] = 'gzip' | |
self.response_body = ActiveSupport::Gzip.compress(body) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment