【问题标题】:Rails ActiveRecord - querying on last record of relationshipRails ActiveRecord - 查询关系的最后一条记录
【发布时间】:2015-08-04 10:51:42
【问题描述】:

我有一个模型 BookState 具有 has_many 关系。

class Book < ActiveRecord::Base
   has_many :states
   ...
end

State 通过name 属性将图书的可见性设置为“私人”、“受限”或“公共”。出于审核目的,我们会记录所有状态更改,以便获取我使用的图书的当前状态

> book = Book.first
> book.states.last.name
> "public"

现在我需要查询当前状态为公开的所有Book 对象。

类似的东西:

Book.joins(:visibility_states).where(states: { state: "public"})

问题是上面的查询返回了所有当前公开的书籍,或者过去已经公开的书籍。我只希望它返回当前“公开”的书籍(即 book.states.last.name == “public”)。

我知道我可以用 select 做到这一点,但这会为每条记录生成一个查询:

Book.all.select { |b| b.states.last.name == "public" }

有没有办法只使用 ActiveRecord 来做到这一点?

【问题讨论】:

  • 您想要 states.name == 'public' 的所有书籍?
  • Book.joins(:states).where("states.name = 'public'").group("books.id")
  • 我怀疑你需要一个 has_many :states 通过关联。否则,您将拥有多余的“公共”、“私人”和“受限”状态项。

标签: ruby-on-rails ruby postgresql ruby-on-rails-4 activerecord


【解决方案1】:

您可以使用窗口功能:

Book.joins(:visibility_states)
    .where(states: { state: "public"})
    .where("visibility_states.id = FIRST_VALUE(visibility_states.id)
            OVER(PARTITION BY books.id ORDER BY visibility_states.created_at DESC))")

或者在您的情况下,最好将当前状态保存在 Book 模型中

【讨论】:

  • 谢谢。我还没有想过将 current_state 添加到 Book 模型中,这会让事情变得简单很多。
【解决方案2】:

我会做一些性能更好的事情。

如果要保存历史状态变化,可以吗。但请尽量避免因此给您的应用程序带来更多复杂性。

为什么不在 Book 模型中添加 current_state 属性?

它将更快,更容易开发。

class Book < ActiveRecord::Base

  def set_new_current_state!(new_state)
     self.current_state = new_state # e.g State.public
     self.stats << State.create(new_state)
  end
end

您的查询将是这样的:

Book.where(current_state: 'public') 

【讨论】:

  • 谢谢。我还没有想过将 current_state 添加到 Book 模型中,这会让事情变得简单很多。
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
相关资源
最近更新 更多