Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions snooty.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ toc_landing_pages = [
"/interact-data/specify-query",
"/data-modeling",
"/configuration",
"/issues-and-help"
]

[constants]
Expand Down
352 changes: 352 additions & 0 deletions source/code-documentation.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,352 @@
.. _mongoid-code-documentation:

==================
Code Documentation
==================

.. contents:: On this page
:local:
:backlinks: none
:depth: 2
:class: singlecol

Overview
--------

In this guide, you can learn about {+odm+}'s code documentation
conventions. If you have a suggestion to improve the API documentation
or introduce a new feature, you can use this guide to help you format
your documentation.

{+odm+} uses a variation of :github:`YARD <lsegal/yard>`, a {+language+}
documentation tool, for its code documentation.

.. _mongoid-code-documentation-structure:

Structure
---------

- **Modules:** All class and module definitions must be preceded by
a documentation comment.

.. code-block:: ruby

# This is the documentation for the class. It's amazing
# what they do with corrugated cardboard these days.
class CardboardBox

- **Methods:** All method definitions must be preceded by a
documentation comment. Use ``@param``, ``@yield``, and ``@return`` to
specify inputs and output. To learn more, see the
:ref:`mongoid-code-documentation-type-declaration` section.

.. code-block:: ruby

# Turn a person into whatever they'd like to be.
#
# @param [ Person ] person The human to transmogrify.
#
# @return [ Tiger ] The transmogrified result.
def transmogrify(person)

- **Errors:** Use ``@raise`` to describe errors specific to the method.

.. code-block:: ruby

# @raise [ Errors::Validations ] If validation failed.
def validate!

- **Private Methods:** Private methods must be documented unless they are
so brief and straightforward that it is obvious what they do. Note that,
for example, a method might be brief and straightforward but the type of
its parameter may not be obvious, in which case the parameter must be
appropriately documented.

.. code-block:: ruby

private

# Documentation is optional here.
def do_something_obvious

- **API Private:** Classes and public methods which are not intended for
external usage must be marked ``@api private``. This macro does not
require a comment.

Note that, because {+odm+}'s modules are mixed into application classes,
``private`` visibility of a method does not necessarily indicate its
status as an API private method.

.. code-block:: ruby

# This is an internal-only method.
#
# @api private
def dont_call_me_from_outside

- **Notes and TODOs:** Use ``@note`` to explain caveats, edge cases,
and behavior which may surprise users. Use ``@todo`` to record
follow-ups and suggestions for future improvement.

.. code-block:: ruby

# Clear all stored data.
#
# @note This operation deletes data in the database.
# @todo Refactor this method for performance.
def erase_data!

- **Deprecation:** Use the ``@deprecated`` macro to indicate deprecated
functionality. This macro does not require a comment.

.. code-block:: ruby

# This is how we did things back in the day.
#
# @deprecated
def the_old_way

.. _mongoid-code-documentation-formatting:

Formatting
----------

- **Line Wrapping:** Use double-space indent when wrapping lines of macros.
Do not indent line wraps in the description.

.. code-block:: ruby

# This is the description of the method. Line wraps in the description
# must not be indented.
#
# @return [ Symbol ] For macros, wraps must be double-space indented
# on the second, third (and so on) lines.

- **Whitespace:** Do not use leading/trailing empty comment lines,
or more than one consecutive empty comment line.

.. code-block:: ruby

# DO THIS:
# @return [ Symbol ] The return value
def my_method

# NOT THIS:
# @return [ Symbol ] The return value
#
def my_method

# NOT THIS:
# @param [ Symbol ] foo The input value
#
#
# @return [ Symbol ] The return value
def my_method(foo)

.. _mongoid-code-documentation-type-declaration:

Type Declaration
----------------

- **Type Unions:** Use pipe ``|`` to denote a union of allowed types.

.. code-block:: ruby

# @param [ Symbol | String ] name Either a Symbol or a String.

- **Nested Types:** Use angle brackets ``< >`` to denote type nesting.

.. code-block:: ruby

# @param [ Array<Symbol> ] array An Array of symbols.

- **Hash:** Use comma ``,`` to denote the key and value types.

.. code-block:: ruby

# @param [ Hash<Symbol, Integer> ] hash A Hash whose keys are Symbols,
# and whose values are Integers.

- **Array:** Use pipe ``|`` to denote a union of allowed types.

.. code-block:: ruby

# @param [ Array<Symbol | String> ] array An Array whose members must
# be either Symbols or Strings.

- **Array:** Use comma ``,`` to denote the types of each position in a tuple.

.. code-block:: ruby

# @return [ Array<Symbol, Integer, Integer> ] A 3-member Array whose first
# element is a Symbol, and whose second and third elements are Integers.

- **Array:** Use pipe ``|`` on the top level if the inner types cannot be
mixed within the Array.

.. code-block:: ruby

# @param [ Array<Symbol> | Array<Hash> ] array An Array containing only
# Symbols, or an Array containing only Hashes. The Array may not contain
# a mix of Symbols and Hashes.

- **Nested Types:** For clarity, use square brackets ``[ ]`` to denote nested unions
when commas are also used.

.. code-block:: ruby

# @param [ Hash<Symbol, [ true | false ]> ] hash A Hash whose keys are Symbols,
# and whose values are boolean values.

- **Ruby Values:** Specific values may be denoted in the type using Ruby syntax.

.. code-block:: ruby

# @param [ :before | :after ] timing One of the Symbol values :before or :after.

- **True, False, and Nil:** Use ``true``, ``false``, and ``nil`` rather than
``TrueClass``, ``FalseClass``, and ``NilClass``. Do not use ``Boolean`` as a type
since it does not exist in Ruby.

.. code-block:: ruby

# DO THIS:
# @param [ true | false | nil ] bool A boolean or nil value.

# NOT THIS:
# @param [ TrueClass | FalseClass | NilClass ] bool A boolean or nil value.
# @param [ Boolean ] bool A boolean value.

- **Return Self:** Specify return value ``self`` where a method returns ``self``.

.. code-block:: ruby

# @return [ self ] Returns the object itself.

- **Splat Args:** Use three-dot ellipses ``...`` in the type declaration and
star ``*`` in the parameter name to denote a splat.

.. code-block:: ruby

# @param [ String... ] *items The list of items' names as Strings.
def buy_groceries(*items)

- **Splat Args:** Do not use ``Array`` as the type unless each arg is actually an Array.

.. code-block:: ruby

# DO NOT DO THIS:
# @param [ Array<String> ] *items The list of items' names as Strings.
def buy_groceries(*items)

buy_groceries("Cheese", "Crackers", "Wine")

# DO THIS:
# @param [ Array<String>... ] *arrays One or more arrays containing name parts.
def set_people_names(*arrays)

set_people_names(["Harlan", "Sanders"], ["Jane", "K", ""Doe"], ["Jim", "Beam"])

- **Splat Args:** Use comma ``,`` to denote positionality in a splat.

.. code-block:: ruby

# @param [ Symbol..., Hash ] *args A list of names, followed by a hash
# as the optional last arg.
def say_hello(*args)

- **Splat Args:** Specify type unions with square brackets ``[ ]``.

.. code-block:: ruby

# @param [ [ String | Symbol ]... ] *fields A splat of mixed Symbols and Strings.

- **Keyword Arguments:** Following YARD conventions, use ``@param`` for keyword
arguments, and specify keyword argument names as symbols.

.. code-block:: ruby

# @param [ String ] query The search string
# @param [ Boolean ] :exact_match Whether to do an exact match
# @param [ Integer ] :results_per_page Number of results
def search(query, exact_match: false, results_per_page: 10)

- **Hash Options:** Define hash key-value options with ``@option`` macro
immediately following the Hash ``@param``. Note ``@option`` parameter names
are symbols.

.. code-block:: ruby

# @param opts [ Hash<Symbol, Object> ] The optional hash argument or arguments.
# @option opts [ String | Array<String> ] :items The items as Strings to include.
# @option opts [ Integer ] :limit An Integer denoting the limit.
def buy_groceries(opts = {})

- **Double Splats:** Use double-star ``**`` in the parameter name to denote a
keyword arg splat (double splat). Note that type does not need declared on
the double-splat element, as it is implicitly <Symbol, Object>. Instead,
define value types with ``@option`` macro below. Note ``@option`` parameter
names are symbols.

.. code-block:: ruby

# @param **kwargs The optional keyword argument or arguments.
# @option **kwargs [ String | Array<String> ] :items The items as Strings to include.
# @option **kwargs [ Integer ] :limit An Integer denoting the limit.
def buy_groceries(**kwargs)

- **Blocks:** Use ``@yield`` to specify when the method yields to a block.

.. code-block:: ruby

# @yield [ Symbol, Symbol, Symbol ] Evaluate the guess of who did the crime.
# Must take the person, location, and weapon used. Must return true or false.
def whodunit
yield(:mustard, :ballroom, :candlestick)
end

- **Blocks:** If the method explicitly specifies a block argument, specify the block
argument using ``@param`` preceded by an ampersand ``&``, and also specify ``@yield``.
Note ``@yield`` must be used even when method calls ``block.call`` rather than
``yield`` internally.

.. code-block:: ruby

# @param &block The block.
# @yield [ Symbol, Symbol, Symbol ] Evaluate the guess of who did the crime.
# Must take the person, location, and weapon used. Must return true or false.
def whodunit(&block)
yield(:scarlet, :library, :rope)
end

# @param &block The block.
# @yield [ Symbol, Symbol, Symbol ] Evaluate the guess of who did the crime.
# Must take the person, location, and weapon used. Must return true or false.
def whodunit(&block)
block.call(:plum, :kitchen, :pipe)
end

- **Blocks:** Use ``@yieldparam`` and ``@yieldreturn`` instead of ``@yield`` where
beneficial for clarity.

.. code-block:: ruby

# @param &block The block.
# @yieldparam [ Symbol ] The person.
# @yieldparam [ Symbol ] The location.
# @yieldparam [ Symbol ] The weapon used.
# @yieldreturn [ true | false ] Whether the guess is correct.
def whodunit(&block)
yield(:peacock, :conservatory, :wrench)
end

- **Proc Args:** Use ``@param`` (not ``@yield``) for proc arguments. The
inputs to the proc may be specified as subtypes.

.. code-block:: ruby

# @param [ Proc<Integer, Integer, Integer> ] my_proc Proc argument which must
# take 3 integers and must return true or false whether the guess is valid.
def guess_three(my_proc)
my_proc.call(42, 7, 88)
end
21 changes: 0 additions & 21 deletions source/contributing.txt

This file was deleted.

Loading
Loading