[譯] Ruby 2.6 Kernel 的system 方法增加是否丟擲異常引數。

Madao-3發表於2018-08-01

本部落格系列翻譯自 Bigbinary 的 Ruby 2.6 系列, 已得到作者允許。Ruby 2.6.0-preview2 現已釋出

平時我們會寫一些自動化設定和部署 Rails 應用的指令碼。在這些指令碼中,我們會時常使用系統命令,例如 bundle install,抑或是 rake db:create等等。

我們假設一下:我們需要在一個Rails 專案裡頭跑 rake db:migrate,我們可以使用 Kernel#system 方法。

irb> system('rake db:migrate')
複製程式碼

Ruby 2.5.0

執行system方法會返回 true 或者 false(Ruby 2.5 下)。system 其中一個Feature(థ౪థ) 就是他會把異常丟擲給吃掉。

我們假設這個命令會成功,那麼我們會得到返回值 true

irb> system('rake db:migrate')
 => true
複製程式碼

那我們繼續假如:這個migration 嘗試加一個欄位到一個不存在的表裡頭。這個情況下,我們會得到返回值 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
複製程式碼

如我們所見,即使執行系統命令失敗,方法返回值還是會是 false。Ruby 不會因此丟擲異常。儘管如此,我們可以用這個方法來丟擲異常。

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 給 system 方法提供了一個新的option, 也就是 exception ,你可以通過設定 exception: true 來讓方法可以丟擲異常。

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 為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
複製程式碼

這裡是相關的commit討論

system 也不是唯一可以執行這些語句的方法,我(作者)六年前寫了一個部落格討論這些(執行系統命令)的方法的異同:backtick, exec, sh, popen3, popen2e and Process.spawn.

原文地址

部落格地址

相關文章