どうしても生クエリが必要になるプロジェクトがある
ActiveRecordで済ませれば良いのですが、複雑な集計が必要なケースなど、どうしても生SQLを使わなければいけないことがあると思います。
また、パラメータや動的にSQLをゴニョゴニョしたいときなど、SQLとRubyのコードがごちゃ混ぜになって煩雑になり、保守性の低いコードになりがちです。
そんなときに便利なのが、sql_query
というgemです。
GitHub - sufleR/sql_query: Ruby gem to load SQL queries from .sql.erb
templates using ERB.
sql_queryのいいところ
- sqlを
hogehoge.sql.erb
(またはhoge.erb.sql
)のように外出し出来る - ということは、IDEなどでSQLとしてハイライトされるので、SQLとしての可視性が(少し)高くなる
- ERBの
partial
みたいなことも出来るので、例えばWITH句などの部分を共通化しやすくなる - SQLファイルのなかでrubyが使えるので、条件分岐などがしやすくなる
などのメリットがあります。
インストール
gem 'sql_query'
$ bundle install
Railsプロジェクトにapp/sql_queries
というディレクトリを作成します。そこに、.sql.erb
またはerb.sql
ファイルを置いていく。
基本的な使い方
以下のようなSQLファイルを用意する
# app/sql_queries/get_player_by_email.sql.erb
SELECT *
FROM players
WHERE email = <%= quote @email %>
quote
はヘルパーメソッドで、クオートで囲ってくれる。
実行
> query = SqlQuery.new(:get_player_by_email, email: 'e@mail.dev')
> query.execute
(0.6ms) SELECT * FROM players WHERE email = 'e@mail.dev'
=> []
Explain
> query.explain
=> EXPLAIN for:
SELECT *
FROM players
WHERE email = 'e@mail.dev'
QUERY PLAN
----------------------------------------------------------
Seq Scan on players (cost=0.00..2.14 rows=1 width=5061)
Filter: ((email)::text = 'e@mail.dev'::text)
(2 rows)
SQL
> query.sql
=> "SELECT *\nFROM players\nWHERE email = 'e@mail.dev'\n"
Pretty SQL
> query.pretty_sql
=> SELECT *
FROM players
WHERE email = 'e@mail.dev'
色々出来て便利ですね。
Partial出来る
WITH句を共通化し、Partialで呼び出したり
## app/sql_queries/_users_clicks.erb.sql
WITH users_clicks AS (
SELECT
id
, name
, code
, clicks
FROM users
WHERE clicks > <%= @count %>
)
上記のようなWITH句のテンプレートを用意しておき、別のerb.sql
の中で、
<%= partial :users_clicks %>
SELECT * FROM users_clicks;
というぐあいに出来ます。
ヒアドキュメント地獄から開放されました
私はこのgemに出会う前は、SQLをヒアドキュメントの中に書いていました。少しでも複雑なSQLになるともうごちゃごちゃ。
それが、sql_queryを使うようになってからは、生SQLをキレイな状態に保つことが出来るようになりました。