2016-09-25 60 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