如何以编程方式访问ActiveRecord

时间:2011-10-17 21:30:31

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

我有一个Rails 3 ActiveRecord属于两个不同的ActiveRecords。实施例

class Animal < ActiveRecord::Base
   belongs_to: species
   belongs_to: zoo
...
end

其中animals表包含species_id,zoo_id,name和description以及具有scientific_name和zoo的表种类具有地址。

在控制器中,我有一个查询

 @animals = Animal.includes(:species, :zoo).order(:name)

以及我希望在视图中显示的列列表

 @columns = ["name", "description", "species.scientific_name", "zoo.address"]

在视图中,我希望创建一个由列名列表驱动的HTML表,例如

<table>
  <tbody>
    <tr>
    <% @animals.each do |animal| %>
      <% %columns.each do |col| } %>
        <td><%= animal[</td>
      <% end %>
    <% end %>
    </tr>
  </tbody>
</table>

这适用于动物的名称和描述,但不适用于species.scientific_name和zoo.address。

我知道我可以特殊情况下循环并直接访问包含的类,如animal.species ['scientific_name'],但我希望有一种方法可以按名称访问包含的类。类似动物['species'] ['scientific_name']

1 个答案:

答案 0 :(得分:2)

方法1

Monkey修补ActiveRecord类。有关猴子修补AR类的详细信息,请参阅此answer

class ActiveRecord::Base
  def read_nested(attrs)
    attrs.split(".").reduce(self, &:send)
  end
end

示例嵌套属性访问:

animal.read_nested("zoos.address")
user.read_nested("contacts.first.credit_cards.first.name")
product.read_nested("industry.category.name")

对于您的用例:

控制器:

@columns = %w(name color zoo.address species.scientific_name)

查看

<% @animals.each do |animal| %>
  <% @columns.each do |col| } %>
    <td><%= animal.read_nested(col)%></td>
  <% end %>
<% end %>

方法2

添加select子句以选择列并为其设置别名。

@animals = Animal.includes(:species, :zoo).select("
    animals.*, 
    species.scientific_name AS scientific_name,
    zoos.address AS zoo_address").
  order(:name)

现在,在您看来,您可以像常规模型属性一样访问scientific_namezoo_address等属性。

相关问题