API ドキュメント作成ガイドライン

本ガイドでは、Rails APIドキュメント作成のガイドラインについて解説します(訳注: APIドキュメントが英語で書かれることを前提とします。また、サンプルのコメントは基本的に英語のままにしています)。

このガイドの内容:

  • APIドキュメントを効果的に書く方法
  • ドキュメント作成用のスタイルガイド (Rubyコード開発用のスタイルガイドとは別)

1 RDoc

Rails API ドキュメントRDocで生成されます。生成するには、Railsのルートディレクトリでbundle installを実行してから、以下を実行します。

$ bundle exec rake rdoc

生成されたHTMLファイルは./doc/rdocディレクトリに置かれます。

RDocの記法についてはmarkupを参照してください(訳注: 別ページですが日本語のRDocライブラリ解説があります)。追加のディレクティブにも目を通しておいてください。

2 リンクの表記

Rails APIドキュメントはGitHub上での表示を想定していません。例えばRails APIで相対リンクを書く場合はRDocの linkを使う必要があります。

これは、GitHub Markdownと、api.rubyonrails.orgedgeapi.rubyonrails.orgで公開されているRDoc生成の違いによるものです。

たとえば、RDocで生成されたActiveRecord::Baseクラスへのリンクを作成するときは[link:classes/ActiveRecord/Base.html]と書きます。

[https://api.rubyonrails.org/classes/ActiveRecord/Base.html]のような絶対URLを使うとAPIドキュメントの読者が別バージョンのドキュメント(edgeapi.rubyonrails.orgなど)を開いてしまう可能性があるので、上のような表記が推奨されます。

3 語調

簡潔かつ宣言的に書くこと。簡潔さはそれだけで長所になります。

現在形で書くこと("Returned a hash that..." や "Will return a hash that..." ではなく"Returns a hash that..."のように書く)。

コメントの英語は大文字で始めること。句読点や記号の用法は常識に従うこと。

# Declares an attribute reader backed by an internally-named
# instance variable.
def attr_internal_reader(*attrs)
  ...
end

現時点の最新の方法が、読者に明示的に(かつ暗黙にも)伝わるように書くこと。先進的な分野で推奨されている慣用表現を使うこと。推奨される方法が強調されるようセクションの順序に注意し、必要であれば順序を入れ替えること。作成するドキュメント自身がRailsのベストプラクティスのよいモデルとなるように、そしてRailsの最新かつ模範的な用法になるように書くこと。

ドキュメントは、簡潔かつ全体を理解できるものであること。例外的なケースについても調査し、ドキュメントに盛り込むこと(あるモジュールが無名であったらどうなるか。あるコレクションの内容が空であったらどうなるか。引数がnilであったらどうなるか、など)。

Railsのコンポーネント名は語の間にスペースを1つ置く表記が正式(例: "Active Support")。なお、ActiveRecordはRubyモジュール名ですが、Active RecordはORMを指します。Railsドキュメント内でコンポーネントを指す場合には常に正式名称を使うこと。ブログ投稿やプレゼンテーションなどでもこの点に留意し、表記ゆれで読者が戸惑わないようにすること。

正しいスペルを使うこと(Arel、Test::Unit、RSpec、HTML、MySQL、JavaScript、ERBなど)。大文字小文字にも注意すること。疑わしい場合は、公式ドキュメントなどの信頼できる情報源を参照すること。

"SQL" という語の前には冠詞 "an" を付けること(例: "an SQL statement")。同様に、"an SQLite database"のようにすること。

"you"や"your"を含む表現を避けること。

If you need to use `return` statements in your callbacks, it is recommended that you explicitly define them as methods.

上のようにyouを3度も使うのではなく、以下のスタイルで書くこと。

If `return` is needed it is recommended to explicitly define a method.

ただし、説明上何らかの登場人物を仮定して、その人物を代名詞で呼ぶ場合("a user with a session cookie" など)は、以下のようにheやsheのような性別のある代名詞を避け、they/their/themのような性別に影響されない代名詞を使うこと。

  • heまたはshe -> theyに置き換える
  • himまたはher -> themに置き換える
  • hisまたはher -> theirに置き換える
  • hisまたはhers -> theirsに置き換える
  • himselfまたはherself -> themselvesに置き換える

4 英語

単語はアメリカ英語を使うこと(colorcentermodularizeなど)。詳しくはアメリカ英語とイギリス英語のスペルの違い(英語)を参照。

5 オックスフォードカンマ

カンマは、オックスフォードスタイル(カンマなしの"red, white and blue"ではなく、カンマありの"red, white, and blue"で列挙する)で統一すること。

6 サンプルコード

意味のあるサンプルコードを使うこと。概要と基本を端的に示し、かつ興味深い点や落とし穴も示されているのが理想です。

サンプルコードのインデントにはスペース2文字を使うこと。マークアップ用には左マージンに合わせてスペース2文字を使うこと。サンプルコードの例は「Railsコーディングルールに従う」を参照。

短いドキュメントでは、単にパラグラフに続けてスニペットを記述すること("Examples"ラベルでスニペットを明示する必要はありません)。

# Converts a collection of elements into a formatted string by
# calling +to_s+ on all elements and joining them.
#
#   Blog.all.to_formatted_s # => "First PostSecond PostThird Post"

逆に長文ドキュメントでは"Examples"セクションを設けることもできます。

# ==== Examples
#
#   Person.exists?(5)
#   Person.exists?('5')
#   Person.exists?(name: "David")
#   Person.exists?(['name LIKE ?', "%#{query}%"])

式の実行結果は式に続けて書き、冒頭に "# => " を追加して縦を揃えること。

# For checking if a fixnum is even or odd.
#
#   1.even? # => false
#   1.odd?  # => true
#   2.even? # => true
#   2.odd?  # => false

1つの行が長くなりすぎる場合は出力コメントを次の行に置くこともできます。

#   label(:article, :title)
#   # => <label for="article_title">Title</label>
#
#   label(:article, :title, "A short title")
#   # => <label for="article_title">A short title</label>
#
#   label(:article, :title, "A short title", class: "title_label")
#   # => <label for="article_title" class="title_label">A short title</label>

実行結果をputspなどの出力用メソッドで示すことはなるべく避けること。

逆に(実行結果を示さない)通常のコメントには矢印(=>)を書かないこと。

#   polymorphic_url(record)  # same as comment_url(record)

7 論理値

述語やフラグの記述は、truefalse(実際のリテラル値)よりも平文のtrueやfalseを優先すること。

trueやfalseをRubyの定義(nilfalse以外はすべてtrue)どおりに使う場合は、trueやfalseを平文で表記すること。逆にシングルトンのtrueおよびfalseが必要な場合は等幅フォントで表記すること。「truthy」のような用語は避けること(Rubyでは言語レベルでtrueとfalseが定義されているので、これらの用語は技術的に厳密な意味が与えられており、他の言語の用語を使う必要はありません)

原則として、シングルトンのtruefalseをAPIドキュメントに書かないこと(やむを得ない場合を除く)。シングルトンのtruefalseを避けることで、読者がシングルトンにつられて!!や三項演算子のような余分な人工的記法を使うことも避けられ、リファクタリングもしやすくなります。また、実装で呼び出されるメソッドが返す値の表現が少しでも違うとコードが正常に動作しなくなる事態も避けられます。

例:

`config.action_mailer.perform_deliveries` specifies whether mail will actually be delivered and is true by default
`config.action_mailer.perform_deliveries`: メールを実際に配信するかどうかを指定します(デフォルト値はtrue)。

上の例では、フラグの実際のデフォルト値がtrueそのものかどうかをユーザーが知る必要はないので、trueで論理値の意味だけをドキュメントに書きます。

述語の例:

# Returns true if the collection is empty.(コレクションが空の場合はtrueを返す。)
#
# If the collection has been loaded(コレクションが読み込まれる場合は)
# it is equivalent to <tt>collection.size.zero?</tt>. (<tt>collection.size.zero?</tt>と同値)
# if the collection has not been loaded, it is equivalent to(コレクションが読み込まれなかった場合は)
# <tt>collection.exists?</tt>. <tt>collection.exists?</tt>と同値。)
# If the collection has not already been (コレクションが読み込まれていない状態で)
# loaded and you are going to fetch the records anyway(レコードを取り出したい場合は)
# it is better to check <tt>collection.length.zero?</tt>. (<tt>collection.length.zero?</tt>をチェックするとよい)
def empty?
  if loaded?
    size.zero?
  else
    @target.blank? && !scope.exists?
  end
end

このAPIが返す値は具体的なtruefalseに限定しないよう注意が払われており、?で終わることで述語メソッドであることも示されているので、これで十分です。

8 ファイル名

原則として、ファイル名はRailsアプリケーションのルートディレクトリからの相対パスで記述すること。

config/routes.rb            # YES
routes.rb                   # NO
RAILS_ROOT/config/routes.rb # NO

9 フォント

9.1 等幅フォント

以下の場合は等幅フォントを使うこと。

  • 定数名(特にクラス名やモジュール名)
  • メソッド名
  • 次のようなリテラル: nilfalsetrueself
  • シンボル
  • メソッドのパラメータ
  • ファイル名
class Array
  # Calls +to_param+ on all its elements and joins the result with
  # slashes. This is used by +url_for+ in Action Pack.
  def to_param
    collect { |e| e.to_param }.join '/'
  end
end

等幅フォントを+...+というマークアップで表記するのは、通常のメソッド名、シンボル、(通常のスラッシュを用いる)パスのようなシンプルなものだけにすること。これらよりも複雑なものを表記する場合は必ず<tt>...</tt>でマークアップすること。特に名前空間を使うクラス名やモジュール名では必須(<tt>ActiveRecord::Base</tt>など)。

RDocの出力は以下のコマンドで手軽に確認できます。

$ echo "+:to_param+" | rdoc --pipe
# => <p><code>:to_param</code></p>

9.2 平文フォント

Rubyのキーワードでない、英語としてのtrueやfalseには平文フォント(等幅でないフォント)を使うこと。

# Runs all the validations within the specified context.
# Returns true if no errors are found, false otherwise.
#
# If the argument is false (default is +nil+), the context is
# set to <tt>:create</tt> if <tt>new_record?</tt> is true,
# and to <tt>:update</tt> if it is not.
#
# Validations with no <tt>:on</tt> option will run no
# matter the context. Validations with # some <tt>:on</tt>
# option will only run in the specified context.
def valid?(context = nil)
  # ...
end

10 説明のリスト

項目(オプションやパラメータのリストなど)と説明の間にはハイフンを置くこと(コロンはシンボルで使われるのでハイフンの方が読みやすい)。

# * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+.

説明文は通常の英語として大文字で始め、ピリオドで終わること。

11 動的に生成されるメソッド

(module|class)_eval(文字列)メソッドで作成されるメソッドの右側に、コードで生成されるインスタンスをコメントで書くこと。このように作成されたコメントには、スペース2文字分のインデントを与えること。

for severity in Severity.constants
  class_eval <<-EOT, __FILE__, __LINE__ + 1
    def #{severity.downcase}(message = nil, progname = nil, &block)  # def debug(message = nil, progname = nil, &block)
      add(#{severity}, message, progname, &block)                    #   add(DEBUG, message, progname, &block)
    end                                                              # end
                                                                     #
    def #{severity.downcase}?                                        # def debug?
      #{severity} >= @level                                          #   DEBUG >= @level
    end                                                              # end
  EOT
end

生成された行が多過ぎる(200行を超える)場合は、コメントを呼び出しの上に置くこと。

# def self.find_by_login_and_activated(*args)
#   options = args.extract_options!
#   ...
# end
self.class_eval %{
  def self.#{method_id}(*args)
    options = args.extract_options!
    ...
  end
}

12 メソッドの可視性

Railsのドキュメントを作成するときは、ユーザー向けに公開するパブリックなAPIと内部APIの違いを理解しておくことが重要です。

多くのライブラリと同様、Railsでも内部APIの定義にprivateキーワードが使われますが、公開するAPIのルールは若干異なります。内部APIであるメソッドには:nodoc:ディレクティブを追加すること。

つまりRailsでは、可視性がpublicのメソッドであっても、ユーザーに公開されているとは限りません。

ActiveRecord::Core::ClassMethods#arel_tableの例

module ActiveRecord::Core::ClassMethods
  def arel_table # :nodoc:
    # 何か書く
  end
end

上のメソッドはActiveRecord::Coreのpublicなクラスメソッドに見えますし、可視性は実際にpublicです。しかしRailsチームはこの種のメソッドに依存して欲しくないと考えているので、:nodoc:を指定してAPIドキュメントに出力されないようにしています。可視性をpublicにする実際の理由は、Railsチームがこの種の内部メソッドの振る舞いを必要に応じてリリースごとに変更可能にするためです。これらのメソッドは名前や戻り値が変更されたり、クラス自体が消滅したりする可能性もあるので、外部に対して何も保証しません。Railsアプリケーションやプラグインは、この種のAPIに依存すべきではありません。これらのAPIに依存してしまうと、Railsを次のリリースでアップグレードしたときにアプリケーションやgemが動かなくなるリスクが生じます。

Railsコントリビュータがドキュメントを作成する場合、そのAPIを外部開発者に公開してよいかどうかに常に注意を払うことが重要です。Railsチームは、パブリックなAPIに対する重大な変更は、必ず非推奨サイクルを経てから行なうようにしています。内部メソッドや内部クラスの可視性がprivateになっていない場合は、:nodoc:オプションを指定することが推奨されます(なお可視性がprivateの場合はデフォルトで内部扱いになります)。APIが安定した後は可視性の変更も一応可能ですが、後方互換性を維持しながらパブリックAPIを変更するのはかなり困難です。

:nodoc:をクラスやモジュールに対して指定すると、それらの中にあるメソッドはすべて内部APIであり、直接のアクセスは許されていないことを示せます。

まとめ: Railsチームは、可視性がpublicで内部利用限定のメソッドやクラスには:nodoc:を指定すること。APIの可視性変更は慎重に行なうべきであり、pull requestでの議論を経てからにすること。

13 Railsスタック

Rails APIの一部をドキュメント化するときは、そのAPIがRailsスタックの一部に組み込まれることを意識することが重要です。

つまり、ドキュメント化するメソッドやクラスのスコープやコンテキストに応じて、振る舞いが変化する可能性があります。

同じコードでも、スタック全体を考慮するとさまざまな場所で振る舞いが変化することがあります。以下のActionView::Helpers::AssetTagHelper#image_tagは典型的な例です。

# image_tag("icon.png")
#   # => <img src="/assets/icon.png" />

#image_tagはデフォルトでは常に/images/icon.pngを返しますが、アセットパイプラインなどを含むRailsのフルスタックでは上のように結果が変わることがあります。

通常、私たちがRailsフルスタックを使うときは、デフォルトの振る舞いしか気にしないものです。

しかしこの場合は、特定のメソッドの振る舞いだけではなく、フレームワークの振る舞いもドキュメントに書きたいと思うでしょう。

Railsチームが特定のAPIをどのように扱っているかを知りたい場合は、Railsリポジトリでお気軽にissueをオープンするか、issue trackerにパッチを送ってください。

フィードバックについて

Railsガイドは GitHub の yasslab/railsguides.jp で管理・公開されております。本ガイドを読んで気になる文章や間違ったコードを見かけたら、気軽に Pull Request を出して頂けると嬉しいです。Pull Request の送り方については GitHub の README をご参照ください。

原著における間違いを見つけたら『Rails のドキュメントに貢献する』を参考にしながらぜひ Rails コミュニティに貢献してみてください 🛠💨✨

本ガイドの品質向上に向けて、皆さまのご協力が得られれば嬉しいです。

Railsガイド運営チーム (@RailsGuidesJP)

支援・協賛

Railsガイドは下記のサポーターから継続的な支援を受けています。支援・協賛にご興味あれば協賛プランから気軽にお問い合わせいただけると嬉しいです。

  1. Star
  2. このエントリーをはてなブックマークに追加