2016-09-25 51 views
0

我想爲我的模型編寫一個類函數,它返回一個符合我的條件並排除某些記錄的隨機記錄。這個想法是我會製作一個「隨機文章部分」。隨機ActiveRecord與哪裏和某些記錄排除

,我想我的功能看起來像這樣

Article.randomArticle([1, 5, 10]) # array of article ids to exclude 

一些僞代碼:

ids_to_exclude = [1,2,3] 

loop do 
    returned_article = Article.where(published: true).sample 
    break unless ids_to_exclude.include?(returned_article.id) 
do 

回答

0

你可以使用一些像這樣:

ids_to_exclude = [1,2,3,4] 
Article.where("published = ? AND id NOT IN (?)", true , ids_to_exclude).order("RANDOM()").first 
+0

我該如何添加「AND?」我想要一個發佈的地方:真,不在範圍內。 – josh

+0

更改where子句。我編輯了答案。 – inye

+0

請參閱@ Max關於鏈接哪裏調用通常更清潔的建議:'Article.where(published:true).where.not(id:ids_to_exclude).order(「RANDOM()」)' – gmcnaughton

1

讓我們看看DB特定選項。

class Article 
    # ... 
    def self.random(limit: 10) 
    scope = Article.where(published: true) 
    # postgres, sqlite 
    scope.limit(limit).order('RANDOM()') 
    # mysql 
    scope.limit(limit).order('RAND()') 
    end 
end 

Article.random詢問數據庫,以獲得10個隨機記錄我們。 因此,讓我們看看如何將添加一個選項排除一些記錄:

class Article 
    # ... 
    def self.random(limit: 10, except: nil) 
    scope = Article.where(published: true) 
    if except 
     scope = scope.where.not(id: except) 
    end 
    scope.limit(limit).order('RANDOM()') 
    end 
end 

現在Article.random(except: [1,2,3])將獲得10條記錄,其中ID是不[1,2,3]

這是因爲rails中的.where返回一個可鏈接的作用域。例如:

> User.where(email: '[email protected]').where.not(id: 1) 
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."email" = $1 AND ("users"."id" != $2) [["email", "[email protected]"], ["id", 1]] 
=> #<ActiveRecord::Relation []> 

,我們甚至可以在這裏傳遞範圍:

# cause everyone hates Bob 
Article.random(except: Article.where(author: 'Bob')) 

爲什麼一個DB具體的解決方案是在這裏一個不錯的選擇見Rails Quick Tips - Random Records

+0

簽名與此不同。然而,如果參數的順序不是從方法的名稱中看出來的話,那麼使用[keyword arguments](https://robots.thoughtbot.com/ruby-2-keyword-arguments)會好得多。 – max