【问题标题】:Fetching the top-x items from a related object从相关对象中获取前 x 个项目
【发布时间】:2013-01-16 13:04:05
【问题描述】:

我有一个Camping,其中有一个Author。一个Author 有很多Campings

获得“前 5 名”(定义为“最后 5 次露营”)是通过以下方式完成的:

@author.campings.order(:created_at).limit(5)

但是如果将“前 5 名”移动到露营模型中,我希望这个概念,这对我来说似乎更清晰;毕竟,Camping 是唯一知道top 是什么的人。

有点像

@author.campings.top

但是如何在Camping 上定义这个? @author.campings 不是 Camping,而是 ActiveRecord::Relation。因此,models/camping.rb 中的以下内容不起作用:

# Scope for "top" campings
def top(amount)
  self.order("created_at").limit(amount)
end

用作

@author.top(5)

目前,我只需要通过关系 @author 在上述示例中的这个“顶级”事物。目前,“顶级”的定义只是“最近 5 次露营”,但在下一次迭代中,这将根据 Camping 上的观看次数、评级或其他参数和字段的数量而变得更加复杂。这让我相信Camping 是定义“top”的正确位置,而不是Author

我可以将其添加到Author,但我的知识有限,这感觉像是违反了隔离模式;作者突然需要了解 Camping 上的字段:

# Last 5 campings for this author
def top_campings(amount)
  campings.order("created_at").limit(amount)
end

用作

@author.top_campings(5)

这种关系通常是如何解决的?

【问题讨论】:

  • 我认为你的最后一个例子很好。它不违反任何东西,只是做它应该做的。
  • 我把这些例子命名错了。对困惑感到抱歉。最新的编辑解决了这个问题。我想更清楚地指出@author.top_campings 将有关“露营”的知识引入“作者”。我现在澄清了。

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


【解决方案1】:

在 Rails 3 中,您可以使用 scopes with arguments:

class Camping < ActiveRecord::Base
  scope :top, lambda { |amount| order("created_at").limit(amount) }
end

(和Camping添加一个类方法一样,我想这两种方法都可以,所以你可以选择你喜欢的)

您可以按如下方式使用范围:

@author.campings.top(5)

【讨论】:

  • 我更喜欢类方法而不是带有 lambdas 的作用域,但这也是一种有效的方法
  • 再次阅读官方 Rails 指南,我发现我的问题已经得到解答:$。他们用 lambda 向作用域解释这一点,然后解释为什么这不是一个好主意以及类方法是要走的路。不过,两种选择都很好;谢谢。
【解决方案2】:

您可能希望这样在 Camping 类中定义 top

class Camping < ActiveRecord::Base
  def self.top(count)
    order(:created_at).limit(count)
  end
end

当定义为类方法时,可以通过ActiveRecord::Relation获得,所以可以调用@author.campings.top(5)

【讨论】:

  • 我错过了“self”类方法。将 self 从 return 移到方法定义中解决了我的问题。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 2014-11-05
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多