require 'responders' require 'uber/inheritable_attr' require 'roar/rails/responder' require 'roar/rails/formats' module Roar::Rails module ControllerAdditions extend ActiveSupport::Concern included do extend Uber::InheritableAttr inheritable_attr :represents_options self.represents_options ||= Formats.new self.responder = Roar::Rails::Responder end module ClassMethods def represents(format, options) represents_options.add(format, options) respond_to format end end # TODO: move into separate class so we don't pollute controller. def consume!(model, options={}) content_type = request.content_type format = Mime::Type.lookup(content_type).try(:symbol) or raise UnsupportedMediaType.new("Cannot consume unregistered media type '#{content_type.inspect}'") parsing_method = compute_parsing_method(format) representer = prepare_model_for(format, model, options) representer.send(parsing_method, incoming_string, options) # e.g. from_json("...") model end def prepare_model_for(format, model, options) representer = representer_for(format, model, options) representer.prepare(model) end # Central entry-point for finding the appropriate representer. def representer_for(format, model, options={}) options.delete(:represent_with) || self.class.represents_options.for(format, model, controller_path) end private def compute_parsing_method(format) "from_#{format}" end def incoming_string body = request.body body.rewind body.read end # These methods deal with interfacing between the Roar Response object and # ActionController, they simply pass the body of the Roar response up or do nothing def _render_option_json(resource, options) super(_resource_or_body(resource), options) end def _render_option_xml(resource, options) super(_resource_or_body(resource), options) end def _render_option_hal(resource, options) super(_resource_or_body(resource), options) end def _resource_or_body(resource) resource.is_a?(Roar::Rails::Responder::Response) ? resource.body : resource end # Include if you intend to use roar-rails with render json: model. module Render def render(options) format = options.keys.first status = options[:status] || :ok super format => prepare_model_for(format, options.values.first, options), :status => status end end end class UnsupportedMediaType < StandardError #:nodoc: end end