.. _code-documentation: ****************** Code Documentation ****************** .. default-domain:: mongodb .. contents:: On this page :local: :backlinks: none :depth: 2 :class: singlecol Code Documentation ================== Mongoid uses its own flavor of `YARD `_ for code documentation. Please note the conventions outlined in this document. .. _code-documentation-structure: Structure --------- - **Modules:** All class and module definitions should 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 should be preceded by a documentation comment. Use ``@param``, ``@yield``, and ``@return`` to specify inputs and output. For further details, refer to :ref:`Type Declaration ` below. .. 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 explain errors specific to the method. .. code-block:: ruby # @raise [ Errors::Validations ] If validation failed. def validate! - **Private Methods:** Private methods should be documented unless they are so brief and straightforward that it is obvious what they do. Note that, for example, a method may 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 should be marked ``@api private``. This macro does not require a comment. Note that, because Mongoid'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 .. _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 # should not be indented. # # @return [ Symbol ] For macros, wraps must be double-space indented # on the second, third, etc. lines. - **Whitespace:** Do not use leading/trailing empty comment lines, or more than one consecutive empty comment line. .. code-block:: ruby # GOOD: # @return [ Symbol ] The return value def my_method # BAD: # @return [ Symbol ] The return value # def my_method # BAD: # @param [ Symbol ] foo The input value # # # @return [ Symbol ] The return value def my_method(foo) .. _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 ] array An Array of symbols. - **Hash:** Use comma ``,`` to denote the key and value types. .. code-block:: ruby # @param [ Hash ] 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 ] 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 ] 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 | Array ] 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 ] 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 # GOOD: # @param [ true | false | nil ] bool A boolean or nil value. # BAD: # @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 name(s) 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 # BAD: # @param [ Array ] *items The list of items name(s) as Strings. def buy_groceries(*items) buy_groceries("Cheese", "Crackers", "Wine") # OK: # @param [ Array... ] *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 ] The optional hash argument(s). # @option opts [ String | Array ] :items The items(s) 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 . Instead, define value types with ``@option`` macro below. Note ``@option`` parameter names are symbols. .. code-block:: ruby # @param **kwargs The optional keyword argument(s). # @option **kwargs [ String | Array ] :items The items(s) 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`` should 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:** Proc arguments should use ``@param`` (not ``@yield``). The inputs to the proc may be specified as subtype(s). .. code-block:: ruby # @param [ Proc ] 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