<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Hi,<br>
    <br>
    I would like to share with you the first artifacts of the effort to
    build a sustainable API documentation (not only) for Katello. Last
    year I've proposed a master thesis topic on the REST api
    documentation tool for Rails framework at local university and after
    a while a student Pavel Pokorny responded positively to this topic
    and so the story began.<br>
    <br>
    The original idea came from my hobby experimental project active_doc
    (<a class="moz-txt-link-freetext" href="https://github.com/iNecas/active_doc">https://github.com/iNecas/active_doc</a>) which aimed to provide DSL to
    describe the code instead of just using plain comments. The
    advantage of this approach is that you have the documentation
    available on the run-time so that you can do additional things like
    validating that the coming requests are consistent with the
    documentation or serve the documentation to the client directly etc.<br>
    <br>
    The project coming from this cooperation is called rails-restapi
    (<a class="moz-txt-link-freetext" href="https://github.com/Pajk/rails-restapi">https://github.com/Pajk/rails-restapi</a> - we haven't found better
    name for that so far:). You can see a sample output at <br>
    <br>
      <a class="moz-txt-link-freetext" href="http://restapi-likes.rhcloud.com/">http://restapi-likes.rhcloud.com/</a><br>
      <a class="moz-txt-link-freetext" href="http://restapi-likes.rhcloud.com/apidoc#twitter_example">http://restapi-likes.rhcloud.com/apidoc#twitter_example</a> (you can
    get there from the bottom of previous page)<br>
      <a class="moz-txt-link-freetext" href="http://restapi-likes.rhcloud.com/apidoc#twitter_example/lookup">http://restapi-likes.rhcloud.com/apidoc#twitter_example/lookup</a><br>
    <br>
    <br>
    We can divide the whole project into 4 parts:<br>
    <br>
    <b>1. DSL for describing the requests</b>, e.g.:<br>
    <br>
      api :POST, "/organizations/:organization_id/environments", "Create
    an environment in organization"<br>
      param :organization_id, :identifier, :required => true<br>
      param :environment, Hash do<br>
        param :name, :identifier, :required => true, :desc =>
    "Name of the new environment, it has to be unique in the
    organization"<br>
        param :prior, :number, :required => true, :desc => "Id of
    the prior environment. it has to be either Library or an environment
    at the end of a chain"<br>
        param :description, String<br>
      end<br>
      error :code => 400, :desc => "In case the name is already
    taken or the prior is neither Library nor environment at the end of
    the chain"<br>
      desc <<-DESC<br>
      Long description for the action. You can use RDoc formatting for
    this description.<br>
      DESC<br>
      def create<br>
        # ...<br>
      end<br>
    <br>
    We can describe what path and http method to use do to some action.<br>
    With keyword param we specify the arguments we expect. We can also
    specify what value we expect (e.g. with type like Fixnum, String;
    with enumerating acceptable values (["redhat", "custom"]), regular
    expression (/^\<a class="moz-txt-link-abbreviated" href="mailto:w+@\w+\.\w">w+@\w+\.\w</a>{2,3}$) or with custom validator
    (:identifier, :number)).<br>
    You can also specify what error codes might the action return. With
    desc you can write longer documentation using RDoc formatting.<br>
    <br>
    This DSL can be used before each method of an action. You can
    similarly give some basic documentation for the resource. (You can
    take a look at fully described controller at
<a class="moz-txt-link-freetext" href="https://github.com/iNecas/katello/blob/restapi/src/app/controllers/api/environments_controller.rb">https://github.com/iNecas/katello/blob/restapi/src/app/controllers/api/environments_controller.rb</a>)<br>
    <br>
    <b>2. Validator for making sure the documentation is up-to date:</b><br>
    <br>
    When you say:<br>
    <br>
      param :provider_type, ["redhat", "custom"]<br>
    <br>
    it would be nice to make sure  that these are the only values we
    support. Therefore restapi provides a validation mode (configurable
    in config/initializers/restapi.rb). When running in this mode, it
    will fail when you try to call it with a value not valid with the
    description. It's ideal combination with running API or CLI tests
    with this mode so that you can make sure that the requests are
    really consistent with the description.<br>
    <br>
    <b>3. Engine providing the documentation through API<br>
    </b><br>
    The plugin is using Rails Engine architecture to inject it's own
    routes to the application where the documentation can be requested
    for further processing (in JSON format).<br>
    <br>
    <b>4. HTML client to the documentation server</b><br>
    <br>
    There is a sample HTML client provided with the restapi gem, that is
    based on backbone.js. It uses the DOC API described in point 3.<br>
    <br>
    If you run my branch of katello
    (<a class="moz-txt-link-freetext" href="https://github.com/iNecas/katello/tree/restapi">https://github.com/iNecas/katello/tree/restapi</a> - remember to run
    bundle install before and run the app itself in devel mode unless
    you are willing to customize your apache configuration for static
    assets)<br>
    <br>
    <b>Automatically generated doc based on CLI tests = API
      documentation line</b><br>
    <br>
    I've put together a tool for kick-starting the first documentation
    based on requests to the API. The idea is to run all cli tests,
    watch the requests and generate the documentation based on the
    requests, responses and config/routes.rb. You can see the results in
    my branch restapi (<a class="moz-txt-link-freetext" href="https://github.com/iNecas/katello/tree/restapi">https://github.com/iNecas/katello/tree/restapi</a>).
    It's not 100% exact but is very useful for starting.<br>
    <br>
    Before you start run bundle install (I've put a gem restapi.0.0.3.kt
    with some tweaks not yet in the upstream version to a custom gem
    repo <a class="moz-txt-link-freetext" href="http://inecas.fedorapeople.org/rubygems/">http://inecas.fedorapeople.org/rubygems/</a>, it's mentioned in the
    Gemfile).<br>
    <br>
    You can run it in development environment and get the instant
    feedback for you changes (in exchange for longer reload time), in
    production it's much faster because the description not being
    reloaded.<br>
    <br>
    When you go to:<br>
    <br>
    <a class="moz-txt-link-freetext" href="https://localhost/katello/apidoc">https://localhost/katello/apidoc</a><br>
    <br>
    you can see what all possible requests you can make to the API (some
    paths might surprise you but that's what our routes.rb says = we
    need to do some cleenup there).<br>
    <br>
    I've updated documentation for environments a bit so that you can
    see what it might look like:<br>
    <br>
    <a class="moz-txt-link-freetext" href="https://localhost/katello/apidoc#environments">https://localhost/katello/apidoc#environments</a><br>
    <br>
    and what a action description might look like:<br>
    <br>
    <a class="moz-txt-link-freetext" href="https://localhost/katello/apidoc#environments/create">https://localhost/katello/apidoc#environments/create</a><br>
    <br>
    There is still some work to do but I would like to hear your
    feedback, suggestions, options on this approach. I hope it's the
    first step to get more consistent and usable API for our project.<br>
    <br>
    <pre class="moz-signature" cols="72">-- 
Ivan</pre>
  </body>
</html>