Skip to content

Instantly share code, notes, and snippets.

@sdeboer
Last active December 11, 2015 14:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sdeboer/4612099 to your computer and use it in GitHub Desktop.
Save sdeboer/4612099 to your computer and use it in GitHub Desktop.
A very thin abstract class for fast rails responses
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
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