【问题标题】:Build dynamic ActiveRecord query in Rails在 Rails 中构建动态 ActiveRecord 查询
【发布时间】:2014-10-31 13:30:38
【问题描述】:

我想知道如何根据参数是否存在/存在成功设置动态 Active Record 查询。

我有这个问题

Animal.joins(:user).where(animal_type: params[:animal_type], rehomed: params[:rehomed], users: {town: params[:animal_town]})

我已经尝试过这些方法,但我相信我的语法完全错误:

conditions = []
conditions << [ animal_type: params[:animal_type], ] if params[:animal_type].present?
conditions << [ rehomed: params[:rehomed], ] if params[:rehomed].present?
conditions << [ users: {town: params[:animal_town]} ] if params[:animal_town].present?
@animals = Animal.joins(:user).where(conditions)

我不想把它全部放在一个嵌套的哈希中,是吗?

【问题讨论】:

  • 为什么你不想把它放在嵌套散列中?它应该在嵌套哈希中。
  • 在您的情况下,where 无论如何都接受哈希。因此,使用强参数和params 哈希本身可能是可行的方法。
  • 好吧,也许我今天很慢,但要访问条件哈希我会做where(conditions: conditions) ?
  • 类似where(params)不要这样做,使用Rails 的permitrequire 等过滤paramsedgeguides.rubyonrails.org/…
  • @Richlewis 是的,你会做where(conditions: conditions)。在问 BTW 之前,你为什么不试试呢?

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


【解决方案1】:

你必须这样做:

conditions = {}
conditions.merge!(animal_type: params[:animal_type]) if params[:animal_type].present?
conditions.merge!(rehomed: params[:rehomed]) if params[:rehomed].present?
conditions.merge!(users: {town: params[:animal_town]}) if params[:animal_town].present?

@animals = Animal.joins(:user).where(conditions)

【讨论】:

  • 避免合并效率更高!:conditions[:animal_type]= params[:animal_type]
【解决方案2】:

我会这样想:

scope = Animal.joins(:user)
scope = scope.where(animal_type: params[:animal_type])     if params[:animal_type].present?
scope = scope.where(rehomed: params[:rehomed])             if params[:rehomed].present?
scope = scope.where(users: { town: params[:animal_town] }) if params[:animal_town].present?

@animals = scope

进一步改进:将作用域的构建移到 Animal 模型中的方法中:

# in controller
@animals = Animal.find_by_query(params.slice(:animal_type, :rehomed, :animal_town))

# in Animal model
def self.find_by_query(query = {})
  query.reject { |_, v| v.blank? }

  scope = joins(:user)
  scope = scope.where(animal_type: query[:animal_type])     if query[:animal_type]
  scope = scope.where(rehomed: query[:rehomed])             if query[:rehomed]
  scope = scope.where(users: { town: query[:animal_town] }) if query[:animal_town]
  scope
end

【讨论】:

    猜你喜欢
    • 2018-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多