构造一个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子句的主要内容,如果未能解决你的问题,请参考以下文章