かみぽわーる

kamipo's blog

Rails 6.1で `created_at > ?` みたいなクエリをいい感じに生成する

Rails 6.1の目玉機能として以下のように書けるwhere拡張を入れてたんですが、いろいろあって6.1からはrevertされてしまいました🥲

posts = Post.order(:id)

posts.where("id >": 9).pluck(:id)  # => [10, 11]
posts.where("id >=": 9).pluck(:id) # => [9, 10, 11]
posts.where("id <": 3).pluck(:id)  # => [1, 2]
posts.where("id <=": 3).pluck(:id) # => [1, 2, 3]

github.com

github.com

なんですが、そんなことで引き下がる僕ではないので、6.1ではpredicate生成に干渉できる拡張ポイントを用意しており、以下のようなコードを適当に読み込まれるところにしたためておけば、いともたやすくwhere拡張を実現することができます。

ActiveSupport.on_load(:active_record) do
  ActiveRecord::PredicateBuilder.prepend Module.new {
    def [](attr_name, value, operator = nil)
      if !operator && attr_name.end_with?(">", ">=", "<", "<=")
        /\A(?<attr_name>.+?)\s*(?<operator>>|>=|<|<=)\z/ =~ attr_name
        operator = OPERATORS[operator]
      end

      super
    end

    OPERATORS = { ">" => :gt, ">=" => :gteq, "<" => :lt, "<=" => :lteq }.freeze
  }
end

ぜひ活用してくださいね😉