概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Ruby 2.6 added option to raise exception in Kernel#system
- 原文公開日: 2018/04/15
- 著者: Amit Choudhary
- サイト: BigBinary
Ruby 2.6先行チェック: Kernel#systemにexception:オプションが追加(翻訳)
Ruby 2.6シリーズの記事です。Ruby 2.6.0-preview2は最近リリースされました。
私たちが書くRailsアプリの設定/デプロイ自動化スクリプトでは、bundle install やrake db:createやrake db:migrateなどのシステムコマンドをあちこちで実行しています。
Railsプロジェクトのセットアップスクリプトでのマイグレーションをrake db:migrateで行う必要があるとします。これはKernel#systemメソッドで実行できます。
irb> system('rake db:migrate')
Ruby 2.5.0
systemを実行するとtrueかfalseが返ります。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
- コミット: fb29cffab0
- やりとり: #14386
なお、スクリプト実行に使えるのはsystemだけではありません。6年前のBigBinaryブログで、backtick、exec、sh、popen3、 popen2e 、Process.spawnとの違いについて説明しています。