私的Rubyのコーディングガイド


Ruby

Cookpad・Shopify・GitHub・Airbnb・コミュニティ(bbatsov/rubocop)の各スタイルガイドを項目別にマージしたものです。

全般

  • private/protected の可視性を迂回しないよう、send より public_send を優先する。
# ❌
obj.send(:private_method)

# ✅
obj.public_send(:public_method)

インデントと改行

  • インデントはスペース2つ。タブ文字は使わない。
  • 改行コードは Unix 形式(LF)を使う。
  • ; を使って複数の式を1行に書かない。1行1式を原則とする。

複数行の整形

  • 複数行に展開する場合(メソッド呼び出し・ハッシュ・配列)、各要素・引数は必ず1要素1行にする。閉じ括弧は最後の要素の次の行に単独で置く。
# ❌
[value_1, value_2,
 value_3]

# ✅
[
  value_1,
  value_2,
  value_3,
]

デフォルト引数

デフォルト引数の = の前後にスペースを入れる。

# ❌
def foo(x=1, y=2); end

# ✅
def foo(x = 1, y = 2); end

命名規則

  • シンボル・メソッド・変数・ファイル名・ディレクトリ名: snake_case
  • クラス・モジュール: CamelCase(HTTP・RFC・XML のような略語は大文字を維持)
  • その他の定数: SCREAMING_SNAKE_CASE
  • ソースファイル1つにクラス・モジュール1つを定義し、ファイル名はクラス名を snake_case に変換したものにする。
  • 真偽値を返すメソッドの名前は ? をつける
  • 破壊的メソッドには!(bang)をつける
  • 使わないブロック引数・ローカル変数には _ プレフィックスをつけるか、_ 単独で使う。

文字列

  • 文字列連結(+)ではなく、文字列補間("#{...}")またはフォーマット(format())を使う。
  • 補間の #{} 内部の前後にスペースを入れない。インスタンス変数・グローバル変数の補間は #{} で囲む。補間内の不要な .to_s は省略する。
  • gsub が使える場面でより特化したメソッドを優先する。
  • 複数行文字列にはヒアドキュメントを使い、Ruby 2.3+ では <<~ 構文を使う。

配列

  • Array.new より配列リテラル [] を使う。
  • 複数行の配列リテラルは末尾の要素の後にもカンマを付ける(trailing comma)。

ハッシュ

  • Hash.new よりハッシュリテラル {} を使う。Symbol をキーにする場合は新記法 { key: value } を使う。
  • 複数行のハッシュリテラルでは、開き { の後で改行し、各要素を1段インデント、閉じ } は独立した行に、末尾要素の後にもカンマを付ける。
# ✅
hash = {
  first: 42,
  second: 'foo',
}
  • 存在が必須のキーには Hash#fetch を使う。デフォルト値の設定にも Hash#fetch を使い、|| による falsy 誤判定を避ける。(場合による)
heroes = { batman: 'Bruce Wayne' }

# タイポしても nil が返りエラーに気づかない
heroes[:supermann]  # => nil

# KeyError が即座に発生
heroes.fetch(:superman)

# デフォルト値の設定
config = { enabled: false }

# false が true に上書きされる
config[:enabled] || true   # => true

config.fetch(:enabled, true)  # => false

演算子と代入

  • andornot を使わない。常に &&||! を使う。
  • 三項演算子のネストは禁止。複数段になる場合は if/else を使う。
  • ||= を使って変数をデフォルト値で初期化してよい。ただし Boolean 変数への ||= は使わない。
  • ミュータブルな定数オブジェクト(文字列・配列・ハッシュなど)には freeze を呼ぶ。
# ✅
GREETING = 'Hello'.freeze
STATES   = ['draft', 'open'].freeze
CONFIG   = { timeout: 30 }.freeze

制御構造

  • ifなどで代入演算をしない
  • 複数行の if/unless には then を書かない。
  • 1行ボディの場合は修飾子形式を使う。if/unless の条件を () で囲まない。
  • for ループを避け、イテレータを使う。
  • ガード節(guard clause)を使い、無効データに対して早期 return する。また、ガード節後には必ず空行を入れる

メソッド定義と呼び出し

  • パラメータがある場合は括弧を使い、ない場合は省略する。
  • return が制御フローに必要でなければ省略する。self が必要でなければ省略する。
  • キーワード引数をオプションハッシュより優先する。
# ❌
def create_user(options = {})
  name = options[:name]
  role = options[:role]
end

# ✅
def create_user(name:, role:)
  # ...
end
  • TimeDateTime より優先する。ISO8601 形式の文字列には Time.parse より Time.iso8601 を使う。
# ❌
DateTime.now
Time.parse('2025-01-01T00:00:00+09:00')

# ✅
Time.now
Time.iso8601('2025-01-01T00:00:00+09:00')

ブロック・Lambda・Proc

  • 基本は do...end を使う。メソッドチェーンをする場合や、戻り値を使う関数的なブロックには {...} を使う。1行で済む場合はdo..endを使わなず{...}を使う

クラスボディの定義順序

クラス・モジュール内の要素は次の順序で並べる。

  1. include / extend / prepend
  2. 定数
  3. クラス変数(@@
  4. クラスメソッド(class << self ブロック)
  5. attr_reader / attr_writer / attr_accessor
  6. initialize
  7. public インスタンスメソッド
  8. protected / private メソッド
  9. ネストしたクラス・モジュール
  • クラスメソッドを定義する際は def self.method より class << self ブロックを使い、クラスメソッドをまとめる。
  • 単純なアクセサ・ミューテータには attr_accessorattr_readerattr_writer を使う。attr は使わない。
  • クラス変数(@@)を避ける(継承での動作が直感に反するため)。
  • publicprotectedprivate はメソッド定義と同じインデントレベルで書き、上下に空行を入れる。
  • alias より alias_method を使う。

正規表現

  • 文字列の単純な検索には正規表現よりプレーンテキスト検索を使う。
  • キャプチャ結果を使わない場合は非キャプチャグループ (?:...) を使う。
  • Perl 由来のグローバル変数($1 など)より Regexp#match の戻り値を使う。番号付きキャプチャより名前付きキャプチャ (?<name>...) を使う。
  • 文字列全体の先頭・末尾にマッチさせる場合は ^/$ より \A/\z を使う。
Table of Contents
全般 インデントと改行 複数行の整形 デフォルト引数 命名規則 文字列 配列 ハッシュ 演算子と代入 制御構造 メソッド定義と呼び出し ブロック・Lambda・Proc クラスボディの定義順序 正規表現