Ruby 2.6先行チェック: Kernel#systemに`exception:`オプションが追加(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Ruby 2.6先行チェック: Kernel#systemにexception:オプションが追加(翻訳)

Ruby 2.6シリーズの記事です。Ruby 2.6.0-preview2は最近リリースされました

私たちが書くRailsアプリの設定/デプロイ自動化スクリプトでは、bundle installrake db:createrake db:migrateなどのシステムコマンドをあちこちで実行しています。

Railsプロジェクトのセットアップスクリプトでのマイグレーションをrake db:migrateで行う必要があるとします。これはKernel#systemメソッドで実行できます。

irb> system('rake db:migrate')

Ruby 2.5.0

systemを実行するとtruefalseが返ります。systemのもうひとつの機能は、例外を握りつぶすことです。

systemコマンドでマイグレーションが成功した場合は、trueを返します。

irb> system('rake db:migrate')
# => true

マイグレーションでテーブルにカラムを追加しようとしたら、テーブルが存在しなかったとしましょう。この場合systemコマンドはfalseを返します。

irb> system('rake db:migrate')
== 20180311211836 AddFirstNameToAdmins: migrating =============================
-- add_column(:admins, :first_name, :string)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::UndefinedTable: ERROR:  relation "admins" does not exist
: ALTER TABLE "admins" ADD "first_name" character varying
.
.
.
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
# => false

systemコマンドの実行に失敗した場合にfalseが返るので、上では例外が発生しません。

しかし次のように明示的にraiseすればセットアップスクリプトを停止できます。

irb> system('rake db:migrate') || raise('Failed to run migrations')
== 20180311211836 AddFirstNameToAdmins: migrating =============================
-- add_column(:admins, :first_name, :string)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::UndefinedTable: ERROR:  relation "admins" does not exist
: ALTER TABLE "admins" ADD "first_name" character varying
.
.
.
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
Traceback (most recent call last):
        2: from /Users/amit/.rvm/rubies/ruby-2.5.0/bin/irb:11:in `<main>'
        1: from (irb):4
RuntimeError (Failed to run migrations)

Ruby 2.6.0-preview1

Ruby 2.6のKernel#systemではexception: trueオプションが使えるようになったので、上のように明示的なraiseによるスクリプト停止コードを書かなくて済むようになりました。

irb> system('rake db:migrate', exception: true)
== 20180311211836 AddFirstNameToAdmins: migrating =============================
-- add_column(:admins, :first_name, :string)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::UndefinedTable: ERROR:  relation "admins" does not exist
: ALTER TABLE "admins" ADD "first_name" character varying
.
.
.
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
Traceback (most recent call last):
        3: from /Users/amit/.rvm/rubies/ruby-2.6.0-preview1/bin/irb:11:in `<main>'
        2: from (irb):2
        1: from (irb):2:in `system'
RuntimeError (Command failed with exit 1: rake)

exceptionオプションが指定されていない場合はRuby 2.5と同様にfalseを返します。

irb> system('rake db:migrate', exception: false)
== 20180311211836 AddFirstNameToAdmins: migrating =============================
-- add_column(:admins, :first_name, :string)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::UndefinedTable: ERROR:  relation "admins" does not exist
: ALTER TABLE "admins" ADD "first_name" character varying
.
.
.
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
 => false

なお、スクリプト実行に使えるのはsystemだけではありません。6年前のBigBinaryブログで、backtickexecshpopen3、 popen2e 、Process.spawnとの違いについて説明しています。

関連記事

Ruby 2.6先行チェック: rangeの終端をnilまたは省略できる(翻訳)

Ruby 2.6先行チェック: `String#split`がブロックを取れる(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ