Re: Editing Multiple Models in One Form

i am waiting for the edit part code of the tutorial that explains how to create a form with a main model and an arbitraty number of second models...

Re: Editing Multiple Models in One Form

skyblaze wrote:

i am waiting for the edit part code of the tutorial that explains how to create a form with a main model and an arbitraty number of second models...

I second the above. Does anyone have any alternative code that they've created?

Re: Editing Multiple Models in One Form

You've saved me a lot of grief! But I've run into a bit of a problem.
I have two models: @entity and @comment. Each entity can have 0 or more comments (has_many), but each comment can have only one entity (belongs_to).
I used the following edit controller:
    def update
        @entity = Entity.find(params["id"])
        @entity.attributes = params[:entity]
        @entity.comments.each { |c| c.attributes = params[:comment][c.id.to_s]}
        @comment = @entity.comments.build(params[:comment])
       
        if @entity.valid? && @entity.comments.all?(&:valid?)
            @entity.save!
            @entity.comments.each(&:save!)
            flash[:notice] = "Entity updated."
            redirect_to :action => 'show', :id => @entity
        else
            render :action => 'edit'
        end
    end

And the following rhtml:
<% for @comment in @entity.comments %>
<%= error_messages_for :comment %>
    <label for="comment"><%= @comment.commenttype.name %>
        <div>
    <% fields_for "comment[]" do |c| %>
            <%= c.hidden_field :commenttype_id %>
            <%= c.text_area :commenttext, {"cols" => 50, "rows" => 20, "wrap" => "virtual"} %>
    <% end %>
        </div>
    </label>
<% end %>

But I get the following error:
undefined method `1=' for #<Comment:0x4a27d7c>

The parameters are as follows:
Parameters: {"entity"=>{"zip"=>"60606", "cell"=>"", "url1"=>"", "url2"=>"", "middlename"=>"", "firstname"=>"Byron", "lastname"=>"Jones", "id"=>"1", "entitytype_id"=>"1", "fax"=>"", "phone"=>"773-555-5465", "city_id"=>"1", "state_id"=>"1"}, "template"=>{"id"=>"1"}, "id"=>"1", "entitysubtype"=>{"id"=>"1"}, "entity_address1"=>"1234 Wisteria Lane", "entity_address2"=>"", "comment"=>{"1"=>{"id"=>"1", "commenttext"=>"Float like a butterfly, sting like a bee!", "commenttype_id"=>"1"}}}

If you notice, the comment hash has a '"1"=>' key in it, which I think may be the source of the problem, but I'm too much of a noob to be sure. Any and all help will be appreciated.

Re: Editing Multiple Models in One Form

bchodo wrote:

"comment"=>{"1"=>{"id"=>"1", "commenttext"=>"Float like a butterfly, sting like a bee!", "commenttype_id"=>"1"}

Looks like the "id" attribute is being passed for each comment. I think that's the problem. Are you passing this through a hidden field or something? Try removing it.

Railscasts - Free Ruby on Rails Screencasts

Re: Editing Multiple Models in One Form

Same error, with these parms:
Parameters: {"entity"=>{"zip"=>"60606", "cell"=>"", "url1"=>"", "url2"=>"", "middlename"=>"", "firstname"=>"Byron", "lastname"=>"Jones", "id"=>"1", "entitytype_id"=>"1", "fax"=>"", "phone"=>"773-555-5465", "city_id"=>"1", "state_id"=>"1"}, "template"=>{"id"=>"2"}, "id"=>"1", "entitysubtype"=>{"id"=>"1"}, "entity_address1"=>"1234 Wisteria Lane", "entity_address2"=>"", "comment"=>{"1"=>{"commenttext"=>"Float like a butterfly, sting like a bee!", "commenttype_id"=>"1"}}}

Re: Editing Multiple Models in One Form

Can you post the stack trace?

Railscasts - Free Ruby on Rails Screencasts

Re: Editing Multiple Models in One Form

Sure. Full trace follows:

D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1857:in `method_missing'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1672:in `send'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1672:in `attributes='
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1671:in `each'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1671:in `attributes='
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1505:in `initialize_without_callbacks'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/callbacks.rb:225:in `initialize'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/associations/has_many_association.rb:13:in `new'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/associations/has_many_association.rb:13:in `build'
#{RAILS_ROOT}/app/controllers/entity_controller.rb:37:in `update'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/base.rb:1095:in `send'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/base.rb:1095:in `perform_action_without_filters'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:632:in `call_filter'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:638:in `call_filter'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:438:in `call'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:637:in `call_filter'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:619:in `perform_action_without_benchmark'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/benchmarking.rb:66:in `perform_action_without_rescue'
D:/InstantRails/ruby/lib/ruby/1.8/benchmark.rb:293:in `measure'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/benchmarking.rb:66:in `perform_action_without_rescue'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/rescue.rb:83:in `perform_action'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/base.rb:430:in `send'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/base.rb:430:in `process_without_filters'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/filters.rb:624:in `process_without_session_management_support'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/session_management.rb:114:in `process'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/base.rb:330:in `process'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/dispatcher.rb:41:in `dispatch'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel/rails.rb:78:in `process'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel/rails.rb:76:in `synchronize'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel/rails.rb:76:in `process'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel.rb:618:in `process_client'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel.rb:617:in `each'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel.rb:617:in `process_client'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel.rb:736:in `run'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel.rb:736:in `initialize'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel.rb:736:in `new'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel.rb:736:in `run'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel.rb:720:in `initialize'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel.rb:720:in `new'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel.rb:720:in `run'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel/configurator.rb:271:in `run'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel/configurator.rb:270:in `each'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel/configurator.rb:270:in `run'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/bin/mongrel_rails:127:in `run'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/lib/mongrel/command.rb:211:in `run'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/mongrel-1.0.1-mswin32/bin/mongrel_rails:243
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:488:in `load'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:488:in `load'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:342:in `new_constants_in'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:488:in `load'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/commands/servers/mongrel.rb:60
D:/InstantRails/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
D:/InstantRails/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:495:in `require'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:342:in `new_constants_in'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:495:in `require'
D:/InstantRails/ruby/lib/ruby/gems/1.8/gems/rails-1.2.3/lib/commands/server.rb:39
D:/InstantRails/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
D:/InstantRails/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
script/server:3

Re: Editing Multiple Models in One Form

Could the problem be somewhere around
"@entity.comments.each { |c| c.attributes = params[:comment][c.id.to_s]}"? This seems to be about where the "1=" is generated.

Re: Editing Multiple Models in One Form

The problem is this line:

@comment = @entity.comments.build(params[:comment])

Not sure what you're doing here, but params[:comment] is a hash of all the other submitted comments. Not just one.

Railscasts - Free Ruby on Rails Screencasts

Re: Editing Multiple Models in One Form

My thoughts were that each entity can have multiple comments (the number is not previously known until the Comment model is queried). So the hash representing the group of comments would have to have a set of params for each of the entities' comments in the model.

I'm just not sure I'm doing it the right way.

Re: Editing Multiple Models in One Form

So you're trying to create comments and edit them in the same form? This tutorial only supports editing multiple comments. Creating them in the same form is worthy of its own tutorial which someday I may get around to writing...

Railscasts - Free Ruby on Rails Screencasts

Re: Editing Multiple Models in One Form

No, I create the entity/comments in one form, and edit them in another.

Re: Editing Multiple Models in One Form

I don't see why you're calling comments.build then. This will create a new comment. Try just removing that line and see if everything works.

Railscasts - Free Ruby on Rails Screencasts

Re: Editing Multiple Models in One Form

Eureka! Gold at last!

Your help has been invaluable.

Now let's see if I can do it the right way myself!

Re: Editing Multiple Models in One Form

Does this method work for 3 models?

I have the following view:

  <% form_for :question, :url => { :action => 'create' } do |f| %>
  <% f.text_field :name %>
  <% f.text_area :description %>

<div id="options">
  <label>Options:</label>
  <!-- Needs to be ajaxified-->
  <% question.options.each_with_index do |option, index|%>
    <% fields_for "options[#{index}]", option do |f| %>
      <p><%= f.text_field :name, :size => 20 %></p>
    <% end %>
  <% end %>
</div>
<div id="factors">
  <label>Factors:</label>
  <!-- Needs to be ajaxified-->
  <% question.factors.each_with_index do |factor, index|%>
    <% fields_for "factors[#{index}]", factor do |f| %>
      <p><%= f.text_field :name, :size => 20 %></p>
    <% end %>
  <% end %>
</div>


Without factors it works fine, but putting factors into the form leads to rails putting both options and factors into the Option model, and neither into the Factor model.

Any thoughts?

Thanks

Re: Editing Multiple Models in One Form

Being a rails newbie this is such great tutorial for me, but in my case I only got 1 task for 1 project, so it's not project has_many tasks but project has_one task.

I know from database design point of view this isn't normalized but this is just a test case for me.

What should I do with the update method?

Thank you.

Re: Editing Multiple Models in One Form

Hi Ryan... an awesome guideline you have painted through this article.

I am very new to Rails, and have following structure to take care of to update 2 models with one form.

:user and :user_profile.

User Model
class User < ActiveRecord::Base
has_one :user_profile
end

UserProfile Model
class UserProfile < ActiveRecord::Base
  belongs_to :user
  belongs_to :country
  belongs_to :community
  belongs_to :occupation
end


------------------------------The VIEW
          <div>
<% form_for :user do |form|%>
  <%= error_messages_for :user %>
  <table width="80%" border="0" align="center" cellpadding="3" cellspacing="0">
    <tr>
    <td width="25%" align="left"><strong>Maiden&nbsp;Last&nbsp;Name&nbsp;:</strong></td>
    <td><%= form.text_field :maiden_last_name %></td>
    </tr>
   
    <tr>
    <td width="25%" align="left"><strong>Birth Date :</strong></td>
    <td><%= form.date_select :birth_date, :start_year => 1940 %></td>
    </tr>

    <tr>
    <td width="25%" align="left"><strong>Maritial Status</strong></td>
    <td><%= form.check_box :married %></td>
    </tr>
   
    <tr>
    <td align="left"><strong>Occupation&nbsp:</strong></td>
    <td><label>
    <%=  collection_select :user, :occupation_id, Occupation.find(:all), :id, :occupation,    {:prompt => true} %>
      </label></td>
    </tr>

      <tr>
      <td align="left"><strong>Community&nbsp:</strong></td>
      <td><label>
       <%=  collection_select :user, :community_id, Community.find(:all), :id, :name, {:prompt => true} %>
            </label></td>
    </tr>

     <tr>
     <td width="25%" align="left"><strong>Marriage&nbsp;Anniversary&nbsp;Date&nbsp;:</strong></td>
     <td><%= form.date_select :marriage_anniversary_date, :start_year => 1940 %></td>
     </tr>
     
     
<tr>
<td><label>
<%= submit_tag "Join", :class => "button1" %>
</label></td>
</tr>
</table>
<% end%>
</div>


#user_controller, tellusmore action is called
#with provided :id=>@user.id, from previous page submit
...which saves few entries of both "users" and "user_profiles" tables.
#-----------------------And this is the Controller
def tellusmore
    if request.post? and params[:user]
     
      @user = User.find(params[:id], :include=>"user_profile")
      @user_profile=UserProfile.new
     
      @community = Community.find_by_id(params[:user_profile][:community_id])
      @user_profile.community_id = @community.id
      @occupation = Occupation.find_by_id(params[:user_profile][:occupation_id])
      @user_profile.occupation_id = @occupation.id
 
     
      @user.user_profile = @user_profile
     
       if @user.save
         flash[:notice]= "Step Over"
         redirect_to :action=>'login'
       else
         @user.reset_form_password
      end
    end
  end




    Please help me save these entries, into users and user_profiles using the single template.........tellusmore

Out of these -
married, maiden_last_name, birth_date belong to users table rest belongs to user_profiles table.

Re: Editing Multiple Models in One Form

hi

I am facing the following issue:

I have two models named: Project and AgreementFile
Every Project can have only one agreement file
So they share following relationships

class Project < ActiveRecord::Base
  belongs_to :agreementfile
end

class Agreementfile < ActiveRecord::Base
  has_one :project
 
  def sow_file=(input_data)
    self.name = input_data.original_filename
    self.content_type = input_data.content_type.chomp
    self.content = input_data.read
  end

end


I want to create agreementfile in the same view as project new
New is working for me but edit do not

In edit.html.erb file of project view I did following

<h1>Editing project</h1>

<%= error_messages_for :project, :agreementfile %>

<% form_for(:project, @project, :url => {:action => 'update'}, :html => { :multipart => true }) do |f| %>

    <p>
    <b>Name</b><br />
    <%= f.text_field :name %>
  </p>
   
  <p>
    <b>Budget</b><br />
    <%= f.text_field  :budget %>
  </p>

  <p>
    <b>Billable count</b><br />
    <%= f.text_field :billable_count %>
  </p>
   

<% fields_for(:agreementfile, @project.agreementfile) do |i| %>
    <p>
      <b>Upload file</b>
      <%= i.file_field :sow_file %>
     </p>
   <% end %>

  <p>
    <%= submit_tag "Update" %>
  </p>

<% end %>

<%= link_to 'Show', @project %> |
<%= link_to 'Back', projects_path %>


But still I found the view do not show me upload image file name in file_field of corresponding to "Upload file"

Requirement: During the edit of particular project all the fields corresponding to that project should be pre-filled. User can change the value of any field and click "Update" . The new values should then replace the old values.
So the first step itself populating the old values of project in edit form is not working. Please help me how to go about.

Re: Editing Multiple Models in One Form

There is one more issue I am facing after updating

I changed my update function like this:

  def update
    @project = Project.find(params[:id])
    @project.attributes = params[:project]
    @project.agreementfile.attributes = params[:agreementfile]

    respond_to do |format|
      if @project.valid? && @project.agreementfile.valid
        @project.save!
        @project.agreementfile.save!
        flash[:notice] = 'Project was successfully updated.'
        format.html { redirect_to(@project) }
        format.xml  { head yikesk }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @project.errors, :status => :unprocessable_entity }
      end
    end
  end

but when I do update it says
Unknown action
No action responded to 1

Please let me know what I am doing wrong in update function

Re: Editing Multiple Models in One Form

Hi All,
I have tried to edit the multiple models in one form using ryns tutorial editing multiple models in one form.
But could not able to make it work.

And error am getting like:
Unknown action
No action responded to 79. Actions: create, destroy, edit, index, new, redirect_back, show, and update

and my code snippet:
in containterformatcontrolelr:
--------------------
def update
    @containerformat = Containerformat.find(params[:id])
    @containerformat.attributes = params[:containerformat]
    @containerformat.transportstreams.each { |t| t.attributes = params[:transportstream][t.id.to_s] }

    respond_to do |format|
      if @containerformat.update_attributes(params[:containerformat])
        flash[:notice] = 'Containerformat was successfully updated.'
        format.html { redirect_to(@containerformat) }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @containerformat.errors, :status => :unprocessable_entity }
      end
    end
  end

edit.html.erb
-------------
<div id="content">
<h1>Edit containerformat</h1>
<%= error_messages_for :containerformat %>
<%= form_tag :action => 'update', :id => params[:id] %>
<p>  Stream Name:  <%= text_field :containerformat, :streamName %></p>
<h2>transportstream</h2>
<% for @transportstream in @containerformat.transportstreams %> 
<%= error_messages_for :transportstream %> 
<% fields_for "transportstream[]" do |f| %> 
<p><%= f.text_field :numPrograms %></p>
<% end %>
<% end %>
<p><%= submit_tag 'Update' %></p>

can anyone suggested me wher i am doing the mistake?

thanks
Srikanth