构造一个Rails ActiveRecord where子句

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了构造一个Rails ActiveRecord where子句相关的知识,希望对你有一定的参考价值。

使用Rails ActiveRecord构造where子句的最佳方法是什么?例如,假设我有一个控制器操作,它返回一个博客帖子列表:

def index
  @posts = Post.all
end

现在,假设我希望能够传入url参数,以便此控制器操作仅返回特定作者的帖子:

def index
  author_id = params[:author_id]

  if author_id.nil?
    @posts = Post.all
  else
    @posts = Post.where("author = ?", author_id)
  end
end

这对我来说感觉不太干。如果我要添加排序或分页或更糟糕的是,更多可选的URL查询字符串参数进行过滤,此控制器操作将变得非常复杂。

答案

怎么样:

def index
  author_id = params[:author_id]

  @posts = Post.scoped

  @post = @post.where(:author_id => author_id) if author_id.present?

  @post = @post.where(:some_other_condition => some_other_value) if some_other_value.present?
end

Post.scoped本质上是一个延迟加载等效于Post.all(因为Post.all立即返回一个数组,而Post.scoped只返回一个关系对象)。在您实际尝试在视图中迭代它(通过调用.each)之前,不会执行此查询。

另一答案

嗯,你想要使用的最佳方法是将其传播到2个动作中

def index
   @post = Post.all
end

def get
  @post = Post.where("author=?", params[:author_id])
end

恕我直言,如果你考虑一个RESTful API更有意义,索引意味着列出所有并获取(或显示)获取所请求的并显示它!

另一答案

这个问题已经相当陈旧了,但它在2019年仍然在谷歌中出现了很高,而且一些早期的答案已被弃用,所以我想我会分享一个可能的解决方案。

在模型中引入一些范围,测试是否存在传递的参数:

class Post
    scope :where_author_ids, ->(ids){ where(author_id: ids.split(‘,’)) if ids }
    scope :where_topic_ids,  ->(ids){ where(topic_id:  ids.split(‘,’)) if ids }

然后在控制器中,您可以根据需要添加尽可能多的过滤器,例如:

def list
    @posts = Post.where_author_ids(params[:author_ids])
                 .where_topic_ids(params[:topic_ids])                                  
                 .where_other_condition_ids(params[:other_condition_ids])
                 .order(:created_at)

然后,该参数可以是单个值或以逗号分隔的值列表,两者都可以正常工作。

如果param不存在,它只是跳过where子句而不过滤该特定条件。如果param存在但其值为空字符串,那么它将“过滤掉”所有内容。

当然,这种解决方案并不适合所有情况。如果您有一个包含多个过滤器的视图页面,但是在第一次打开时您希望显示所有数据而不是数据,直到您按下“提交”按钮或类似(如此控制器),那么您将不得不稍微调整一下。

我已经开始使用SQL注入这个并且rails似乎在保持一切安全方面做得很好,据我所见。

另一答案

您应该使用嵌套资源建模url。预期的网址是/ authors / 1 / posts。将作者视为资源。阅读本指南中的嵌套资源:http://guides.rubyonrails.org/routing.html(滚动到2.7 - 嵌套资源)。

另一答案

会这样的吗?

def get
  raise "Bad parameters...why are you doing this?" unless params[:filter].is_a?(Hash)
  @post = Post.where(params[:filter])
end

然后你可以这样做:?filter [author_id] = 1&filter [post_date] = ...等

以上是关于构造一个Rails ActiveRecord where子句的主要内容,如果未能解决你的问题,请参考以下文章

Rails ActiveRecord 查询不等于

has_one: through: 不添加构造函数

Rails 查询具有关联条件的多个主键

ActiveRecord何时会保存关联?

Rails,ActiveRecord,Squeel:检查数组中是不是存在值

为此使用啥 Rails-ActiveRecord 关联?