在我的应用中,Team
belongs_to :hunt
。确认Hunt
后,所有关联的团队都准备就绪。
这是我team.rb
文件中的一个示例,我使用ready?
方法检查team.hunt
是否已确认。
#team.rb
def ready?
hunt.confirmed? ? true : false
end
我希望在team.rb
文件中设置一个范围,以便我可以致电Teams.all.ready.count
来显示准备就绪的团队数量。
如何编写方法或范围来实现上述行为,而无需向数据库添加任何内容或迭代数组等?
答案 0 :(得分:5)
感谢@ TomLord的洞察力,你宁愿做下面的解决方案1而不是解决方案2.此外,添加示例SQL以显示比较。
class Team < ApplicationRecord
belongs_to :hunt
scope :ready, -> { joins(:hunt).where(hunts: { confirmed: true }) }
end
用法:的
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]]
class Team < ApplicationRecord
belongs_to :hunt
end
class Hunt < ApplicationRecord
scope :confirmed, -> { where(confirmed: true) }
end
用法:的
# 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]]
答案 1 :(得分:1)
解决方案:如果Hunts#confirmed
是数据库列:
class Team < ApplicationRecord
belongs_to :hunt
scope :ready, -> { joins(:hunt).where(hunts: { confirmed: true }) }
end
在这种情况下,Team.ready
将返回ActiveRecord::Relation
。
解决方案:如果Hunts#confirmed?
不是数据库列:
class Team < ApplicationRecord
belongs_to :hunt
scope :ready, -> { includes(:hunts).select(&:ready?) }
end
在这种情况下,Team.ready
将返回Array
您需要知道第二个解决方案是循环遍历每个调用ready?
的团队记录,而第一个解决方案正在执行数据库查询。首先是效率更高。