Skip to content

takayama-daisuke/ruby-style-guide

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 

Repository files navigation

Ruby コーディング規約

これは マネーフォワード Ruby コーディング規約です.

これらを、お手本(ベース)にしています

次の目標は、Railsコーディング規約です.

以下は、ドメインの前提条件です

  • Rubyのバージョンは2.1以降を前提とする(バージョンの異なるプロダクトが無い為)
  • 複数の表記がある場合、新しく採用された表記を強く推奨します
  • 複数の同じ振る舞いのメソッドやシンタックスシュガーが存在する場合、短い方を利用します
  • ex) mapとcollectは双方の価値を認めつつ、mapを採用します
  • ex) []とArray.newは双方の価値を認めつつ、[]を採用します
  • 強い理由がない場合は統一性の為合わせてください。これは可読性を担保する為です。
  • 本規約に沿わない表記を否定するものではありません
  • 他のメンバーを説得出来る強い理由がある場合は、理由を説明した上で任意の表記を行ってください
  • これに該当するケースでは、本規約へのフィードバックを検討してください

目次

レイアウト

  • ソースファイルのエンコーディングにはUTF-8を用いましょう。

  • ソースコード中にマジックコメントが書かれることはありません [link]

  • インデントには スペース 2つ(別名ソフトタブ)。 ハードタブを用いてはいけません。 [link]

    # 悪い例 - 4つのスペース
    def some_method
        do_something
    end
    
    # 良い例
    def some_method
      do_something
    end
  • Unix-styleの改行にしましょう。 (*BSD/Solaris/Linux/OS X ユーザーはデフォルトで設定されています。 Windows ユーザーは特に注意が必要です。) [link]

    • もしGitを使っていれば、プロジェクトにWindowsの改行が紛れ込まないように、以下の設定を追加したほうがよいかもしれません:

      $ git config --global core.autocrlf true
  • 命令文や式の区切りに;を用いてはいけません。 当然、1行につき式1つにしましょう。 [link]

    # 悪い例
    puts 'foobar'; # 余分なセミコロンです。
    
    puts 'foo'; puts 'bar' # 2つの式が1行にあります。
    
    # 良い例
    puts 'foobar'
    
    puts 'foo'
    puts 'bar'
    
    puts 'foo', 'bar' # 特にputsでは適用されます。
  • 本文のないクラスは1行のフォーマットが好まれます。 [link]

    # 悪い例
    class FooError < StandardError
    end
    
    # 悪くない例
    class FooError < StandardError; end
    
    # 良い例
    FooError = Class.new(StandardError)
  • 1行のメソッドは避けましょう。 いくらか使われているところもありますが、 それらの定義構文の仕様が望ましくないとさせるいくつかの特殊性があります。 ともかく - 1行メソッドには多くとも式1つまでにすべきです。 [link]

    # 悪い例
    def too_much; something; something_else; end
    
    # 悪くない例 - 最初の ; は必要です。
    def no_braces_method; body end
    
    # 悪くない例 - 2つ目の ; は任意です。
    def no_braces_method; body; end
    
    # 悪くない例 - 文法上は正しいです。ただし、; がない記述は少し読みづらいです。
    def some_method() body end
    
    # 良い例
    def some_method
      body
    end

    本文が空のメソッドはこのルールの例外です。

    # 良い例
    def no_op; end
  • 演算子の前後、コンマ、コロン、セミコロンの後ろに、{の前後、}の前にはスペースを入れましょう。 スペースはRubyのインタープリタには(ほとんどの場合)重要ではありませんが、 スペースの適切な使用は、読みやすいコードを容易に書くための鍵です。 [link]

    sum = 1 + 2
    a, b = 1, 2
    1 > 2 ? true : false; puts 'Hi'
    [1, 2, 3].each { |e| puts e }

    演算子についてただひとつの例外は、指数演算子です:

    # 悪い例
    e = M * c ** 2
    
    # 良い例
    e = M * c**2

    {}は、構文の明確化のために有用です。 だから、文字列に式を埋め込む時と同様に、 ブロックやハッシュ構文に使われます。 ハッシュ構文には、2つのスタイルが許容できます。

    # 良い例 - スペースを { の後と } の前に入れる
    { one: 1, two: 2 }
    
    # 良い例 - スペースを { の後と } の前に入れない
    {one: 1, two: 2}

    1つ目の構文は、わずかながら少し読みやすいです(そして、ほぼ間違いなく一般的なRubyコミュニティで人気があります)。 2つ目の構文は、ブロックとハッシュを視覚的に差別化できるという点で有利です。 どちらでも片方を採用すれば、常に同じ構文を採用しましょう。

    文字列に埋め込む構文も、2つのスタイルが許容できます:

    # 良い例 - スペースを入れない
    "string#{expr}"
    
    # 良い例 - ほぼ間違いなくにこちらのほうが読みやすい
    "string#{ expr }"

    1つ目の式は、他の式よりも非常に人気があり、一般的にこちらを使うように進められる書き方です。 一方2つ目は、(間違いなく)少し読みやすいです。 ハッシュと同じように - 片方を採用すれば、常に同じ方を採用しましょう。

  • ([の後と、])の前にはスペースは入れません。 [link]

    some(arg).other
    [1, 2, 3].size
  • !の後にはスペースは入れません。 [link]

    # 悪い例
    ! something
    
    # 良い例
    !something
  • 範囲リテラルの内側にスペースは不要です。 [link]

    # 悪い例
    1 .. 3
    'a' ... 'z'
    
    # 良い例
    1..3
    'a'..'z'
  • whencaseと同じ深さに揃えましょう。 多くの人が同意できないのを知っていますが、 このスタイルは"The Ruby Programming Language"、"Programming Ruby" 双方で確立されたものなのです。 [link]

    # 悪い例
    case
      when song.name == 'Misty'
        puts 'Not again!'
      when song.duration > 120
        puts 'Too long!'
      when Time.now.hour > 21
        puts "It's too late"
      else
        song.play
    end
    
    # 良い例
    case
    when song.name == 'Misty'
      puts 'Not again!'
    when song.duration > 120
      puts 'Too long!'
    when Time.now.hour > 21
      puts "It's too late"
    else
      song.play
    end
  • 条件式を変数に代入するときは、 その式の通常のアラインメントを維持しましょう。 [link]

    # 悪い例 - かなり複雑です
    kind = case year
    when 1850..1889 then 'Blues'
    when 1890..1909 then 'Ragtime'
    when 1910..1929 then 'New Orleans Jazz'
    when 1930..1939 then 'Swing'
    when 1940..1950 then 'Bebop'
    else 'Jazz'
    end
    
    result = if some_cond
      calc_something
    else
      calc_something_else
    end
    
    # 良い例 - 何が行われているか明らかです
    kind = case year
           when 1850..1889 then 'Blues'
           when 1890..1909 then 'Ragtime'
           when 1910..1929 then 'New Orleans Jazz'
           when 1930..1939 then 'Swing'
           when 1940..1950 then 'Bebop'
           else 'Jazz'
           end
    
    result = if some_cond
               calc_something
             else
               calc_something_else
             end
    
    # 良い例 (少しだけ幅の効率がよいです)
    kind =
      case year
      when 1850..1889 then 'Blues'
      when 1890..1909 then 'Ragtime'
      when 1910..1929 then 'New Orleans Jazz'
      when 1930..1939 then 'Swing'
      when 1940..1950 then 'Bebop'
      else 'Jazz'
      end
    
    result =
      if some_cond
        calc_something
      else
        calc_something_else
      end
  • 定義式の間には空行をいれ、 メソッド内の論理的段落ごとに分割しましょう。 [link]

    def some_method
      data = initialize(options)
    
      data.manipulate!
    
      data.result
    end
    
    def some_method
      result
    end
  • メソッド呼び出しの最後の引数の後ろのコンマは避けましょう。 引数が複数行にわかれていない時は、特に避けましょう。 [link]

    # 悪い例 - 簡単に引数を移動・追加・削除できますが、それでもお奨めできません。
    some_method(
                 size,
                 count,
                 color,
               )
    
    # 悪い例
    some_method(size, count, color, )
    
    # 良い例
    some_method(size, count, color)
  • メソッドの引数に初期値を割り当てるとき、 =演算子の周りにはスペースを入れましょう。 [link]

    # 悪い例
    def some_method(arg1=:default, arg2=nil, arg3=[])
      # do something...
    end
    
    # 良い例
    def some_method(arg1 = :default, arg2 = nil, arg3 = [])
      # do something...
    end

    いくつかのRuby本は最初のスタイルを提案しているけど、 2つ目の方が、実用的により優れています (そして、ほぼ間違いなく少し読みやすいです)。

  • 不要な\を用いた行の継続は避けましょう。 実際、文字列連結以外での行の継続は避けましょう。 [link]

    # 悪い例
    result = 1 - \
             2
    
    # 良い例 (しかしそれでも地獄のように醜い)
    result = 1 \
             - 2
    
    long_string = 'First part of the long string' \
                  ' and second part of the long string'
  • 一貫した複数行のメソッドチェーンのスタイルを採用しましょう。 Rubyコミュニティには2つの有名なスタイル - 先頭に.を付けるもの (Option A)、 末尾に.を付けるもの (Option B) - があり、 どちらも良いと考えられています。 我々は先頭に.を付けるもの (Option A)を採用します。 [link]

    • (Option A) メソッドチェーンを次の行へつなげる時は、 .は次の行に置きましょう。

      # 悪い例 - 2行目を理解するのに1行目を調べなければなりません
      one.two.three.
        four
      
      # 良い例 - 2行目で何が行われているかすぐに理解できます
      one.two.three
        .four

    双方のスタイルのメリットに関する議論はこちら で見ることができます。

  • メソッド呼び出しが複数行に及ぶときは、引数は揃えましょう。 1行の長さの制約のために、引数を揃えるのに適していない時は、 最初の引数以降をインデント1つ分で揃えるスタイルも許容できます。 [link]

    # 初期値 (1行がとても長いです)
    def send_mail(source)
      Mailer.deliver(to: 'bob@example.com', from: 'us@example.com', subject: 'Important message', body: source.text)
    end
    
    # 悪い例 (インデント2つで揃えています)
    def send_mail(source)
      Mailer.deliver(
          to: 'bob@example.com',
          from: 'us@example.com',
          subject: 'Important message',
          body: source.text)
    end
    
    # 良い例
    def send_mail(source)
      Mailer.deliver(to: 'bob@example.com',
                     from: 'us@example.com',
                     subject: 'Important message',
                     body: source.text)
    end
    
    # 良い例 (普通のインデントです)
    def send_mail(source)
      Mailer.deliver(
        to: 'bob@example.com',
        from: 'us@example.com',
        subject: 'Important message',
        body: source.text
      )
    end
  • 複数行に及ぶ配列は、要素を揃えましょう。 [link]

    # 悪い例 - インデント1つです
    menu_item = ["Spam", "Spam", "Spam", "Spam", "Spam", "Spam", "Spam", "Spam",
      "Baked beans", "Spam", "Spam", "Spam", "Spam", "Spam"]
    
    # 良い例
    menu_item = [
      "Spam", "Spam", "Spam", "Spam", "Spam", "Spam", "Spam", "Spam",
      "Baked beans", "Spam", "Spam", "Spam", "Spam", "Spam"
    ]
    
    # 良い例
    menu_item =
      ["Spam", "Spam", "Spam", "Spam", "Spam", "Spam", "Spam", "Spam",
       "Baked beans", "Spam", "Spam", "Spam", "Spam", "Spam"]
  • 可読性のため、大きな数値にはアンダースコアをつけましょう。 [link]

    # 悪い例 - 0はいくつありますか?
    num = 1000000
    
    # 良い例 - 人の頭でもより簡単に解析できます
    num = 1_000_000
  • 桁数が大きな2進法および16進法の数値リテラルは4桁毎に下線を入れて読みやすくする。 [link]

    • 例: 0xABCD_1234
  • 16進法はアルファベットの大文字で書いても小文字で書いても良いが、1つのファイルの中では統一すること。

  • 分数は r サフィックスを用いて書くこと。 [link]

    • 例: 1/2r #=> (1/2)
  • 複素数は i または ri サフィックスを用いて書くこと。 [link]

    • 例: 1 + 2i #=> (1+2i)
  • APIのドキュメントのため、RDocの規約に従いましょう。 コメント行とdefの間に空行を入れてはいけません。 [link]

  • [推奨] 特殊な事情が無い限りは1行の文字数を80文字以内に納めること (全角文字は2文字と数えること)。

  • どんな事情があろうとも1行の文字数が100文字を越えてはならない [link]

  • 行末のスペースは避けましょう。 [link]

  • ファイルの終端には改行を入れましょう。 [link]

  • ブロックコメントは使ってはいけません。 前にスペースが入ると機能しませんし、 通常のコメントと違い、簡単に見分けが付きません。 [link]

    # 悪い例
    == begin
    comment line
    another comment line
    == end
    
    # 良い例
    # comment line
    # another comment line

構文

  • ::は、定数(クラスやモジュールも含みます)や コンストラクタ(例えばArray()Nokogiri::HTML())を参照するときにのみ使いましょう。 通常のメソッド呼び出しでは::の使用は避けましょう。 [link]

    # 悪い例
    SomeClass::some_method
    some_object::some_method
    
    # 良い例
    SomeClass.some_method
    some_object.some_method
    SomeModule::SomeClass::SOME_CONST
    SomeModule::SomeClass()
  • 引数があるとき、def()と共に使いましょう。 引数がない場合は()は除きましょう。 [link]

    # 悪い例
    def some_method()
      # body omitted
    end
    
    # 良い例
    def some_method
      # body omitted
    end
    
    # 悪い例
    def some_method_with_arguments arg1, arg2
      # body omitted
    end
    
    # 良い例
    def some_method_with_arguments(arg1, arg2)
      # body omitted
    end
  • あなたが使ってはならない理由を正確に知っていなければ、決してforを使ってはいけません。 代わりにイテレータが使われるべきです。 foreachの観点で実装されています(だから、あなた方は遠回りでも使っています)が、 forは(eachと違い)新しいスコープを導入せず、 そのブロック内で定義された変数は、ブロックの外からも見えるようになってしまいます。 [link]

    arr = [1, 2, 3]
    
    # 悪い例
    for elem in arr do
      puts elem
    end
    
    # elemはルーブの外からも参照できることに注意しましょう
    elem # => 3
    
    # 良い例
    arr.each { |elem| puts elem }
    
    # elemはeachブロックの外からは参照できません
    elem # => NameError: undefined local variable or method `elem'
  • thenは複数行にまたがるif/unlessでは使ってはいけません。

  • if/unless 式には then を付加せず記述します。 [link]

# 悪い例
if some_condition then
  # 本文省略
end

# 良い例
if some_condition
  # 本文省略
end
  • 複数行にまたがるif/unlessでは、条件式は常にif/unlessと同じ行に置きましょう。 [link]

    # 悪い例
    if
      some_condition
      do_something
      do_something_else
    end
    
    # 良い例
    if some_condition
      do_something
      do_something_else
    end
  • if/then/else/end構文よりも三項演算子(?:)を好みます。 そちらの方がより明快で簡潔です。 [link]

    # 悪い例
    result = if some_condition then something else something_else end
    
    # 良い例
    result = some_condition ? something : something_else
  • 三項演算子は1つの式につき1つまでにしましょう。 つまり、三項演算子はネストしてはいけません。 このケースではif/elseの方がよいです。 [link]

    # 悪い例
    some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else
    
    # 良い例
    if some_condition
      nested_condition ? nested_something : nested_something_else
    else
      something_else
    end
  • if x: ...は使ってはいけません - Ruby 1.9現在は廃止されました。 代わりに三項演算子を使いましょう。 [link]

    # 悪い例
    result = if some_condition: something else something_else end
    
    # 良い例
    result = some_condition ? something : something_else
  • if x; ...を使ってはいけません。代わりに三項演算子を使いましょう。 [link]

  • 結果を返すifcase式の値を活用しましょう。 [link]

    # 悪い例
    if condition
      result = x
    else
      result = y
    end
    
    # 良い例
    retuls =
      if condition
        x
      else
        y
      end
  • 1行のcase文ではwhen x then ...を使いましょう。 代わりの表現であるwhen x: ...は、Ruby 1.9で廃止されました。 [link]

  • when x; ...を使ってはいけません。前のルールを見てください。 [link]

  • notの代わりに!を使いましょう。 [link]

    # 悪い例 - 評価順のため、()が必要になります
    x = (not something)
    
    # 良い例
    x = !something
  • !!は避けましょう。 [link]

    # 悪い例
    x = 'test'
    # obscure nil check
    if !!x
      # body omitted
    end
    
    x = false
    # 二重否定はbooleanとして役に立ちません。
    !!x # => false
    
    # 良い例
    x = 'test'
    unless x.nil?
      # body omitted
    end
  • andornotの使用は禁止です。それらにその価値はありません。 常に、代わりに&&||!を使いましょう。

  • ただし、式 or raise 'message'の時のみorを使っても良い。 [link]

# 悪い例
# boolean式
if some_condition and some_other_condition
  do_something
end

# 制御構文
document.saved? or document.save!

# 良い例
# boolean式
if some_condition && some_other_condition
  do_something
end

# 制御構文
document.saved? || document.save!
  • 複数行にまたがる三項演算子?:は避けましょう; 代わりにif/unlessを使いましょう。 [link]

  • 本文が1行のときは、if/unless修飾子を利用するのが好まれます。 他の良い代替案としては&&/||を使った制御構文があります。 [link]

    # 悪い例
    if some_condition
      do_something
    end
    
    # 良い例
    do_something if some_condition
    
    # もう1つの良い例
    some_condition && do_something
  • 重要な複数行のブロックにif/unless修飾子を用いるのは避けましょう。 [link]

    # 悪い例
    10.times do
      # 複数行のbody省略
    end if some_condition
    
    # 良い例
    if some_condition
      10.times do
        # 複数行のbody省略
      end
    end
  • 否定形のときはifよりunlessが好まれます。(もしくは||構文を使いましょう)。 [link]

    # 悪い例
    do_something if !some_condition
    
    # 悪い例
    do_something if not some_condition
    
    # 良い例
    do_something unless some_condition
    
    # もう1つの良い例
    some_condition || do_something
  • unlesselse付きで使ってはいけません。 肯定条件を先にして書き換えましょう。 [link]

    # 悪い例
    unless success?
      puts 'failure'
    else
      puts 'success'
    end
    
    # 良い例
    if success?
      puts 'success'
    else
      puts 'failure'
    end
  • unless および until の条件式に複数の項を || で結合した論理式 (加法標準形) を書いてはならない。 [link]

  • if/unless/while/until構文では()の使用は避けましょう. [link]

    # 悪い例
    if (x > 10)
      # body omitted
    end
    
    # 良い例
    if x > 10
      # body omitted
    end
  • while !condition の代わりに until condition と書くこと。 [link]

  • 複数行のwhile/untilでは、while/until condition doを使ってはいけません。 [link]

    # 悪い例
    while x > 5 do
      # 本文省略
    end
    
    until x > 5 do
      # 本文省略
    end
    
    # 良い例
    while x > 5
      # 本文省略
    end
    
    until x > 5
      # 本文省略
    end
  • 本文が1行のときは、while/until修飾子を利用しましょう。 [link]

    # 悪い例
    while some_condition
      do_something
    end
    
    # 良い例
    do_something while some_condition
  • 否定形のときは、whileよりもuntilの方が好まれます。 [link]

    # 悪い例
    do_something while !some_condition
    
    # 良い例
    do_something until some_condition
  • 無限ループが必要な時は、while/untilの代わりにKernel#loopを用いましょう。 [link]

    # 悪い例
    while true
      do_something
    end
    
    until false
      do_something
    end
    
    loop do
      do_something
    end
  • 後判定ループの場合、begin/end/untilbegin/end/whileより、break付きのKernel#loopが好まれます。 [link]

    # 悪い例
    begin
      puts val
      val += 1
    end while val < 0
    
    # 良い例
    loop do
      puts val
      val += 1
      break unless val < 0
    end
  • 内部DSL(例えばRake,Rails,RSpecなど)、 Ruby内で"キーワード"となるステータスを持ったメソッド(例えばattr_readerputsなど)や アトリビュートにアクセスするメソッドでは、 引数の周りの()を省略しましょう。 それ以外のメソッドでは、メソッド呼び出しの時に()を付けましょう。 [link]

    class Person
      attr_reader :name, :age
    
      # 省略
    end
    
    temperance = Person.new('Temperance', 30)
    temperance.name
    
    puts temperance.age
    
    x = Math.sin(y)
    array.delete(e)
    
    bowling.score.should == 0
  • 暗黙のオプションハッシュの外側の{}は省略しましょう。 [link]

    # 悪い例
    user.set({ name: 'John', age: 45, permissions: { read: true } })
    
    # 良い例
    user.set(name: 'John', age: 45, permissions: { read: true })
  • パラメータリストの末尾にハッシュリテラルを書く場合は、ハッシュリテラルの括弧を省略すること。 [link]

    # 良い例
    foo(1, 2, foo: :bar, baz: 42)
    
    # bad
    foo(1, 2, { foo: :bar, baz: 42 })
  • 内部DSLの一部として使われるメソッドの引数では、外側の(){}は省略しましょう [link]

    class Person < ActiveRecord::Base
      # 悪い例
      validates(:name, { presence: true, length: { within: 1..10 } })
    
      # 良い例
      validates :name, presence: true, length: { within: 1..10 }
    end
  • 引数のないメソッド呼び出しの()は省略しましょう。 [link]

    # 悪い例
    Kernel.exit!()
    2.even?()
    fork()
    'test'.upcase()
    
    # 良い例
    Kernel.exit!
    2.even?
    fork
    'test'.upcase
  • 1行のブロックではdo...endより{...}の方が好まれます。 複数行のブロックでは{...}は避けましょう (複数行のメソッドチェーンは常に醜いです)。 "制御構文"や"メソッド定義"では常にdo...endを使いましょう (例えばRakefilesや特定のDSLなど) メソッドチェーンでのdo...endは避けましょう。 [link]

    names = ['Bozhidar', 'Steve', 'Sarah']
    
    # 悪い例
    names.each do |name|
      puts name
    end
    
    # 良い例
    names.each { |name| puts name }
    
    # 悪い例
    names.select do |name|
      name.start_with?('S')
    end.map { |name| name.upcase }
    
    # 良い例
    names.select { |name| name.start_with?('S') }.map { |name| name.upcase }

    {...}を用いた複数行のメソッドチェーンをOKと主張する人もいるかもしれないが、 自問してみてほしい - このコードは本当に読みやすいだろうか? また、このブロックの本文は素早く展開できるだろうか?

  • do/end によるブロックでは、doの前後に空白を1つ入れ、ブロックパラメータの後で改行し、end は独立した行に書くこと。ブロック本体のインデントは1レベル下げ、end のインデントはメソッド呼び出しの1行目にあわせること。 [link]

    # 良い例
    [1, 2, 3].each do |num|
      puts num
    end
    
    # 悪い例
    [1, 2, 3].each do |num|
        puts num
      end
    
    # 悪い例
    [1, 2, 3].each do |num|
                     puts num
                   end
    
    # bad
    [1, 2, 3].each do |num| puts num end
  • 中括弧によるブロックでは、{ の前に空白を1つ入れること。 [link]

  • 中括弧によるブロックを1行で書く場合は、{ またはブロックパラメータと本体コードの間、および本体コードと } の間に空白を1つずつ入れること。 [link]

    # 良い例
    [1, 2, 3].each {|num| puts num }
    [1, 2, 3].each { |num| puts num }
    
    # 悪い例
    [1, 2, 3].each {|num| puts num}
    
    # 悪い例
    [1, 2, 3].each { |num| puts num}
    
    # 良い例
    10.times { puts 'Hello world' }
    
    # 悪い例
    10.times {puts 'Hello world' }
    
    # 悪い例
    10.times {puts 'Hello world'}
    
    # 悪い例
    10.times { puts 'Hello world'}
  • 長いメソッドチェインの最後のメソッド呼び出しでブロックを渡す場合、最後のメソッド呼び出しのレシーバをローカル変数として抽出し、ブロック付きメソッド呼び出しを独立した式として書くこと。 [link]

    # 良い例
    posts = Post.joins(:user)
      .merge(User.paid)
      .where(created_at: target_date)
    posts.each do |post|
      next if stuff_ids.include?(post.user_id)
      comment_count += post.comments.size
    end
    
    # 悪い例
    posts = Post.joins(:user)
      .merge(User.paid)
      .where(created_at: target_date).each do |post|
        next if stuff_ids.include?(post.user_id)
        comment_count += post.comments.size
      end
  • 式の途中で改行する場合は、2行目以降を1行目より1段深くインデントすること。 [link]

    # 良い例
    User.active
      .some_scope(foo)
      .other_scope(bar)
    
    # 悪い例
    User.active.
    some_scope(foo).
    other_scope(bar)
  • 単に他のブロックに引数を渡すだけのブロックリテラルを避けるため、 ブロック引数を明示することを検討しましょう。 ただしブロックがProcに変換されることでのパフォーマンスに気をつけましょう。 [link]

    require 'tempfile'
    
    # 悪い例
    def with_tmp_dir
      Dir.mktmpdir do |tmp_dir|
        Dir.chdir(tmp_dir) { |dir| yield dir }  # block just passes arguments
      end
    end
    
    # 良い例
    def with_tmp_dir(&block)
      Dir.mktmpdir do |tmp_dir|
        Dir.chdir(tmp_dir, &block)
      end
    end
    
    with_tmp_dir do |dir|
      puts "dir is accessible as parameter and pwd is set: #{dir}"
    end
  • 制御構文上不要なreturnは避けましょう。 [link]

    # 悪い例
    def some_method(some_arr)
      return some_arr.size
    end
    
    # 良い例
    def some_method(some_arr)
      some_arr.size
    end
  • 不要なselfは避けましょう (自身のアトリビュートへの書き込みでのみ必要です)。 [link]

    # 悪い例
    def ready?
      if self.last_reviewed_at > self.last_updated_at
        self.worker.update(self.content, self.options)
        self.status = :in_progress
      end
      self.status == :verified
    end
    
    # 良い例
    def ready?
      if last_reviewed_at > last_updated_at
        worker.update(content, options)
        self.status = :in_progress
      end
      status == :verified
    end
  • 当然の帰結として、ローカル変数でメソッドを隠すのは、 それらが等価なものでない限り避けましょう。 [link]

    class Foo
      attr_accessor :options
    
      # ok
      def initialize(options)
        self.options = options
        # both options and self.options are equivalent here
      end
    
      # 悪い例
      def do_something(options = {})
        unless options[:when] == :later
          output(self.options[:message])
        end
      end
    
      # 良い例
      def do_something(params = {})
        unless params[:when] == :later
          output(options[:message])
        end
      end
    end
  • 代入部分を()で囲まずに、=の返り値を条件式に用いてはいけません。 これは、Rubyistの中では 条件式内での安全な代入 としてとても有名です。 [link]

    # 悪い例 (+ 警告が出ます)
    if v = array.grep(/foo/)
      do_something(v)
      ...
    end
    
    # 良い例 (MRIはこれでも文句を言いますが、RuboCopでは問題ありません)
    if (v = array.grep(/foo/))
      do_something(v)
      ...
    end
    
    # 良い例
    v = array.grep(/foo/)
    if v
      do_something(v)
      ...
    end
  • 利用できるときには省略された自己代入演算子を用いましょう。 [link]

    # 悪い例
    x = x + y
    x = x * y
    x = x**y
    x = x / y
    x = x || y
    x = x && y
    
    # 良い例
    x += y
    x *= y
    x **= y
    x /= y
    x ||= y
    x &&= y
  • 変数の初期化には、||=を自由に使いましょう。 [link]

    # nameがnilかfalseでなければ、Bozhidarで初期化します
    name ||= 'Bozhidar'
  • boolean変数には||=を用いてはいけません (現在の値がfalseであったときに何が起こるか考えてみましょう)。 [link]

    # 悪い例 - たとえenabledがfalseでもtrueが入ります
    enabled ||= true
    
    # 良い例
    enabled = true if enabled.nil?
  • 値が入っているかわからない変数の前処理のは&&=を用いましょう。 &&=を使えば変数が存在するときのみ値を変更するので、 存在確認に用いている不要なifを除去できます。 [link]

    # 悪い例
    if something
      something = something.downcase
    end
    
    # 悪い例
    something = something ? something.downcase : nil
    
    # ok
    something = something.downcase if something
    
    # 良い例
    something = something && something.downcase
    
    # より良い例
    something &&= something.downcase
  • 等価演算子===の露骨な使用は避けましょう。 その名が示す通り、caseの条件判定で用いられており、 その外で用いられると混乱のもとになります。 [link]

    # 悪い例
    Array === something
    (1..100) === 7
    /something/ === some_string
    
    # 良い例
    something.is_a?(Array)
    (1..100).include?(7)
    some_string =~ /something/
  • Perlスタイルの($:$;などのような)特別な変数の使用は避けましょう。 それらは極めて不可解で、 1行のスクリプト以外でそれらが使われるとやる気が削がれます。 Englishライブラリから提供される人にやさしいエイリアスを用いましょう。 [link]

    # 悪い例
    $:.unshift File.dirname(__FILE__)
    
    # 良い例
    require 'English'
    $LOAD_PATH.unshift File.dirname(__FILE__)
  • メソッド名と引数の始まりの(の間にスペースを入れてはいけません。 [link]

    # 悪い例
    f (3 + 2) + 1
    
    # 良い例
    f(3 + 2) + 1
  • メソッドの最初の引数が(で始まるならば、 常にメソッド呼び出しに()を用いましょう。 例えば次のように書きます f((3 + 2) + 1)[link]

  • Rubyインタープリタを走らせるときは、常に-wオプションを付けましょう。 これまでのルールのどれかを忘れてしまった時に警告を出してくれます! [link]

  • 1行の本文を持つラムダには新しいリテラルを持ちましょう。 lambdaは複数行にまたがるときに使いましょう。 [link]

    # 悪い例
    l = lambda { |a, b| a + b }
    l.call(1, 2)
    
    # 正しい例、ですがギクシャクしています
    l = ->(a, b) do
      tmp = a * 7
      tmp * b / 50
    end
    
    # 良い例
    l = ->(a, b) { a + b }
    l.call(1, 2)
    
    l = lambda do |a, b|
      tmp = a * 7
      tmp * b / 50
    end
  • Proc.newよりprocを好みます。 [link]

    # 悪い例
    p = Proc.new { |n| puts n }
    
    # 良い例
    p = proc { |n| puts n }
  • ラムダやprocの呼び出しにはproc[]proc.()よりproc.call()を好みます。 [link]

    # 悪い例 - 列挙型のアクセスに似ているように見えます
    l = ->(v) { puts v }
    l[1]
    
    # こちらも悪い例 - 珍しい構文です
    l = ->(v) { puts v }
    l.(1)
    
    # 良い例
    l = ->(v) { puts v }
    l.call(1)
  • 使わないブロック引数やローカル変数の先頭には_を付けましょう。 単に_を用いるのも許容されます (少し説明不足ではありますが)。 この慣習はRubyインタープリタやRubocopのようなツールには認識されており、 変数を使っていないという警告を抑えることでしょう。 [link]

    # 悪い例
    result = hash.map { |k, v| v + 1 }
    
    def something(x)
      unused_var, used_var = something_else(x)
    end
    
    # 良い例
    result = hash.map { |_, v| v + 1 }
    
    def something(x)
      _, used_var = something_else(x)
    end
  • STDOUT/STDERR/STDINの代わりに$stdout/$stderr/$stdinを用いましょう。 STDOUT/STDERR/STDINは定数であり、 Rubyでの定数は、実際は再割当てできますが(他のストリームへのリダイレクトも可能)、 もし再割当てするとインタープリタからの警告が出るでしょう。 [link]

  • $stderr.putsの代わりにwarnを用いましょう。 簡潔さや明快さはさておき、 warnは必要であれば警告を抑制することができます (警告レベルを-W0を用いて0に設定することによって実現できます)。 [link]

  • 不可解なString#%メソッドよりsprintfformatを好みます。 [link]

    # 悪い例
    '%d %d' % [20, 10]
    # => '20 10'
    
    # 良い例
    sprintf('%d %d', 20, 10)
    # => '20 10'
    
    # 良い例
    sprintf('%{first} %{second}', first: 20, second: 10)
    # => '20 10'
    
    format('%d %d', 20, 10)
    # => '20 10'
    
    # 良い例
    format('%{first} %{second}', first: 20, second: 10)
    # => '20 10'
  • 不可解なArray#*メソッドよりもArray#joinを好みます。 [link]

    # 悪い例
    %w(one two three) * ', '
    # => 'one, two, three'
    
    # 良い例
    %w(one two three).join(', ')
    # => 'one, two, three'
  • 引数が配列かどうかわからないが、それを配列として扱って処理したいとき、 配列のチェックを明示するより、[*var]Array()を代わりに使いましょう。 [link]

    # 悪い例
    paths = [paths] unless paths.is_a? Array
    paths.each { |path| do_something(path) }
    
    # 良い例
    [*paths].each { |path| do_something(path) }
    
    # 良い例 (そして少し読みやすいです)
    Array(paths).each { |path| do_something(path) }
  • 複雑な比較ロジックの代わりに、 可能な限りRangeComparable#between?を用いましょう。 [link]

    # 悪い例
    do_something if x >= 1000 && x <= 2000
    
    # 良い例
    do_something if (1000..2000).include?(x)
    
    # 良い例
    do_something if x.between?(1000, 2000)
  • ==を明示した比較よりも判定メソッドを用いましょう。 数値の比較はOKです。 [link]

    # 悪い例
    if x % 2 == 0
    end
    
    if x % 2 == 1
    end
    
    if x == nil
    end
    
    # 良い例
    if x.even?
    end
    
    if x.odd?
    end
    
    if x.nil?
    end
    
    if x.zero?
    end
    
    if x == 0
    end
  • ブーリアン値を扱わない限り、露骨なnilでないかの検査は避けましょう。 [link]

    # 悪い例
    do_something if !something.nil?
    do_something if something != nil
    
    # 良い例
    do_something if something
    
    # 良い例 - ブーリアン値を扱うとき
    def value_set?
      !@some_boolean.nil?
    end
  • BEGINブロックの使用は避けましょう。 [link]

  • ENDブロックを使ってはいけません。代わりにKernel#at_exitを使いましょう。 [link]

    # 悪い例
    
    END { puts 'Goodbye!' }
    
    # 良い例
    
    at_exit { puts 'Goodbye!' }
  • フリップフロップの使用は避けましょう。 [link]

  • 制御構文で条件式のネストは避けましょう。 [link]

    不正なデータをアサートするにはガード節を好みます。 ガード節は、可能な限り関数から出ていくために、 関数の先頭付近で宣言される条件式です。

    # 悪い例
    def compute_thing(thing)
      if thing[:foo]
        update_with_bar(thing)
        if thing[:foo][:bar]
          partial_compute(thing)
        else
          re_compute(thing)
        end
      end
    end
    
    # 良い例
    def compute_thing(thing)
      return unless thing[:foo]
      update_with_bar(thing[:foo])
      return re_compute(thing) unless thing[:foo][:bar]
      partial_compute(thing)
    end

    ループ内では条件判定ブロックよりもnextが好まれます。

    # 悪い例
    [0, 1, 2, 3].each do |item|
      if item > 1
        puts item
      end
    end
    
    # 良い例
    [0, 1, 2, 3].each do |item|
      next unless item > 1
      puts item
    end

命名規則

  • 識別子は英語で名づけましょう。
  • 変数名は英単語を省略せずに使って名付けること。
  • ただし、変数名が長くなってしまう場合は、単語の頭文字を除く母音を削除したり、一般的な略語を選択するなどの方法で短縮化してよい。
  • また、慣習的な名前 (ループカウンタとしての ij など) は許可する。 [link]
# 悪い例 - 識別子がnon-asciiな文字列です
заплата = 1_000

# 悪い例 - (キリル文字の代わりに)ラテン文字で書かれてはいますが、識別子がブルガリア語です
zaplata = 1_000

# 良い例
salary = 1_000
  • シンボル、メソッド、変数にはsnake_caseを用いましょう。 [link]

    # 悪い例
    :'some symbol'
    :SomeSymbol
    :someSymbol
    
    someVar = 5
    
    def someMethod
      ...
    end
    
    def SomeMethod
     ...
    end
    
    # 良い例
    :some_symbol
    
    def some_method
      ...
    end
  • クラスやモジュールにはCamelCaseを用いましょう。(HTTP, RFC, XMLのような頭字語は大文字を保ちましょう)。 [link]

    # 悪い例
    class Someclass
      ...
    end
    
    class Some_Class
      ...
    end
    
    class SomeXml
      ...
    end
    
    # 良い例
    class SomeClass
      ...
    end
    
    class SomeXML
      ...
    end
  • ファイル名にはsnake_caseを用いましょう。例えばhello_world.rbのように。 [link]

  • ディレクトリ名にはsnake_caseを用いましょう。例えばlib/hello_world/hello_world.rbのように。 [link]

  • 1つのclass/moduleにつき、ちょうど1つのファイルを持つことを目指しましょう。 ファイル名はCamlCasesnake_caseに置き換えたclass/module名を用いて命名しましょう。 [link]

  • 他の定数はSCREAMING_SNAKE_CASEを用いましょう。 [link]

    # 悪い例
    SomeConst = 5
    
    # 良い例
    SOME_CONST = 5
  • 条件判定メソッド(boolean値が返る)には?を末尾に付けましょう (すなわちArray#empty?のように)。 メソッドがboolean値を返さなければ、末尾に?を付けてはいけません。 [link]

  • 危険 な可能性のあるメソッド (すなわちselfのアトリビュートに変更が加えられるものや、 exit!(exitと違ってファイナライザが走らない)のようなもの) は、 危険 であることを示すため、 末尾に!を付けましょう。 [link]

    # 悪い例 - '安全'なメソッドです
    class Person
      def update!
      end
    end
    
    # 良い例
    class Person
      def update
      end
    end
    
    # 良い例
    class Person
      def update!
      end
    
      def update
      end
    end
  • 可能な限り、危険なメソッドの観点から安全なメソッドを定義しましょう。 [link]

    class Array
      def flatten_once!
        res = []
    
        each do |e|
          [*e].each { |f| res << f }
        end
    
        replace(res)
      end
    
      def flatten_once
        dup.flatten_once!
      end
    end
  • 短いブロックと共にreduceを使うとき、引数は|a, e|と名づけましょう。 (accumulator, element). [link]

  • 二項演算子を定義するとき、引数はotherを用いましょう (<<[]は意味が違ってくるので、このルールの例外です)。 [link]

    def +(other)
      # body omitted
    end
  • collectよりmapdetectよりfindfind_allよりselect injectよりreducelengthよりsizeを好みます。 これは厳しい要件ではありません; もしエイリアスを用いるほうが可読性が上がるのであれば、 使うのもOKです。 それらの同韻のメソッドはSmalltalkから継承されており、 他の言語ではあまり一般的ではありません。 find_allよりもselectが推奨される理由は、 rejectと共に用いた時、その名前が極めて自己説明的だからです。 [link]

  • sizeの代わりにcountを用いてはいけません。 Array以外のEnumerableオブジェクトでは、 サイズを求めるためにコレクション全てをイテレートしてしまいます。 [link]

    # 悪い例
    some_hash.count
    
    # 良い例
    some_hash.size
  • mapflattenの組み合わせの代わりに、flat_mapを用いましょう。 これは深さが2以上の配列には適用できません。 すなわち、users.first.songs == ['a', ['b','c']]のときは、 flat_mapよりmap + flattenを用いましょう。 flattenは配列を全て平坦にするのに対し、flat_mapは配列を1次元だけ平坦にします。 [link]

    # 悪い例
    all_songs = users.map(&:songs).flatten.uniq
    
    # 良い例
    all_songs = users.flat_map(&:songs).uniq
  • reverse.eachの代わりにreverse_eachを用いましょう。 reverse_eachは新しい配列を作らないので、それが利点です。 [link]

    # 悪い例
    array.reverse.each { ... }
    
    # 良い例
    array.reverse_each { ... }

コメント

  • コードそのものがドキュメントになるような説明的なコードを書いて、このセクションの残りのパートは無視しましょう。本当に! [link]

  • コメントは英語で書きましょう。 [link]

  • 最初の#とコメントの間にスペースを1つ入れましょう。 [link]

  • 1語より長いコメントを活用し、句読点を使いましょう。 ピリオドの後にone spaceを使いましょう。 [link]

  • 余計なコメントは避けましょう。 [link]

    # 悪い例
    counter += 1 # Increments counter by one.
  • ドキュメンテーションコメントはTomDocのフォーマットに従うこと。

  • モジュールやクラスが外部に公開するメソッドとアクセサに対してドキュメンテーションコメントを Markdown 形式で書くこと。

[link]

  • コメントは最新に保ちましょう。 古くなったコメントは、コメントがないより悪いです。 [link]

  • 悪いコードを説明するコメントは避けましょう。 自己説明的なコードへのリファクタリングを行いましょう [link]

  • メソッドの本体コードにコメントを書かなければ理解できないようなコードを書いてはならない。

  • メソッド本体内にコメントを書くよりも、別のメソッドに分けて適切な名前を付ける方が可読性が向上する。

  • ただし、数式に対する補足や出展などはコード本体中にコメントとして書いても良い。 [link]

注釈

  • 注釈は、通常関連するコードのすぐ上に書きましょう。 [link]

  • 注釈のキーワードの後ろは: を続けましょう。 その後ろに問題点を書きましょう。 [link]

  • もし問題点の記述に複数行かかる場合は、 後続の行は#の後ろにスペース2つでインデントしましょう。 [link]

    def bar
      # FIXME: This has crashed occasionally since v3.2.1. It may
      #   be related to the BarBazUtil upgrade.
      baz(:quux)
    end
  • もし問題が明らかで、記述が冗長な場合は、 問題のある行の末尾に、本文なしの注釈だけ付けましょう。 この用法は例外であり、ルールではありません。 [link]

    def bar
      sleep 100 # OPTIMIZE
    end
  • あとで追加されるべき、今はない機能や関数を書き留めるにはTODOを使いましょう。 [link]

  • 直す必要がある壊れたコードを書き留めるにはFIXMEを使いましょう。 [link]

  • パフォーマンスに問題を及ぼすような、遅い、または非効率なコードを書き留めるにはOPTIMIZEを使いましょう。 [link]

  • 疑わしくリファクタリングで除去すべきコードの匂いを書き留めるにはHACKを使いましょう。 [link]

  • 意図したとおりに動くか確認する必要がある箇所を書き留めるにはREVIEWを使いましょう。 例: REVIEW: Are we sure this is how the client does X currently? [link]

  • 適切に感じるのであれば、他の独自のキーワードを用いても構いませんが、 それらのキーワードはREADMEやそれに類するものに書いておきましょう。 [link]

クラス

  • クラス定義は置いて一貫性のある構造にしましょう。 [link]

    class Person
      # extend や include を最初に行います
      extend SomeModule
      include AnotherModule
    
      # 定数定義はその次です
      SOME_CONSTANT = 20
    
      # その後ろはアトリビュートマクロです
      attr_reader :name
    
      # 他のマクロが続きます(もしあれば)
      validates :name
    
      # public class methods が次に来ます
      def self.some_method
      end
    
      # public instance methods が続きます
      def some_method
      end
    
      # protected and private methods は後ろの方にまとめます
      protected
    
      def some_protected_method
      end
    
      private
    
      def some_private_method
      end
    end
  • 複数行のクラスの中に複数行のクラスをネストさせてはいけません。 そのようにネストされたクラスは、それが含まれるクラス名のフォルダの中に それぞれのクラスのファイルを置くように努めましょう。 [link]

    # 悪い例
    
    # foo.rb
    class Foo
      class Bar
        # 中に30メソッド
      end
    
      class Car
        # 中に20メソッド
      end
    
      # 中に30メソッド
    end
    
    # 良い例
    
    # foo.rb
    class Foo
      # 中に30メソッド
    end
    
    # foo/bar.rb
    class Foo
      class Bar
        # 中に30メソッド
      end
    end
    
    # foo/car.rb
    class Foo
      class Car
        # 中に20メソッド
      end
    end
  • クラスメソッドしかないクラスはモジュールであることが好まれます。 クラスはインスタンスを生成することにのみ意味があります。 [link]

    # 悪い例
    class SomeClass
      def self.some_method
        # body omitted
      end
    
      def self.some_other_method
      end
    end
    
    # 良い例
    module SomeClass
      module_function
    
      def some_method
        # body omitted
      end
    
      def some_other_method
      end
    end
  • モジュールのインスタンスメソッドをクラスメソッドにしたいときは、 extend selfよりもmodule_functionが好まれます。 [link]

    # 悪い例
    module Utilities
      extend self
    
      def parse_something(string)
        # do stuff here
      end
    
      def other_utility_method(number, string)
        # do some more stuff
      end
    end
    
    # 良い例
    module Utilities
      module_function
    
      def parse_something(string)
        # do stuff here
      end
    
      def other_utility_method(number, string)
        # do some more stuff
      end
    end
  • クラス階層の設計を行うときは、 リスコフの置換原則. に従いましょう。 [link]

  • あなたのクラスを可能な限り SOLID に保ちましょう。 [link]

  • クラスの領分を説明するため、常にto_sメソッドを提供しましょう。 [link]

    class Person
      attr_reader :first_name, :last_name
    
      def initialize(first_name, last_name)
        @first_name = first_name
        @last_name = last_name
      end
    
      def to_s
        "#{@first_name} #{@last_name}"
      end
    end
  • 単純なアクセサやミューテータの定義には、attr群を用いましょう。 [link]

    # 悪い例
    class Person
      def initialize(first_name, last_name)
        @first_name = first_name
        @last_name = last_name
      end
    
      def first_name
        @first_name
      end
    
      def last_name
        @last_name
      end
    end
    
    # 良い例
    class Person
      attr_reader :first_name, :last_name
    
      def initialize(first_name, last_name)
        @first_name = first_name
        @last_name = last_name
      end
    end
  • attrの使用は避けましょう。代わりにattr_readerattr_accessorを使いましょう。 [link]

    # 悪い例 - 1つのアクセサしか作れません(1.9で廃止されました)
    attr :something, true
    attr :one, :two, :three # attr_readerと同じです
    
    # 良い例
    attr_accessor :something
    attr_reader :one, :two, :three
  • Struct.newの使用を考えましょう、 それは、単純なアクセサ、コンストラクタや比較演算子を定義してくれます。 [link]

    # 良い例
    class Person
      attr_accessor :first_name, :last_name
    
      def initialize(first_name, last_name)
        @first_name = first_name
        @last_name = last_name
      end
    end
    
    # より良い例
    Person = Struct.new(:first_name, :last_name) do
    end
  • Struct.newを拡張してはいけません - それは既に新しいクラスです。 それは余分なクラスレベルをもたらし、 複数回requireされた時に、奇妙なエラーの原因にもなります。 [link]

  • あるクラスのインスタンス生成する追加の方法を提供したいときは、 ファクトリメソッドの追加を検討しましょう。 [link]

    class Person
      def self.create(options_hash)
        # body omitted
      end
    end
  • 継承よりダック・タイピングが好まれます。 [link]

    # 悪い例
    class Animal
      # abstract method
      def speak
      end
    end
    
    # 継承
    class Duck < Animal
      def speak
        puts 'Quack! Quack'
      end
    end
    
    # 継承
    class Dog < Animal
      def speak
        puts 'Bau! Bau!'
      end
    end
    
    # 良い例
    class Duck
      def speak
        puts 'Quack! Quack'
      end
    end
    
    class Dog
      def speak
        puts 'Bau! Bau!'
      end
    end
  • 継承での振る舞いが"扱いづらい"ので、クラス変数(@@)の使用は避けましょう。代わりに class_attribute を使用すること [link]

    class Parent
      @@class_var = 'parent'
    
      def self.print_class_var
        puts @@class_var
      end
    end
    
    class Child < Parent
      @@class_var = 'child'
    end
    
    Parent.print_class_var # => will print "child"

    クラス階層内の全てのクラスを見ることができるように、 実際にクラス変数を1つ共有してみましょう。 クラスインスタンス変数はクラス変数より好まれます。

  • 意図した使い方に沿って、可視性(privateprotected)を設定しましょう。 全てをpublic(デフォルトの設定)のままにしないようにしましょう。 結局私達は今 Ruby を書いているのだから。 Python ではなく。 [link]

  • publicprotectedprivateは、適用するメソッド定義と同じインデントにしましょう。 可視性を定義する識別子以降のメソッドに適用されることを強調するため、 識別子の上下に空行を入れましょう。 [link]

    class SomeClass
      def public_method
        # ...
      end
    
      private
    
      def private_method
        # ...
      end
    
      def another_private_method
        # ...
      end
    end
  • メソッド定義の後で、そのメソッドの可視性を変更するために privateprotectedpublic を引数付きで呼び出す場合は、メソッド定義とこれらのメソッド呼び出しの間に空行を入れてはならない。 [link]

    class Foo
      # 良い例
      def foo
      end
      private :foo
    
      # 悪い例
      def foo
      end
    
      private :foo
    end
  • privateprotectedpublic を引数なしで使用する場合、インデントレベルはメソッド定義と同じレベルとし、前後に1行ずつ空白を入れること。 [link]

    # 良い例
    class Foo
      def foo
      end
    
      private
    
      def bar
      end
    end
    
    # 悪い例
    class Foo
      def foo
      end
    
    private
    
      def bar
      end
    end
    
    # 悪い例
    class Foo
      def foo
      end
    
      private
    
        def bar
        end
    end
    
    # 悪い例
    class Foo
      def foo
      end
    
      private
      def bar
      end
    end
  • シングルトンメソッドを定義するときはdef self.methodを用いましょう。 クラス名を繰り返さないので、簡単にリファクタリングできるようになります。 [link]

    class TestClass
      # 悪い例
      def TestClass.some_method
        # body omitted
      end
    
      # 良い例
      def self.some_other_method
        # body omitted
      end
    
      # たくさんのシングルトンメソッドを定義しなければならない時
      # この書き方も便利で、許容できます。
      class << self
        def first_method
          # body omitted
        end
    
        def second_method_etc
          # body omitted
        end
      end
    end

例外

  • 例外発生にはfailを用いましょう。 raiseは例外をキャッチして、再度発生させるときにのみ使いましょう (何故なら、ここでは落ちるのではなく、明示的に目的を持って例外を発生させているからです)。 [link]

    begin
      fail 'Oops'
    rescue => error
      raise if error.message != 'Oops'
    end
  • 2引数のfail/raiseでは、RuntimeErrorを明示しないようにしましょう。 [link]

    # 悪い例
    fail RuntimeError, 'message'
    
    # 良い例 - デフォルトでRuntimeErrorが発生します
    fail 'message'
  • 例外インスタンスの代わりに、 例外クラスとメッセージが分かれているfail/raiseが好まれます。 [link]

    # 悪い例
    fail SomeException.new('message')
    # `fail SomeException.new('message'), backtrace`とする書き方が存在しないことに注意しましょう。
    
    # 良い例
    fail SomeException, 'message'
    # `fail SomeException, 'message', backtrace`の用法と一貫性があります
  • ensureブロックからreturnしてはいけません。 もしensureから明示的に値を返したい場合は、 returnはどの例外発生よりも前に書いておき、 例外など発生していなかったかのように値を返しましょう。 事実上、例外は静かに捨てられます。 [link]

    def foo
      begin
        fail
      ensure
        return 'very bad idea'
      end
    end
  • 可能な場所では、 暗黙のbeginブロック を用いましょう。 [link]

    # 悪い例
    def foo
      begin
        # main logic goes here
      rescue
        # failure handling goes here
      end
    end
    
    # 良い例
    def foo
      # main logic goes here
    rescue
      # failure handling goes here
    end
  • 不確実性のあるメソッド(Avdi Grimmによって作られた言葉です) を用いてbeginの蔓延を和らげましょう。 [link]

    # 悪い例
    begin
      something_that_might_fail
    rescue IOError
      # handle IOError
    end
    
    begin
      something_else_that_might_fail
    rescue IOError
      # handle IOError
    end
    
    # 良い例
    def with_io_error_handling
      yield
    rescue IOError
      # handle IOError
    end
    
    with_io_error_handling { something_that_might_fail }
    
    with_io_error_handling { something_else_that_might_fail }
  • 例外をもみ消してはいけません。 [link]

    # 悪い例
    begin
      # an exception occurs here
    rescue SomeError
      # the rescue clause does absolutely nothing
    end
    
    # 悪い例
    do_something rescue nil
  • rescueを修飾子として利用するのは避けましょう。 [link]

    # 悪い例 - StandardErrorとそれを継承した全てのクラスをキャッチしてしまいます
    read_file rescue handle_error($!)
    
    # 良い例 - Errno::ENOENTとそれを継承したクラスのみをキャッチします
    def foo
      read_file
    rescue Errno::ENOENT => ex
      handle_error(ex)
    end
  • 制御フローに例外を使っては行けません。 [link]

    # 悪い例
    begin
      n / d
    rescue ZeroDivisionError
      puts 'Cannot divide by 0!'
    end
    
    # 良い例
    if d.zero?
      puts 'Cannot divide by 0!'
    else
      n / d
    end
  • Exceptionrescueするのは避けましょう。 これはexitのシグナルも捕捉するため、kill -9が必要になります。 [link]

    # 悪い例
    begin
      # calls to exit and kill signals will be caught (except kill -9)
      exit
    rescue Exception
      puts "you didn't really want to exit, right?"
      # exception handling
    end
    
    # 良い例
    begin
      # a blind rescue rescues from StandardError, not Exception as many
      # programmers assume.
    rescue => e
      # exception handling
    end
    
    # こちらも良い例
    begin
      # an exception occurs here
    
    rescue StandardError => e
      # exception handling
    end
  • より詳細な例外をrescueチェーンの上に配置しましょう。 そうでなければ、決してrescueされません。 [link]

    # 悪い例
    begin
      # 処理
    rescue Exception => e
      # エラー処理
    rescue StandardError => e
      # 決して到達しないエラー処理
    end
    
    # 良い例
    begin
      # 処理
    rescue StandardError => e
      # エラー処理
    rescue Exception => e
      # エラー処理
    end
  • 外部リソースの含まれるプログラムでは、ensureで開放しましょう [link]

    f = File.open('testfile')
    begin
      # .. process
    rescue
      # .. handle error
    ensure
      f.close if f
    end
  • 新しい例外クラスを導入するより、基本ライブラリの例外クラスを用いることが好まれます。 [link]

Collections

  • 配列やハッシュのリテラルの方が好まれます。 (コンストラクタに引数を渡す場合を除けば、ということですが)
  • 引数なしの Array.new Hash.new を使ってはならない。
  • 同じ要素を n 個持つ配列を初期化するときは Array.new(n, obj) を使用すること。[obj] * n と書いてはならない。

[link]

# 悪い例
arr = Array.new
hash = Hash.new

# 良い例
arr = []
hash = {}
  • 範囲リテラルを配列に変換するときは、Range#to_a ではなく [*range] を使うこと。 [link]

    # 良い例
    [*1..10]  #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    # bad
    (1..10).to_a  #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • (空文字列や、文字列内にスペースが入っていない)文字列の配列構文は、 %wリテラルの方が好まれます。 このルールは要素が2つ以上の配列に適用されます。 [link]

    # 悪い例
    STATES = ['draft', 'open', 'closed']
    
    # 良い例
    STATES = %w(draft open closed)
  • シンボルの配列が必要なときは%iが好まれます (Ruby 1.9との互換性の維持が必要で無ければ)。 このルールは要素が2つ以上の配列に適用されます。 [link]

    # 悪い例
    STATES = [:draft, :open, :closed]
    
    # 良い例
    STATES = %i(draft open closed)
  • ArrayHashリテラルの最後の要素の後ろの,は避けましょう。 複数行にわかれていない時は特に避けましょう。 [link]

    # 悪い例 - 簡単に要素を移動・追加・削除できますが、それでも好まれません。
    VALUES = [
               1001,
               2020,
               3333,
             ]
    
    # 悪い例
    VALUES = [1001, 2020, 3333, ]
    
    # 良い例
    VALUES = [1001, 2020, 3333]
  • 配列に大きな隙間を作るのは避けましょう。 [link]

    arr = []
    arr[100] = 1 # now you have an array with lots of nils
  • 配列の最初や最後にアクセスしたいときは、 [0][-1]よりfirstlastが好まれます。 [link]

  • 要素が一意のものを扱うときは、Arrayの代わりにSetを用いましょう。 Setは重複がない要素が順序を持たないように実装されています。 これはArrayの直感的な内部操作と、Hashの要素発見の速さが合わさっています。 [link]

  • 配列リテラルを複数行で書く場合、[ の後ろで改行し、要素行のインデントを1レベル下げ、] は独立した行に置いて [ を書いた行の行頭にインデントを揃える。 [link]

    # 良い例
    [
      :foo,
      :bar,
      :baz
    ]
    
    # 悪い例
    [:foo,
      :bar,
      :baz
    ]
  • 代入の後ろに配列リテラルを複数行で書く場合は、[ の後ろで改行し、要素行のインデントを1レベル下げ、] は独立した行に置いて [ を書いた行の行頭にインデントを揃える。 [link]

    # 良い例
    array = [
      :foo,
      :bar,
      :baz
    ]
    
    # 悪い例
    array = [ :foo,
              :bar,
              :baz, ]
    
    # 悪い例
    array = [ :foo,
              :bar,
              :baz,
            ]
    
    # 悪い例
    array = [
      :foo,
      :bar,
      :baz, ]
  • ハッシュのキーには文字列よりシンボルが好まれます。 [link]

    # 悪い例
    hash = { 'one' => 1, 'two' => 2, 'three' => 3 }
    
    # 良い例
    hash = { one: 1, two: 2, three: 3 }
  • 変更のできるオブジェクトをハッシュのキーに使うのは避けましょう。 [link]

  • ハッシュのキーがシンボルの時は、Ruby 1.9のハッシュリテラル記法を用いましょう。 [link]

    # 悪い例
    hash = { :one => 1, :two => 2, :three => 3 }
    
    # 良い例
    hash = { one: 1, two: 2, three: 3 }
  • Ruby 1.9のハッシュ記法とハッシュロケットを同じハッシュリテラル内で混在させてはいけません。 シンボルでないキーがある場合は、ハッシュロケット記法を続けなければなりません。

  • ハッシュリテラルの key が symbol だが、., -等を含む場合、HashRocket に統一するのが望ましい。 [link]

# 悪い例
{ a: 1, 'b' => 2 }

# 良い例
{ :a => 1, 'b' => 2 }
```ruby
# 良い例
{ :cookpad => 42,
  :'cookpad.com' => 'foo',
}
# bad
{ cookpad: 42,
  :'cookpad.com' => 'foo',
}
```
  • ハッシュリテラルを単独で複数行で書く場合は、{ の後で改行し、要素行のインデントを1レベル下げ、} は独立した行に置いて { を書いた行の行頭にインデントを揃える。 [link]

    # 悪い例
    { first: 42,
      second: 'foo',
    }
    
    # 良い例
    {
      first: 42,
      second: 'foo',
    }
    
    # 悪い例
    { first: 42,
    second: 'foo',
    }
  • 代入の後ろに配列リテラルを複数行で書く場合は、{ の後で改行し、要素行のインデントを1レベル下げ、} は独立した行に置いて { を書いた行の行頭にインデントを揃える。 [link]

    # 良い例
    hash = {
      first: 42,
      second: 'foo',
    }
    
    # 悪い例
    hash = { first: 42,
             second: 'foo',
           }
    
    # 悪い例
    hash = { first: 42,
             second: 'foo',
    }
    
    # 悪い例
    hash = { first: 42,
      second: 'foo',
    }
    
    # 悪い例
    hash = {
    first: 42,
    second: 'foo',
    }
  • Hash#has_key?よりHash#key?を、 Hash#has_value?よりHash#value?を用いましょう。 ここ でMatzが述べているように、長い記法は廃止が検討されています。 [link]

    # 悪い例
    hash.has_key?(:test)
    hash.has_value?(value)
    
    # 良い例
    hash.key?(:test)
    hash.value?(value)
  • 存在すべきキーを扱う時は、Hash#fetchを用いましょう。 [link]

    heroes = { batman: 'Bruce Wayne', superman: 'Clark Kent' }
    # 悪い例 - もし誤りがあってもすぐに気づくことができないかもしれません
    heroes[:batman] # => "Bruce Wayne"
    heroes[:supermann] # => nil
    
    # 良い例 - fetchはKeyErrorを投げるので、問題が明らかになります
    heroes.fetch(:supermann)
  • 独自のロジックを用いないようにするため、 Hash#fetch経由でデフォルト値を導入しましょう。 [link]

    batman = { name: 'Bruce Wayne', is_evil: false }
    
    # 悪い例 - falseと判定される値が入っていた場合、望んだとお降りに動かないかもしれません
    batman[:is_evil] || true # => true
    
    # 良い例 - falseと判定される値が入っていても正しく動きます
    batman.fetch(:is_evil, true) # => false
  • Hash#fetchでは、デフォルト値の代わりにブロックを用いることが好まれます。 [link]

    batman = { name: 'Bruce Wayne' }
    
    # 悪い例 - デフォルト値が使われると、先に評価してしまいます
    # だから、もし複数回呼ばれると、プログラムが遅くなります
    batman.fetch(:powers, get_batman_powers) # get_batman_powers は高価な呼び出しです
    
    # 良い例 - ブロックは後から評価されます。だから、KeyErrorが評価の引き金になります
    batman.fetch(:powers) { get_batman_powers }
  • ハッシュから連続して複数の値が必要になる時は、Hash#values_atを用いましょう。 [link]

    # 悪い例
    email = data['email']
    nickname = data['nickname']
    
    # 良い例
    email, username = data.values_at('email', 'nickname')
  • Ruby 1.9現在ではハッシュは順序付けられるということを信頼しましょう。 [link]

  • コレクションを走査している時に変更を加えてわいけません。 [link]

変数

  • ひとつの変数を異なる役割のために使い回してはならない。そうしたくなる場合は、メソッドを複数のメソッドに分割できる。 [link]

  • ローカル変数のスコープ (有効範囲) を可能な限り小さくすること。ローカル変数が存在しないメソッドは良いメソッドである。 [link]

文字列

  • 空文字列は '' と書くこと。

  • 理由が無い限り引数なしの String.new を使ってはならない。

  • 文字列内部のエスケープシーケンスが最も少なくなるよう、適切な区切り記号を選択すること。

  • 文字列連結の代わりに文字列挿入や文字列整形を好みます。 [link]

    # 悪い例
    email_with_name = user.name + ' <' + user.email + '>'
    
    # 良い例
    email_with_name = "#{user.name} <#{user.email}>"
    
    # 良い例
    email_with_name = format('%s <%s>', user.name, user.email)
  • 式展開の中で Object#to_s だけを呼び出してはならない。たとえばこういうの→"#{obj.to_s}"

  • 式展開の中括弧を省略してはならない。

  • 文字列挿入時にはスペースを入れることを検討しましょう。 文字列から分かれたコードがより明確になります。 [link]

    "#{ user.last_name }, #{ user.first_name }"
  • 一貫した文字列リテラルの引用記号のスタイルを採用しましょう。 Rubyコミュニティには2つの有名なスタイル - デフォルトでシングルクォートを用いるもの (Option A)、 ダブルクォートを用いるもの (Option B) - があり、 どちらも良いと考えられています。   文字列内部のエスケープシーケンスが最も少なくなるよう、適切な区切り記号を選択すること。 [link]

    • (Option A) 文字列挿入の必要がないときや、\t\n`’`等の特別な文字がない場合は、 シングルクォーテーションが好まれます。

      # 悪い例
      name = "Bozhidar"
      
      # 良い例
      name = 'Bozhidar'
    • (Option B) 文字列中に"を含んでいたり、エスケープ文字を抑えたいときでない限り、 ダブルクォーテーションが好まれます。

      # 悪い例
      name = 'Bozhidar'
      
      # 良い例
      name = "Bozhidar"

    Rubyコミュニティの中では、ほぼ間違いなく 2つ目のスタイルの方が有名です。 しかしながら、このガイド内の文字列リテラル表記は、 1つ目のスタイルを採用しています。

  • % 記法で文字列リテラルを書く場合は、括弧を区切り記号に使用すること。括弧の種類はどれでも良い。ただし、次のような特殊な場合は括弧以外を区切り記号として良い: [link]

    OPEN_PARENTHESES = %!({[!
  • 文字リテラル構文?xを用いてはいけません。 [link]

    # 悪い例
    char = ?c
    
    # 良い例
    char = 'c'
  • 文字列の中の挿入されるインスタンス変数やグローバル変数の周りの {}は省略してはいけません。 [link]

    class Person
      attr_reader :first_name, :last_name
    
      def initialize(first_name, last_name)
        @first_name = first_name
        @last_name = last_name
      end
    
      # 悪い例 - 有効ですが不格好です
      def to_s
        "#@first_name #@last_name"
      end
    
      # 良い例
      def to_s
        "#{@first_name} #{@last_name}"
      end
    end
    
    $global = 0
    # 悪い例
    puts "$global = #$global"
    
    # 良い例
    puts "$global = #{$global}"
  • 文字列に挿入するときにObject#to_sを使ってはいけません。 自動的に呼び出されます。 [link]

    # 悪い例
    message = "This is the #{result.to_s}."
    
    # 良い例
    message = "This is the #{result}."
  • 大きなデータの塊を作る必要があるときは、String#+の使用は避けましょう。 代わりに、String#<<を使いましょう。 連結String#<<は、文字列インスタンスを直接書き換えるため、 String#+よりも常に速いです、 String#+はたくさんの新しいオブジェクトを作ってしまいます。 [link]

    # 良く、そして速い例
    html = ''
    html << '<h1>Page title</h1>'
    
    paragraphs.each do |paragraph|
      html << "<p>#{paragraph}</p>"
    end
  • 複数行のヒアドキュメントを用いるときは、 先頭のスペースも保持してしまうということを頭に入れておかなければなりません。 過剰なスペースを取り除くためのマージンを採用するのを実用的です。 [link]

    code = <<-END.gsub(/^\s+\|/, '')
      |def test
      |  some_method
      |  other_method
      |end
    END
    # => "def test\n  some_method\n  other_method\nend\n"
  • ループ内で文字列リテラルを書いてはならない。ここでループとは whileuntilfor、およびイテレータ (each などのブロックを何度も呼び出すブロック付きメソッド呼び出しのブロック内) である。 [link]

正規表現

  • 単にプレーンテキストを文字列中から探すだけの時は、 正規表現を使ってはいけません: string['text']を使いましょう。 [link]

  • 単純化のため、文字列の添字に直接正規表現を渡しましょう。 [link]

    match = string[/regexp/]             # get content of matched regexp
    first_group = string[/text(grp)/, 1] # get content of captured group
    string[/text (grp)/, 1] = 'replace'  # string => 'text replace'
  • 捕捉した結果を使う必要のないとき、捕捉しないグループを用いましょう。

  • 必要のない後方参照グループを作成してはならない。(?: ... ) を使うこと。 [link]

/(first|second)/   # 悪い例
/(?:first|second)/ # 良い例
  • 最後に正規表現にマッチした値を示すPerlレガシーの暗号的な変数を用いてはいけません ($1$2など)。 代わりにRegexp.last_match[n]を用いましょう。 [link]

    /(regexp)/ =~ string
    ...
    
    # 悪い例
    process $1
    
    # 良い例
    process Regexp.last_match[1]
  • どの値が入っているか追うのが困難になるので、 順序付けられたグループを使うのは避けましょう。 代わりに名付けられたグループを使いましょう。 [link]

    # 悪い例
    /(regexp)/ =~ string
    ...
    process Regexp.last_match[1]
    
    # 良い例
    /(?<meaningful_var>regexp)/ =~ string
    ...
    process meaningful_var
  • 文字クラスの中では、特別な意味を持つ文字が少ないので注意が必要です: ^-\]のみが特別な意味を持つので、 .[]の中でエスケープしてはいけません。 [link]

  • ^$は、文字列の先頭や末尾ではなく、 行頭や行末にマッチするので注意が必要です。 もし文字列全体の先頭末尾にマッチさせたいときは、 \A\zを使いましょう (\n?\zと等価である\Zと混同しないようにしましょう)。 [link]

    string = "some injection\nusername"
    string[/^username$/]   # matches
    string[/\Ausername\z/] # don't match
  • 複雑な正規表現にはx識別子を用いましょう。 これを用いることで、より読みやすくなり、 便利なコメントを使えるようになります。 スペースが無視されることに注意しましょう。

  • 具体例は uri/common.rb で定義されている正規表現 が参考になる。 [link]

regexp = /
  start         # some text
  \s            # white space char
  (group)       # first group
  (?:alt1|alt2) # some alternation
  end
/x
  • sub/gsubでの複雑な置換は、ブロックやハッシュを用いることで実現できます。 [link]

代入式

  • 複合代入はリテラルまたは引数なしのメソッド呼び出しの結果を代入する場合、および2つの変数または属性の値を交換する場合のみ使ってよい。 [link]

  • 代入記号の両側に空白を入れること。 [link]

パーセントリテラル

  • 挿入と"双方が入る1行の文字列には、 %()(%Q()の短縮形)を使いましょう。 複数行の時はヒアドキュメントを好みます。 [link]

    # 悪い例 (挿入の必要がありません)
    %(<div class="text">Some text</div>)
    # should be '<div class="text">Some text</div>'
    
    # 悪い例 (ダブルクォートがありません)
    %(This is #{quality} style)
    # should be "This is #{quality} style"
    
    # 悪い例 (複数行です)
    %(<div>\n<span class="big">#{exclamation}</span>\n</div>)
    # should be a heredoc.
    
    # 良い例 (挿入が必要、ダブルクォートがある、そして1行です)
    %(<tr><td class="name">#{name}</td>)
  • 文字列に'"双方が含まれない限り、 %qの使用は避けましょう。 たくさんの文字列をエスケープしなくてもよいときは、 通常の文字列リテラルのほうがより読みやすく、 推奨されるべきです。 [link]

    # 悪い例
    name = %q(Bruce Wayne)
    time = %q(8 o'clock)
    question = %q("What did you say?")
    
    # 良い例
    name = 'Bruce Wayne'
    time = "8 o'clock"
    question = '"What did you say?"'
  • '/'が1つ より多い 正規表現に限り、%rを使いましょう。 [link]

    # 悪い例
    %r(\s+)
    
    # こちらも悪い例
    %r(^/(.*)$)
    # should be /^\/(.*)$/
    
    # 良い例
    %r(^/blog/2011/(.*)$)
  • 呼び出すコマンドにバッククォートが含まれる(かなり起こりえないが)ことがない限り、 %xの使用は避けましょう。 [link]

    # 悪い例
    date = %x(date)
    
    # 良い例
    date = `date`
    echo = %x(echo `date`)
  • %sの使用は避けましょう。 Rubyコミュニティは、スペース含むシンボルをを作る時は :"文字列"がよいと決めたようです。 [link]

  • パーセントリテラルの区切り文字は、%rを除いて()が好まれます。 正規表現の中では、()は色々なシーンで使われるので、 正規表現の内容によっては、より使われる機会の少ない{のほうが 良い選択となることがあるかもしれません。 [link]

    # 悪い例
    %w[one two three]
    %q{"Test's king!", John said.}
    
    # 良い例
    %w(one two three)
    %q("Test's king!", John said.)

ブロック

  • ブロックの呼び出しは、yieldを用い、block.callは使いません。 記述量だけでなく、実行速度においても優れている為です。 [link]

参考

メタプログラミング

  • 不要なメタプログラミングは避けましょう。Avoid needless metaprogramming. [link]

  • ライブラリに書かれているコアなクラスを汚すのはやめましょう (モンキーパッチを当ててはいけません)。 [link]

  • ブロック渡しのclass_evalのほうが、文字列挿入型よりも好ましいです。

    • 文字列挿入型を使う時は、バックトレースが働くように、常に__FILE____LINE__を渡しましょう: [link]
    class_eval 'def use_relative_model_naming?; true; end', __FILE__, __LINE__
    • define_methodの方が、class_eval{ def ... }よりも好まれます。
  • 文字列挿入型のclass_eval(または他のeval)を用いる時は、 挿入されたときのコードをコメントに追加しましょう(Railsでは活用されています)。 [link]

    # from activesupport/lib/active_support/core_ext/string/output_safety.rb
    UNSAFE_STRING_METHODS.each do |unsafe_method|
      if 'String'.respond_to?(unsafe_method)
        class_eval <<-EOT, __FILE__, __LINE__ + 1
          def #{unsafe_method}(*args, &block)       # def capitalize(*args, &block)
            to_str.#{unsafe_method}(*args, &block)  #   to_str.capitalize(*args, &block)
          end                                       # end
    
          def #{unsafe_method}!(*args)              # def capitalize!(*args)
            @dirty = true                           #   @dirty = true
            super                                   #   super
          end                                       # end
        EOT
      end
    end
  • method_missingを用いたメタプログラミングは避けましょう。 何故なら、バックトレースが面倒になり、 #methodsのリストの中に出てこず、 ミススペルしたメソッド呼び出しも無言で動いてしまいます、 例えばnukes.launch_state = falseのようにです。 代わりに、移譲、プロキシ、またはdefine_methodを使いましょう。 もしmethod_missingを使わなければならない時は: [link]

    • respond_to_missing?も実装されているか確かめましょう
    • 既知の接頭辞、find_by_*のようなものを捕捉しましょう -- 可能な限りアサートさせましょう
    • 最後にsuperを呼び出しましょう
    • アサートする、特別でないメソッドに移譲しましょう:
    # 悪い例
    def method_missing?(meth, *args, &block)
      if /^find_by_(?<prop>.*)/ =~ meth
        # ... lots of code to do a find_by
      else
        super
      end
    end
    
    # 良い例
    def method_missing?(meth, *args, &block)
      if /^find_by_(?<prop>.*)/ =~ meth
        find_by(prop, *args, &block)
      else
        super
      end
    end
    
    # それでも最も良い選択は、発見できる全てのアトリビュートにdefine_methodすることです

雑則

  • ruby -wで安全なコードを書きましょう。 [link]

  • オプショナルな変数としてのハッシュの使用を避けましょう。やりすぎてはいませんか?(オブジェクトの初期化はこのルールの例外です) [link]

  • コードのある行が10行を超えるメソッドは避けましょう。 理想を言えば、多くのメソッドは5行以内がよいです。 空行は行数には含めません。 [link]

  • 3つや4つ以上引数を設定するのは避けましょう。 [link]

  • もし本当に"global"なメソッドが必要な場合は、 Kernelに定義し、privateに設定しましょう。 [link]

  • グローバル変数の代わりに、モジュールのインスタンス変数を使用しましょう。 [link]

    # 悪い例
    $foo_bar = 1
    
    # 良い例
    module Foo
      class << self
        attr_accessor :bar
      end
    end
    
    Foo.bar = 1
  • alias_methodが動く時は、aliasは避けましょう。 [link]

  • 複雑なコマンドラインオプションをパースするためにOptionParserを使いましょう。 また、些細なオプションにはruby -sを使いましょう。 [link]

  • 現在のシステム時間を読み出すには、Time.newよりもTime.nowを使いましょう。 [link]

  • それで問題ない時は、破壊的処理を避け関数型の手法でコードを書きましょう。 [link]

  • それがメソッドの目的でない限り、引数に破壊的変更をするのはやめましょう。 [link]

  • 破壊的メソッドを使用する際は、その副作用を最小限の範囲に留めること。 [link]

  • 3段階を超えるネストは避けましょう。 [link]

  • 一貫性を保ちましょう。理想を言えば、このガイドラインに沿いましょう。 [link]

  • 常識を用いましょう。 [link]

ツール

ここでは、このガイドに反するコードを自動的にチェックするのを支援するツールをいくつか紹介します。

RuboCop

RuboCopは、このガイドに基づいた Rubyコードスタイルチェッカーです。 Rubocopはすでにこのガイドの重要な部分をカバーしており、 MRI 1.9, MRI 2.0 双方をサポートし、Emacs向けのよいプラグインがあります。

RubyMine

RubyMine のコードインスペクションは、このガイドに 部分的に基づいています

Be Consistent

Google C++ Style Guide

About

Ruby Style Guide

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published