将'where'子句与方法结合使用

Mik*_*ord 0 ruby scope ruby-on-rails

在我的应用程序中,a Team belongs_to :hunt.一旦Hunt确认,所有相关团队都准备好了.

这是我的team.rb文件中的一个示例,我使用该方法ready?检查是否team.hunt已确认.

#team.rb

def ready?
  hunt.confirmed? ? true : false
end
Run Code Online (Sandbox Code Playgroud)

我希望在team.rb档案中有一个范围,所以我可以打电话Teams.all.ready.count来显示准备好的团队数量.

如何在不向我的数据库添加任何内容或迭代数组等的情况下编写方法或范围来实现上述行为?

Jay*_*rio 5

更新:

感谢@ TomLord的洞察力,你宁愿做下面的解决方案1而不是解决方案2.此外,添加示例SQL以显示比较.

解决方案1

class Team < ApplicationRecord
  belongs_to :hunt
  scope :ready, -> { joins(:hunt).where(hunts: { confirmed: true }) }
end
Run Code Online (Sandbox Code Playgroud)

用法:

Team.ready # or: Team.all.ready
# SELECT  "teams".* FROM "teams" INNER JOIN "hunts" ON "hunts"."id" = "teams"."hunt_id" WHERE "hunts"."confirmed" = ? LIMIT ?  [["confirmed", "t"], ["LIMIT", 11]]
Run Code Online (Sandbox Code Playgroud)

或者,解决方案2

class Team < ApplicationRecord
  belongs_to :hunt
end

class Hunt < ApplicationRecord
  scope :confirmed, -> { where(confirmed: true) }
end
Run Code Online (Sandbox Code Playgroud)

用法:

# you can also move the logic below as a method/scope inside `Team` model (i.e. as `ready` method/scope)

# Example 1 (using JOINS):
Team.joins(:hunt).where(hunts: { id: Hunt.confirmed })
# SELECT  "teams".* FROM "teams" INNER JOIN "hunts" ON "hunts"."id" = "teams"."hunt_id" WHERE "hunts"."id" IN (SELECT "hunts"."id" FROM "hunts" WHERE "hunts"."confirmed" = ?) LIMIT ?  [["confirmed", "t"], ["LIMIT", 11]]

# Example 2 (same as Example 1 above but faster and more efficient):
Team.where(hunt_id: Hunt.confirmed)
# SELECT  "teams".* FROM "teams" WHERE "teams"."hunt_id" IN (SELECT "hunts"."id" FROM "hunts" WHERE "hunts"."confirmed" = ?) LIMIT ?  [["confirmed", "t"], ["LIMIT", 11]]
Run Code Online (Sandbox Code Playgroud)