如果你想鏈接一個開放式的條件列表(屬性名稱和值),我會建議使用一個arel表。
這是一個有點很難給具體,因爲你的問題是如此模糊,所以我就解釋一下如何爲Post
模型的一個簡單的例子和幾個屬性做到這一點,說title
,summary
和user_id
(即用戶has_many
帖子)。
首先,獲得AREL表型號:
table = Post.arel_table
然後,開始建立您的謂詞(你最終會用它來創建一個SQL查詢):
relation = table[:title].eq("Foo")
relation = relation.or(table[:summary].eq("A post about foo"))
relation = relation.and(table[:user_id].eq(5))
這裏,table[:title]
,table[:summary]
和table[:user_id]
是posts
表中列的表示。當您調用table[:title].eq("Foo")
時,您正在創建謂詞,大致等同於查找條件(獲取標題列等於「Foo」的所有行)。這些謂詞可以與and
和or
鏈接在一起。
當你的總謂詞是準備好了,你可以得到的結果是:
Post.where(relation)
這將生成SQL:
SELECT "posts".* FROM "posts"
WHERE (("posts"."title" = "Foo" OR "posts"."summary" = "A post about foo")
AND "posts"."user_id" = 5)
這將讓你有任何標題的所有帖子「 Foo「或摘要」關於foo的帖子「,和,它們屬於具有ID 5的用戶。
請注意,arel謂詞可以b無盡地鏈接在一起創造更多和更復雜的查詢。這意味着如果你有(比如說)屬性/值對的哈希值以及某種方式知道每個上面是否使用AND
或OR
,則可以逐一循環並構建條件:
relation = table[:title].eq("Foo")
hash.each do |attr, value|
relation = relation.and(table[attr].eq(value))
# or relation = relation.or(table[attr].eq(value)) for an OR predicate
end
Post.where(relation)
從方便鏈接條件
除此之外,AREL表的另一個優點是,他們是獨立的數據庫,所以你不必擔心你的MySQL查詢是否將在PostgreSQL的工作,等
這裏有一個Railscast更多關於arel:http://railscasts.com/episodes/215-advanced-queries-in-rails-3?view=asciicast
希望有所幫助。
如果你發佈你遇到問題的代碼,這會是有益的豐富。 – mharper 2011-02-17 22:22:18
好吧,Dan在下面發佈的代碼幾乎是我想要做的,除了我不知道會有多少條件,因此也不知道有多少個替換。所以,我認爲我可以傳遞一個包含要替換的值的數組作爲第二個參數。 – wkhatch 2011-02-18 06:49:14
「不同數量的屬性通過它們之間的AND或OR連接在一起」據我瞭解,該條件可以匹配任何給定的屬性,也可以匹配所有屬性但不匹配二者。像`attribute =? OR attribute2 =? OR attribute3 =?`或`attribute =? AND attribute2 =? AND attribute3 =?`。 – 2012-09-27 08:02:07