具有多态模型的 Rails 范围

Posted

技术标签:

【中文标题】具有多态模型的 Rails 范围【英文标题】:Rails scope with polymorphic model 【发布时间】:2015-01-20 20:08:25 【问题描述】:

我从具有多态关系的模型的非常基本的范围中得到了一些奇怪的结果。这是关系的简要摘要和详细信息。

models/financials.rb

class Financial < ActiveRecord::Base    
  belongs_to :financiable, :polymorphic => true
  #ltm is a boolean field in the model
  scope :ltm,  ->  where(ltm: true).last 

还有一个包含许多财务数据的基本公司模型

models/firm.rb

class Firm < ActiveRecord::Base
  has_many :financials, :as => :financiable, dependent: :destroy

所以当 firm 没有 ltm 财务(即没有 ltm: true 的财务)时,我得到了一个奇怪的结果。但是当我打电话给firm.financials.ltm 时,我得到了属于该公司但没有 ltm: true 的财务数据的 activerecord 关系。但是,当我只做firm.financials.where(ltm: true).last 时,我得到nil

公司没有 ltm 财务时的结果摘要:

firm.financials.ltm #AR relation of financials that belong to the firm but are not ltm
firm.financials.where(ltm: true).last #nil

更奇怪的是,当一家公司确实拥有 ltm 财务时,范围会按预期工作。

以前有没有人遇到过这个问题或有任何想法?我的意思是简单的答案是不使用范围,但我想了解可能导致这种情况的原因。

---基于评论的更新--- 谢谢你们在这件事上花了很多心思。

    D 方面你是对的。代码是 firm.financials.ltm 而不是 firm.financials.ltm.last。当我输入问题时,这是一个错字。我更新了上面的内容以反映,下面还有 SQL 查询。 Jiří Pospíšil - 很棒的建议。我将在我的应用程序中进行更新,但在此处保持不变,以免造成混乱。 楚马科夫。如果用户没有通过 before_save 调用输入 true,我会强制 ltm 为 false,所以我认为不是这样,但感谢您的想法。

所以这些来自 firm 没有任何 financials 且 ltm = true 的场景。如您所见,范围请求正在对数据库进行第二次查询,以查找属于公司的所有财务数据。为什么在初始查询中找不到它时会这样做?

公司.financials.ltm

财务负载 (4.6 毫秒) SELECT "financials".* FROM "financials" WHERE "财务"."financiable_id" = $1 AND "财务"."financiable_type" = $2 AND "财务"."ltm" = 't' ORDER BY "financials"."id" DESC LIMIT 1 [["financiable_id", 11], ["financiable_type", "公司"]] 财务负载 (1.2ms) SELECT "financials".* FROM "financials" WHERE "财务"."financiable_id"= $1 AND "财务"."financiable_type" = $2 [["financiable_id", 11], ["financiable_type", "Firm"]]

firm.financials.where(ltm: true).last

财务负载 (16.8 毫秒) SELECT "financials".* FROM "financials" WHERE "财务"."financiable_id" = $1 AND "财务"."financiable_type" = $2 AND "财务"."ltm" = 't' ORDER BY "financials"."id" DESC LIMIT 1 [["financiable_id", 11], ["financiable_type", "公司"]]

【问题讨论】:

生成的 SQL 查询会很有帮助。 ...等等,你真的有.last 完成你的范围吗?这根本不适用于下面的代码。请检查问题并更正代码。 可能与问题无关,但我强烈建议不要对范围使用与属性本身相同的名称。使用with_ltm 之类的名称甚至可能会更好地阅读范围。 可能问题的原因可能是 DB 中有 ltm=nil 值。如果是这样,请确保 ltm 具有 true 或 false 值。 谢谢大家。我在阅读您的 cmets 后更新了问题。 【参考方案1】:

您的作用域无法正常工作,.last 在您的作用域中得到一个结果而不是 ActiveRecord 关系,删除 .last 并且作用域将正常工作以获取所有 Financialsltm=true

【讨论】:

以上是关于具有多态模型的 Rails 范围的主要内容,如果未能解决你的问题,请参考以下文章

Rails 查询关联的模型范围

Rails 5 + Shrine + 多态模型 + 漂亮的位置

如何为具有范围批量分配的 Rails 3.1 应用程序播种

如何在整个 Rails 活动记录关联链中取消特定模型的默认范围?

Rails:使用范围来显示模型的不同子集以及如何以较少 DRY 的方式构建它?

在 Rails 范围内获取动态表别名