list > partial > edit

HI, i have a simple list of users, underneath each one i want to display
the corresponding edit view via a partial.
BUt, it always displays the person no1 in the edit view...

Person1
...edit(partial)

Person1(should be 1)

Person2

Preson1(should be 1)

Person3

Person1(should be 1)

Person4
....

whats wrong here? im not passing locals to the partial...

thx

HI, i have a simple list of users, underneath each one i want to
display
the corresponding edit view via a partial.
BUt, it always displays the person no1 in the edit view...

Person1
...edit(partial)

Person1(should be 1)

Person2

Preson1(should be 1)

Person3

Person1(should be 1)

Person4
....

whats wrong here? im not passing locals to the partial...

What are you doing?

Fred

Frederick Cheung wrote:

Preson1(should be 1)

Person3

Person1(should be 1)

Person4
....

whats wrong here? im not passing locals to the partial...

What are you doing?

Fred

woops, myu mistake: should be:

Person3

Edit Person3

Person4

Edit Person4

....
....

but the edit view is always Person1

....

Frederick Cheung wrote:

Preson1(should be 1)

Person3

Person1(should be 1)

Person4
....

whats wrong here? im not passing locals to the partial...

What are you doing?

Fred

Can't guess what's wrong if we can't see what you're doing.

Fred

user/_edit:
<% form_for(@user) do |f| %>
  <%= f.error_messages %>
      <b>Title</b><br />
    <%= f.text_field :username %>
  </p>
  <p>
    <%= f.submit "Update" %>
  </p>
<% end %>

user/_edit:
<% form_for(@user) do |f| %>
<%= f.error_messages %>
     <b>Title</b><br />
   <%= f.text_field :username %>
</p>
<p>
   <%= f.submit "Update" %>
</p>
<% end %>
-----------------------------------------
user/index
<h1>Listing Users</h1>
<table border=1>
<tr>
   <th>Firstname</th>
   <th>Lastname</th>
   <th>Username</th>
</tr>
<% for u in @users %>
<tr>
   <td><%=h u.firstname + u.id.to_s %></td>
   <td><%=h u.lastname %></td>
   <td><%=h u.username %></td>
   <td><%= link_to 'Show', u %></td>
</tr>
   <td colspan=4><%= render :partial =>'edit' %></td>
</tr>
<% end %>
</table>
<br />

Well, that's expected - in your partial you always edit @user.
if you do render :partial => 'edit', :object => u
and then change the partial to be
form_for(object) ...

then you should be ok

Fred

Hey Tom,
in your index, you have to pass the right variable to the partial,
like Fred wrote:
render :partial => 'edit', :user => u

u is the local variable you are passing (you called: for u in @users)
user is then the name of the variable you will use in your edit
partial (in Fred's example, it was called 'object').

So in your partial, you need to do:
<% form_for user do %>

You can call it anything you want, but the symbol you use must match
the variable name you use in your partial. In your example, you're
using 'u' but you never passed a variable called 'u' to the partial
(you passed 'object').

Frederick Cheung wrote:

<% end %>
<tr>

Well, that's expected - in your partial you always edit @user.
if you do render :partial => 'edit', :object => u
and then change the partial to be
form_for(object) ...

then you should be ok

Fred

ii changed it into
a)
, :object => u
and
<% form_for(u) do |f| %>
b)
, :object => u
and
<% form_for(u) do |f| %>

that should be form_for object. The current object is always available
under two names: the name derived from the partial and object.

Fred

deegee wrote:

Hey Tom,
in your index, you have to pass the right variable to the partial,
like Fred wrote:
render :partial => 'edit', :user => u

u is the local variable you are passing (you called: for u in @users)
user is then the name of the variable you will use in your edit
partial (in Fred's example, it was called 'object').

So in your partial, you need to do:
<% form_for user do %>

You can call it anything you want, but the symbol you use must match
the variable name you use in your partial. In your example, you're
using 'u' but you never passed a variable called 'u' to the partial
(you passed 'object').

mhh, somehow im totally confused now. the index action /view iterates
through @users with an iterator called u:
<h1>Listing Users</h1>
<table border=1>
  <tr>
    <th>Firstname</th>
    <th>Lastname</th>
    <th>Username</th>
  </tr>
<% for u in @users %>
  <tr>
    <td><%=h u.firstname + u.id.to_s %></td>
    <td><%=h u.lastname %></td>
    <td><%=h u.username %></td>
    <td><%= link_to 'Show', u %></td>
  </tr>
    <td colspan=4><%= render :partial =>'edit' , :@user => @users
%></td>
  </tr>
<% end %>
</table>
<br />
///////////////////////////
user edit controller:
  def edit
    @user = User.find(params[:id])
  end
means i have somehow to use that variable.

////////////////////////////////
partial:
<h1>Editing User</h1>
<% form_for(@user) do |f| %>
  <p>
    <b>Title</b><br />
    <%= f.text_field :username %>
  </p>
<p>
  <p>
    <%= f.submit "Update" %>
  </p>
<% end %>

...........summary: means i could replace

<%= render :partial =>'edit' , :@user => @users %>
with
<%= render :partial =>'edit' , :@whatever => u %> //u because of the
iterator

and use @whatever in the edit-display:
% form_for(whatever) do |f|
???
but that cant be true, where is the @users being used from the EDIT
action out of the controller?
i cant see thriough right now. help

thx

deegee wrote:

Hey Tom,
in your index, you have to pass the right variable to the partial,
like Fred wrote:
render :partial => 'edit', :user => u

u is the local variable you are passing (you called: for u in @users)
user is then the name of the variable you will use in your edit
partial (in Fred's example, it was called 'object').

Um, that's just wrong. :object is an option to render. if you want to
pass arbitrality named local variables use the locals option

So in your partial, you need to do:
<% form_for user do %>

You can call it anything you want, but the symbol you use must match
the variable name you use in your partial. In your example, you're
using 'u' but you never passed a variable called 'u' to the partial
(you passed 'object').

mhh, somehow im totally confused now. the index action /view iterates
through @users with an iterator called u:
<h1>Listing Users</h1>
<table border=1>
<tr>
   <th>Firstname</th>
   <th>Lastname</th>
   <th>Username</th>
</tr>
<% for u in @users %>
<tr>
   <td><%=h u.firstname + u.id.to_s %></td>
   <td><%=h u.lastname %></td>
   <td><%=h u.username %></td>
   <td><%= link_to 'Show', u %></td>
</tr>
   <td colspan=4><%= render :partial =>'edit' , :@user => @users
%></td>
</tr>
<% end %>
</table>
<br />
///////////////////////////
user edit controller:
def edit
   @user = User.find(params[:id])
end
means i have somehow to use that variable.

////////////////////////////////
partial:
<h1>Editing User</h1>
<% form_for(@user) do |f| %>
<p>
   <b>Title</b><br />
   <%= f.text_field :username %>
</p>
<p>
<p>
   <%= f.submit "Update" %>
</p>
<% end %>

Are you reusing this same partial both from the edit action and from
the index action ?
If so then in the edit action you would do
render :partial => 'edit', :object => @user
in the list action
render :partial => 'edit', :object => u

and in the partial itself:
form_for object

Fred

Sorry, my mistake, it should be :object => @user in the edit view,
and :object => u in the index view. I was thinking of locals indeed.
Would work as well :slight_smile:

Here are the two variants from the rdoc of actionview, I was thinking
of the first one but forgot to add the :locals part, sorry about that.

# Renders the same partial with a local variable.
  render :partial => "person", :locals => { :name => "david" }

  # Renders the partial, making @new_person available through
  # the local variable 'person'
  render :partial => "person", :object => @new_person

deegee wrote:

Sorry, my mistake, it should be :object => @user in the edit view,
and :object => u in the index view. I was thinking of locals indeed.
Would work as well :slight_smile:

thx guys - ill try to get this done.
please stay subscribed.thx tom

ok i tried a few things, and it seems that everything depends on two
lines:

<td colspan=4><%= render :partial =>'edit', :object=>@users %></td>

and
...."_edit"...
<% form_for :user, @users do |f| %>
  <p>
    <b>Title</b><br />
    <%= f.text_field :username %>
....

facts:
yes i copied the origin edit to _edit because there a minor differences.
here i would like to use the partial "_edit". i can see and understand
that the edit action out of the user controller wont be triggered,
though i havent read the api for that yet.
so, so far i understood what u tried to xplain is: regardless what i
pass into the partial, i have to reuse that name because it appears
within the "scope" od that function / loop (one output).
i dont understand why i should pass the list-object called @object
because that contains for my understanding all users returned by the
list-action-controller. anyhow i tried to pass on the local variable u
and neither that worked because it couldnt find the attributes later
like here: "f.text_field :username". the few times the server doesnt
throw an exception is when the result list gives me always the same name
in the edit partial...
does anyone have a working example? or can reproduce it?
thx

ok i tried a few things, and it seems that everything depends on two
lines:

<td colspan=4><%= render :partial =>'edit', :object=>@users %></td>

and
...."_edit"...
<% form_for :user, @users do |f| %>
<p>
<b>Title</b><br />
<%= f.text_field :username %>
....

I'll try again. What you need to do to reuse the partial is decouple
it from whatever instance variables are used. That means that @ signs
are banished from your partial. use the local variable the partial
creates for you (object or the name of the partial).
when you render a partial, you can specify what that object should be
with the :object option. That's all there is to it.

You'll never need :object => @users.

Fred

Frederick Cheung wrote:

fred, im really sorry, but im missing her something. when does the
partial create a variable except the local variable f?

if you do render :partial => 'something', :object => @foo

then in the context of the partial there will be two local variables:
something and object, which will have the same value as @foo.

Fred

hi,

mh:
<td colspan=4><%= render :partial =>'edit', :var=>u %></td>

means the variable called var is a instance varibale with the value of u, which is at a certain point of the loop that single (user)record.
what values has "edit" and what is it for?

<% form_for :user, :var do |f| %>

doesnt work
what am i doing wrong?

im really sorry

hi,

mh:
<td colspan=4><%= render :partial =>'edit', :var=>u %></td>

That is not supposed to work. You have to say :object => u. :object is
the name of an option, not something you can make up your self.
Similarly what you get in your partial will always be the name of the
partial and object.

Fred

Tom,
My previous mistake probably gave you the wrong idea about what
the :object is doing. Like Fred says, :object is an option of the
render method. It tells the method which variable should be passed to
the partial. The variable can then be accessed in the partial with the
name of the partial itself ('edit' in your case) or just 'object'.

So:
render :partial => 'edit', :object => u

passes u to the partial, which is what you want as you're accessing an
instance of a User and you called it u. In the partial you can access
it with the variables object or edit, like so
<% form_for :user, edit, , :url => {:action => 'update'} do |f| %>

or

<% form_for :user, object, , :url => {:action => 'update'} do |f| %>

I don't like the first one because in this case it's not very good
semantics about what is being done in the form (you would be better
off renaming your partial 'user' so you would then be able to do
form_for user).

Like i mentioned before, I prefer to use the :locals option, it's more
explicit about what is being passed into the partial:
render :partial => 'edit', :locals => {:user => u}

and then you have a variable named 'user' that you can use in your
partial:
<%form_for :user, user, :url => {:action => 'update'} do |f| %>

So you have a couple of options here. Note that I like to explicitely
name all the arguments in the form_for method, makes it more readable.
What I'm saying here is to create a form for an object called
'user' (the first :user) which will be passed in the params hash, use
the object called 'object', 'edit' or 'user' (depending on the above
you choose) for the values of the fields to pre-fill and responding to
the submit button by calling the action 'update'.

Let me know if this works now.