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
http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials
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
http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials
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