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.
F639e0cdf2fa098b535d6ec766b2aee1?d=identicon&s=25 Szymon Nowak (g0nzo)
on 2006-03-04 10: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 :)
A025f68d8100c2f0fa78c6cfcc4cbfd1?d=identicon&s=25 James Mccarthy (noagenda)
on 2006-03-04 13: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.
F639e0cdf2fa098b535d6ec766b2aee1?d=identicon&s=25 Szymon Nowak (g0nzo)
on 2006-03-04 20: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?
A025f68d8100c2f0fa78c6cfcc4cbfd1?d=identicon&s=25 James Mccarthy (noagenda)
on 2006-03-04 23: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...
858392acd1398aa6071fb1d44cc33842?d=identicon&s=25 John Smilanick (Guest)
on 2006-03-13 20: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 Smilanick
Computing Staff - Webmaster
Kavli Institute for Theoretical Physics
University of California, Santa Barbara
jsmilani@kitp.ucsb.edu
(805) 893-6307
308c16a466779961a4968b1b4830ec97?d=identicon&s=25 Eric Steiner (Guest)
on 2006-03-28 23: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 Smilanick 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 Smilanick
> Computing Staff - Webmaster
> Kavli Institute for Theoretical Physics
> University of California, Santa Barbara
> jsmilani@kitp.ucsb.edu
> (805) 893-6307
This topic is locked and can not be replied to.