Home > Back-end >  How to store the result when iterating?
How to store the result when iterating?

Time:09-04

I am a Rails newbie so I don't have a clear idea on how to approach this problem.

I have an ActiveRecord::Associations::CollectionProxy object stored in @electives. Specifically, I have
@electives = @degree.electives

Degree and Elective are models with tables degrees and electives. I have defined a has_and_belongs_to_many association between Degree and Elective models.

Additionally, I also have a Course model with a corresponding courses table. I have also defined another has_and_belongs_to_many association between Course and Elective models.

In addition to the above listed tables, I also have degrees_electives and courses_electives join tables.

Now, I want to display on a page, a list of Electives in a Degree, and all the Courses associated to an Elective. So, I want something like:

- Software Engineering Elective A
    - COMP SCI 3008 Computer Networks & Applications
    - COMP SCI 1234 Object Oriented Programming
    - COMP SCI 4567 Algorithm Design & Data Structure Analysis

- Software Engineering Elective B
    - MATHS 1012 Mathematics IA
    - CIVIL 2000 Civil Engineering Introduction

- Software Engineering Elective C
    - COMP SCI 1012 Introduction to Programming

I am able to display the list:

- Software Engineering Elective A
- Software Engineering Elective B
- Software Engineering Elective C

But I don't know how to display the sub-list.

Currently, I have in my controller:

@degree = @student.degrees.first
@electives = @degree.electives

@degree contains a Degree object.

And, my view contains:

<ul>
<% @electives.each do |elective| %>
  <li>
    <%= elective.name %>
  </li>
<% end %>
</ul>

The webpage looks like this:

Screenshot of the webpage

I would like help with displaying the sub-list.

What I am stuck at is, how should I store the list and make it available to the view, when I call .courses on each element of @electives. For example, I could do:

@electives.each do |elective|
  @courses = elective.courses
end

But then, @courses will contain courses that correspond with the last element of @electives, if and when I use @courses in the view.

Is there like a vector data structure available in Ruby that I can push values to? I don't know how to do this. Any help will be very much appreciated. Thank you.

CodePudding user response:

You can iterate over courses that are associated with an elective in the same way as you already iterate over the courses with the only difference to do it nested within the other iteration:

<ul>
  <% @electives.each do |elective| %>
    <li><%= elective.name %>
      <ul>
        <% elective.courses.each do |course| %>
          <li><%= course.name %></li>
        <% end %>
      </ul>
    </li>
  <% end %>
</ul>

To avoid a N 1 queries problem I suggest eager loading all courses that are associated with the electives in one query by changing your controller to:

@degree = @student.degrees.first
@electives = @degree.electives.includes(:courses)

CodePudding user response:

You don't even need variable

<ul>
<% @electives.each do |elective| %>
    <li>
       <%= elective.name %>
       <ul>
          <% @elective.courses.each do |course|%>
            <li>
            <%= course.name %>
            </li>
        <% end %>
    </li>
<% end %>
</ul>

In controller you better include elective with course to have it initialized, to not have n*m calls to database

@electives = Elective.includes(:courses)
  • Related