2012-02-25 22 views
3

我很新的Rails和我似乎无法让我的头围绕这一点:如何在Ruby on Rails 3中合并作用域?

我有不同的项目属于各个客户

在我项目模型我有两个搜索功能:

scope :search_by_name, lambda { |fn| where('name LIKE ?', "%#{fn}%") } 

scope :search_by_client, lambda { |fn| where('client_id LIKE ?', fn) } 

似乎都工作。例如,在URL我可以通过此查询:

/projects?search_by_name=fooproject 

我同样可以做到这一点:

/projects?search_by_client_name=misterx 

这将产生所有项目属于客户 MisterX。

现在是有办法结合这两个搜索功能,使查询

/projects?search=foofoo 

将检索名为foofoo以及属于客户项目的项目命名为foofoo

感谢您的帮助!

+1

是什么你的控制器看起来像? – 2012-02-25 17:20:17

+0

就像这样:'@projects = current_user.projects.search_by_name(PARAMS [:名字])。search_by_client(PARAMS [:客户端])' – Tintin81 2012-02-25 17:55:34

回答

7

在SQL中,您可以通过多种条件进行搜索。您已经定义了两个范围的,他们可以如下链接在一起:

Project.search_by_name('fooproject').search_by_client('misterx') 

这将创建下列SQL:

SELECT "projects".* FROM "projects" WHERE "projects".name LIKE '%fooproject%' AND "projects".client_id LIKE '%misterx' 

运营商加入这两个条件是“AND”,这意味着结果将是符合两个条件的条件,而不是条件。

有几种方法可以检索具有特定名称的项目或属于客户端的项目。最简单的方法是创建一个新的范围,指定或运算符:

scope :search_by_name_or_client, lambda { |name, client| where('name LIKE ? OR client_id LIKE ?', "%#{name}%", "%#{client}%") } 

您可能也想看看SQL工会,它结合了结果集的两个或更多个SELECT语句。 ActiveRecord的不处理UNION的功能,但也有宝石来扩展功能,包括这一点,如https://github.com/tsmango/union

而且例如写这个使用联盟宝石是这样的:

Project.union([{:conditions => ['name like ?', "%#{name}%"]}, {:conditions => ['client like ?', "%#{client}%"]}]) 

这将产生下面的SQL:

SELECT "projects".* FROM "projects" WHERE "projects".name LIKE '%fooproject%' 
UNION 
SELECT "projects".* FROM "projects" WHERE "projects".client_id LIKE '%misterx' 

更多关于UNION的SQL语句的信息可以在这里找到:http://www.w3schools.com/sql/sql_union.asp

+0

嘿本,感谢您的帮助。你能告诉我如何在我的控制器中使用这个功能吗?现在我有这个,但我不能得到它的工作:'@projects = current_user.projects.search_by_name_or_client(PARAMS [:名字],则params [:客户端])' – Tintin81 2012-02-25 18:03:21

+0

你会在你的项目类中定义的范围,将看如: '作用域:search_by_name_or_client,lambda {| name,client_id |在哪里(“name like?OR client_id like?”,“%#{name}%”,“%#{client_id}”)' – 2012-02-25 21:32:07

+0

同样在你的问题中,你似乎在搜索client_name,但检查client_id列。我不确定你想要搜索哪个字段。 client_id大概是你项目表中的一列,这意味着你不需要加入客户端来按名称搜索。如果客户端相关的数据,你的范围可能是这样的: '范围:search_by_name_or_client,拉姆达{|名称,CLIENT_NAME |在哪里(“name like?OR clients.name like?”,“%#{name}%”,“%#{client_name}”)。joins(:client)' – 2012-02-25 21:36:30