1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionpack/lib/action_controller/metal/renderers.rb

134 lines
3.7 KiB
Ruby
Raw Normal View History

2011-09-26 18:57:49 -04:00
require 'set'
2010-01-31 21:32:28 -05:00
module ActionController
# See <tt>Renderers.add</tt>
def self.add_renderer(key, &block)
2009-12-20 21:15:20 -05:00
Renderers.add(key, &block)
end
# See <tt>Renderers.remove</tt>
def self.remove_renderer(key)
Renderers.remove(key)
end
class MissingRenderer < LoadError
def initialize(format)
super "No renderer defined for format: #{format}"
end
end
2009-12-20 21:15:20 -05:00
module Renderers
extend ActiveSupport::Concern
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
end
module ClassMethods
def use_renderers(*args)
2011-09-26 18:57:49 -04:00
renderers = _renderers + args
self._renderers = renderers.freeze
end
alias use_renderer use_renderers
end
def render_to_body(options)
_handle_render_options(options) || super
end
2009-05-21 17:51:29 -04:00
def _handle_render_options(options)
2011-09-26 18:57:49 -04:00
_renderers.each do |name|
if options.key?(name)
_process_options(options)
2011-09-26 18:57:49 -04:00
return send("_render_option_#{name}", options.delete(name), options)
end
end
nil
end
# 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
# 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"
# 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 }
# }
# end
# To use renderers and their mime types in more concise ways, see
# <tt>ActionController::MimeResponds::ClassMethods.respond_to</tt> and
# <tt>ActionController::MimeResponds#respond_with</tt>
def self.add(key, &block)
define_method("_render_option_#{key}", &block)
2011-09-26 18:57:49 -04:00
RENDERERS << key.to_sym
2009-05-21 17:51:29 -04:00
end
# This method is the opposite of add method.
#
# Usage:
#
# ActionController::Renderers.remove(:csv)
def self.remove(key)
RENDERERS.delete(key.to_sym)
method = "_render_option_#{key}"
remove_method(method) if method_defined?(method)
end
module All
extend ActiveSupport::Concern
2009-12-20 21:15:20 -05:00
include Renderers
included do
self._renderers = RENDERERS
end
end
add :json do |json, options|
json = json.to_json(options) unless json.kind_of?(String)
if options[:callback].present?
self.content_type ||= Mime::JS
"#{options[:callback]}(#{json})"
else
self.content_type ||= Mime::JSON
json
end
2009-05-21 17:51:29 -04:00
end
2009-05-21 19:35:40 -04: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
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
end
end
end