2012-02-25 63 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