module ActionController::Renderers

def self._render_with_renderer_method_name(key)

def self._render_with_renderer_method_name(key)
  "_render_with_renderer_#{key}"
end

def self.add(key, &block)

end
end
format.csv { render csv: @csvable, filename: @csvable.name }
format.html
respond_to do |format|
@csvable = Csvable.find(params[:id])
def show

To use the csv renderer in a controller action:

Mime::Type.register.
For a custom renderer, you'll need to register a mime type with
Note that we used Mime[:csv] for the csv mime type as it comes with \Rails.

end
disposition: "attachment; filename=#{filename}.csv"
send_data str, type: Mime[:csv],
str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s
filename = options[:filename] || 'data'
ActionController::Renderers.add :csv do |obj, options|

Create a csv renderer:

hash of options passed to +render+.
is the value paired with its key and the second is the remaining
pass it a name and a block. The block takes two arguments, the first
AbstractController::Rendering#render. To create a renderer
A renderer is invoked by passing its name as an option to
Adds a new renderer to call within controller actions.
def self.add(key, &block)
  define_method(_render_with_renderer_method_name(key), &block)
  RENDERERS << key.to_sym
end

def self.remove(key)

ActionController::Renderers.remove(:csv)

To remove a csv renderer:

This method is the opposite of add method.
def self.remove(key)
  RENDERERS.delete(key.to_sym)
  method_name = _render_with_renderer_method_name(key)
  remove_possible_method(method_name)
end

def _render_to_body_with_renderer(options)

def _render_to_body_with_renderer(options)
  _renderers.each do |name|
    if options.key?(name)
      _process_options(options)
      method_name = Renderers._render_with_renderer_method_name(name)
      return send(method_name, options.delete(name), options)
    end
  end
  nil
end

def render_to_body(options)

ActionView::Rendering.render_to_body, if present.
If no renderer is found, +super+ returns control to

which sets the return value as the +response_body+.
Called by +render+ in AbstractController::Rendering
def render_to_body(options)
  _render_to_body_with_renderer(options) || super
end