ActiveRecord Scope:选择关系时的奇怪行为

时间:2012-12-18 17:28:05

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

我有两种不同的模型,它们具有1:N的关系。 让我们将它们命名为myobject'和'相关'

class Myobject < ActiveRecord::Base
  has_many :related
  scope :without_related, includes(:related).select{ |o| o.related.size == 0 }
end
class Related < ActiveRecord::Base
end

只要我没有从Myobjects创建新的作业到相关内容,定义的范围似乎很有效:

  • 直接导轨c命令&#34; Myobject.includes(:related).select ...(在Scope中定义)按预期工作
  • 调用范围&#34; Myobject.without_related&#34;仍然返回在此期间已分配的对象

似乎可以通过重新启动rails控制台或重新启动Webrick来解决此问题。 但我不能只重新启动web应用程序,因为对象之间的关系已经改变;)

有没有办法解决这个问题或以更好的方式编写范围?

PS:我需要将此查询作为范围,以my_ject模型的形式将其名称作为group_method传递给grouped_select

3 个答案:

答案 0 :(得分:3)

您的问题实际上是您的范围不是范围:)

范围必须返回关系,但范围会返回数组。

虽然它可以像你期望的那样工作,如果你用lambda包装它

 scope :without_related, lambda{ includes(:related).select{ |o| o.related.size == 0 } }

但我建议将此代码重写为通常的类方法,以免误导那些将来使用此代码的人

def self.without_related
  includes(:related).select{ |o| o.related.size == 0 }
end

或使用计数器缓存,如其他答案中所述。

答案 1 :(得分:0)

我建议您使用counter_cache,您需要将类型为int的column * related_count *添加到Myobject,进行迁移,然后您就可以这样做了:

class Myobject < ActiveRecord::Base
  has_many :related
  scope :without_related, where(related_count: 0)
end

class Related < ActiveRecord::Base
  belongs_to :myobject, counter_cache: true
end

之后,您将获得超快的范围,以获取所有没有相关记录的对象以及该对象的计数

答案 2 :(得分:0)

或者,如果您知道相关表中应存在的列名,请使用以下定义:

class Myobject < ActiveRecord::Base
  has_many :related
  scope :without_related, includes(:related).where('related.id', true)
end