随机ActiveRecord与where和排除某些记录

时间:2016-09-25 14:00:28

标签: ruby-on-rails ruby 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

2 个答案:

答案 0 :(得分: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: 'test@example.com').where.not(id: 1)
User Load (0.7ms)  SELECT "users".* FROM "users" WHERE "users"."email" = $1 AND ("users"."id" != $2)  [["email", "test@example.com"], ["id", 1]]
=> #<ActiveRecord::Relation []>

我们甚至可以在这里通过一个范围:

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

请参阅Rails Quick Tips - Random Records,了解为何DB特定解决方案在这里是一个不错的选择。

答案 1 :(得分:0)

您可以使用以下内容:

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