Ruby on Rails API:计算属性模式最佳实践

Ruby on Rails API: computed attribute pattern best practice

当我需要一个需要调用数据库的计算属性时,我想知道最佳实践。

如果我有一个包含许多 ChildParent,我将如何在 ParentController#index 中呈现 children_count 属性,因为我不想呈现子项,只是伯爵?最好的方法是什么?

谢谢!

型号:

class Parent < ApplicationRecord
  has_many :children

  def children_count
    children.count # Wouldn't it ask the database when I call this method?
  end
end

控制器:

class ParentsController < ApplicationController
  def index
    parents = Parent.all

    render json: parents, only: %i[attr1, attr2] # How do I pass children_count?
  end
end

children.count会调用数据库,是的;但是,它将作为 SQL 计数:

SELECT COUNT(*) FROM "children" WHERE "children"."parent_id" = 

它实际上并没有加载所有的子记录。一种更有效的方法是针对这种特定情况使用 Rails counter_cache:https://guides.rubyonrails.org/association_basics.html#options-for-belongs-to-counter-cache

在这种情况下避免额外数据库查询的 Rails 方法是实施 counter cache.

这样做改变

belongs_to :parent

child.rb

belongs_to :parent, counter_cache: true

并将名为 children_count 的整数列添加到您的 parents 数据库 table。当您的数据库中已有记录时,您应该 运行 类似于

Parent.ids.each { |id| Parent.reset_counters(id) }

用正确数量的现有记录填充 children_count(例如在您添加新列的迁移中)。

完成这些准备工作后,Rails 将在您添加或删除子项时自动增加和减少计数。

因为 children_count 数据库列的处理方式与所有其他属性一样,您必须从 Parent class 中删除自定义 children_count 方法,并且仍然可以简单地调用

<%= parent.children_count %> 

在您看来。或者您可以将其添加到您想要 return 的属性列表中,如 JSON:

render json: parents, only: %i[attr1 attr2 children_count]