Question

I have three tables that are created by a non rails application. The following models are just the associations for the tables.

class Client < ActiveRecord::Base
  has_many :programs
  has_many :locations, :through => :programs
end

class Program < ActiveRecord::Base
  belongs_to :location
  belongs_to :client
end

class Location < ActiveRecord::Base
  has_many :programs
  has_many :clients, :through => :programs
end

I would like a simpler way to list out all the programs by location for a client.

I thought the following code would work, but it returns all programs for that location, and that completely makes sense.

@client.locations.each do |location|
  <h2>location.name</h2>
  <ul>
   location.programs.each do |program|
   <li>program.name</li>
  end
  </ul>
end

I'm currently using

@client.locations.each do |location|
      <h2>location.name</h2>
      <ul>
       Program.where(:location_id => location.id, :client_id => @client.id).each do |program|
       <li>program.name</li>
      end
      </ul>
    end

But this is against MVC principals and is ugly.

I'm not sure how to write this code elegantly, and would appreciate input.

Was it helpful?

Solution

You can use includes method for eager loading the data. Also, using include for this situation will create a join query that will fetch only those programs which are related to both location and client.

@client.locations.includes(:programs).each do |location|
  <h2>location.name</h2>
  <ul>
    location.programs.each do |program|
      <li>program.name</li>
    end
  </ul>
end

Though you should avoid using database queries in view files. So you can move @locations = @client.locations.includes(:programs) to your controller action and use @locations in view to maintain the structure.

OTHER TIPS

You can do this

@client.programs.each do |program|
  <h2>program.location.name</h2>
  <ul>
      <li>program.name</li>
    end
  </ul>
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top