使用哈希而不是链接方法的Rails / ActiveRecord查询

时间:2018-07-25 12:16:55

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

执行查询的常用方法是链接方法,例如:

Post.where(active: true).select(:id, :title).limit(5)

有没有一种方法可以使用哈希来构造此查询?即:

Post.where(
  where: [{active: true}],
  select: [:id, :title],
  limit: 5
)

(各种原因,例如可以响应用户查询来构造哈希,然后将其序列化以供以后处理。)

2 个答案:

答案 0 :(得分:1)

简短的回答是“否”。

但是

ransackrack-reducer之类的宝石可以帮助您做到这一点

OR

您总是可以自己做。

让我们从一个非常幼稚的方法开始:

定义一种方法来获取我们感兴趣的参数:

def query_params
  params.slice(:where, :select, :limit) # or make a proper permit call
end

为此用户定义基本范围:

def base_scope
  Post.where(whateveryouwant)
end

然后,您需要遍历这些并将它们应用于我们的ActiveRecord::Relation

query_params.reduce(base_scope) { |ac, (key, value)| ac.public_send(key, value) }

答案 1 :(得分:1)

您可以在模型上定义自定义类方法,以将查询参数作为大哈希值传递,然后使用inject准备链接的查询。 (如果适用,您也可以使用each_with_object)。

class Post
  def self.criteria(options = {})
    options.inject(self) do |out, (k, v)|
      out = out.send(k, v)
      out
    end
  end
end

hash = {
  where: { active: true },
  select: [:id, :title],
  limit: 5
}

Post.criteria(hash)
 => # ActiveRecord Relation for above query

如果您的where键具有如问题中所述的哈希数组作为值,则可以将其转换为单个哈希,如下所示:

Post.where(foo: 1).where(bar: 2)

与:

Post.where(foo: 1, bar: 2)

执行以下转换:

hash[:where] = hash[:where].each_with_object({}) { |h, out| out.merge!(h) }