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@@ 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
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 += ...
.
精彩评论