Problem with layout for partials


#1

I like the feature to have layouts even for partials now. But I have a
problem related to this topic:

My controller sets the variable @my_profile somewhere before
rendering. In the view I have the following code:

<%= debug @my_profile %>
<% if me? %>
<%= render :partial => “profiles/private”, :layout => ‘layout’ %>
<% else %>
<%= render :partial => “profiles/public”, :layout => ‘layout’ %>
<% end %>

The “debug” outputs the correct value. The two actual partials are not
important, but the _layout partial is where the trouble begins. In
case this “if” renders the second option (the _public partial), I can
also trace the @my_profile in the _layout partial - everything is
fine. However, if the above statement branches to the first option
(_private partial), tracing the @my_profile variable in the _layout
partial gives me a DIFFERENT value (actually another valid profile,
but not the one it is supposed to be)! I have no idea, how @my_profile
is set to a different value?! Is it possible for a controller action
to happen in the middle of rendering a view? I can’t imagine that,
since a partial has no action associate with it (and neither has a
partial layout). Does anyone have an idea how this value could become
set differently during the parital rendering process?

I would appreciate any kind of help! Thanks.


#2

I tried the following workaround:

<%= render :partial => “profiles/private”, :layout =>
‘layout’, :locals => {:my_profile => @my_profile } %>

Now I can access the correct profile by using the local variable
“my_profile” in the _layout partial. But the question remains: How
come the @my_profile has a different value in the above view code than
in the _layout partial? Is this a bug in rails?


#3

maybe try the following:

restructure your code to have your debug-statement inside the if-
clause (the first branch).
post the code for the private partial.
finally, tell us what @my_profile is before the render-command and
then inside the partial (at the beginning).
it should really be the same.


#4

Hey, thanks for the instructions. Here is the result:

Placing a “debug @my_profile” anywhere ( before the “if” statement,
inside the first branch of the “if” statement, inside the _private
partial) leads to the correct value (the first_name of the sample
profile is “De”). At the same time placing the debug command inside
the _layout partial gives me a different value (first_name =
‘Martha’):

show.html.erb:
<%= debug @my_profile.first_name %> # => “De”
<% if params[:public_view].blank? && @my_profile && me? %>
<%= debug @my_profile.first_name %> # => “De”
<%= render :partial => “profiles/private”, :layout =>
‘layout’, :object => @my_profile %>
<% else %>
<%= render :partial => “profiles/public”, :layout => ‘layout’ %>
<% end %>

_private.html.erb:
<% top_bar do %>
<% @user = @profile.user %>

Über mich: <%= " #{@profile.first_name} [#{@user.login}]" %> <% end %>

<% left_sidebar do %>
<%= link_to ’

Profil
bearbeiten
', edit_profile_path
(@my_profile), :class=>‘button’ %>
<%= link_to ’
Fotos
bearbeiten
', profile_photos_path
(@my_profile), :class=>‘button’ %>
<% end %>

<%= debug '_private: ’ + @my_profile.first_name %> # => “De”

<%= render :partial => ‘profiles/bio’ %>
<%= render :partial => ‘profiles/getting_started’ %>
<%= render :partial => ‘comments/list’, :locals => {:with_form =>
true, :with_wall_to_wall => true} %>
<%= render :partial => ‘photos/gallery’, :locals => {:mini => true} %>
<%= render :partial => ‘friends/list’, :locals => {:type => ‘friends’}
%>
<%= render :partial => ‘profiles/recent_activity’ %>

_layout.html.erb:

<%= debug '_layout: ’ + @my_profile.first_name %> # =>
“Martha” ???

<%= yield(:top_bar) %>

<%= render :partial => ‘shared/livesidebar’ %>

<!-- LEFT_SIDEBAR -->
<div id="leftcontent">
  <div id="profilebox">
    <div class="roundedImage">
      <%= icon @profile, :big %>
    </div>
  </div>
  <%= yield(:left_sidebar) %>
</div>

<!-- MAIN -->
<div id="rightcontent">
  <%= yield %>
</div>

I just don’t get it - it seems weird.


#5

<%= render :partial => “profiles/private”, :layout =>
‘layout’, :object => @my_profile %>
now that you’re passing :object to your partial you should be able to
access @private which equals @my_profile. does this lead to the same
behaviour?


#6

usually it should work without the “:object => @my_profile” part (and
i tried that). however, since relying on global variables like
@my_profile in a partial isn’t nice coding style anyway. so i tried to
pass the variable explicitly to the partial. i would have expected the
variable @my_profile to appear as “layout” in my _layout partial (and
as “private” in my _private partial). however, the “layout” variable
is not defined in my _layout partial :(. btw: i also tried “@layout”,
but this isn’t defined either).


#7

a no, forget what i just said. this should only work, if you have a
Private-model.
sorry, getting a bit tired.