Rails协会嵌套

时间:2013-10-23 20:03:25

标签: ruby-on-rails activerecord rails-models

我有三个由非rails应用程序创建的表。以下模型只是表格的关联。

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

我想要一种更简单的方法,按位置为客户列出所有程序。

我认为以下代码可以正常工作,但它会返回该位置的所有程序,这完全有意义。

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

我正在使用

@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

但这是针对MVC校长并且很难看。

我不确定如何优雅地编写此代码,并希望输入。

2 个答案:

答案 0 :(得分:0)

你可以这样做

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

答案 1 :(得分:0)

您可以使用includes方法来急切加载数据。此外,在这种情况下使用include将创建一个连接查询,该查询将仅获取与位置和客户端相关的那些程序。

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

虽然您应该避免在视图文件中使用数据库查询。因此,您可以将@locations = @client.locations.includes(:programs)移动到控制器操作中,并使用@locations来维护结构。