2011-09-26 18:57:49 -04:00
|
|
|
require 'set'
|
2010-01-31 21:32:28 -05:00
|
|
|
|
2009-05-21 17:34:42 -04:00
|
|
|
module ActionController
|
2011-02-10 00:16:06 -05:00
|
|
|
# See <tt>Renderers.add</tt>
|
2009-12-09 16:38:47 -05:00
|
|
|
def self.add_renderer(key, &block)
|
2009-12-20 21:15:20 -05:00
|
|
|
Renderers.add(key, &block)
|
2009-12-09 16:38:47 -05:00
|
|
|
end
|
|
|
|
|
2014-05-18 04:54:20 -04:00
|
|
|
# See <tt>Renderers.remove</tt>
|
|
|
|
def self.remove_renderer(key)
|
|
|
|
Renderers.remove(key)
|
|
|
|
end
|
|
|
|
|
2013-08-17 21:45:50 -04:00
|
|
|
class MissingRenderer < LoadError
|
|
|
|
def initialize(format)
|
2013-09-06 06:56:33 -04:00
|
|
|
super "No renderer defined for format: #{format}"
|
2013-08-17 21:45:50 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-12-20 21:15:20 -05:00
|
|
|
module Renderers
|
2009-05-28 12:35:36 -04:00
|
|
|
extend ActiveSupport::Concern
|
2009-05-28 10:49:02 -04:00
|
|
|
|
2009-05-21 17:34:42 -04:00
|
|
|
included do
|
2010-01-31 21:32:28 -05:00
|
|
|
class_attribute :_renderers
|
2011-09-26 18:57:49 -04:00
|
|
|
self._renderers = Set.new.freeze
|
2009-05-21 17:34:42 -04:00
|
|
|
end
|
2009-05-28 10:49:02 -04:00
|
|
|
|
2009-05-21 18:23:52 -04:00
|
|
|
module ClassMethods
|
2009-12-09 16:38:47 -05:00
|
|
|
def use_renderers(*args)
|
2011-09-26 18:57:49 -04:00
|
|
|
renderers = _renderers + args
|
|
|
|
self._renderers = renderers.freeze
|
2009-05-21 17:34:42 -04:00
|
|
|
end
|
2009-12-09 16:38:47 -05:00
|
|
|
alias use_renderer use_renderers
|
2009-05-21 18:23:52 -04:00
|
|
|
end
|
2009-05-28 10:49:02 -04:00
|
|
|
|
2009-05-21 18:23:52 -04:00
|
|
|
def render_to_body(options)
|
2014-09-03 18:18:39 -04:00
|
|
|
_render_to_body_with_renderer(options) || super
|
2009-05-21 17:34:42 -04:00
|
|
|
end
|
2009-05-21 17:51:29 -04:00
|
|
|
|
2014-09-03 18:18:39 -04:00
|
|
|
def _render_to_body_with_renderer(options)
|
2011-09-26 18:57:49 -04:00
|
|
|
_renderers.each do |name|
|
|
|
|
if options.key?(name)
|
2010-11-22 11:07:28 -05:00
|
|
|
_process_options(options)
|
2014-09-03 18:18:39 -04:00
|
|
|
method_name = Renderers._render_with_renderer_method_name(name)
|
|
|
|
return send(method_name, options.delete(name), options)
|
2010-11-22 11:07:28 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
2014-04-20 16:46:19 -04:00
|
|
|
# A Set containing renderer names that correspond to available renderer procs.
|
|
|
|
# Default values are <tt>:json</tt>, <tt>:js</tt>, <tt>:xml</tt>.
|
2011-09-26 18:57:49 -04:00
|
|
|
RENDERERS = Set.new
|
2011-02-10 00:16:06 -05:00
|
|
|
|
2014-09-03 18:18:39 -04:00
|
|
|
def self._render_with_renderer_method_name(key)
|
|
|
|
"_render_with_renderer_#{key}"
|
|
|
|
end
|
|
|
|
|
2011-02-10 00:16:06 -05:00
|
|
|
# Adds a new renderer to call within controller actions.
|
|
|
|
# A renderer is invoked by passing its name as an option to
|
|
|
|
# <tt>AbstractController::Rendering#render</tt>. To create a renderer
|
|
|
|
# pass it a name and a block. The block takes two arguments, the first
|
|
|
|
# is the value paired with its key and the second is the remaining
|
|
|
|
# hash of options passed to +render+.
|
|
|
|
#
|
|
|
|
# Create a csv renderer:
|
|
|
|
#
|
|
|
|
# ActionController::Renderers.add :csv do |obj, options|
|
|
|
|
# filename = options[:filename] || 'data'
|
|
|
|
# str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s
|
2012-10-27 16:05:27 -04:00
|
|
|
# send_data str, type: Mime::CSV,
|
|
|
|
# disposition: "attachment; filename=#{filename}.csv"
|
2011-02-10 00:16:06 -05:00
|
|
|
# end
|
|
|
|
#
|
|
|
|
# Note that we used Mime::CSV for the csv mime type as it comes with Rails.
|
|
|
|
# For a custom renderer, you'll need to register a mime type with
|
|
|
|
# <tt>Mime::Type.register</tt>.
|
|
|
|
#
|
|
|
|
# To use the csv renderer in a controller action:
|
|
|
|
#
|
|
|
|
# def show
|
|
|
|
# @csvable = Csvable.find(params[:id])
|
|
|
|
# respond_to do |format|
|
|
|
|
# format.html
|
2012-10-27 16:05:27 -04:00
|
|
|
# format.csv { render csv: @csvable, filename: @csvable.name }
|
2014-05-26 02:12:38 -04:00
|
|
|
# end
|
2011-02-10 00:16:06 -05:00
|
|
|
# end
|
|
|
|
# To use renderers and their mime types in more concise ways, see
|
2014-11-05 23:36:45 -05:00
|
|
|
# <tt>ActionController::MimeResponds::ClassMethods.respond_to</tt>
|
2009-12-09 16:38:47 -05:00
|
|
|
def self.add(key, &block)
|
2014-09-03 18:18:39 -04:00
|
|
|
define_method(_render_with_renderer_method_name(key), &block)
|
2011-09-26 18:57:49 -04:00
|
|
|
RENDERERS << key.to_sym
|
2009-05-21 17:51:29 -04:00
|
|
|
end
|
|
|
|
|
2014-05-18 04:54:20 -04:00
|
|
|
# This method is the opposite of add method.
|
|
|
|
#
|
|
|
|
# Usage:
|
|
|
|
#
|
|
|
|
# ActionController::Renderers.remove(:csv)
|
|
|
|
def self.remove(key)
|
|
|
|
RENDERERS.delete(key.to_sym)
|
2014-09-03 18:18:39 -04:00
|
|
|
method_name = _render_with_renderer_method_name(key)
|
|
|
|
remove_method(method_name) if method_defined?(method_name)
|
2014-05-18 04:54:20 -04:00
|
|
|
end
|
|
|
|
|
2009-12-09 16:38:47 -05:00
|
|
|
module All
|
|
|
|
extend ActiveSupport::Concern
|
2009-12-20 21:15:20 -05:00
|
|
|
include Renderers
|
2009-05-28 10:49:02 -04:00
|
|
|
|
2009-12-09 16:38:47 -05:00
|
|
|
included do
|
|
|
|
self._renderers = RENDERERS
|
2009-05-28 10:49:02 -04:00
|
|
|
end
|
2009-05-22 20:07:40 -04:00
|
|
|
end
|
|
|
|
|
2009-12-09 16:38:47 -05:00
|
|
|
add :json do |json, options|
|
2010-11-15 17:52:39 -05:00
|
|
|
json = json.to_json(options) unless json.kind_of?(String)
|
2012-04-29 04:16:13 -04:00
|
|
|
|
|
|
|
if options[:callback].present?
|
2014-09-03 18:18:39 -04:00
|
|
|
if content_type.nil? || content_type == Mime::JSON
|
2014-07-02 17:48:04 -04:00
|
|
|
self.content_type = Mime::JS
|
|
|
|
end
|
|
|
|
|
2014-07-09 14:33:09 -04:00
|
|
|
"/**/#{options[:callback]}(#{json})"
|
2012-04-29 04:16:13 -04:00
|
|
|
else
|
|
|
|
self.content_type ||= Mime::JSON
|
|
|
|
json
|
2011-07-28 07:42:20 -04:00
|
|
|
end
|
2009-05-21 17:51:29 -04:00
|
|
|
end
|
2009-05-21 19:35:40 -04:00
|
|
|
|
2009-12-09 16:38:47 -05:00
|
|
|
add :js do |js, options|
|
|
|
|
self.content_type ||= Mime::JS
|
2011-04-18 02:12:51 -04:00
|
|
|
js.respond_to?(:to_js) ? js.to_js(options) : js
|
2009-05-21 19:35:40 -04:00
|
|
|
end
|
2009-05-22 20:15:46 -04:00
|
|
|
|
2009-12-09 16:38:47 -05:00
|
|
|
add :xml do |xml, options|
|
|
|
|
self.content_type ||= Mime::XML
|
2011-04-18 02:12:51 -04:00
|
|
|
xml.respond_to?(:to_xml) ? xml.to_xml(options) : xml
|
2009-12-09 16:38:47 -05:00
|
|
|
end
|
2009-05-21 17:34:42 -04:00
|
|
|
end
|
2009-05-21 23:54:28 -04:00
|
|
|
end
|