有条件地链接范围的最佳方式

时间:2016-07-01 02:28:49

标签: ruby-on-rails ruby rails-activerecord

我试图扩展我的服务器端数据表的功能。我将一些额外的过滤器传递给我的控制器/数据表,我用它来过滤结果。目前在我的模型中,我在测试范围之前是否存在params,但是我不相信这是最好的方法因为我的列表中有很多if / else场景过滤器的增长。我怎样才能做到这一点' rails方式'?

if params[:store_id].present? && params[:status].present?
  Order.store(params[:store_id]).status(params[:status])
elsif params[:store_id].present? && !params[:status].present?
  Order.store(params[:store_id])
elsif !params[:store_id].present? && params[:status].present?
  Order.status(params[:status])
else
  Order.joins(:store).all
end

解答: 将答案结合到这个工作代码中:

query = Order.all
query = query.store(params[:store_id]) if params[:store_id].present?
query = query.status(params[:status]) if params[:status].present?
query.includes(:store)

3 个答案:

答案 0 :(得分:11)

你可以这样做:

query = Order
query = query.store(params[:store_id]) if params[:store_id].present?
query = query.status(params[:status]) if params[:status].present?
query = Order.joins(:store) if query == Order

或者,您也可以重新构建statusstore范围,以包含条件:

scope :by_status, -> status { where(status: status) if status.present? }

然后你可以这样做:

query = Order.store(params[:store_id]).by_status(params[:status])
query = Order.joins(:store) unless (params.keys & [:status, :store_id]).present?

答案 1 :(得分:10)

由于关系是可以链接的,因此它往往有助于建立关系。您的搜索查询。这样做的确切模式差别很大,我要注意不要过度设计任何东西,但是使用普通的Ruby对象(PO​​RO)来构建查询在大多数大型Rails代码库中很常见。在你的情况下,你可能只是简单地简化你的逻辑:

relation = Order.join(:store)

if params[:store_id]
  relation = relation.store(params[:store_id])
end

if params[:status]
  relation = relation.status(params[:status])
end

@orders = relation.all

Rails甚至提供ways to "undo" logic that has been chained previously,以防您的需求变得特别复杂。

答案 2 :(得分:0)

上面的最佳答案对我有用。以下是其实际实施的示例:

      lessons = Lesson.joins(:member, :office, :group)
      if @member.present?
        lessons = lessons.where(member_id: @member)
      end
      if @office.present?
        lessons = lessons.where(office_id: @office)
      end
      if @group.present?
        lessons = lessons.where(group_id: @group)
      end
      @lessons = lessons.all