問題
次のように where メソッドの引数に SQL 文字列を渡しているコードがあるとします。
[1] pry(main)> Character.where('EXISTS (SELECT 1 FROM anime_characters WHERE anime_characters.anime_id = characters.id)').to_a
Character Load (70.1ms) SELECT "characters".* FROM "characters" WHERE (EXISTS (SELECT 1 FROM anime_characters WHERE anime_characters.anime_id = characters.id))
SQL 文字列が長い (せいで Rubocop に怒られかねない) のでヒアドキュメントを使って見やすくします。
[2] pry(main)> Character.where(<<~SQL)
[2] pry(main)* EXISTS (
[2] pry(main)* SELECT
[2] pry(main)* 1
[2] pry(main)* FROM
[2] pry(main)* anime_characters
[2] pry(main)* WHERE
[2] pry(main)* anime_characters.character_id = characters.id
[2] pry(main)* )
[2] pry(main)* SQL
Character Load (1.7ms) SELECT "characters".* FROM "characters" WHERE (EXISTS (
SELECT
1
FROM
anime_characters
WHERE
anime_characters.character_id = characters.id
)
)
コード上は美しくなりましたが、残念なことにログ上でもこの SQL 文字列の部分だけ美しく改行されていて違和感があります…。
解決策
Active Support コア拡張機能の String#squish を使って複数行の SQL 文字列を 1 行にすることで、コード上の見た目を維持しつつ、ログ上では 1 行で表示されるようになりました
[3] pry(main)> Character.where(<<~SQL.squish)
[3] pry(main)* EXISTS (
[3] pry(main)* SELECT
[3] pry(main)* 1
[3] pry(main)* FROM
[3] pry(main)* anime_characters
[3] pry(main)* WHERE
[3] pry(main)* anime_characters.character_id = characters.id
[3] pry(main)* )
[3] pry(main)* SQL
Character Load (1.0ms) SELECT "characters".* FROM "characters" WHERE (EXISTS ( SELECT 1 FROM anime_characters WHERE anime_characters.character_id = characters.id ))