Tech Racho エンジニアの「?」を「!」に。
  • 開発

Railsのmigrationで生SQLを使う+パラメータを使う

migrationファイル内では、モデルクラスを使わないのが安全です。
これは、将来的に仕様変更やリファクタでそのモデルがなくなったりリネームされた際、rake db:migrate:resetが通らなくなるからです。

migration内でデータの変換処理をすることも多いので、SQLを生で叩くには以下のようにします。

sql = "UPDATE users SET some_flag = 1;"
ActiveRecord::Base.connection.execute(sql)

さすがにパラメータを指定したいことも多いですが、ActiveRecordのノリで?などのplaceholderを渡しても処理してくれません。
かといって、自分でエスケープ処理をするのは嫌です。

このあたりのエスケープとプレースホルダー処理は、#sanitize_sql_arrayが担当しています。
protectedメソッドですが、ここは使わせてもらっちゃいましょう。

args = ["UPDATE users SET name=? WHERE id=?", "Tom Brown", 1]
sql = ActiveRecord::Base.send(:sanitize_sql_array, args)
ActiveRecord::Base.connection.execute(sql)

なお、もう少し高級っぽく書くには、migrationファイル内でモデルクラスを定義してしまうという方法もあります。

追記(2019/03/07)

#sanitize_sql_arrayはRails 5.2からpublicになりました🎉。


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。