2011-03-26 150 views
1

嗨,我有以下范围:轨道范围过滤

scope :expires_within, lambda 
{|time| where("created_at BETWEEN ? AND ?", 30.days.ago, 
                 time.from_now - 30.days)} 

它并不那么重要,它的工作原理。

这只是给了我所有这些都在一定时间范围内创建我的数据库中的对象。我想要做的是过滤这个范围,以便它删除一些对象。

以上范围是在一个名为模型。我有一个名为锁定另一个模型,“属于”一邮政,每个有许多。所以这意味着每个锁上都有一个外键,其中有相应的Post的ID。

我想完成的是以下内容:我想过滤掉上述范围内的帖子,其中不是有任何锁定。所以从抽象/高级视图:我想要得到的职位从上述范围返回和删除任何具有任何相关的锁(哪怕只有一个)。

这可能吗?我将不得不使用某种形式的复合查询的,使用类似except?我会很感激任何帮助。

我现在有一些作品,但我有一种挥之不去的感觉,是不是很有效的,也许它可以在数据库上通过修改上述范围内进行,并更高效:

Post.expires_within(1.day) - Lock.all.collect { |lock| lock.post } 

所以这基本上得到岗位的集合,然后取每个锁的帖子,并将其所有转储到一个数组,然后将其从原来的一套岗位减去。

回答

3

有人谁已经经历过这个问题,是一种足以帮助我在IRC(雷达),并指出我this answer。现在我的新范围如下:

scope :not_locked, lambda { joins("LEFT JOIN locks on 
    (posts.id = locks.post_id)").where("locks.post_id IS NULL") } 
scope :expires_within, lambda {|time| where("posts.created_at BETWEEN ? AND ?", 
    30.days.ago, time.from_now - 30.days).not_locked } 

它的工作得很好。希望能帮助其他人解决同样的问题。

0

你应该使用子查询,像这样做...

scope :without_locks, :conditions => "not exists(select * from locks where posts.id = locks.post_id)" 
1

带滑动ActiveRelation,基于字符串的LEFT JOIN s为不可避免的;然而,使用Ruby类别Range可以大大简化BETWEEN的计算:

scope :expires_within, lambda { |time| 
    where(:created_at => 30.days.ago..(time.from_now - 30.days)) }