problem with passing local variables to a partial view

Hi,

I use Rails 2.5 and have following problem. I'm trying to pass local variable to a partial view, as explained in

section 3.4.4

I have following code in /app/views/forum_posts/show.html.erb

<%= render :partial => 'forum_posts/recursive_comments', :locals => { :fp => @forum_post } %>

and following code in /app/views/forum_posts/ _recursive_comments.html.erb

<% myvar=:fp %> <%= h myvar.inspect %> <%= h myvar.class %> <%= link_to 'Reply',{:controller => :forum_comments, :action=> :new,:parent_id=> comment.id,:forum => myvar} %>

When I click on the link I get: http://example.com/forum_comments/new?forum=fp&parent_id=2 instead of: http://example.com/forum_comments/new?forum=1&parent_id=2

For some strange reason symbol :fp is being passed to the partial. Please help me and explain where I misunderstood the manual. I want to pass value of @forum_post.id to the partial. If I don't get satisfactory response I intend to move everything into the view, which means code duplication :frowning: , because I planned to do similar with blog coments.

I know that I could use some plugin, but I want to do it learn more about Rails, so kindly please respond regarding passing information to partials, or suggest other solution that doesn't require a plugin.

Jack

Hi,

I use Rails 2.5 and have following problem. I'm trying to pass local variable to a partial view, as explained in Layouts and Rendering in Rails — Ruby on Rails Guides section 3.4.4

I have following code in /app/views/forum_posts/show.html.erb

<%= render :partial => 'forum_posts/recursive_comments', :locals => { :fp => @forum_post } %>

and following code in /app/views/forum_posts/ _recursive_comments.html.erb

<% myvar=:fp %> <%= h myvar.inspect %> <%= h myvar.class %> <%= link_to 'Reply',{:controller => :forum_comments, :action=> :new,:parent_id=> comment.id,:forum => myvar} %>

When I click on the link I get: http://example.com/forum_comments/new?forum=fp&parent_id=2 instead of: http://example.com/forum_comments/new?forum=1&parent_id=2

For some strange reason symbol :fp is being passed to the partial.

That is because you have said <% myvar=:fp %> so you have assigned symbol :fp to myvar. You want <% myvar=fp %> or just use fp directly in link.

Colin

Why the whole :fp inside the partial?

Just use fp...

I've trie and got this :frowning:

undefined local variable or method `fp' for #<ActionView::Base: 0xb66f8d60>

view: <%= render :partial => 'forum_posts/recursive_comments', :locals => { :fp => @forum_post } %>

partial: <%= link_to 'Reply',{:controller => :forum_comments, :action=> :new,:parent_id=> comment.id,:forum => fp} %>

gives following error: Showing app/views/forum_posts/_recursive_comments.html.erb where line #28 raised:

undefined local variable or method `fp' for #<ActionView::Base: 0xb668368c> Extracted source (around line #28):

28: <%= link_to 'Reply',{:controller => :forum_comments, :action=> :new,:parent_id=> comment.id,:forum => fp} %>

hope this information will help someone to point me in right direction

thanks

Jack

sucess!!!

view: <%= render :partial => 'forum_posts/recursive_comments', :object => @forum_post %>

partial: <%= link_to 'Reply',{:controller => :forum_comments, :action=> :new,:parent_id=> comment.id,:forum => @forum_post.id } %>

The code above works, but still I can't understand why locals => {:foo => @bar} doesn't work in this case.

I wonder what version of Rails :locals was introduced at. You said you were using version 2.5, I assumed you meant 2.3.5. (rails -v to find out).

Colin

It's been there since at least 1.2.2

-Rob

Rob Biedenharn Rob@AgileConsultingLLC.com http://AgileConsultingLLC.com/ rab@GaslightSoftware.com http://GaslightSoftware.com/

That's obviously not the problem then, strange. Is this to go down as one of the great unsolved mysteries of the universe?

Colin

yes it's 2.3.5, congratulations on a good guess

maybe not, I begin to suspect that I have messed up my rails installation.

> That's obviously not the problem then, strange. Is this to go down as > one of the great unsolved mysteries of the universe?

> Colin

maybe not, I begin to suspect that I have messed up my rails installation.

solved it, I think. It was unbelievably simple

following code in view works: <%= render :partial => 'forum_posts/recursive_comments', :locals => {:post_id => @forum_post.id} %>

in partial I had to do following: <% def show_comments(post_id, kind=:children, fcomment=nil)   if kind==:parents     comments=ForumComment.find(:all,:conditions => [ "forum_post_id = ? and parent_comment_id is null", params[:id]] )     colour='green'   elsif kind==:children     comments=ForumComment.find(:all, :conditions => ["parent_comment_id = ? and forum_post_id = ?", fcomment,params[:id]] )     colour='red'   else     raise "wrong kind: shoul be either :parents or children but not #{kind}"   end   %>

  <% comments.each do |comment| %>

    <div style="border: solid <%= colour%> 1px;margin:0.25em;padding- left:1em ;">       <%#= h comment.inspect %>

      <h4><%= h comment.title%></h4>       <p><%= h comment.text%></p>       <% usr=User.find(comment.user_id)%>       <p class="whowhen"><%= h usr.login+' '+comment.created_at.to_s%>

      <%= link_to 'Reply',{:controller => :forum_comments, :action=> :new,:parent_id=> comment.id,:forum => post_id } %>       </p>       <% show_comments(post_id,:children,comment) unless comment==nil %>

    </div>

  <% end %> <% end %>

< %###################################################################### %>

<% show_comments(post_id,:parents) %>

so after because the link_to was within a method I had to pass the partials local as a parameter.

Jacek Podkanski wrote:

> That's obviously not the problem then, strange. �Is this to go down as > one of the great unsolved mysteries of the universe?

> Colin

maybe not, I begin to suspect that I have messed up my rails installation.

solved it, I think. It was unbelievably simple

following code in view works: <%= render :partial => 'forum_posts/recursive_comments', :locals => {:post_id => @forum_post.id} %>

in partial I had to do following: <% def show_comments(post_id, kind=:children, fcomment=nil)   if kind==:parents     comments=ForumComment.find(:all,:conditions => [ "forum_post_id = ? and parent_comment_id is null", params[:id]] )     colour='green'   elsif kind==:children     comments=ForumComment.find(:all, :conditions => ["parent_comment_id = ? and forum_post_id = ?", fcomment,params[:id]] )     colour='red'   else     raise "wrong kind: shoul be either :parents or children but not #{kind}"   end    No! You shouldn't be defining methods in your views.

Best,

... in partial I had to do following: <% def show_comments(post_id, kind=:children, fcomment=nil)

I am sorry but defining a method in a view is horrible. At the very least it should be in a helper.

if kind==:parents comments=ForumComment.find(:all,:conditions => [ "forum_post_id = ? and parent_comment_id is null", params[:id]] )

Even in a helper this would not be ideal, generally direct access to the model should only be from the controller. Prepare all the data you need for display in the controller and just format it in the view. You can tell all is not well if in the view you are working out how to get the data you want to display rather than just displaying it.

Colin

Hi,

Thanks for the advice. I have put the method in a helper. Having it there instantly reduced monstrosity factor. Another improvement could be moving style to *.css, but this will be done later. Is there anything else you see which would help to improve the code below?

  def show_comments(wanted,type,controller,post_id,kind=:children,pcomment=nil)     if kind==:parents       comments=wanted.find(:all,:conditions => [ "#{type}_post_id = ? and parent_comment_id is null", params[:id]] )       colour='green'     elsif kind==:children       comments=wanted.find(:all, :conditions => ["parent_comment_id = ? and #{type}_post_id = ?", pcomment,params[:id]] )       colour='red'     else       raise "wrong kind: shoul be either :parents or children but not #{kind}"     end#if     data=''     comments.each do |comment|       data << '<div style="border: solid '+colour+' 1px;margin-left: 0.5em;padding-left:0.25em;background:#d0eeee;">'       data << '<h3>'+comment.title+'</h3>'       data << '<p>'+comment.text+'</p>'       data << '<p class="whowhen">'+User.find(comment.user_id).login + ' '+comment.created_at.to_s+'</p>'       data << show_comments(wanted,type,controller,post_id,:children,comment) unless comment==nil       data << '</div>'     end#do     return data   end#def