実務で見たコードに対して「これで動くの?」と思ったんですが、実際には動いていたので混乱しました。
ようやく理由がわかったので備忘録としてまとめます。
バージョン
- Ruby 3.0.3
- Rails 6.1.6.1
記事の信頼性
- ぼくは独学で未経験から従業員300名以上の自社開発企業へ転職しました。
- 実務ではVue.jsとRailsを毎日書いています。
- 初心者や駆け出しエンジニアがつまづくポイントも身をもってよく理解しています。
目次
問題
CreateEmployee
クラスからCreateEmployeeCommand
クラスのメソッドを呼び出していたのですが、引数の数が異なるため、動かないように思えました。
class CreateEmployee
def perform
# キーワード引数で4つの引数を渡す
CreateEmployeeCommand.execute(
company_id: @company_id,
name: @name,
rank: @rank,
status: @status
)
end
end
class CreateEmployeeCommand
# 引数は1つだけ
def self.execute(params)
Employee.create!(params)
end
end
しかし実際には動いていたので原因がわからずコードを読むのに時間がかかってしまいました。
解決策
結論として、Rubyではメソッドを呼び出す際に最後の引数がハッシュであれば、波括弧({}
)を省略できます。
つまり先ほどのコードは、実際には次のように記述したのと同じ挙動になります。
class CreateEmployee
def perform
# 実は引数は1つのハッシュとみなされる
CreateEmployeeCommand.execute({
company_id: @company_id,
name: @name,
rank: @rank,
status: @status
})
end
end
class CreateEmployeeCommand
# 引数は1つだけ
def self.execute(params)
Employee.create!(params)
end
end
一見すると4つの引数を渡しているように見えても、実際には1つのハッシュを渡している扱いとなるため、正常に動作していたのです。
ただし、可読性の観点で考えると、以下のように引数の数を合わせるのがベターだとは思います。
class CreateEmployee
def perform
CreateEmployeeCommand.execute(
company_id: @company_id,
name: @name,
rank: @rank,
status: @status
)
end
end
class CreateEmployeeCommand
def self.execute(company_id:, name:, rank:, status:)
Employee.create!(
company_id: company_id,
name: name,
rank: rank,
status: status
)
end
end
おわりに
Rubyはやたらと省略できたりするので、個人的にはあまり好きではないですね。
コメント