2012-12-18 40 views
1

我有两个不同的模型,1:N关系。 让它们命名为“为MyObject”和“关系”ActiveRecord范围:关于选择关系的奇怪行为

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命令“Myobject.includes(:相关)。选择......(在适用范围定义)按预期工作
  • 呼叫至范围‘Myobject.without_related’仍返回已在此期间已分配的对象

看起来这可以通过重新启动导航控制台或重新启动Webrick来解决。 但我不能总是重新启动一个web应用程序,因为对象之间的关系已被改变;)

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

PS:我需要这个查询的范围在MYOBJECT模型

回答

0

我会建议你使用counter_cache这种形式传递它的名字作为group_method到grouped_select,你需要添加列* related_count * int类型为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 

之后,你将拥有超快速的余地越来越所有对象没有相关的记录和,一个计数对象以及

+0

就忘了这个轨道功能。有时候简单是最好的;) –

3

你的问题其实你的范围不是范围:)

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

虽然你期望它可以工作,如果你把它包在拉姆达

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 

或使用计数器缓存,如其他答案中的建议。

0

或者,如果你知道应该出现在相关表的列名,使用这样的定义:

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