views:

69

answers:

2

In my rails application I have a helper function:

def render_page( permalink )
   page = Page.find_by_permalink( permalink )
   content_tag( :h3, page.title ) + inline_render( page.body )
end

If I called the page "home" with:

<%= render_page :home %>

and "home" page's body was:

<h1>Home<h1/>
bla bla

<%= render_page :about %>
<%= render_page :contact %>

I would get "home" page, with "about" and "contact", it's nice and simple... right up to where someone goes and changes the "home" page's content to:

<h1>Home<h1/>
bla bla
<%= render_page :home %>    
<%= render_page :about %>
<%= render_page :contact %>

which will result in a infinite loop ( a segment fault on webrick )...

How would I change the helper function to something that won't fall into this trap?

My first attempt was along the lines of:

@@list = []

def render_page( permalink )
  unless @@list.include?(permalink)
    @@list += [ permalink ]
    page = Page.find_by_permalink
    result = content_tag( :h3, page.title ) + inline_render( page.body )
    @@list -= [ permalink ]
    return result
  else
    content_tag :b, "this page is already being rendered"
  end
end

which worked on my development environment, but bombed out in production...

any suggestions?

Thank You
Stefan

A: 

Are you copy-pasting, or have you edited anything out?

If not, there seems to be a typo here:

unless list.include?(permalink)

I think you meant:

unless @@list.include? permalink

Hope this helps. If it doesn't, activate the logs on production so you can see where the error is exactly (you can do this on the config/environments/production.rb file). If you paste the errors in your question, you will get better help.

EDIT: Also, if you remove the permalink from the list (@@list -= [ permalink ]) I believe the second part of your if-else will never happen (you will never get a "this page is already being rendered" message). Moreover, @@list -= ... isn't exactly efficient. You might want to do @@list.delete(permalink) instead - and @@list.push(permalink) instead of the @@list += ... .

egarcia
yea, it was a typo... furthermore... the second part could happen when inline_code( post.body ) is called ( if post.body called render_page for the same permalink )
NixNinja
i mean inline_render( post.body )
NixNinja
OK. What about the production error logs?
egarcia
mm.. working now...
NixNinja
That is funny :) What did you change?
egarcia
+1  A: 

@@ variables persist across requests. If render_page threw an exception, it would leave values in @@list and probably cause weird behavior for subsequent requests. Try this: @list is an instance variable for the view and is scoped to the request.

def render_page( permalink )
  @list ||= []
  unless @list.include?(permalink)
    @list << permalink
    page = Page.find_by_permalink
    result = content_tag( :h3, page.title ) + inline_render( page.body )
    @list.delete permalink
    return result
  else
    content_tag :b, "this page is already being rendered"
  end
end
Kevin