Yeah, I know, MVC is the “Only True Way™”. But sometimes, just sometimes,
you need your link_to
or html helpers working in the model.
For example, sometimes the cleanest way to implement something is to have
to_html
in the model (widgets anyone?).
Doing this will most probably require generating some urls, and you need a
controller for that. Usually I solved this by passing controller to the
to_html
function, but it always felt wrong.
Another example is when you are working on an API. You somtimes would like to have an option to add actual URIs of related services inside an xml.
Like in
<articles>
<article>
<title>Let my controller go</title>
<href>http://example.com/articles/123</href>
<created>2009-05-24T19:09:06Z</created>
</article>
</articles>
Now how will you implement that? It would be nice if @articles.to_xml
just worked, but then how will you generate the href url? url_for
is not
available in models.
Solution? just make it global and let the purists tear their hairs out! :)
This plugin solves the issues above by making the current controller available
from a global function current_controller
. (actually it uses Thread
local
storage, so it will work even in multithreaded Rails environment)
The installation is simple
script/plugin install git://github.com/astrails/let_my_controller_go.git
Or
braid -p git://github.com/astrails/let_my_controller_go.git
Then you can implement the above as
class Article < ActiveRecord::Base
def href
current_controller.url_for(self)
end
def to_xml(opts = {})
super opts.merge(:methods => :href, :only => [:title, :created_at])
end
end
Then Articles.all.to_xml
will produce what you need (when running in a
context of a web request, i.e. it won’t work from the console).
So, while it might not pass strict software design review, but it is useful. And as with any tool, it’s up to you to use it appropriatly.
Sources are at GitHub.
OK, flame away! /ducks and hides under the desk/