【问题标题】:How to access ActiveRecord includes programmatically如何访问 ActiveRecord 包括以编程方式
【发布时间】:2011-10-19 15:35:24
【问题描述】:

我有一个 Rails 3 ActiveRecord,它属于两个不同的 ActiveRecord。示例

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

其中动物表包含一个species_id、zoo_id、name 和description,表species 有一个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']

【问题讨论】:

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


    【解决方案1】:

    方法 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 等属性。

    【讨论】:

    • 不像我希望的那样灵活。相反,我对一些关键列进行了非规范化。
    • @SteveWilhelm 我添加了一种通用方法。看看吧。
    猜你喜欢
    • 2015-09-03
    • 2020-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多