Re: Creating Two Models in One Form

Has anyone had luck implementing something like this using polymorphic associations? I've got a model called Submissions, which uses a polymorphic association.

@submission = Submission.new(params[:submission])
@submittable = @submission.build_submittable(params[:picture])

I get a method missing error on "build_submittable," which is correct, because according to here, the build method isn't supported for :belongs_to, :polymorphic.

It also appears that if I just create the associated record separately, it needs to be saved before I can assign it to @submission, or else throws a validation error saying :submittable_type wasn't set.

Is there an elegant way to build the associated record like in the tutorial, or do I just need to create and save the records separately?

Re: Creating Two 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.

Online

Re: Creating Two Models in One Form

This is a great tutorial.  Could it be extended to a third model?
Say project has many tasks and then tasks have many assignees.
Could the assignees also be added?
Would that work from the project side with a has_many through?

Re: Creating Two Models in One Form

Hmm, I can get the form to work for three leves down.
But then the problem is how do I keep the third level objects from being applied across the board?  1 Project 5 Tasks each task has 5 asignees.  I can't loop through each of the params for asignee it has to do it in blocks of five.  Is there an elegat way to do this or just brute if then logic?

Re: Creating Two Models in One Form

Sorry but it doesn't work for me, I use Rails 2.2.2 on Windows XP, here are my 3 tables:
clinical_study.rb:

 has_many :clinical_study_countries, :dependent => :destroy
  has_many :countries, :through => :clinical_study_countries, :uniq=>true

clinical_study_country.rb
belongs_to :clinical_study
  belongs_to :country

country.rb
has_many :requirements, :dependent => :destroy
  has_many :clinical_study_countries, :dependent => :destroy
  has_many :clinical_studies, :through=>:clinical_study_countries

In my new.html.erb:
<h1>New clinical_study</h1>

<% form_for(@clinical_study) do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :ref %><br />
    <%= f.text_field :ref %>
  </p>
  <div>
    <div class="prd_select">
      <%= select_tag("select_from",
        options_for_select(@countries, @clinical_study.countries.collect { |country| country.id}),
        {:multiple=>true, :size=>6})%>
      <a href="#" id="add">Add >></a>
    </div>
    <div class ="prd_select">
      <%= select_tag("select_to", options_for_select([]), {:multiple=>true, :size=>6})%>
      <a href="#" id="remove"><< Remove</a>
    </div>
    <br/>
  </div>
  <%fields_for(@clinical_study_country) do |clinical|%>
    <p>
      <%= clinical.label :description %><br />
      <%= clinical.text_field :description %>
    </p>

  <%end%>
  <p>
    <%= f.submit "Create" %>
  </p>
<% end %>

<%= link_to 'Back', clinical_studies_path %>


When I just tried to create, I got:
undefined method `clinical_study_id=' for #<ClinicalStudyCountry:0x4959a44>

What's wrong here?

Re: Creating Two Models in One Form

thanks for helping

Re: Creating Two Models in One Form

Is the above method of creating 2 models in a single form deprecated in rails 2.2.2 ?
i have spent almost 3 days into this, and its not working out.
do we need to put something inside the models as well.., as this thread doesn't talk about it?

Re: Creating Two Models in One Form

You may want to try out the attribute_fu plugin. That is what I ended up using, it is really simple and can even be extended to three (or I assume even more) levels of model nesting. Cheers

Re: Creating Two Models in One Form

Hi All,

i have gone through all posts of complexforms for creating multiple models.
There is only one parent and one child.But in my application i have to associate the multiple models.

in my application i have models like;
containerformat
transport_stream
program
stream

i want to provide the association in between these models like:
Each containerformat has many trasportstreams and each transportstream has many programs and each program may have more than one video and audio streams.details of audio and video streams are updated in stream table.

to do this i have provided the association in my models like;

class Containerformat < ActiveRecord::Base
has_many :transport_streams
has_many :programs, :through=>transport_streams

def transport_stream_attributes=(transport_stream_attributes)
transport_stream_attributes.each do |attributes|
transport_streams.build(attributes)
end
end

def program_attributes=(program_attributes)
program_attributes.each do |attributes|
programs.build(attributes)
end
end

end


class TransportStream < ActiveRecord::Base
has_many :programs
belongs_to :containerformat
end

class Program < ActiveRecord::Base
belongs_to :transport_stream
end

my code details:
in containerformat controller:

def new
    @containerformat = Containerformat.new
    @containerformat.transport_streams.build
    @containerformat.programs.build
   
    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @containerformat }
    end
  end
-----

------i am getting the below error if i use :through=>transport_strams in the containerformat model.
NameError in ContainerformatsController#new
undefined local variable or method `transport_streams' for #<Class:0x4786028>

and is there any thing require to use through with associations.
If i dont use the through in the associations i could able to update the data in other model but violating the associations between the models.

So can any one solve my problem.
suggest me if there is any problem with association between models.
How to cteate the multiple models in one form?



thanks
Srikanth

Re: Creating Two Models in One Form

Anyone tried Rails 2.3.2 ability to do that?

Re: Creating Two Models in One Form

There is something wrong in your models. First you tell that your ContainerStream has many TransportStreams, and each TransportStream has many Programs. In you models you do as if ContainerStream has many TransportStreams, and Program has many TransportsStreams. Beside that you do in you model that TransportStream has many Programs. So it's difficult to understand where you'd like to put many-to-many relation, -
1. Between ContainerFormat and Programs or
2. Between Programs and TransportStreams.
Check it one more time, please.
If the first solution is right, so you should add one more belongs_to rule to your TransportStream model

Re: Creating Two Models in One Form

Hi Javix ,
Thank you for the response.
As i am new to rails i dont have much idea on associations .
But i want to provide the association between models in my application while uploading the sterams.
ex:
I want to upload a stream called '1.ts' the stream has more programs and each program will have one or more video and audio streams and each audio and video details are stored in streams table.

this the data of stream to be uploaded in to database.

For this i have below tables :
containerformats:to store the name of stream and location
----------------

trasportstreams:has below fields
----------------
"num_programs"
"encryption_std"
"containerformat_id"

programs table: has below fields
----------------
"pid"
"closedcaption"
"privatedata_pid"
"transport_stream_id"
"numAudio"
"numVideo"

streams table:has below fields
-----------
"videoCodec_id"
"resolution"
"audioSamplingRate"

And i am using ryans complexforms post to upload data into models.

--Can you suggest me to provide the association between the models.
i could not able to proceede from this step.
Any help is greatly appreciated.

thanks
Srikanth

Re: Creating Two Models in One Form

Hi!
1. Could you please respect some punctuation, because it is not esay to understand wher you stop and start a new sentence?
2. To suggest something I have you to reply for some questions

- do you work with an existing DD schema or you should create one yourself?
- you tell

Each containerformat has many trasportstreams and each transportstream has many programs and each program may have more than one video and audio streams.details of audio and video streams are updated in stream table.

In this case I'd see you models like that

class containerformat < AR
  has_many :transportstreams
end
class transportstream < AR
  belongs_to:containerformat
  has_many :programs
end

class program < AR
  belongs_to:transportstream
  has_many :streams
end


Then you tell as follows:

I want to upload a stream called '1.ts' the stream has more programs and each program will have one or more video and audio streams and each audio and video details are stored in streams table.

That's why I suppose that you have a work flow like that:

containerformat -> has many -> transportstreams -> has many -> programs -> has many -> streams.
If it's the case no need to use has_many :through association. Use it only if something has many 'through something' like for example transportstream has many streams through programs. In this case you program table should have a reference as transportstream_id to the corresponding transportstream.

Re: Creating Two Models in One Form

Hi Javix,
thank you for the suggestions.

Now i have removed the use has_many:through association.
And i could able to upload stream into database.

But the problem here is:
while uploading data into other tables
1)i am not getting the transportstream_id from transportstreams in to the programs table.
2)throughing the error like:
ActiveRecord::StatementInvalid in Containerformats#show
Showing app/views/containerformats/show.html.erb where line #26 raised:

Mysql::Error: Unknown column 'programs.containerformat_id' in 'where clause': SELECT * FROM `programs` WHERE (`programs`.containerformat_id = 2)

but data is storing in the correspomding tables.

my code details;

in containerformatcontroller:
def new
    @containerformat = Containerformat.new
    @containerformat.transport_streams.build
     @containerformat.programs.build
     @containerformat.streams.build

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @containerformat }
    end
  end

--------in containerformat model
class Containerformat < ActiveRecord::Base
has_many :transport_streams
has_many :programs
has_many :streams

def transport_stream_attributes=(transport_stream_attributes)
transport_stream_attributes.each do |attributes|
transport_streams.build(attributes)
end
end

def program_attributes=(program_attributes)
program_attributes.each do |attributes|
programs.build(attributes)
end
end
def stream_attributes=(stream_attributes)
stream_attributes.each do |attributes|
streams.build(attributes)
end
end

end
---------------------in views(new.html.erb)<h1>New containerformat</h1>

<% form_for(@containerformat) do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :stream_name %><br />
    <%= f.text_field :stream_name %>
  </p>
  <p>
    <%= f.label :location %><br />
    <%= f.text_field :location %>
  </p>
  <p>
    <%= f.label :containertype_id %><br />
    <%= f.text_field :containertype_id %>
  </p>
 
  <%for transport_stream in @containerformat.transport_streams%>
     <%fields_for "containerformat[transport_stream_attributes][]", transport_stream do |ts_form|%>
     <p>Num_programs</p>
     <p><%= ts_form.text_field :num_programs%></p>
     <p>Encryption std</p>
     <p><%= ts_form.text_field :encryption_std%></p>
     <% end %>
     <% end %>

 
    <%for program in @containerformat.programs%>
       <%fields_for "containerformat[program_attributes][]", program do |ts_form|%>
       <p>PID</p>
       <p><%= ts_form.text_field :pid%></p>
       
       <% end %>
       <% end %>
       
       
       <%for stream in @containerformat.streams%>
              <%fields_for "containerformat[stream_attributes][]", stream do |ts_form|%>
              <p>videocodecid</p>
              <p><%= ts_form.text_field :videoCodec_id%></p>
              <p>audiocodecid</p>
              <p><%= ts_form.text_field :audioCodec_id%></p>
             
              <% end %>
              <% end %>
 
 
  <p>
 
    <%= f.submit "Create" %>
  </p>
<% end %>

<%= link_to 'Back', containerformats_path %>
-------showpage
<p>
  <b>Stream name:</b>
  <%=h @containerformat.stream_name %>
</p>

<p>
  <b>Location:</b>
  <%=h @containerformat.location %>
</p>

<p>
  <b>containertype_id:</b>
  <%=h @containerformat.containertype_id %>
</p>

<%- @containerformat.transport_streams.each do |task| -%>
<p>
    <b>Number of programs:</b>
    <%= task.num_programs %>
</p>
<%- end -%>

<%- @containerformat.programs.each do |task| -%>
<p>
    <b>PID:</b>
    <%= task.pid %>
</p>
<%- end -%>

<%- @containerformat.streams.each do |task| -%>
<p>
    <b>videoCodec_id:</b>
    <%= task.videoCodec_id %>
   
    <b>audiocodecid:</b>
    <%= task.audioCodec_id %>
    </p>
<%- end -%>

<%= link_to 'Edit', edit_containerformat_path(@containerformat) %> |
<%= link_to 'Back', containerformats_path %>

Can you tell me where i am doing the mistake?
Can you suggest me how to get the valus of other tables in the show page?

regards
Srikanth

Re: Creating Two Models in One Form

Hi, I have two models. The parent model uses a sequence table for getting the primary key value, and the child model is joint with the parent model through the parent model's primary key.

class Event < ActiveRecord::Base
  set_table_name "er_event"
  set_sequence_name "er_event_seqno"
  set_primary_key :eventid
  has_many :product
end


class Product < ActiveRecord::Base
  set_table_name "er_product"
  set_primary_key :productid
  belongs_to :event, :class_name => "Event", :foreign_key => [:eventid]
end


here it is my controller where I try to save these two models:

class CreateController < ApplicationController
  def create
    @event = Event.new(params[:er_event])
    @product = @event.product.build(params[:product])
    if @event.save
      flash[:notice] = 'New promotion is created.'
    else
      flash[:error] = 'Please correct the errors below:'
    end

    render :action => "index"
 
  end
end


but the problem now is the auto-generated eventid is not passed to the child model while saving. here is the log
 select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT er_product.productid FROM er_product WHERE (er_product.productid = 'P1' AND er_product.eventid IS NULL) ) raw_sql_ where rownum <= 1) where raw_rnum_ > 0
  Event Exists (2.2ms)   select * from (select raw_sql_.*, rownum raw_rnum_ from (SELECT er_event.eventid FROM er_event WHERE (er_event.title = 'test') ) raw_sql_ where rownum <= 1) where raw_rnum_ > 0
Rendering template within layouts/application

Does anyone has an idea how I can pass the value of the parent model primary key to the child model? Specifically the primary key is generated by sequence table. Thanks!

Re: Creating Two Models in One Form

there are so many tutorials on how to create multiple models in one form, but i want to do something more simple and its killing me, i cant find ANY examples.  How do you create multiple instances of the SAME model on one form.  Say you wanted a tasks entry screen where you could enter 4 tasks in one view and submit and have them all created.  What then? please help, ive wasted half the day on this

Re: Creating Two Models in One Form

Maybe a presenter - never used one myself, but I've heard of stuff like this being done using such patterns.

Re: Creating Two Models in One Form

Hi all

I have 2 tables. Lesson and Tag. A lesson can have multiple tags. When I save, records are saving in both tables but the tag.body is saving as NULL. What am I doing wrong?

This is lesson,rb
class Lesson < ActiveRecord::Base
#Mandatory fields validation
validates_presence_of :title, :contact_yn
has_many :tags
end

This is tag.rb
class Tag < ActiveRecord::Base
    belongs_to :lesson
end

My lesson.new is
<h1>New lesson</h1>

<%= error_messages_for :lesson %>
<%= error_messages_for :tag %>

<% form_for(@lesson) do |f| %>
  <p>
    <%= f.label :title %><br />
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.label :description %><br />
    <%= f.text_area :description %>
  </p>

  <p>
    Can others contact you?<br />
   <%= f.select :contact_yn, ['Yes', 'No'] %>
  </p>
<% fields_for :tags do |i| %>
      <p>
        Tags:<br />
    <%= i.text_field :body %>
</p>
<% end %>
  <p>
    <%= f.submit 'Save' %>
  </p>

<% end %>
<%= link_to 'Back', lessons_path %>

My lesson controller is
def new
    @lesson = Lesson.new
    @tag = Tag.new
   
    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @lesson }
    end
  end

  # GET /lessons/1/edit
  def edit
    @lesson = Lesson.find(params[:id])
  end

  # POST /lessons
  # POST /lessons.xml
  def create
    @lesson = Lesson.new(params[:lesson])
    $tag = @lesson.tags.build(params[:tag])

    respond_to do |format|
      if @lesson.save
        flash[:notice] = 'Lesson was successfully created.'
        format.html { redirect_to(@lesson) }
        format.xml  { render :xml => @lesson, :status => :created, :location => @lesson }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @lesson.errors, :status => :unprocessable_entity }
      end
    end
  end


When I save, records are saving in both tables but the tag.body is saving as NULL. What am I doing wrong?

TIA
-vas

Re: Creating Two Models in One Form

Is there a more up-to-date tutorial?

Re: Creating Two Models in One Form

I have gone through your example.
Its really very nice.

Can u provide me some more functionalities like Update and delete operations of multiple tables (models) through single form.

If we are able to perform these operations then only our article should be perfect right...!!

I looking for your reply.