Skip to content

Nested module form in rails3

22/03/2011

Today i learn Nested module in rails using Javascript and Ajax. here i share what i created .

This is the tour program form for  MSR to visit Doctors.

first create the rails application adapted by mysql and set its user and password in database.yml file.

here i used three modules by crating scaffold.

create Tourplane scaffold with necessary fields.


rails g scaffold Tourplane name:string form:date to:date

create Hospital scaffold with necessary fields.


rails g scaffold Hospital tourplane:references name:string location:string

create Doctors scaffold with necessary fields.


rails g scaffold Doctors hospital:references name:string phone:integer

then set the relationship of those modules.

Tourplan has many hospital to visit so enable the nested modules.


class Tourplane < ActiveRecord::Base
 has_many :hospitals
 accepts_nested_attributes_for :hospitals
end

Hospital has many doctors so need nested module to add and also hospital belongs to Tourplane


class Hospital < ActiveRecord::Base
 belongs_to :tourplane
 has_many :doctors
 accepts_nested_attributes_for :doctors
end

Doctors only belongs to Hospitals.

class Doctor < ActiveRecord::Base
 belongs_to :hospital
end

All relations are set now can create database and crate table

rake db:create
rake db:migrate

now start the server open the Tourplanes in server it shows like.


To set nested module we need ajax server call so include the jquery library.
download the unzip file from http://jquery.com and include file in /javascript/jquery.js
it is the library for jquery method.
To active jquery file set the link in application.erb. and also i write my script in mtscript file

<%= javascript_include_tag 'jquery','myscript' %>

now set the Hospital link in Tourplanes/new  and while click this link catch the hospital/new include in this page for that we use helper method to set link.

Write the method to set the link in tourplane_helper.rb


module TourplanesHelper
 def add_hospital_link(name)
 link_to name, '#', :class => "add_hospital"
 end
end

class name set for this for catch this method in jquery.

Then call the method from tourplane/_form.html.erb


<div>
 <%= add_hospital_link("Add Hospital") %>
 </div>

Now check it will set the link like


Then catch the method in jquery and call the ajax call to server


$(document).ready(function(){
 $('.add_hospital').click(function(){
 alert('it works');
 $.ajax({
 method:"POST",
 url:'/tourplanes/add_hospitals',
 data:"",
 });
 });
});

It call the url link to routes now we match the link and set the routes in /config/routes.rb


Tourplanner::Application.routes.draw do
 resources :doctors
 resources :hospitals
 match 'tourplanes/add_hospitals' => 'tourplanes#add_hospitals'
 resources :tourplanesend

Then it call to<strong> /app/controllers/tourplanes_controller.rb </strong>file method name <strong>add_hospitals. </strong>create the method set the partial and create the hospital object pass to that partial file. like<strong>
</strong>


def add_hospitals
 render :partial => 'hospital', :locals => {:hospital_object => Hospital.new}
 end

Then render the hospital field here. For that we have to create partial file in /views/tourplanes/_hospital.html.erb . and include like.


<div>
 <%= fields_for "tourplane[new_hospital_attributes[]]",hospital_object do |hospital| %>  # new_hospital_attributes is a method call tourplane.rb to insert multi record into hospital table from the tourplane
 <%= "Hospital Name" %>
 <%= hospital.text_field :name %>
 <% end %>
</div>

Now the server create the new file in hospital. catch the data and pass to the view. to catch the passed data in view create the empty div tag in /view/tourplanes/_form.html.erb


<div class="result_hospital">

 </div>

Catch the passed data by ajax success method and pass to view by using that class name. in myscript add like this

$(document).ready(function(){
 $('.add_hospital').click(function(){
 alert('it works');
 $.ajax({
 method:"POST",
 url:'/tourplanes/add_hospitals',
 data:"",
 success:function(data){
 //$('.hospital_result').html(data);
 $(data).appendTo('.hospital_result');
 }
 });
 });
});

now run the application and click the hospital it will add the text box for hospital like this

Then, to store the hospital value in hospitals table create the method to build multi record in /app/models/tourplane.rb

class Tourplane < ActiveRecord::Base
 has_many :hospitals
 accepts_nested_attributes_for :hospitals
 def new_hospital_attributes=attributes
 attributes.each do |record|
 hospitals.build(record)
 end
 end
end

now run the application and add multi hospitals and create like

see your server it show like

now the both toueplane and hospital record saved successfully in database.

but in show method shows tourplane values only.

To show hospital values set in _form.html.erb file as


<p>
Hospital
<ol>
 <% for hospital in @tourplane.hospitals %>
 <li> <%= hospital.name %></li>
 <% end %>
 <ol>
 </p>

now show displays the hospital values.like this


Advertisements

From → Rails

2 Comments
  1. I wrote an article for an ajaxed nested form implementation in rails 3… it could be interesting…
    http://www.dynamick.it/rails-3-ajaxed-nested-form-4721.html

  2. In the routes file example the word end is not in the line it should be.

    in the div example it’s written:

    while in the js it says:
    $(data).appendTo(‘.hospital_result’)

    Appart from that I’ve followed the whole example, and I keep getting the same error when saving:
    “Hospitals tourplane can’t be blank” (with my equivalent controller names). This happens because in my equivalent hospitals model I force the reference id not to be blank, I expected rails to take care of that. If I remove the validation, it works fine and the id is there.

    I’ve given up for today on making it work forcing the id validation in my hospitals equivalent model, hope to make it work some day.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: