LoginSignup
1
0

More than 3 years have passed since last update.

ActiveRecord の where でレコードを直接絞れないケースでも絞り込む方法を調べた

Last updated at Posted at 2019-09-28

はじめに

Rails でアプリ開発をする際、モデルのレコードを where で絞り込むケースはよくあると思いますが、where で直接絞れないケースで絞り込む必要があり、その方法について調べました。

課題

例として、Post モデルを考えます。Post モデルには、title と、API からのレスポンス json を保持しておく raw_json カラムがあります。作成するときはこんなイメージです。

Post.create(
  title: 'テスト1',
  raw_json: '{"date": "2019-08-01"}'
)

Post.create(
  title: 'テスト2',
  raw_json: '{"date": "2019-08-02"}'
)

この raw_json カラムの date の日付でデータを絞り込む必要があったのですが、この方法について調べていました。

tl;dr

こんなスコープを作りました。

scope :filter_by_tartet_date, -> (target_date) {
  return if !target_date.present?
  ids = self.select do |s|
    if date = JSON.parse(s.raw_json)['date']
      Date.parse(date) == Date.parse(target_date)
    end
  end.map(&:id)
  where(id: ids)
}

使い方としては、Post.filter_by_tartet_date('2019-08-01') という感じで日付文字列を引数に指定すると、raw_json 内の date2019-08-01 のレコードに絞り込んでくれます。

解説

ざっくりしたイメージとしては以下のようになります。

  • select メソッドで raw_json 内の値を使って比較
  • map メソッドで対象レコードの id のみの配列を作成
  • where メソッドで対象 id のレコードのみ絞り込んで ActiveRecord::Relation クラスの戻り値に

select メソッドを使うだけだと、戻り値が Array クラスになってしまい、ページネーションなどの使い勝手が悪かったため、最後に where メソッドで ActiveRecord::Relation クラスの戻り値に変換して使いやすくしています。

おわりに

直接 where メソッドで絞れない場合でも、Array クラスのメソッドを挟んで絞る方法が使えました。直感的に書ける ruby はやっぱり便利だなと感じます。

他にもいい方法ありましたら教えていただけるとありがたいです。

参考

1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0