Normally in rails, you can only render views inside of the controller. But what if you want to render a view somewhere else? For instance we wanted to generate xml-files using views. Haml can be used to describe xml just as well as plain html.
There is a gem called render_anywhere that allows just that. So how does this work, for example:
class Organisation < ActiveRecord::Base
has_many :members
include RenderAnywhere
def to_xml
render partial: "#{self.to_partial_path}", object: self, layout: 'my_xml_layout'
end
end
We had a little problem when using partials though.
Normally if you type something like
= render @member
it will ask the partial path from the model (@member.to_partial_path
), but somehow this always got prefixed with render_anywhere
. The gem creates a dummy RenderingController
in the RenderAnywhere
namespace, so apparently it will look for the following view:
render_anywhere/members/member
In our case, I did not want to use the render_anywhere
subfolder. It took me a while to figure out how to overrule this, but in essence it is pretty simple: rails uses the namespace of the rendering controller to prefix the path. Some deep googling proved that any controller has a method called _prefixes
which lists all the prefixes for that class.
We can easily verify this in the rails console
:
:001 > RenderAnywhere::RenderingController._prefixes
=> ["render_anywhere/rendering"]
So if we could overrule _prefixes
to just return ["rendering"]
... Mmmmmm fork the code of render_anywhere
? Or ...
There is another option: render_anywhere
allows you to supply your own RenderingController
and will use that instead if found in the context where the RenderAnywhere
code is included.
So, if you write something like:
class Organisation < ActiveRecord::Base
has_many :members
include RenderAnywhere
class RenderingController < RenderAnywhere::RenderingController
def self._prefixes
["rendering"]
end
end
def to_xml
render partial: "#{self.to_partial_path}", object: self, layout: 'my_xml_layout'
end
end
it will look for a view called members/member
. Woot. To specify a different sub-folder you can adapt the _prefixes
method as you wish :)