Render view outside of a controller/view

We’re putting together a searchable online help site in Rails, and I’m
using FastRI to full-text index some existing Rails view pages to do
it.

I don’t want to use Sphinx or some other solution, just because it’s
way overkill for the 15-20 .html.erb partials I am looking to index.

So… I need to violate MVC (flog me now)… trying to write a Ruby
class that renders each of these pages as a string, and feeds the
rendered text as a string into FastRI for indexing.

I’ve seen plenty of links, most of which have about the same
approach.

Here are a few of the approaches I have seen:

http://railsforum.com/viewtopic.php?id=16885
http://www.compulsivoco.com/2008/10/rendering-rails-partials-in-a-model-or-background-task/
http://ethilien.net/archives/render-rails-templates-anywhere-even-in-a-model/
http://www.swombat.com/rails-rendering-templates-outside-of-a-contro

All seem to work until I try to render a page with a link_to helper
with a restful route (games_path) or a hash representing the path.

As best I can tell, I think I need a controller and some kind of mock
request.

Using a slight derivation from the more recent blog post:

def render_anywhere(partial, assigns={})
view = ActionView::Base.new(Rails::Configuration.new.view_path,
assigns)
ActionView::Base.included_modules.each { |helper| view.extend
helper }
view.extend ApplicationHelper
view.render(partial)
end

render_anywhere(:file => “/full/path/to/app/views/helps/
_send_credentials.html.erb”)

gives me this:

ActionView::TemplateError (You have a nil object when you didn’t
expect it!
The error occurred while evaluating nil.url_for) on line #6 of app/
views/helps/_send_credentials.html.erb:

actionpack (2.3.4) lib/action_view/helpers/url_helper.rb:85:in send' actionpack (2.3.4) lib/action_view/helpers/url_helper.rb:85:in url_for’
app/views/helps/_send_credentials.html.erb:6

As best I can tell, I’m missing a controller and possibly a request
object in there somewhere, since it seems to be barfing on:

@controller.send(:url_for, options)

I’ve tried assigning a mock controller in there, and then it looks
like the controller needs a request object. I’ve tried following the
rabbit down the hole, and I just keep getting “nil object when you
didn’t expect it” errors of various flavors.

I’m lost, any ideas?

Thanks in advance–

Jeff Wigal

jeff_wigal wrote:

We’re putting together a searchable online help site in Rails, and I’m
using FastRI to full-text index some existing Rails view pages to do
it.

I don’t want to use Sphinx or some other solution, just because it’s
way overkill for the 15-20 .html.erb partials I am looking to index.

So… I need to violate MVC (flog me now)… trying to write a Ruby
class that renders each of these pages as a string, and feeds the
rendered text as a string into FastRI for indexing.
[…]

If you need to do this, then you probably have a design problem which
you should correct. It seems to me that you’d only be using ERb for
your help text for one of two reasons:

  1. The help text is written right in the ERb file, and Ruby is only used
    for things like navbars which aren’t part of the help text itself.

  2. The help text is not written in the ERb file, but rather comes from a
    database or something.

In neither case do you need to render the ERb to index the information.
For case 1, just index the literal ERb (perhaps with all <%…%> removed
for security). For case 2, use a database query.

If neither of these is your use case, please explain further.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Thanks for your response.

I’m basically building static content within an existing rails
application.

I can just as easily do this with straight HTML, but since this is a
static site for our online documentation. I’m using ERb because the
individual help documents may link to each other, or link to other
parts of the rails application. I’d prefer to use the link_to helper
methods that tie into the routes, so that if a route changes, I’m not
having to hunt down these changes in my static content.

Our help text is written into the ERb files, and Ruby is used for some
of the basic helper methods (link_to, maybe some of the other more
common ones but nothing too exotic). We’d rather not put the help
text into the database, since it’s a lot easier to maintain by editing
the help files while we’re editing the application code.

We have direct control over the help text, so arbitrary code execution
is not a concern.

My show.html.erb action looks something like this:

<%= h @page.description%>

<%= render @page.file %>

@page.file returns a string representing the partial to be rendered,
and we have about 15-25 ERb partials that represent our help text.

Thanks–

Quoting jeff_wigal [email protected]:

We’re putting together a searchable online help site in Rails, and I’m
using FastRI to full-text index some existing Rails view pages to do
it.

As you have found, trying to fake a controller, request, etc. is a lot
of
work. One possibilty is to just throw the necessary methods into some
applicable controller and call them as normal GET request:

def render_anywhere
return unless local_request?

DB access and/or instance variable assignment…

page = render_to_string :action => … OR :template => …
FastRI.whatever(page)
end

This only is safe if there are no untrusted users on the server host.

HTH,
Jeffrey

Thanks for the advice… I think I am going to pull this out of the
model and make it a controller method (/help/reindex) since that will
give me easier access to the stuff I need.

On Jan 11, 10:31Â pm, jeff_wigal [email protected] wrote:

having to hunt down these changes in my static content.
My show.html.erb action looks something like this:
Thanks–

I don’t want to use Sphinx or some other solution, just because it’s
your help text for one of two reasons:

If neither of these is your use case, please explain further.

Best,

Marnen Laibow-Koserhttp://www.marnen.org
[email protected]

Posted viahttp://www.ruby-forum.com/.

Assuming I understand you, what I do whenever I want to use Rails’
routing helpers in a non-Controller/View is just “include
ActionController::UrlWriter” in the class. link_to is in
ActionView::UrlHelper… you get the idea.