SitePoint Sponsor

User Tag List

Results 1 to 17 of 17
  1. #1
    SitePoint Member
    Join Date
    Dec 2005
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Rails: Multiple edit forms in one view

    Hello. thanks in advance for your time, i hope this is a simple question.. (I'm very new (< 1 week) to ruby and rails).

    I'd like to create a list view displaying all 'user' records. At the same time, each list item should be a small form with auto-filled fields and a submit button labelled 'update'.

    I'm a little stuck on how to implement multiple 'edit' type forms in one view page (all the tutes ive seen deal with only a single form).

    My code looks like the listing below. I didn't expect it to work, but incase it's useful to know, at the moment it results in the appropriate number of forms being created, but the fields of the forms aren't being populated:

    in the controller:
    PHP Code:
    def list_users
          
    @existingusersUser.find_all
      end
      
      def update_user
       
    @existinguser=User.find(@params[:id])
       if @
    existinguser.update_attributes(params[:existinguser])
           
    flash[:notice] = 'Account was successfully updated.'
        
    redirect_to (:action => 'list_users')
        else
           
    flash[:error] = 'Account couldnt be updated.'
           
    render :action => 'list_users'
        
    end
      end 
    in the list_users.rhtml view:
    PHP Code:
    <%= render(:partial => "user_edit", :collection => @existingusers) %> 
    in the _user_edit.rhtml partial
    PHP Code:
    <%= form_tag :action=> "update_user", :id => user_edit %>

    <
    label for="user_username">Username:</label><br/>
    <%= 
    text_field "user""username", :size => 15 %><br/>
      
    <
    label for="user_password">Password:</label><br/>
    <%= 
    password_field "user""password", :size => 15 %><br/>
      
    <
    label for="user_password_confirmation">Confirm password:</label><br/>
    <%= 
    password_field "user""password_confirmation", :size => 15 %><br/>
      
    <
    input type="submit" value="Update user" class="primary" />
    <%= 
    end_form_tag %> 

  2. #2
    SitePoint Zealot
    Join Date
    Nov 2004
    Location
    Yakima WA.
    Posts
    100
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey bitterclarence-

    You need to change the names of your variables inside of the partial. When you do this:
    Code:
    <%= render(:partial => "user_edit", :collection => @existingusers) %>
    You are passing @existingusers into the partial and asking it to loop over all the users inside of @existingusers. So the variable that will be available inside of the partial is called existinguser singular and without the @ sign. So make your partial look like this instead:
    Code:
    <%= form_tag :action=> "update_user", :id => existinguser %> 
    
    <label for="user_username">Username:</label><br/> 
    <%= text_field "existinguser", "username", :size => 15 %><br/> 
       
    <label for="user_password">Password:</label><br/> 
    <%= password_field "existinguser", "password", :size => 15 %><br/> 
       
    <label for="user_password_confirmation">Confirm password:</label><br/> 
    <%= password_field "existinguser", "password_confirmation", :size => 15 %><br/> 
       
    <input type="submit" value="Update user" class="primary" /> 
    <%= end_form_tag %>
    Try that, it should do what you want it to do. If for some reason it still complains, then try adding this line at the very top of the partial:
    Code:
    <% @existinguser = existinguser %>
    Sometimes you have to do that for it to recognize the objects you are passing in.

    Hope that helps.

    -Ezra

  3. #3
    SitePoint Member
    Join Date
    Dec 2005
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thanks for your reply!

    i copy pasted your code, and added:
    PHP Code:
    <% @existinguser existinguser %> 
    to the top, but i get the following error:

    "Showing app/views/account/_user_edit.rhtml where line #1 raised:

    undefined local variable or method `existinguser'"

    Looking again at the agile web dev book, it looks like it's the :partial parameter that determines the name of the variable you can access inside the partial, not the :collection.. the :collection is the array you pass to the partial..

  4. #4
    SitePoint Zealot
    Join Date
    Nov 2004
    Location
    Yakima WA.
    Posts
    100
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ahh. I think you are correct. I was just looking at the api and it was a bit unclear which one gets used as the variable inside the partial. Did you get it working?

  5. #5
    SitePoint Member
    Join Date
    Dec 2005
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    no im still a bit stuck..

    i need to see an example i think.

    At the moment my questions are:

    1. How can i create a view with multiple forms that are populated with the data from an array of User.find_all objects?

    2. If one of these edit forms is submitted, but the data fails validation defined in the User model, how will the view know which of the edit forms is the source of the bad data? (ie. how would it know which form to apply the error highlighting to?)

  6. #6
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    export a hidden field with the id of the object being edited.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  7. #7
    SitePoint Member
    Join Date
    Dec 2005
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    hi sweatje,

    i was thinking that passing the id of the object being edited via a hidden form wouldnt be necessary since the id of each object is already being included in the 'action' path of each form.

    in the view:
    PHP Code:
    <%= render(:partial => "user_edit", :collection => @existingusers) %> 
    in the _user_edit.rhtml partial:
    PHP Code:
    <%= form_tag :action=> "update_user", :id => user_edit %> 
    which renders as (for example):
    PHP Code:
    <form action="/account/update_user/4" method="post"

  8. #8
    SitePoint Member
    Join Date
    Dec 2005
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    hi samsm,

    the step you described isnt necessary afaik..

    i'm using a partial to render each form in the list,

    Inside the partial, the current object is referenced by the local variable with the same name as the :partial argument, in my case 'user_edit' (not existinguser)

    eg. if i type the following inside the partial:
    PHP Code:
    <%= user_edit.id %></br
    i get a list of all the id numbers of the User objects that have been passed to the partial. (if i try using existingnumber inside the partial i get an error because that variable doesnt exist in that scope).

    maybe i misunderstood..

  9. #9
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by bitterclarence
    hi samsm,
    Sorry for the confusion, I deleted that post after realizing that I was being dumb but apparently before you started replying.
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  10. #10
    SitePoint Member
    Join Date
    Dec 2005
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    ah! np.. i appreciate you posting

  11. #11
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, I'll start over and see if I can actually understand what is going on.

    Quote Originally Posted by bitterclarence
    1. How can i create a view with multiple forms that are populated with the data from an array of User.find_all objects?
    It sounds like you have worked some of this out, but here is what I was going to post:

    In the view:
    Code:
    <%= render(:partial => "user_edit", :collection => @existingusers) %>
    in _user_edit.rhtml
    Code:
    <% @existing_user = user_edit %>
    <%= form('existing_user') %>
    Unfortunately, I am almost positive this would be a problem (as you identified) for the error handling. Unless ... how about in the event of an error direct the user to a page with just one form? I know that's not the solution you asked for, but it would be easy.
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  12. #12
    SitePoint Member
    Join Date
    Dec 2005
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thanks samsm, i hadn't seen the 'form('existing_user')' command before.. thats very handy .. now i have the list of forms being correctly populated at least.

    this is a big step forward for me, thanks again!

    yeah, the error notification will be tricky i suppose.. in the event of an error a single form page might be a good way like you said.

  13. #13
    SitePoint Wizard samsm's Avatar
    Join Date
    Nov 2001
    Location
    Atlanta, GA, USA
    Posts
    5,011
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This comes to mind as a little messy little compromise ...

    in _user_edit.rhtml:
    Code:
    <% @existing_user = user_edit %>
    <% div_id = "edit_user_" + @existing_user.id.to_s %>
    
    <div id="<%= div_id %>">
    
    <%= form_remote_tag :html => 
                                 { :action => 
    				  url_for(:controller => "user", 
    				            :action => "no_ajax_update", 
    				            :id=>@existing_user.id) 
    			  }, 
    			  :update => div_id, 
    			  :url => { :action => "ajax_update", 
    				        :id => @existing_user.id 
    				     } 
    %>
    
    *** the rest of the form inputs would go here ***
    
    <%= end_form_tag %>
    </div>
    Using your unpaid time to add free content to SitePoint Pty Ltd's portfolio?

  14. #14
    SitePoint Guru silver trophy Luke Redpath's Avatar
    Join Date
    Mar 2003
    Location
    London
    Posts
    794
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Perhaps there is a specific reason for doing so, but wouldn't the simplest thing to do here be to have an edit action that handles a single record instead of multiple?

  15. #15
    SitePoint Member
    Join Date
    Dec 2005
    Posts
    9
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    samsm: thanks for that, i'm looking through it to try and figure out whats going on!

    luke: i agree a single edit form page seems to be the simplest to build. The reason i'd like a list of forms is that the Objects being listed have a very small number of fields ('methods'?) and i'd like to eliminate the extra clicking that opening a seperate edit page would involve (the resulting edit page would also be largely empty, and i'd also like to avoid that for design reasons).

    This is an approach that i often take when building publishing systems in php, so of course its one of the first things i'm trying to do in rails

  16. #16
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    One thing I often find annoying is to have to only change one record at a time and press submit when I have a multiple line form (that was one of my early PHP habits as well). I instead now tend to go for a "table at a time" editing where all of the rows displayed are processed at once in the action. I recently started a thread where I had models for "Questions" and "Answers". Here is the code I am using to process all of the "Answer" changes at once:

    in the view:
    Code:
    <h2>Answers</h2>
    <%= start_form_tag :action => 'update_answers', :id => @question %>
    <% if @answers.size > 0 %>
    <ol style="list-style-type: upper-alpha">
    	<% for answer in @answers %>
    	<li>
    	  <%= hidden_field  "answer#{answer.id}", "id", "value" => answer.id %>
    	  <%= text_field "answer#{answer.id}", "answer",  "size" => 40, "value" => answer.answer %>
    	  <% correct = answer.correct ? "1" : "0" %><select id="answer<%= answer.id %>"
    	      name="answer<%= answer.id %>[correct]">
    	      <%= options_for_select [["Wrong","0"],["Correct","1"]], correct %>
    	</select></li>
    	<% end %>
    </ol>
    <% end %>
     New: <%= text_field "answernew", "answer",  "size" => 40  %>
       <select id="answernew_correct" name="answernew[correct]">
      	<%= options_for_select [["Wrong","0"],["Correct","1"]]  %></select><br>
      <%= submit_tag 'Change Question Answers' %>
    <%= end_form_tag %>
    and in the questions_controller

    Code:
      def update_answers
        @question = Question.find(params[:id])}
        update_answers = params.keys.reject { |k| m = k.match /^answer(\d+)$/; true if m.nil? }
        update_answers.each do |a|
          update = params[a]
          answer = Answer.find(update[:id])
          answer.answer = update[:answer]
          answer.correct = update[:correct] == "1" ? true : false
          answer.save
          flash[:notice] = 'Answers Updated'
        end 
        answernew = params[:answernew]
        if answernew['answer'] != ""
          add = Answer.new
          add.question_id = @question.id
          add.answer = answernew[:answer]
          add.correct = answernew[:correct] == "1" ? true : false
          add.save
          flash[:notice] = 'Answer Added'
        end
        redirect_to :action => 'edit', :id => @question
      end
    Please look at this as an example of "working" code, not necessarily "good" code. Any ideas for improvment are welcome.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  17. #17
    SitePoint Member
    Join Date
    Feb 2006
    Posts
    4
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm very new to Rails too (3rd day), and needed to create a form for editing of all elements.

    Using your examples, after some time I managed to create a form that is populated with the existing values to edit all elements, or 'bulk editing' (just to throw in some words for google ). The examples here didn't work for me in the first, so I'm posting the code to how I got it to work.

    First, the controller code:
    Filename: questions_controller.rb
    Code:
      def edit_questions
        @questions= Question.find_all 
      end 
      
      def update_question 
        @question = Question.find(@params[:id]) 
        if @question.update_attributes(params[:question]) 
          flash[:notice] = 'Sp&oslash;rgsm&aring;l ' + @question.number + ' was successfully updated.' 
          redirect_to (:action => 'edit_questions') 
        else 
          flash[:error] = 'Account couldnt be updated.' 
          render :action => 'list_questions' 
        end 
      end
    Then the view that passes "edit_question", @questions into the partial
    Filename: edit_questions.rhtml
    Code:
    <h1>Editing all questions</h1>
    
    <tr>
    	<th>Gruppe</th>
    	<th>Nr.</th>
    	<th>Sp&oslash;rgsm&aring;l</th>
    	<th>Type</th>
    </tr>
    
    <%= render(:partial => "edit_question", :collection => @questions) %>
    
    <%= link_to 'Back', :action => 'list' %>
    Now, the 'thing' (template, right?) that the partial is passed into:
    Filename: _edit_question.rhtml
    Code:
    <% @question = edit_question %>
    
    
    <tr>
    	<%= start_form_tag :action => 'update_question', :id => @question %>
    
    	<td><label for="group">Gruppe</label><br/>
    		<%= text_field 'question', 'group', "size" => 5   %></td>
    
    	<td><label for="q_number">Nummer</label><br/>
    		<%= text_field 'question', 'number', "size" => 4   %></td>
    
    	<td><label for="q_text">Sp&oslash;rgsm&aring;l</label><br/>
    		<%= text_area 'question', 'text', "rows" => 4, 'cols' => 30   %></td>
    
    	<td><label for="q_type">Type</label><br/>
    		<%= select 'question', 'q_type', ['Valg', 'Tekst', 'Valg+Tekst']   %></td>
    		
    	<td><input type="submit" value="Update question" class="primary" /></td>
    	
    </tr>
       
    <%= end_form_tag %>
    I hope this will be useful to somebody.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •