how to render nested collection in erb file - ruby on rails

I am stuck since two days...

My problem is: i cant print nested collection object's values at .erb

Let me explain my case:

  • I have student class and subject class.
  • One student has many subjects.

Use Case: I have a search page from which i can search (e.g: by name) students' information.

Output: List of students. ( And every student has a list of subjects)

Problem: ON view part, at .erb file:- i can print name of the students but cant print name of the subjects.

Here it is the snippet of my files...

Model Classes:

class student < ActiveRecord::Base

    has_many :subjects, :class_name=>"subject"

    attr_accessible :first_name, :middle_name, :last_name, 

    self.table_name="students"
    set_primary_key :id

    blahblah
end

class subject < ActiveRecord::Base

    belongs_to :student, :foreign_key=>'student_id'

    attr_accessible :student_id, :name

    self.table_name="subjects"

    blahblah
end

Controller class:

class StudentController < ApplicationController

    require "student.rb"

    def populate
        @pos=0

        filter_query = ''
        if !params[:firstName].blank?
            filter_query +=" first_name='" + params[:firstName].to_s + "' and"
        end

        if filter_query !=''
            filter_query= filter_query[0..filter_query.length-4]
            @stuData= Student.find(:all, :conditions=>filter_query)
        end

    end

populate.html.erb

div class="header">
    <div class="heading" style="float:left;width:900px;">    
        <% form_tag(:controller=>"student", :action=>"populate") do %>
            <table>
                <tr>
                    <td width="10"> <label> First Name:</label> </td>
                    <td width="40"> <%= text_field_tag('firstName') %> </td>
                </tr>
            </table>

            <input name="submitFormName" class="form_submit" type="submit" value="Search" />

        <% end %>

        <div height="10">&nbsp;</div>

    </div> 
</div>

<div class="students" style="float:left;width:1330px;">

    <% if !@stuData.blank? %>
        size = <%= @stuData.size %>
        <% if !@stuData.nil? %>
            <%= render :partial=>'populate' , :locals=>{:stuData => @stuData} %>
        <% end %>
    <% else %>
        <div>Not found...</div>
    <% end %>
</div>

_populate.html.erb

<div style="overflow-y:auto;overflow-x:scroll;">              
    <table >
      <thead>
        <th>Id</th>
        <th>First Name</th>
        <th>Middle Name </th>
        <th>Last Name</th>
        <th>Subject Name</th>
      </thead>    
      <% stuData.each do |item| %>
      <tr>
        <td id="studentId"> <%= item.id %> </td>
        <td id="firstNameId"> <%= item.promotion_code %> </td>
        <td id="middleNameId"> &nbsp; </td>
        <td id="lastNameId"> &nbsp; </td>
        <td id="cityId">
          <% @var1 = item.Subject %>
          <% if @var1.nil? %>
            <% @var1.each do |pc| %>
              <%= pc.name %>
            <% end %>
          <% end %>
        </td>
      </tr>
    <% end %>
  </table>
</div>

I do not know how to "render page" when response contain "collection" where "every object of the collections" contain another "collection"

Response: List of students Collection: student Every student object: contains collection (list of subjects)

Someone pls help.......

EDIT

i have tried following ways for rendering collection... but can not get success.

 - <%= render :partial=>'populate' , :locals=>{:stuData =>
   @stuData} %> 

 - <%= render :partial=>'populate' , :collection=>
   @stuData.subjects %>

 - <% render :partial=>'populate' , :collection=>
   @stuData.subjects %>

 - <%= render @stuData %>

 - <%= render :partial=>"populate", :collection=>@stuData,
   :as=>:item %>

EDIT 2nd time

As problem is not solved by below answers.... i have crossed check with database and console... and it looks OK.

@student = Student.find(144)
=> #<Student id: 4, first_name: "ABC", middle_name: "DEF", last_name: "GHI">
>> 
?> @isNullCheck = @student.Subject.nil?
=> false
>> 
?> @subList = @student.Subject
=> [#<Subject id: 5, student_id: 4, name: "Maths">, #<Subject id: 6, student_id: 4, name: "English"> ]
>> 
?> @StuSub1 = @student.Subject[0]
=> #<Subject id: 5, student_id: 4, name: "Maths">
>> 
?> @StuSub2 = @student.Subject[1]
=> #<Subject id: 6, student_id: 4, name: "English">
==
?> @StuSub3 = @student.Subject[2]
=> nil
>> 
>> @StuSubValue1 = @student.Subject[0].value
=> Maths
>> 
>> @StuSubValue2 = @student.Subject[0].value
=> English
>> 

EDIT 3rd time...

at least can anyone help me in how to render the page in erb... when response has Array of objects in which every object itself contains another collection. (here, Array of students. And every student contains array of subjects.)

Anyone???

Answers


You should be able to do something like this

stuData.each do |stud|
 stud.name
 bla bla bla...

 stud.subjects.each do |sub|
   sub.name
 end
end

instead of this, where you're not using the association you defined in your model

var1 = item.Subject
var1.each ....

EDIT: as you're saying the problem is the collection you're passing to your partial. As @Rich Peck is suggesting you, you should pass something like:

<%unless @stuData.nil? %>
  <%= render :partial=>'populate', :stuData => @stuData %>
<%end%>

Models

  1. Need to be CamelCase -- Class Student < ActiveRecord::Base
  2. Need to be simplified:
class Student < ActiveRecord::Base
    has_many :subjects, :class_name=>"subject"
    attr_accessible :first_name, :middle_name, :last_name, 
end

class Subject < ActiveRecord::Base
    belongs_to :student
    attr_accessible :student_id, :name
end

In your data tables, you should have the following schemas:

students
id | first_name | middle_name | last_name | created_at | updated_at

subjects
id | student_id | name | etc | created_at | updated_at

Views

This will allow you to show this:

@stuData = Student.all

<%= render partial: "populate", collection: @stuData, as: :stuData %>

#_populate.html.erb
<% stuData.each do |student| %>
    <%= "#{student.first_name} #{student.last_name}" %>

    <% student.subjects.each do |subject| %>
        <%= subject.name %>
    <% end %>
<% end %>

Refactoring

Your code could do with some refactoring:

   <% unless @stuData.blank? %>
        <%= "size = #{@stuData.size}" %>
        <%= render :partial=>'populate' , :locals=>{:stuData => @stuData} unless @stuData.nil? %>
    <% else %>
        <div>Not found...</div>
    <% end %>

Update

I think your problem lies in your controller action:

 def populate

     unless params[:firstName].blank?
         filter_query +=" first_name='" + params[:firstName].to_s + "' and"
         filter_query= filter_query[0..filter_query.length-4]

         @stuData = Student.where(first_name: filter_query) unless filter_query.blank?
         #only sets @stuData if filter_query is present. It's likely that filter_query is not present for you
     end

 end

Need Your Help

jersey restful webservice tomcat version

tomcat java jersey

I want to write a simple restful webservice. As it would be as simple as accessing data from / to the database, I am planning to use tomcat &amp; not any heavy application server. I have existing t...

Create Multiple Instances of a Form (and keep them there) in C#

c#

I'm very new to C#, and I'm trying to create a Windows Form Application that would create multiple instances of the same form and keep them in existence, and end them all on a certain keypress. Rig...