👩‍🏫

Ransack の params が増えてきたらハッシュ展開で注入できることを知っておこう

2021/05/14に公開

こういう時は関係ない

ERB の form からくる情報を params[:q] とかに突っ込んでて

User.ransack(params[:q]).result

とかしてるときは今回のようなケースにならない。
今回は ransack メソッドに Matcher を個別に書いてる時の話です。

Ransack を使っていると ransack() の params が増えてしまうことがある

例えば User モデルがこんな感じで

  • 名前:name
  • 住所:address
  • 請求先住所:billing_address
  • 配送先住所:shipping_address

どこかに「宿」という単語が含まれている User を探したい、という時に

query = "宿" # 実際は query = params[:query] など
users = User.ransack(name_cont: query, address_cont: query, billing_address_cont: query, shipping_address_cont: query, m: 'or').result

たった3つなのにもう読みたくないコードが……
さらに、特定の条件の時だけ請求先住所の検索はしないことにする、とかやると

query = "宿" # 実際は query = params[:query] など
users = if ([何かの条件])
          User.ransack(name_cont: query, address_cont: query, billing_address_cont: query, shipping_address_cont: query, m: 'or').result
        end
	  User.ransack(name_cont: query, address_cont: query, shipping_address_cont: query, m: 'or').result
	end

ほげえええええええええええええええええええええええ
どうにかしたいですね。

ハッシュ展開で注入できる

**opts でハッシュを可変長引数として受け取れるrubyの仕組みを転じて
ハッシュ展開に使えるというのがあります。
(この説明はちょっと間違ってるかも……;;)

要するにこういうことです。

irb(main):001:0> aa = {a: 1, b: 2}
=> {:a=>1, :b=>2}
irb(main):002:0> cc = {**aa, c: 3}
=> {:a=>1, :b=>2, :c=>3}
irb(main):003:0> cc
=> {:a=>1, :b=>2, :c=>3}

これを使って 先程の Ransack のコードを書き直してみましょう。

query = "宿" # 実際は query = params[:query] など

condition = {
  name_cont: query,
  address_cont: query,
  billing_address_cont: query,
  shipping_address_cont: query,
  m: 'or'
}

users = User.ransack(**condition).result

はるかに読みやすくなりました!!!!

では条件で分岐したい時はどうでしょう?
これは、 Hash#merge! で実現できます

query = "宿" # 実際は query = params[:query] など

condition = {
  name_cont: query,
  address_cont: query,
  shipping_address_cont: query,
  m: 'or'
}

condition.merge!(billing_address_cont: keyword) if ([何かの条件])

users = User.ransack(**condition).result

こちらも、はるかに読みやすくなりましたね!!

今回の記事は以上です。
ぜひ使ってみてください。じゃ!

Discussion