2010-01-25 26 views
1

我创建了一个应用程序,它可以根据传递给它的多个服务来查找服务提供者。这是通过具有many_through完成的,所以有一个连接对象。基本上,如果用户要求提供服务A和服务B的服务提供商,我的范围会返回提供服务A和服务B的服务提供商或提供服务A或服务B的其他服务提供商。取而代之,我们希望只限于提供两种服务的提供者。如何在Rails中使用命名范围进行独占而不是包含查询?

我的范围是这样的:

named_scope :with_services, lambda { |services| { 
     :conditions => ["services.id IN (#{services.map{|s| s.id}.join(', ')}) 
         AND service_options.service_owner_type='ServiceProvider' 
         AND service_options.service_owner_id = service_providers.id"], 
     :include => [:services, :service_options] 
    } 
    } 

正如你可以看到我使用IN操作符来做到这一点。但是,当我真正想要的是“让我有服务A和服务B的任何服务提供商”时,IN就像在说“让我有任何提供服务A或服务B的提供商”。“

是否有可能在单个查询中执行此类过滤,或者如果不支持所有必需的服务,我是否需要执行复合查询或只是循环遍历结果并将它们从列表中删除?

回答

1

我想你也许可以做到这一点通过为每个服务A和B.

的提供服务的列表

因此,要么修改范围采取两个列表:

:conditions => ["services.id IN (service_a) AND services.id IN (service_b)"] 

你甚至可能实际上能够调用范围的两倍

Model.with_services(service_a).with_services(service_b) 

而且无需额外成本,就可以速记你的数组操作,以找到IDS:

services.collect(&:id).join 

&:id等同于使用“| o | o.id“

+0

谢谢我会给你一个答案,我忘了在问题中提到的一个问题是,这是可变的,所以你可以有1个服务或5个服务通过 最好的方法是要映射服务并生成该片段的SQL?像这样: :conditions => [“#{services.map {| s | 'services.id IN('+ s.id +')}。join('AND')} ...“] – 2010-01-25 05:57:42

+0

不幸的是,当我尝试这种方法时,我得到零。我相信这是因为给定的ID不能等于或者是IN两个互斥的值,看起来它几乎需要一个复合查询,我可能只需要使用for循环来解析结果: - \ – 2010-01-25 06:16:07