Forum: Ruby on Rails has_many and belongs_to example?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Szymon N. (Guest)
on 2006-03-04 11:20
Hi!

If i have 2 tables i.e. product and images and product has_many images,
image belongs_to product - how to create _form.rhtml, new/create and
edit/update methods in product controller, so in a single form i can add
one product and MANY (let's assume for now that this number is fixed)
images for this product?

Pleeeeease help me :)
James M. (Guest)
on 2006-03-04 14:12
g0nzo  wrote:
> Hi!
>
> If i have 2 tables i.e. product and images and product has_many images,
> image belongs_to product - how to create _form.rhtml, new/create and
> edit/update methods in product controller, so in a single form i can add
> one product and MANY (let's assume for now that this number is fixed)
> images for this product?
>
> Pleeeeease help me :)

Here are some snips that worked for me (thanks to the guys here);

CREATE TABLE cvs(
	id		INT			not null	AUTO_INCREMENT	PRIMARY KEY,
	first_name	VARCHAR(30) 		not null,
	family_name	VARCHAR(30) 		not null,
	.
	.
	updated_on	timestamp(14)		not null
);

drop table if exists skills;
CREATE TABLE skills(
	id		INT			not null	AUTO_INCREMENT	PRIMARY KEY,
	title		VARCHAR(20) 		not null,
	detail		VARCHAR(200) 		not null,
	cv_id		int			not null,
	created_on	timestamp(14)		not null,
	updated_on	timestamp(14)		not null,
	constraint	fk_skills_cv	foreign key (cv_id) 	references cvs(id)
);

The at the command line;
script/generate model CV
script/generate model Skill

(in addition I generated controller & scaffold for each just to get
going;
script/generate controller CV_admin
script/generate controller Skill

script/generate scaffold CV CV_admin
script/generate scaffold skill skills
)

Then edit the 2 models created;
class CV < ActiveRecord::Base
has_many :skills
end

class Skill < ActiveRecord::Base
belongs_to :cv
end

to get the skills to be created from within the CV form;

<div class="ccv_items_skills">
<h2>Skills</h2>
	<% for skill in @cv.skills %>
		<p><strong><%= h(skill.title) %></strong><%= h(skill.detail) %></p>
	<% end %>
</div>
<%= link_to "add_skill",  :controller => "skills", :action => "new", :id
=> @cv %>

Inside the skills controller;

  def new
    @session[:cv_id] = params[:id]
    @skill = Skill.new
  end

  def create
   @cv = Cv.find(@session[:cv_id])
   @cv.skills << Skill.new(params[:skill])
    if @cv.save
      flash[:notice] = 'Skill was successfully created.'
      redirect_to :action => 'show', :controller => 'cv_admin', :id =>
@cv
    else
      render :action => 'new'
    end
  end

the @cv.save updates both the skills list and the cv and takes care of
all the associations for the foreign keys.

good luck.
Szymon N. (Guest)
on 2006-03-04 21:35
Thanks!!!

But one question: you have separate form for adding skills?
Would it be possible to add (many) skills directly via CV form, without
using separate form just for skills?
James M. (Guest)
on 2006-03-05 00:15
g0nzo  wrote:
> Thanks!!!
>
> But one question: you have separate form for adding skills?
> Would it be possible to add (many) skills directly via CV form, without
> using separate form just for skills?

I believe so... I would just put the code from the new & create methods
for skills (from my example) into those for cv & obviously put the
skills form in the cv form, but having not tried this yet & as a newbie
myself, let me know how it works...
John S. (Guest)
on 2006-03-13 21:43
(Received via mailing list)
I believe you are doing the same thing I had to do for a person
having multiple visits for a given program. I am using AJAX links to
add and remove visits. My form looked like this...
=====================================
<% unless @pgm_update.pgm_visits.empty? -%>
   <% @pgm_update.pgm_visits.each_index do |index| %>
     <p>
       <table>
         <tr>
           <td><%= plus_one(index) %>. &nbsp;</td>
           <td>Start: <br>
               End: </td>
               <td><%= date_select "pgm_visit#{plus_one
(index)}","start", :start_year => @program.start_date.year, :end_year
=> @program.end_date.year + 1, :order => [:month, :day, :year] %><br>
               <%= date_select "pgm_visit#{plus_one
(index)}","ends", :start_year => @program.start_date.year, :end_year
=> @program.end_date.year + 1, :order => [:month, :day, :year] %></td>
               <td>
                 <% if @pgm_update.pgm_visits.size > 1 -%>
                   <%= link_to_remote 'remove',
                     :update => 'visits',
                     :url => {:action => :ajax_remove_visit, :id =>
index },
                     :with => "Form.serialize('application_form')"
                     %>
                 <% end -%>
                 </td>
         </tr>
       </table>
     </p>
   <% end -%>
<% else -%>
   <p>click '+' to add a visit</p>
<% end -%>
====================================

each visit instance variable (pgm_visit1...i) is dynamically
generated and set in the action with the following:
=====================
@pgm_update.pgm_visits.each_index do |i|
       visit = i+1
       instance_variable_set("@pgm_visit#{visit}".to_sym,
@pgm_update.pgm_visits[i])
     end
if request.post?
       @pgm_update.pgm_visits.each_index do |i|
         visit = i+1
         instance_variable_get("@pgm_visit#
{visit}".to_sym).attributes = params["pgm_visit#{visit}"]
       end
end
=====================
I can give more details on request

-John

--
John S.
Computing Staff - Webmaster
Kavli Institute for Theoretical Physics
University of California, Santa Barbara
removed_email_address@domain.invalid
(805) 893-6307
Eric Steiner (Guest)
on 2006-03-29 01:58
These examples have helped me a lot!

My problem is this,  how do you UPDATE child records?  Every tutorial
and book I see only addresses the parent/child saving issue in the New
method.

I can't do a find for children, because I don't know the child.id  and
each parent will have at least 3 children.


John S. wrote:
> I believe you are doing the same thing I had to do for a person
> having multiple visits for a given program. I am using AJAX links to
> add and remove visits. My form looked like this...
> =====================================
> <% unless @pgm_update.pgm_visits.empty? -%>
>    <% @pgm_update.pgm_visits.each_index do |index| %>
>      <p>
>        <table>
>          <tr>
>            <td><%= plus_one(index) %>. &nbsp;</td>
>            <td>Start: <br>
>                End: </td>
>                <td><%= date_select "pgm_visit#{plus_one
> (index)}","start", :start_year => @program.start_date.year, :end_year
> => @program.end_date.year + 1, :order => [:month, :day, :year] %><br>
>                <%= date_select "pgm_visit#{plus_one
> (index)}","ends", :start_year => @program.start_date.year, :end_year
> => @program.end_date.year + 1, :order => [:month, :day, :year] %></td>
>                <td>
>                  <% if @pgm_update.pgm_visits.size > 1 -%>
>                    <%= link_to_remote 'remove',
>                      :update => 'visits',
>                      :url => {:action => :ajax_remove_visit, :id =>
> index },
>                      :with => "Form.serialize('application_form')"
>                      %>
>                  <% end -%>
>                  </td>
>          </tr>
>        </table>
>      </p>
>    <% end -%>
> <% else -%>
>    <p>click '+' to add a visit</p>
> <% end -%>
> ====================================
>
> each visit instance variable (pgm_visit1...i) is dynamically
> generated and set in the action with the following:
> =====================
> @pgm_update.pgm_visits.each_index do |i|
>        visit = i+1
>        instance_variable_set("@pgm_visit#{visit}".to_sym,
> @pgm_update.pgm_visits[i])
>      end
> if request.post?
>        @pgm_update.pgm_visits.each_index do |i|
>          visit = i+1
>          instance_variable_get("@pgm_visit#
> {visit}".to_sym).attributes = params["pgm_visit#{visit}"]
>        end
> end
> =====================
> I can give more details on request
>
> -John
>
> --
> John S.
> Computing Staff - Webmaster
> Kavli Institute for Theoretical Physics
> University of California, Santa Barbara
> removed_email_address@domain.invalid
> (805) 893-6307
This topic is locked and can not be replied to.