[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7960":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":20,"hasPages":20,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":23,"readmeContent":24,"aiSummary":25,"trendingCount":16,"starSnapshotCount":16,"syncStatus":26,"lastSyncTime":27,"discoverSource":28},7960,"apipie-rails","Apipie\u002Fapipie-rails","Apipie","Ruby on Rails API documentation tool","",null,"Ruby",2506,453,29,208,0,1,60.07,"Apache License 2.0",false,"master",[],"2026-06-12 04:00:36","# API Documentation Tool\n\n[![image](https:\u002F\u002Fgithub.com\u002FApipie\u002Fapipie-rails\u002Factions\u002Fworkflows\u002Fbuild.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002FApipie\u002Fapipie-rails\u002Factions\u002Fworkflows\u002Fbuild.yml)\n[![image](https:\u002F\u002Fcodeclimate.com\u002Fgithub\u002FApipie\u002Fapipie-rails.svg)](https:\u002F\u002Fcodeclimate.com\u002Fgithub\u002FApipie\u002Fapipie-rails)\n[![Join the chat at https:\u002F\u002Fgitter.im\u002FApipie\u002Fapipie-rails](https:\u002F\u002Fbadges.gitter.im\u002FApipie\u002Fapipie-rails.svg)](https:\u002F\u002Fgitter.im\u002FApipie\u002Fapipie-rails?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n[![Latest release](https:\u002F\u002Fimg.shields.io\u002Fgem\u002Fv\u002Fapipie-rails.svg)](https:\u002F\u002Frubygems.org\u002Fgems\u002Fapipie-rails)\n\nApipie-rails is a DSL and Rails engine for documenting your RESTful API.\nInstead of traditional use of `#comments`, Apipie lets you describe the\ncode, through the code. This brings advantages like:\n\n-   No need to learn yet another syntax, you already know Ruby, right?\n-   Possibility of reusing the docs for other purposes (such as\n    validation)\n-   Easier to extend and maintain (no string parsing involved)\n-   Possibility of reusing other sources for documentation purposes\n    (such as routes etc.)\n\nThe documentation is available from within your app (by default under\nthe `\u002Fapipie` path.) In development mode, you can see the changes as you\ngo. It\\'s markup language agnostic, and even provides an API for reusing\nthe documentation data in JSON.\n\n## Getting started\n\nThe easiest way to get Apipie up and running with your app is:\n\n``` sh\necho \"gem 'apipie-rails'\" >> Gemfile\nbundle install\nrails g apipie:install\n```\n\nNow you can start documenting your resources and actions (see [DSL\nReference](#dsl-reference) for more info):\n\n``` ruby\napi :GET, '\u002Fusers\u002F:id'\nparam :id, :number, desc: 'id of the requested user'\ndef show\n  # ...\nend\n```\n\nRun your application and see the result at\n`http:\u002F\u002Flocalhost:3000\u002Fapipie`. For further processing, you can use\n`http:\u002F\u002Flocalhost:3000\u002Fapipie.json`.\n\nFor a more comprehensive getting started guide, see [this\ndemo](https:\u002F\u002Fgithub.com\u002FApipie\u002Fapipie-demo), which includes features\nsuch as generating documentation from tests, recording examples etc.\n\n## Screenshots\n\n![image](https:\u002F\u002Fgithub.com\u002FApipie\u002Fapipie-rails\u002Fblob\u002Fmaster\u002Fimages\u002Fscreenshot-1.png)\n\n![image](https:\u002F\u002Fgithub.com\u002FApipie\u002Fapipie-rails\u002Fblob\u002Fmaster\u002Fimages\u002Fscreenshot-2.png)\n\n## Authors\n\n[Pajk](https:\u002F\u002Fgithub.com\u002FPajk) and [iNecas](https:\u002F\u002Fgithub.com\u002FiNecas)\n\n## Contributors\n\nSee [Contributors\npage](https:\u002F\u002Fgithub.com\u002FApipie\u002Fapipie-rails\u002Fgraphs\u002Fcontributors).\nSpecial thanks to all of them!\n\n## License\n\nApipie-rails is released under the [MIT\nLicense](https:\u002F\u002Fopensource.org\u002Flicenses\u002FMIT)\n\n## Table Of Contents\n\n- [API Documentation Tool](#api-documentation-tool)\n- [Getting started](#getting-started)\n- [Screenshots](#screenshots)\n- [Authors](#authors)\n- [Contributors](#contributors)\n- [License](#license)\n- [Documentation](#documentation)\n   - [DSL Reference](#dsl-reference)\n      - [Resource Description](#resource-description)\n      - [Method Description](#method-description)\n      - [Parameter Description](#parameter-description)\n      - [DRY with param_group](#dry-with-param_group)\n      - [Action Aware params](#action-aware-params)\n      - [Response Description](#response-description)\n      - [Concerns](#concerns)\n      - [Response validation](#response-validation)\n   - [Configuration Reference](#configuration-reference)\n      - [Rails Routes Integration](#rails-routes-integration)\n      - [Processing](#processing)\n      - [Validators](#validators)\n         - [TypeValidator](#typevalidator)\n         - [RegexpValidator](#regexpvalidator)\n         - [EnumValidator](#enumvalidator)\n         - [ProcValidator](#procvalidator)\n         - [HashValidator](#hashvalidator)\n         - [NilValidator](#nilvalidator)\n         - [NumberValidator](#numbervalidator)\n         - [DecimalValidator](#decimalvalidator)\n         - [ArrayValidator](#arrayvalidator)\n         - [NestedValidator](#nestedvalidator)\n         - [Adding custom validator](#adding-custom-validator)\n      - [Versioning](#versioning)\n      - [Markup](#markup)\n      - [Localization](#localization)\n      - [Modifying Views](#modifying-views)\n      - [Static files](#static-files)\n      - [Static Swagger (OpenAPI 2.0) files](#static-swagger-openapi-20-files)\n        - [Specifying default values for parameters](#specifying-default-values-for-parameters)\n        - [Generated Warnings](#generated-warnings)\n        - [Swagger-Specific Configuration Parameters](#swagger-specific-configuration-parameters)\n        - [Known limitations of the current implementation](#known-limitations-of-the-current-implementation)\n      - [Dynamic Swagger generation](#dynamic-swagger-generation)\n      - [JSON checksums](#json-checksums)\n      - [Tests Integration](#tests-integration)\n        - [Documentation Bootstrapping](#documentation-bootstrapping)\n        - [Examples Recording](#examples-recording)\n        - [Caveats](#caveats)\n      - [Bindings Generator](#bindings-generator)\n   - [Contributing](#contributing)\n   - [Disqus Integration](#disqus-integration)\n   - [External References](#external-references)\n\n# DSL Reference\n\n## Resource Description\n\nYou can describe a resource on the controller level. The description is\nintroduced by calling `resource_description do ... end`.\n\nInheritance is supported, so you can specify common params for group of\ncontrollers in their parent class.\n\nThe following keywords are available (all are optional):\n\n`resource_id`\n\nHow the resource will be referenced in Apipie (paths, `see` command etc.); by default `controller_name.downcase` is used.\n\n`name`\n\nHuman readable name of resource. By default `class.name.humanize` is\nused.\n\n  -   Can be specified as a proc, which will receive the controller\n      class as an argument.\n  -   Can be a symbol, which will be sent to the controller class to\n      get the name.\n  -   Can be a string, which will be used as is.\n\n`short` (also `short_description`)\n\nShort description of the resource (it\\'s shown on both the list of resources, and resource details)\n\n`desc` (also description and full_description)\n\nFull description of the resource (shown only in resource details)\n\n`param`\n\nCommon params for all methods defined in controller\u002Fchild controllers.\n\n`returns`\n\nCommon responses for all methods defined in controller\u002Fchild controllers.\n\n`api_base_url`\n\nWhat URL is the resource available under.\n\n`api_versions` (also api_version)\n\nWhat versions does the controller define the resource. (See [Versioning](#versioning) for details.)\n\n`formats`\n\nRequest \u002F response formats.\n\n`error`\n\nDescribe every possible error that can happen when calling all\nmethods defined in controller. HTTP response code and description\ncan be provided.\n\n`app_info`\n\nIn case of versioning, this sets app info description on a per_version basis.\n\n`meta`\n\nHash or array with custom metadata.\n\n`deprecated`\n\nBoolean value indicating if the resource is marked as deprecated. (Default `false`)\n\n### Example:\n\n``` ruby\nresource_description do\n  short 'Site members'\n  formats ['json']\n  param :id, Integer, :desc => \"User ID\", :required => false\n  param :resource_param, Hash, :desc => 'Param description for all methods' do\n    param :ausername, String, :desc => \"Username for login\", :required => true\n    param :apassword, String, :desc => \"Password for login\", :required => true\n  end\n  api_version \"development\"\n  error 404, \"Missing\"\n  error 500, \"Server crashed for some \u003C%= reason %>\", :meta => {:anything => \"you can think of\"}\n  error :unprocessable_entity, \"Could not save the entity.\"\n  returns :code => 403 do\n     property :reason, String, :desc => \"Why this was forbidden\"\n  end\n  meta :author => {:name => 'John', :surname => 'Doe'}\n  deprecated false\n  description \u003C\u003C-EOS\n    == Long description\n     Example resource for rest api documentation\n     These can now be accessed in \u003Ctt>shared\u002Fheader\u003C\u002Ftt> with:\n       Headline: \u003C%= headline %>\n       First name: \u003C%= person.first_name %>\n\n     If you need to find out whether a certain local variable has been\n     assigned a value in a particular render call, you need to use the\n     following pattern:\n\n     \u003C% if local_assigns.has_key? :headline %>\n        Headline: \u003C%= headline %>\n     \u003C% end %>\n\n    Testing using \u003Ctt>defined? headline\u003C\u002Ftt> will not work. This is an\n    implementation restriction.\n\n    === Template caching\n\n    By default, Rails will compile each template to a method in order\n    to render it. When you alter a template, Rails will check the\n    file's modification time and recompile it in development mode.\n  EOS\nend\n```\n\n## Method Description\n\nThen describe methods available to your API.\n\n`api`\n\nDescribe how this method is exposed, and provide a short\ndescription. The first parameter is HTTP method (one of\n:GET\u002F:POST\u002F:PUT\u002F:DELETE). The second parameter is the relative URL\npath which is mapped to this method. The last parameter is the\nmethods short description. You can use this +api+ method more than\nonce per method. It could be useful when there are more routes\nmapped to it.\n\nWhen providing just one argument (description), or no argument at\nall, the paths will be loaded from the routes.rb file.\n\n`api!`\n\nProvide a short description and additional option. The last\nparameter is the methods short description. The paths will be loaded\nfrom routes.rb file. See [Rails Routes\nIntegration](#rails-routes-integration) for more details.\n\n`api_versions` (also api_version)\n\nWhat version(s) does the action belong to. (See\n[Versioning](#versioning) for details.)\n\n`param`\n\nLook at [Parameter description](#parameter-description) section for\ndetails.\n\n`returns`\n\nLook at [Response description](#response-description) section for\ndetails.\n\n`tags`\n\nAdds tags for grouping operations together in Swagger outputs. See\n[swagger](#Swagger) for more details. You can also provide tags in\nthe [Resource Description](#resource-description) block so that they\nare automatically prepended to all action tags in the controller.\n\n`formats`\n\nMethod level request \u002F response formats.\n\n`error`\n\nDescribe each possible error that can happen while calling this\n    method. HTTP response code and description can be provided.\n\n`description`\n\nFull method description, which will be converted into HTML by the\n    chosen markup language processor.\n\n`example`\n\nProvide an example of the server response; whole communication or\n    response type. It will be formatted as code.\n\n`see`\n\nProvide reference to another method, this has to be a string with\n    controller_name#method_name.\n\n`meta`\n\nHash or array with custom metadata.\n\n`show`\n\nResource is hidden from documentation when set to false (true by\n    default)\n\n### Example:\n\n``` ruby\n# The simplest case: just load the paths from routes.rb\napi!\ndef index\nend\n\n# More complex example\napi :GET, \"\u002Fusers\u002F:id\", \"Show user profile\"\nshow false\nerror :code => 401, :desc => \"Unauthorized\"\nerror :code => 404, :desc => \"Not Found\", :meta => {:anything => \"you can think of\"}\nparam :session, String, :desc => \"user is logged in\", :required => true\nparam :regexp_param, \u002F^[0-9]* years\u002F, :desc => \"regexp param\"\nparam :array_param, [100, \"one\", \"two\", 1, 2], :desc => \"array validator\"\nparam :boolean_param, [true, false], :desc => \"array validator with boolean\"\nparam :proc_param, lambda { |val|\n  val == \"param value\" ? true : \"The only good value is 'param value'.\"\n}, :desc => \"proc validator\"\nparam :param_with_metadata, String, :desc => \"\", :meta => [:your, :custom, :metadata]\nreturns :code => 200, :desc => \"a successful response\" do\n   property :value1, String, :desc => \"A string value\"\n   property :value2, Integer, :desc => \"An integer value\"\n   property :value3, Hash, :desc => \"An object\" do\n     property :enum1, ['v1', 'v2'], :desc => \"One of 2 possible string values\"\n   end\nend\ntags %w[profiles logins]\ntags 'more', 'related', 'resources'\ndescription \"method description\"\nformats ['json', 'jsonp', 'xml']\nmeta :message => \"Some very important info\"\nexample \" 'user': {...} \"\nsee \"users#showme\", \"link description\"\nsee :link => \"users#update\", :desc => \"another link description\"\ndef show\n  #...\nend\n```\n\n## Parameter Description\n\nUse `param` to describe every possible parameter. You can use the Hash\nvalidator in conjunction with a block given to the param method to\ndescribe nested parameters.\n\n`name`\n\nThe first argument is the parameter name as a symbol.\n\n`validator`\n\nSecond parameter is the parameter validator, choose one from section\n    [Validators](#validators)\n\n`desc`\n\nParameter description.\n\n`required`\n\nSet this true\u002Ffalse to make it required\u002Foptional. Default is\n    optional\n\n`example`\n\nProvide the example for this parameter.\n\n`allow_nil`\n\nSetting this to true means that `nil` can be passed.\n\n`allow_blank`\n\nLike `allow_nil`, but for blank values. `false`, `\"\"`, `' '`, `nil`,\n    `[]`, and `{}` are all blank.\n\n`as`\n\nUsed by the processing functionality to change the name of a key params.\n\n`meta`\n\nHash or array with custom metadata.\n\n`show`\n\nParameter is hidden from documentation when set to false (true by default)\n\n`missing_message`\n\nSpecify the message to be returned if the parameter is missing as a\nstring or Proc. Defaults to `Missing parameter #{name}` if not\nspecified.\n\n`only_in`\n\nThis can be set to `:request` or `:response`. Setting to `:response`\ncauses the param to be ignored when used as part of a request\ndescription. Setting to `:request` causes this param to be ignored\nwhen used as part of a response description. If `only_in` is not\nspecified, the param definition is used for both requests and\nresponses. (Note that the keyword `property` is similar to `param`,\nbut it has a `:only_in => :response` default).\n\n### Example:\n\n``` ruby\nparam :user, Hash, :desc => \"User info\" do\n  param :username, String, :desc => \"Username for login\", :required => true, :example => 'John'\n  param :password, String, :desc => \"Password for login\", :required => true, :example => '1234567'\n  param :membership, [\"standard\",\"premium\"], :desc => \"User membership\"\n  param :admin_override, String, :desc => \"Not shown in documentation\", :show => false\n  param :ip_address, String, :desc => \"IP address\", :required => true, :missing_message => lambda { I18n.t(\"ip_address.required\") }\nend\ndef create\n  #...\nend\n```\n\n`deprecated`\n\nIndicates if the parameter is marked as deprecated.\n\n### Example\n\n``` ruby\nparam :pet_name, String, desc: \"Name of pet\", deprecated: true\nparam :pet_name, String, desc: \"Name of pet\", deprecated: 'Some deprecation info'\nparam :pet_name, String, desc: \"Name of pet\", deprecated: { in: \"2.3\", info: \"Something\", sunset: \"3.0\" }\ndef create\n  #...\nend\n```\n\n## DRY with param_group\n\nOften, params occur together in more actions. Typically, most of the\nparams for `create` and `update` actions are shared between them.\n\nThese params can be extracted with `def_param_group` and `param_group`\nkeywords.\n\nThe definition is looked up in the scope of the controller. If the group\nis defined in a different controller, it might be referenced by\nspecifying the second argument.\n\n### Example:\n\n``` ruby\n# v1\u002Fusers_controller.rb\ndef_param_group :address do\n  param :street, String\n  param :number, Integer\n  param :zip, String\nend\n\ndef_param_group :user do\n  param :user, Hash do\n    param :name, String, \"Name of the user\"\n    param_group :address\n  end\nend\n\napi :POST, \"\u002Fusers\", \"Create a user\"\nparam_group :user\ndef create\n  # ...\nend\n\napi :PUT, \"\u002Fusers\u002F:id\", \"Update a user\"\nparam_group :user\ndef update\n  # ...\nend\n\n# v2\u002Fusers_controller.rb\napi :POST, \"\u002Fusers\", \"Create a user\"\nparam_group :user, V1::UsersController\ndef create\n  # ...\nend\n```\n\n## Action Aware params\n\nIn CRUD operations, this pattern occurs quite often - params that need\nto be set are:\n\n-   for create action: `required => true` and `allow_nil => false`\n-   for update action: `required => false` and `allow_nil => false`\n\nThis makes it hard to share the param definitions across these actions.\nTherefore, you can make the description a bit smarter by setting\n`:action_aware => true`.\n\nYou can specify explicitly how the param group should be evaluated with\n`:as` option (either :create or :update)\n\n### Example\n\n``` ruby\ndef_param_group :user do\n  param :user, Hash, :action_aware => true do\n    param :name, String, :required => true\n    param :description, String\n  end\nend\n\napi :POST, \"\u002Fusers\", \"Create a user\"\nparam_group :user\ndef create\n  # ...\nend\n\napi :PUT, \"\u002Fusers\u002Fadmin\", \"Create an admin\"\nparam_group :user, :as => :create\ndef create_admin\n  # ...\nend\n\napi :PUT, \"\u002Fusers\u002F:id\", \"Update a user\"\nparam_group :user\ndef update\n  # ...\nend\n```\n\nIn this case, `user[name]` will be not be allowed nil for all actions\nand required only for `create` and `create_admin`. Params with\n`allow_nil` set explicitly don\\'t have this value changed.\n\nAction awareness is inherited from ancestors (in terms of nested\nparams).\n\n## Response Description\n\nThe response from an API call can be documented by adding a `returns`\nstatement to the method description. This is especially useful when\nusing Apipie to auto-generate a machine-readable Swagger definition of\nyour API (see the [swagger](#Swagger) section for more details).\n\nA `returns` statement has several possible formats:\n\n``` ruby\n# format #1:  reference to a param-group\nreturns \u003Cparam-group-name> [, :code => \u003Cnumber>|\u003Chttp-response-code-symbol>] [, :desc => \u003Chuman-readable description>]\n\n# format #2:  inline response definition\nreturns :code => \u003Cnumber>|\u003Chttp-response-code-symbol> [, :desc => \u003Chuman-readable description>] do\n    # property ...\n    # property ...\n    # param_group ...\nend\n\n# format #3:  describing an array-of-objects response\nreturns :array_of => \u003Cparam-group-name> [, :code => \u003Cnumber>|\u003Chttp-response-code-symbol>] [, :desc => \u003Chuman-readable description>]\n```\n\nIf the `:code` argument is omitted, `200` is used.\n\n### Example\n\n``` ruby\n# ------------------------------------------------\n# Example of format #1 (reference to param-group):\n# ------------------------------------------------\n# the param_group :pet is defined here to describe the output returned by the method below.\ndef_param_group :pet do\n  property :pet_name, String, :desc => \"Name of pet\"\n  property :animal_type, ['dog','cat','iguana','kangaroo'], :desc => \"Type of pet\"\nend\n\napi :GET, \"\u002Fpets\u002F:id\", \"Get a pet record\"\nreturns :pet, :desc => \"The pet\"\ndef show_detailed\n  render JSON({:pet_name => \"Skippie\", :animal_type => \"kangaroo\"})\nend\n\n# ------------------------------------------------\n# Example of format #2 (inline):\n# ------------------------------------------------\napi :GET, \"\u002Fpets\u002F:id\u002Fwith-extra-details\", \"Get a detailed pet record\"\nreturns :code => 200, :desc => \"Detailed info about the pet\" do\n  param_group :pet\n  property :num_legs, Integer, :desc => \"How many legs the pet has\"\nend\ndef show\n  render JSON({:pet_name => \"Barkie\", :animal_type => \"iguana\", :legs => 4})\nend\n\n# ------------------------------------------------\n# Example of format #3 (array response):\n# ------------------------------------------------\napi :GET, \"\u002Fpets\", \"Get all pet records\"\nreturns :array_of => :pet, :code => 200, :desc => \"All pets\"\ndef index\n  render JSON([ {:pet_name => \"Skippie\", :animal_type => \"kangaroo\"},\n                {:pet_name => \"Woofie\", :animal_type => \"cat\"} ])\nend\n```\n\nNote the use of the `property` keyword rather than `param`. This is the\npreferred mechanism for documenting response-only fields.\n\n#### Specify response headers\n\nWe can specify the response headers using the `header` keyword within the `returns` block.\n\n##### Example\n```ruby\napi :GET, \"\u002Fpets\u002F:id\u002Fwith-extra-details\", \"Get a detailed pet record\"\nreturns code: 200, desc: \"Detailed info about the pet\" do\n  param_group :pet\n  property :num_legs, Integer, :desc => \"How many legs the pet has\"\n  header 'Link', String, 'Relative links'\n  header 'Current-Page', Integer, 'The current page', required: true\nend\n\ndef show\n  render JSON({ :pet_name => \"Barkie\", :animal_type => \"iguana\", :legs => 4 })\nend\n```\n\n#### The Property keyword\n\n`property` is very similar to `param` with the following differences:\n\n-   a `property` is `:only_in => :response` by default\n-   a `property` is `:required => :true` by default\n-   a `property` can be an `:array_of` objects\n\n##### Example\n\n``` ruby\nproperty :example, :array_of => Hash do\n  property :number1, Integer\n  property :number2, Integer\nend\n```\n\n#### Describing multiple return codes\n\nTo describe multiple possible return codes, the `:returns` keyword can\nbe repeated as many times as necessary (once for each return code). Each\none of the `:returns` entries can specify a different response format.\n\n##### Example\n\n``` ruby\napi :GET, \"\u002Fpets\u002F:id\u002Fextra_info\", \"Get extra information about a pet\"\n  returns :desc => \"Found a pet\" do\n    param_group :pet\n    property 'pet_history', Hash do\n      param_group :pet_history\n    end\n  end\n  returns :code => :unprocessable_entity, :desc => \"Fleas were discovered on the pet\" do\n    param_group :pet\n    property :num_fleas, Integer, :desc => \"Number of fleas on this pet\"\n  end\n  def show_extra_info\n    # ... implementation here\n  end\n```\n\n#### Reusing a param_group to describe inputs and outputs\n\nIn many cases (such as CRUD implementations), the output from certain\nAPI calls is very similar - but not identical - to the inputs of the\nsame or other API calls.\n\nIf you already have a `:param_group` that defines the input to a\n`create` or `update routine, it would be quite\nfrustrating to have to define a completely separate `:param_group` to\ndescribe the output of the `show` routine.\n\nTo address such situations, it is possible to define a single\n`:param_group` which combines `param` and `property` statements (as well\nas `:only_in => :request` \u002F `:only_in => :response`) to differentiate\nbetween fields that are only expected in the request, only included in\nthe response, or common to both.\n\nThis is somewhat analogous to the way [Action Aware\nparams](#action-aware-params) work.\n\n##### Example\n\n``` ruby\ndef_param_group :user_record\n    param :name, String                                         # this is commong to both the request and the response\n    param :force_update, [true, false], :only_in => :request    # this does not show up in responses\n    property :last_login, String                                # this shows up only in the response\nend\n\napi :POST, \"\u002Fusers\", \"Create a user\"\nparam_group :user_record  # the :last_login field is not expected here, but :force_update is\ndef create\n # ...\nend\n\napi :GET, \"\u002Fusers\", \"Create a user\"\nreturns :array_of => :user_record  # the :last_login field will be included in the response, but :force_update will not\ndef index\n # ...\nend\n```\n\n#### Embedded response descriptions\n\nIf the code creating JSON responses is encapsulated within dedicated\nclasses, it can be more convenient to place the response descriptions\noutside of the controller and embed them within the response generator.\n\nTo support such use cases, Apipie allows any class to provide a\n`describe_own_properties` class method which returns a\ndescription of the properties such a class would expose. It is then\npossible to specify that class in the `returns` statement\ninstead of a `param_group`.\n\nThe `describe_own_properties` method is expected to return\nan array of `Apipie::prop` objects, each one describing a\nsingle property.\n\n##### Example\n\n``` ruby\nclass Pet\n  # this method is automatically called by Apipie when Pet is specified as the returned object type\n  def self.describe_own_properties\n    [\n        Apipie::prop(:pet_name, 'string', {:description => 'Name of pet', :required => false}),\n        Apipie::prop(:animal_type, 'string', {:description => 'Type of pet', :values => [\"dog\", \"cat\", \"iguana\", \"kangaroo\"]}),\n        Apipie::additional_properties(false)  # this indicates that :pet_name and :animal_type are the only properties in the response\n    ]\n  end\n\n  # this method w\n  def json\n    JSON({:pet_name => @name, :animal_type => @type })\n  end\nend\n\n\nclass PetsController\n    api :GET, \"\u002Findex\", \"Get all pets\"\n    returns :array_of => Pet  # Pet is a 'self-describing-class'\n    def index\n     # ...\n    end\nend\n```\n\nA use case where this is very useful is when JSON generation is done\nusing a reflection mechanism or some other sort of declarative\nmechanism.\n\nThe `Apipie::prop` function expects the following inputs:\n\n``` ruby\nApipie::prop(\u003Cproperty-name>, \u003Cproperty-type>, \u003Coptions-hash> [, \u003Carray of sub-properties>])\n\n# property-name should be a symbol\n#\n# property-type can be any of the following strings:\n#   \"integer\": maps to a swagger \"integer\" with an \"int32\" format\n#   \"long\": maps to a swagger \"integer\" with an \"int64\" format\n#   \"number\": maps to a swagger \"number\"(no format specifier)\n#   \"float\": maps to a swagger \"number\" with a \"float\" format\n#   \"double\": maps to a swagger \"number\" with a \"double\" format\n#   \"string\": maps to a swagger \"string\" (no format specifier)\n#   \"byte\": maps to a swagger \"string\" with a \"byte\" format\n#   \"binary\": maps to a swagger \"string\" with a \"binary\" format\n#   \"boolean\": maps to a swagger \"boolean\" (no format specifier)\n#   \"date\": maps to a swagger \"string\" with a \"date\" format\n#   \"dateTime\": maps to a swagger \"string\" with a \"date-time\" format\n#   \"password\": maps to a swagger \"string\" with a \"password\" format\n#   \"object\": the property has sub-properties. include \u003Carray of sub-properties> in the call.\n# (see https:\u002F\u002Fgithub.com\u002FOAI\u002FOpenAPI-Specification\u002Fblob\u002Fmaster\u002Fversions\u002F2.0.md#data-types for more information\n# about the mapped swagger types)\n#\n# options-hash can include any of the options fields allowed in a :returns statement.\n# additionally, it can include the ':is_array => true', in which case the property is understood to be\n# an array of the described type.\n```\n\nTo describe an embedded object:\n\n``` ruby\n#\n# PetWithMeasurements is a self-describing class with an embedded object\n#\nclass PetWithMeasurements\n  def self.describe_own_properties\n    [\n        Apipie::prop(:pet_name, 'string', {:description => 'Name of pet', :required => false}),\n        Apipie::prop('animal_type', 'string', {:description => 'Type of pet', :values => [\"dog\", \"cat\", \"iguana\", \"kangaroo\"]}),\n        Apipie::prop(:pet_measurements, 'object', {}, [\n            Apipie::prop(:weight, 'number', {:description => \"Weight in pounds\" }),\n            Apipie::prop(:height, 'number', {:description => \"Height in inches\" }),\n            Apipie::prop(:num_legs, 'number', {:description => \"Number of legs\", :required => false }),\n            Apipie::additional_properties(false)\n        ])\n    ]\n  end\nend\n\n#\n# PetWithManyMeasurements is a self-describing class with an embedded array of objects\n#\nclass PetWithManyMeasurements\n  def self.describe_own_properties\n    [\n        Apipie::prop(:pet_name, 'string', {:description => 'Name of pet', :required => false}),\n        Apipie::prop(:many_pet_measurements, 'object', {is_array: true}, [\n            Apipie::prop(:weight, 'number', {:description => \"Weight in pounds\" }),\n            Apipie::prop(:height, 'number', {:description => \"Height in inches\" }),\n        ])\n    ]\n  end\nend\n```\n\n## Concerns\n\nSometimes, the actions are not defined in the controller class directly\nbut included from a module instead. You can load the Apipie DSL into the\nmodule by extending it with `Apipie::DSL::Concern`.\n\nThe module can be used in more controllers. Therefore there is a way to\nsubstitute parts of the documentation in the module with controller\nspecific values. These substitutions can be stated explicitly with\n`apipie_concern_subst(:key => \"value\")` (needs to be called before the\nmodule is included to take effect). The substitutions are performed in\nthe paths and descriptions of APIs and names and descriptions of params.\n\nThere are some default substitutions available:\n\n`:controller_path`\n\nvalue of `controller.controller_path`, e.g. `api\u002Fusers` for\n    `Api::UsersController`. Only if not using the `api!` keyword.\n\n`:resource_id`\n\nApipie identifier of the resource, e.g. `users` for\n    `Api::UsersController` or set by `resource_id`\n\n### Example\n\n``` ruby\n# users_module.rb\nmodule UsersModule\n  extend Apipie::DSL::Concern\n\n  api :GET, '\u002F:controller_path', 'List :resource_id'\n  def index\n    # ...\n  end\n\n  api! 'Show a :resource'\n  def show\n    # ...\n  end\n\n  api :POST, '\u002F:resource_id', \"Create a :resource\"\n  param :concern, Hash, :required => true\n    param :name, String, 'Name of a :resource'\n    param :resource_type, ['standard','vip']\n  end\n  def create\n    # ...\n  end\n\n  api :GET, '\u002F:resource_id\u002F:custom_subst'\n  def custom\n    # ...\n  end\nend\n\n# users_controller.rb\nclass UsersController \u003C ApplicationController\n\n  resource_description { resource_id 'customers' }\n\n  apipie_concern_subst(:custom_subst => 'custom', :resource => 'customer')\n  include UsersModule\n\n  # the following paths are documented\n  # api :GET, '\u002Fusers'\n  # api :GET, '\u002Fcustomers\u002F:id', 'Show a customer'\n  # api :POST, '\u002Fcustomers', 'Create a customer'\n  #   param :customer, :required => true do\n  #     param :name, String, 'Name of a customer'\n  #     param :customer_type, ['standard', 'vip']\n  #   end\n  # api :GET, '\u002Fcustomers\u002F:custom'\nend\n```\n\nSometimes, it\\'s needed to extend an existing controller method with\nadditional parameters (usually when extending exiting API from\nplugins\u002Frails engines). The concern can be also used for this purposed,\nusing `update_api` method. The params defined in this block\nare merged with the params of the original method in the controller this\nconcern is included to.\n\n### Example\n\n``` ruby\nmodule Concerns\n  module OauthConcern\n    extend Apipie::DSL::Concern\n\n    update_api(:create, :update) do\n      param :user, Hash do\n        param :oauth, String, :desc => 'oauth param'\n      end\n    end\n  end\nend\n```\n\nThe concern needs to be included to the controller after the methods are\ndefined (either at the end of the class, or by using\n`Controller.send(:include, Concerns::OauthConcern)`.\n\n## Response validation\n\nThe swagger definitions created by Apipie can be used to auto-generate\nclients that access the described APIs. Those clients will break if the\nresponses returned from the API do not match the declarations. As such,\nit is very important to include unit tests that validate the actual\nresponses against the swagger definitions.\n\nThe implemented mechanism provides two ways to include such validations\nin RSpec unit tests: manual (using an RSpec matcher) and automated (by\ninjecting a test into the http operations \\'get\\', \\'post\\', raising an\nerror if there is no match).\n\n### Example of the manual mechanism:\n\n``` ruby\nrequire 'apipie\u002Frspec\u002Fresponse_validation_helper'\n\nRSpec.describe MyController, :type => :controller, :show_in_doc => true do\n\n  describe \"GET stuff with response validation\" do\n    render_views   # this makes sure the 'get' operation will actually\n                   # return the rendered view even though this is a Controller spec\n\n    it \"does something\" do\n      response = get :index, {format: :json}\n\n      # the following expectation will fail if the returned object\n      # does not match the 'returns' declaration in the Controller,\n      # or if there is no 'returns' declaration for the returned\n      # HTTP status code\n      expect(response).to match_declared_responses\n    end\n  end\nend\n```\n\n### Example of the automated mechanism:\n\n``` ruby\nrequire 'apipie\u002Frspec\u002Fresponse_validation_helper'\n\nRSpec.describe MyController, :type => :controller, :show_in_doc => true do\n\n  describe \"GET stuff with response validation\" do\n    render_views\n    auto_validate_rendered_views\n\n    it \"does something\" do\n      get :index, {format: :json}\n    end\n    it \"does something else\" do\n      get :another_index, {format: :json}\n    end\n  end\n\n  describe \"GET stuff without response validation\" do\n    it \"does something\" do\n      get :index, {format: :json}\n    end\n    it \"does something else\" do\n      get :another_index, {format: :json}\n    end\n  end\nend\n```\n\n# Configuration Reference\n\nCreate a configuration file in e.g. `\u002Fconfig\u002Finitializers\u002Fapipie.rb`.\nYou can set the application name, footer text, API and documentation\nbase URL and turn off validations. You can also choose your favorite\nmarkup language for full descriptions.\n\n`app_name`\n\nName of your application; used in breadcrumbs navigation.\n\n`copyright`\n\nCopyright information (shown in page footer).\n\n`compress_examples`\n\nIf `true` recorded examples are compressed using `Zlib`. Useful for\n    big test-suits.\n\n`doc_base_url`\n\nDocumentation frontend base url.\n\n`api_base_url`\n\nBase url for default version of your API. To set it for specific\n    version use `config.api_base_url[version] = url`.\n\n`default_version`\n\nDefault API version to be used (1.0 by default)\n\n`validate`\n\nParameters validation is turned off when set to false. When set to\n    `:explicitly`, you must invoke parameter validation yourself by\n    calling controller method `apipie_validations` (typically in a\n    before_action). When set to `:implicitly` (or just true), your\n    controller\\'s action methods are wrapped with generated methods\n    which call `apipie_validations`, and then call the action method.\n    (`:implicitly` by default)\n\n`validate_value`\n\nCheck the value of params against specified validators (true by default)\n\n`validate_presence`\n\nCheck the params presence against the documentation.\n\n`validate_key`\n\nCheck the received params to ensure they are defined in the API.\n    (false by default)\n\n`action_on_non_validated_keys`\n\nEither `:raise` or `:skip`. If `validate_key` fails, raise error or\ndelete the non-validated key from the params and log the key (`:raise` by default)\n\n`process_params`\n\nProcess and extract the parameter defined from the params of the\n    request to the api_params variable\n\n`app_info`\n\nApplication long description.\n\n`reload_controllers`\n\nSet to enable\u002Fdisable reloading controllers (and the documentation\n    with it). Enabled by default in development.\n\n`api_controllers_matcher`\n\nFor reloading to work properly you need to specify where your API\n    controllers are. Can be an array if multiple paths are needed\n\n`api_action_matcher`\n\nDetermines the strategy to identity the correct controller action.\n    Needs to be a class that implements a `.call(controller)` method\n\n`api_routes`\n\nSet if your application uses a custom API router, different from the\n    Rails default\n\n`routes_formatter`\n\nAn object providing the translation from the Rails routes to the\n    format usable in the documentation when using the `api!`\n    keyword. By default, the `Apipie::RoutesFormatter` is used.\n\n`markup`\n\nYou can choose markup language for descriptions of your application,\n    resources and methods. RDoc is the default but you can choose from\n    Apipie::Markup::Markdown.new or Apipie::Markup::Textile.new. In\n    order to use Markdown you need Maruku gem and for Textile you need\n    RedCloth. Add those to your gemfile and run bundle if you want to\n    use them. You can also add any other markup language processor.\n\n`layout`\n\nName of a layout template to use instead of Apipie\\'s layout. You\n    can use Apipie.include_stylesheets and Apipie.include_javascripts\n    helpers to include Apipie\\'s stylesheets and javascripts.\n\n`ignored`\n\nAn array of controller names (strings) (might include actions as\n    well) to be ignored when generating the documentation e.g.\n    `%w[Api::CommentsController Api::PostsController#post]`\n\n`namespaced_resources`\n\nUse controller paths instead of controller names as resource id.\n    This prevents same named controllers overwriting each other.\n\n`authenticate`\n\nPass a proc in order to authenticate user. Pass nil for no\n    authentication (by default).\n\n`authorize`\n\nPass a proc in order to authorize controllers and methods. The Proc\n    is evaluated in the controller context.\n\n`show_all_examples`\n\nSet this to true to set show_in_doc=1 in all recorded examples\n\n`ignore_allow_blank_false`\n\n`allow_blank: false` was incorrectly ignored up until\n    version 0.6.0, this bug was fixed in 0.7.0 if you need the old\n    behavior, set this to true\n\n`link_extension`\n\nThe extension to use for API pages (\\'.html\\' by default). Link\n    extensions in static API docs cannot be changed from \\'.html\\'.\n\n`languages`\n\nList of languages the API documentation should be translated into.\n    Empty by default.\n\n`default_locale`\n\nLocale used for generating documentation when no specific locale is\n    set. Set to \\'en\\' by default.\n\n`locale`\n\nPass locale setter\u002Fgetter\n\n``` ruby\nconfig.locale = lambda { |loc| loc ? FastGettext.set_locale(loc) : FastGettext.locale }\n```\n\n`translate`\n\nPass proc to translate strings using the localization library your\n    project uses. For example see [Localization](#localization)\n\nExample:\n\n``` ruby\nApipie.configure do |config|\n  config.app_name = \"Test app\"\n  config.copyright = \"&copy; 2012 Pavel Pokorny\"\n  config.doc_base_url = \"\u002Fapidoc\"\n  config.api_base_url = \"\u002Fapi\"\n  config.validate = false\n  config.markup = Apipie::Markup::Markdown.new\n  config.reload_controllers = Rails.env.development?\n  config.api_controllers_matcher = File.join(Rails.root, \"app\", \"controllers\", \"**\",\"*.rb\")\n  config.api_action_matcher = proc { |controller| controller.params[:action] }\n  config.api_routes = Rails.application.routes\n  config.app_info[\"1.0\"] = \"\n    This is where you can inform user about your application and API\n    in general.\n  \"\n  config.authenticate = Proc.new do\n     authenticate_or_request_with_http_basic do |username, password|\n       username == \"test\" && password == \"supersecretpassword\"\n    end\n  end\n  config.authorize = Proc.new do |controller, method, doc|\n    !method   # show all controller doc, but no method docs.\n  end\nend\n```\n\n`checksum_path`\n\nUsed in ChecksumInHeaders middleware (see [JSON\n    checksums](#json-checksums) for more info). It contains path\n    prefix(es) where the header with checksum is added. If set to nil,\n    checksum is added in headers in every response. e.g.\n    `%w[\u002Fapi \u002Fapipie]`\n\n`update_checksum`\n\nIf set to `true`, the checksum is recalculated with every\n    documentation_reload call\n\n# Rails Routes Integration\n\nApipie is able to load the information about the paths based on the\nroutes defined in the Rails application, by using the `api!`\nkeyword in the DSL.\n\nIt should be usable out of box, however, one might want to do some\ncustomization (such as omitting some implicit parameters in the path\netc.). For this kind of customizations one can create a new formatter\nand pass as the `Apipie.configuration.routes_formatter` option, like\nthis:\n\n``` ruby\nclass MyFormatter \u003C Apipie::RoutesFormatter\n  def format_path(route)\n    super.gsub(\u002F\\(.*?\\)\u002F, '').gsub('\u002F\u002F','') # hide all implicit parameters\n  end\nend\n\nApipie.configure do |config|\n ...\n config.routes_formatter = MyFormatter.new\n ...\nend\n```\n\nA similar way can be used to influence things like order, or a\ndescription of the loaded APIs, even omitting some paths if needed.\n\n# Processing\n\nThe goal is to extract and pre-process parameters of the request.\n\nFor example Rails, by default, transforms an empty array to nil value.\nPerhaps you want to transform it again into an empty array. Or you want\nto support an enumeration type (comma separated values) and you want to\nautomatically transform this string into an array.\n\nTo use it, set the `process_params` configuration variable to true.\n\nAlso by using `as` you can separate your API parameter names from the\nnames you are using inside your code.\n\nTo implement it, you just have to write a process_value function in your\nvalidator:\n\nFor an enumeration type:\n\n``` ruby\ndef process_value(value)\n value ? value.split(',') : []\nend\n```\n\n# Validators\n\nEvery parameter needs to have an associated validator. For now there are\nsome basic validators. You can always provide your own to achieve\ncomplex results.\n\nIf validations are enabled (default state) the parameters of every\nrequest are validated. If the value is wrong an +ArgumentError+\nexception is raised and can be rescued and processed. It contains a\ndescription of the parameter value expectations. Validations can be\nturned off in the configuration file.\n\nHere is an example of how to rescue and process a +ParamMissing+ or\n+ParamInvalid+ error from within the ApplicationController.\n\n``` ruby\nclass ApplicationController \u003C ActionController::Base\n\n  # ParamError is superclass of ParamMissing, ParamInvalid\n  rescue_from Apipie::ParamError do |e|\n    render text: e.message, status: :unprocessable_entity\n  end\n\n  # ...\nend\n```\n\nParameter validation normally happens after before_actions, just before\nyour controller method is invoked. If you prefer to control when\nparameter validation occurs, set the configuration parameter `validate`\nto `:explicitly`. You must then call the `apipie_validations` method\nyourself, e.g.:\n\n``` ruby\nbefore_action :apipie_validations\n```\n\nThis is useful if you have before_actions which use parameter values:\njust add them after the `apipie_validations` before_action.\n\n## TypeValidator\n\nCheck the parameter type. Only String, Integer, Hash and Array are\nsupported for the sake of simplicity. Read more to find out how to add\nyour own validator.\n\n``` ruby\nparam :session, String, :desc => \"user is logged in\", :required => true\nparam :facts, Hash, :desc => \"Additional optional facts about the user\"\n```\n\n## RegexpValidator\n\nCheck parameter value against given regular expression.\n\n``` ruby\nparam :regexp_param, \u002F^[0-9]* years\u002F, :desc => \"regexp param\"\n```\n\n## EnumValidator\n\nCheck if parameter value is included in the given array.\n\n``` ruby\nparam :enum_param, [100, \"one\", \"two\", 1, 2], :desc => \"enum validator\"\n```\n\n## ProcValidator\n\nIf you need more complex validation and you know you won\\'t reuse it,\nyou can use the Proc\u002Flambda validator. Provide your own Proc, taking the\nvalue of the parameter as the only argument. Return true if value passes\nvalidation or return some text about what is wrong otherwise. Don't\nuse the keyword *return* if you provide an instance of Proc (with lambda\nit is ok), just use the last statement return property of ruby.\n\n``` ruby\nparam :proc_param, lambda { |val|\n  val == \"param value\" ? true : \"The only good value is 'param value'.\"\n}, :desc => \"proc validator\"\n```\n\n## HashValidator\n\nYou can describe hash parameters in depth if you provide a block with a\ndescription of nested values.\n\n``` ruby\nparam :user, Hash, :desc => \"User info\" do\n  param :username, String, :desc => \"Username for login\", :required => true\n  param :password, String, :desc => \"Password for login\", :required => true\n  param :membership, [\"standard\",\"premium\"], :desc => \"User membership\"\nend\n```\n\n## NilValidator\n\nIn fact there isn\\'t any NilValidator, but setting it to nil can be used\nto override parameters described on the resource level.\n\n``` ruby\nparam :user, nil\ndef destroy\n  #...\nend\n```\n\n## NumberValidator\n\nCheck if the parameter is a positive integer number or zero\n\n``` ruby\nparam :product_id, :number, :desc => \"Identifier of the product\", :required => true\nparam :quantity, :number, :desc => \"Number of products to order\", :required => true\n```\n\n## DecimalValidator\n\nCheck if the parameter is a decimal number\n\n``` ruby\nparam :latitude, :decimal, :desc => \"Geographic latitude\", :required => true\nparam :longitude, :decimal, :desc => \"Geographic longitude\", :required => true\n```\n\n## ArrayValidator\n\nCheck if the parameter is an array\n\nAdditional options\n\n`of`\n\nSpecify the type of items. If not given it accepts an array of any item type\n\n`in`\n\nSpecify an array of valid item values.\n\n### Examples\n\nAssert `things` is an array of any items\n\n``` ruby\nparam :things, Array\n```\n\nAssert `hits` must be an array of integer values\n\n``` ruby\nparam :hits, Array, of: Integer\n```\n\nAssert `colors` must be an array of valid string values\n\n``` ruby\nparam :colors, Array, in: [\"red\", \"green\", \"blue\"]\n```\n\nThe retrieving of valid items can be deferred until needed using a\nlambda. It is evaluated only once\n\n``` ruby\nparam :colors, Array, in: ->  { Color.all.pluck(:name) }\n```\n\n### NestedValidator\n\nYou can describe nested parameters in depth if you provide a block with\na description of nested values.\n\n``` ruby\nparam :comments, Array, :desc => \"User comments\" do\n  param :name, String, :desc => \"Name of the comment\", :required => true\n  param :comment, String, :desc => \"Full comment\", :required => true\nend\n```\n\n## Adding custom validator\n\nOnly basic validators are included but it is really easy to add your\nown. Create a new initializer with a subclass of\nApipie::Validator::BaseValidator. Two methods are required to implement\nthis - instance method `validate(value)` and class method\n`build(param_description, argument, options, block)`.\n\nWhen searching for the validator +build+ method, every subclass of\nApipie::Validator::BaseValidator is called. The first one that returns\nthe constructed validator object is used.\n\nExample: Adding IntegerValidator\n\nWe want to check if the parameter value is an integer like this:\n\n``` ruby\nparam :id, Integer, :desc => \"Company ID\"\n```\n\nSo we create apipie_validators.rb initializer with this content:\n\n``` ruby\nclass IntegerValidator \u003C Apipie::Validator::BaseValidator\n\n  def initialize(param_description, argument)\n    super(param_description)\n    @type = argument\n  end\n\n  def validate(value)\n    return false if value.nil?\n    !!(value.to_s =~ \u002F^[-+]?[0-9]+$\u002F)\n  end\n\n  def self.build(param_description, argument, options, block)\n    if argument == Integer\n      self.new(param_description, argument)\n    end\n  end\n\n  def description\n    \"Must be #{@type}.\"\n  end\n\n  def expected_type\n    'numeric'\n  end\nend\n```\n\nParameters of the build method:\n\n`param_description`\n\nInstance of Apipie::ParamDescription contains all given information about the validated parameter.\n\n`argument`\n\nSpecified validator; in our example it is +Integer+\n\n`options`\n\nHash with specified options, for us just `{:desc => \"Company ID\"}`\n\n`block`\n\nBlock converted into Proc, use it as you desire. In this example nil.\n\nIf your validator includes valid values that respond true to\n`.blank?`, you should also define:\n\n``` ruby\ndef ignore_allow_blank?\n  true\nend\n```\n\nso that the validation does not fail for valid values.\n\n# Versioning\n\nEvery resource\u002Fmethod can belong to one or more versions. The version is\nspecified with the `api_version` DSL keyword. When not\nspecified, the resource belongs to `config.default_version`\n(\\\"1.0\\\" by default)\n\n``` ruby\nresource_description do\n  api_versions \"1\", \"2\"\nend\n\napi :GET, \"\u002Fapi\u002Fusers\u002F\", \"List: users\"\napi_version \"1\"\ndef index\n  # ...\nend\n\napi :GET, \"\u002Fapi\u002Fusers\u002F\", \"List: users\", :deprecated => true\n```\n\nIn the example above we say the whole controller\u002Fresource is defined for\nversions \\\"1\\\" and \\\"2\\\", but we override this by explicitly saying\n`index` belongs only to version \\\"1\\\". Also, inheritance\nworks (therefore we can specify the api_version for the parent\ncontroller, and all children will know about that). Routes can be\nflagged as deprecated, and an annotation will be added to them when\nviewing in the API documentation.\n\nFrom the Apipie API perspective, the resources belong to the version.\nWith versioning, there are paths like this provided by apipie:\n\n```\n\u002Fapipie\u002F1\u002Fusers\u002Findex\n\u002Fapipie\u002F2\u002Fusers\u002Findex\n```\n\nWhen not specifying the version explicitly in the path (or in DSL),\ndefault version (`Apipie.configuration.default_version`) is\nused instead (\\\"1.0\\\" by default). Therefore, an application that\ndoesn\\'t need versioning should work as before.\n\nThe static page generator takes a version parameter (or uses default).\n\nYou can specify the versions for the examples, with the\n`versions` keyword. It specifies the versions the example is\nused for. When not specified, it\\'s shown in all versions with the given\nmethod.\n\nWhen referencing or querying the resource\u002Fmethod descripion, this format\nshould be used: \\\"version#resource#method\\\". When not specified, the\ndefault version is used instead.\n\n# Markup\n\nThe default markup language is\n[RDoc](https:\u002F\u002Fruby.github.io\u002Frdoc\u002FRDoc\u002FMarkup.html). It can be changed\nin the config file (`config.markup=`) to one of these:\n\nMarkdown\n\nUse Apipie::Markup::Markdown.new. You need Maruku gem.\n\nTextile\n\nUse Apipie::Markup::Textile.new. You need RedCloth gem.\n\nOr provide you own object with a `to_html(text)` method. For\ninspiration, this is how Textile markup usage is implemented:\n\n``` ruby\nclass Textile\n  def initialize\n    require 'RedCloth'\n  end\n  def to_html(text)\n    RedCloth.new(text).to_html\n  end\nend\n```\n\n# Localization\n\nApipie has support for localized API documentation in both formats (JSON\nand HTML). Apipie uses the library I18n for localization of itself.\nCheck `config\u002Flocales` directory for available translations.\n\nA major part of strings in the documentation comes from the API. As\npreferences regarding localization libraries differ amongst project,\nApipie needs to know how to set the locale for your project, and how to\ntranslate a string using the library your project uses. That can be done\nusing lambdas in configuration.\n\nSample configuration when your project uses FastGettext\n\n``` ruby\nApipie.configure do |config|\n ...\n config.languages = ['en', 'cs']\n config.default_locale = 'en'\n config.locale = lambda { |loc| loc ? FastGettext.set_locale(loc) : FastGettext.locale }\n config.translate = lambda do |str, loc|\n   old_loc = FastGettext.locale\n   FastGettext.set_locale(loc)\n   trans = _(str)\n   FastGettext.set_locale(old_loc)\n   trans\n end\nend\n```\n\nAnd the strings in the API documentation need to be marked with the\n`N_()` function\n\n``` ruby\napi :GET, \"\u002Fusers\u002F:id\", N_(\"Show user profile\")\nparam :session, String, :desc => N_(\"user is logged in\"), :required => true\n```\n\nWhen your project use I18n, localization related configuration could\nappear as follows\n\n``` ruby\nApipie.configure do |config|\n ...\n config.languages = ['en', 'cs']\n config.default_locale = 'en'\n config.locale = lambda { |loc| loc ? I18n.locale = loc : I18n.locale }\n config.translate = lambda do |str, loc|\n   return '' if str.blank?\n   I18n.t str, locale: loc, scope: 'doc'\n end\nend\n```\n\nAnd the strings in the API documentation needs to be in the form of\ntranslation keys\n\n``` ruby\napi :GET, \"\u002Fusers\u002F:id\", \"show_user_profile\"\nparam :session, String, :desc => \"user_is_logged_in\", :required => true\n```\n\nThe localized versions of the documentation are distinguished by\nlanguage in the filename. E.g. `doc\u002Fapidoc\u002Fapidoc.cs.html` is static\ndocumentation in the Czech language. If the language is missing, e.g.\n`doc\u002Fapidoc\u002Fapidoc.html`, the documentation is localized with the\n`default_locale`.\n\nThe dynamic documentation follows the same schema. The\n`http:\u002F\u002Flocalhost:3000\u002Fapidoc\u002Fv1.cs.html` is documentation for version\n\\'1\\' of the API in the Czech language. For JSON descriptions, the API\napplies the same format: `http:\u002F\u002Flocalhost:3000\u002Fapidoc\u002Fv1.cs.json`\n\n# Modifying Views\n\nTo modify the views of your documentation, run `rails g apipie:views`.\nThis will copy the Apipie views to `app\u002Fviews\u002Fapipie\u002Fapipies` and\n`app\u002Fviews\u002Flayouts\u002Fapipie`.\n\n# Static files\n\nTo generate a static version of documentation (perhaps to put it on your\nproject site or something), run the `rake apipie:static` task. It will\ncreate a set of HTML files (multi-pages, single-page, plain) in your doc\ndirectory. If you prefer a JSON version run `rake apipie:static_json`.\nBy default the documentation for the default API version is used. You\ncan specify the version with `rake apipie:static[2.0]`\n\nWhen you want to avoid any unnecessary computation in production mode,\nyou can generate a cache with `rake apipie:cache` and configure the app\nto use it in production with `config.use_cache = Rails.env.production?`\n\nDefault cache dir is `File.join(Rails.root, \"public\", \"apipie-cache\")`,\nyou can change it to where you want, example:\n`config.cache_dir = File.join(Rails.root, \"doc\", \"apidoc\")`.\n\nIf, for some complex cases, you need to generate\u002Fre-generate just part\nof the cache use `rake apipie:cache cache_part=index` resp.\n`rake apipie:cache cache_part=resources` To generate it for different\nlocations for further processing use\n`rake apipie:cache OUT=\u002Ftmp\u002Fapipie_cache`.\n\n# Static Swagger (OpenAPI 2.0) files\n\nTo generate a static Swagger definition file from the api, run\n`rake apipie:static_swagger_json`. By default the documentation for the\ndefault API version is used. You can specify the version with\n`rake apipie:static_swagger_json[2.0]`. A swagger file will be generated\nfor each locale. The files will be generated in the same location as the\nstatic_json files, but instead of being named\n`schema_apipie[.locale].json`, they will be called\n`schema_swagger[.locale].json`.\n\n## Specifying default values for parameters\n\nSwagger allows method definitions to include an indication of the the\ndefault value for each parameter. To include such indications, use\n`:default_value => \u003Csome value>` in the parameter definition DSL. For\nexample:\n\n``` ruby\nparam :do_something, Boolean, :desc => \"take an action\", :required => false, :default_value => false\n```\n\n## Generated Warnings\n\nThe help identify potential improvements to your documentation, the\nswagger generation process issues warnings if it identifies various\nshortcomings of the DSL documentation. Each warning has a code to allow\nselective suppression (see swagger-specific configuration below)\n\n| Error Code | Description                                                                         |\n|------------|-------------------------------------------------------------------------------------|\n| 100        | Missing short description for method                                                |\n| 101        | Added missing \u002F at beginning of path                                                |\n| 102        | No return codes specified for method                                                |\n| 103        | A parameter is a generic Hash without an internal type specification                |\n| 104        | A parameter is an 'in-path' parameter, but specified as 'not required' in the DSL   |\n| 105        | A parameter is optional but does not have a default value specified                  |\n| 106        | A parameter was omitted from the swagger output because it is a Hash without fields in a formData specification |\n| 107        | A path parameter is not described                                                   |\n| 108        | Inferring that a parameter type is boolean because described as an enum with `[false true]` values |\n\n\n## Swagger-Specific Configuration Parameters\n\nThere are several configuration parameters that determine the structure\nof the generated swagger file:\n\n`config.generator.swagger.content_type_input`\n\n- If the value is `:form_data` - the swagger file will indicate that\nthe server consumes the content types\n`application\u002Fx-www-form-urlencoded` and `multipart\u002Fform-data`.\nNon-path parameters will have the value `\"in\": \"formData\"`. Note\nthat parameters of type Hash that do not have any fields in them\nwill *be omitted* from the resulting files, as there is no way to\ndescribe them in swagger.\n\n- If the value is `:json` - the swagger file will indicate that the\nserver consumes the content type `application\u002Fjson`. All non-path\nparameters will be included in the schema of a single `\"in\": \"body\"`\nparameter of type `object`.\n\n- You can specify the value of this configuration parameter as an\nadditional input to the rake command (e.g.,\n`rake apipie:static_swagger_json[2.0,form_data]`).\n\n`config.generator.swagger.json_input_uses_refs`\n\n- This parameter is only relevant if `swagger.content_type_input` is\n    `:json`.\n\n- If `true`: the schema of the `\"in\": \"body\"` parameter of each method\nis given its own entry in the `definitions` section, and is\nreferenced using `$ref` from the method definition.\n\n- If `false`: the body parameter definitions are inlined within the\nmethod definitions.\n\n`config.generator.swagger.include_warning_tags`\n\n- If `true`: in addition to tagging methods with the name of the\nresource they belong to, methods for which warnings have been issued\nwill be tagged with.\n\n`config.generator.swagger.suppress_warnings`\n\n- If `false`: no warnings will be suppressed\n\n- If `true`: all warnings will be suppressed\n\n- If an array of values (e.g., `[100,102,107]`), only the warnings\nidentified by the numbers in the array will be suppressed.\n\n`config.generator.swagger.api_host`\n\n- The value to place in the swagger host field. Default is `localhost:3000`\n- If `nil` then then host field will not be included.\n\n`config.generator.swagger.allow_additional_properties_in_response`\n\n- If `false` (default): response descriptions in the generated swagger\nwill include an `additional-properties: false` field\n\n- If `true`: the `additional-properties: false` field will not be\nincluded in response object descriptions\n\n`config.generator.swagger.schemes`\n\n- An array of transport schemes that the API supports. This can\ninclude any combination of `http`, `https`, `ws` and `wss`. By\ndefault to encourage good security practices, `['https']` is\nspecified.\n\n`config:swagger.security_definitions`\n\n- If the API requires authentication, you can specify details of the\nauthentication mechanisms supported as a (Hash) value here. See\n\\[\u003Chttps:\u002F\u002Fswagger.io\u002Fdocs\u002Fspecification\u002F2-0\u002Fauthentication\u002F>\\] for\ndetails of what values can be specified By default, no security is\ndefined.\n\n`config.generator.swagger.global_security`\n\n- If the API requires authentication, you can specify which of the\nauthentication mechanisms are supported by all API operations as an\nArray of hashes here. This should be used in conjunction with the\nmechanisms defined by `swagger.security_definitions`. See\n\\[\u003Chttps:\u002F\u002Fswagger.io\u002Fdocs\u002Fspecification\u002F2-0\u002Fauthentication\u002F>\\] for\ndetails of what values can be specified By default, no security is\ndefined.\n\n`config.generator.swagger.skip_default_tags`\n\n- By setting `false` (default): The resource name for e.g.\n`\u002Fpets\u002F{petId}` will automatically be added as a tag `pets`. By\nsetting `true`: The tags needs to be explicitly added to the\nresource using the DSL.\n\n## Known limitations of the current implementation\n\n-   There is currently no way to document the structure and content-type\n    of the data returned from a method\n-   Recorded examples are currently not included in the generated\n    swagger file\n-   The apipie `formats` value is ignored.\n-   It is not possible to specify the \\\"consumed\\\" content type on a\n    per-method basis\n-   It is not possible to leverage all of the parameter type\u002Fformat\n    capabilities of swagger\n-   Only OpenAPI 2.0 is supported\n-   Responses are defined inline and not as a \\$ref\n-   It is not possible to specify per-operation security requirements\n    (only global)\n\n# Dynamic Swagger generation\n\nTo generate swagger dynamically, use\n`http:\u002F\u002Flocalhost:3000\u002Fapipie.json?type=swagger`.\n\nNote that authorization is not supported for dynamic swagger generation,\nso if `config.authorize` is defined, dynamic swagger generation will be\ndisabled.\n\nDynamically generated swagger is not cached, and is always generated on\nthe fly.\n\n# JSON checksums\n\nIf the API client needs to be sure that the JSON didn\\'t changed, add\nthe `ApipieChecksumInHeaders` middleware in your rails app. It can add a\nchecksum of the entire JSON document in the response headers.\n\n```\n\"Apipie-Checksum\"=>\"fb81460e7f4e78d059f826624bdf9504\"\n```\n\n[Apipie bindings](https:\u002F\u002Fgithub.com\u002FApipie\u002Fapipie-bindings) uses this\nfeature to refresh its JSON cache.\n\nTo set it up add the following to your `application.rb`\n\n```\nrequire 'apipie\u002Fmiddleware\u002Fchecksum_in_headers'\n# Add JSON checksum in headers for smarter caching\nconfig.middleware.use \"Apipie::Middleware::ChecksumInHeaders\"\n```\n\nAnd in your apipie initializer allow checksum calculation\n\n```\nApipie.configuration.update_checksum = true\n```\n\nBy default the header is added to responses for `config.doc_base_url`\nand `\u002Fapi`. It can be changed in configuration (see [Configuration\nReference](#configuration-reference) for details).\n\nThe checksum calculation is lazy, and done with the first request. If\nyou run with `use_cache = true`, do not forget to run the rake task\n`apipie:cache`.\n\n# Tests Integration\n\nApipie integrates with automated testing in two ways. *Documentation\nbootstrapping* and *examples recording*.\n\n## Documentation Bootstrapping\n\nLet\\'s say you have an application without REST API documentation.\nHowever you have a set of tests that are run against this API. A lot of\ninformation is already included in these tests, it just needs to be\nextracted somehow. Luckily, Apipie provides such a feature.\n\nWhen running the tests, set the `APIPIE_RECORD=params` environment\nvariable or call `Apipie.record('params')` from specs starter. You can\neither use it with functional tests:\n\n```\nAPIPIE_RECORD=params rake test:functionals\n```\n\nor you can run your server with this param, in case you run the tests\nagainst running server:\n\n```\nAPIPIE_RECORD=params rails server\n```\n\nWhen the process quits, the data from requests\u002Fresponses are used to\ndetermine the documentation. It\\'s quite raw, but it makes the initial\nphase much easier.\n\n## Examples Recording\n\nYou can also use the tests to generate up-to-date examples for your\ncode. Similar to the bootstrapping process, you can use it with\nfunctional tests or a running server, setting `APIPIE_RECORD=examples`\nor calling `Apipie.record('examples')` in your specs starter.\n\n```\nAPIPIE_RECORD=examples rake test:functionals\nAPIPIE_RECORD=examples rails server\n```\n\nThe data is written into `doc\u002Fapipie_examples.yml`. By default, only the\nfirst example is shown for each action. You can customize this by\nsetting the `show_in_doc` attribute at each example.\n\nYou can add a title to the examples (useful when showing more than one\nexample per method) by adding a \\'title\\' attribute.\n\n```\n--- !omap\n  - announcements#index:\n    - !omap\n      - title: This is a custom title for this example\n      - verb: :GET\n      - path: \u002Fapi\u002Fblabla\u002F1\n      - versions:\n        - '1.0'\n      - query:\n      - request_data:\n      - response_data:\n        ...\n      - code: 200\n      - show_in_doc: 1   # If 1, show. If 0, do not show.\n      - recorded: true\n```\n\nIn RSpec you can add metadata to examples. We can use that feature to\nmark selected examples - the ones that perform the requests that we want\nto show as examples in the documentation.\n\nFor example, we can add `show_in_doc` to examples, like this:\n\n``` ruby\ndescribe \"This is the correct path\" do\n  it \"some test\", :show_in_doc do\n    ....\n  end\nend\n\ncontext \"These are edge cases\" do\n  it \"Can't authenticate\" do\n    ....\n  end\n\n   it \"record not found\" do\n     ....\n   end\nend\n```\n\nAnd then configure RSpec in this way:\n\n``` ruby\nRSpec.configure do |config|\n  config.treat_symbols_as_metadata_keys_with_true_values = true\n  config.filter_run :show_in_doc => true if ENV['APIPIE_RECORD']\nend\n```\n\nThis way, when running in recording mode, only the tests that have been\nmarked with the `:show_in_doc` metadata will be run, and hence only\nthose will be used as examples.\n\n## Caveats\n\nMake sure to enable `config.render_views` in your\n`config\u002Frails_helper.rb` or `config\u002Fspec_helper.rb` if you\\'re using\njbuilder, or you will get back empty results\n\n# Bindings Generator\n\nIn earlier versions (\\\u003C= 0.0.13), there was a simple client generator as\na part of Apipie gem. As more features and users came to Apipie, there\nwas a greater need for changes on a per project basis. It\\'s hard (or\neven impossible) to provide a generic solution for the client code. We\nalso don\\'t want to tell you what\\'s the right way to do it (what gems\nto use, how the API should look like etc.).\n\nTherefore you can\\'t generate client code directly by a rake task in\nfurther versions.\n\nThere is, however, an even better and more flexible way to reuse your\nAPI documentation for this purpose: using the API the Apipie provides in\nthe generator code. Check out our sister project\n[apipie-bindings](https:\u002F\u002Fgithub.com\u002FApipie\u002Fapipie-bindings), as they\nuse exactly this approach. You also don\\'t need to run the service,\nprovided it uses Apipie as a backend.\n\nAnd if you write one on your own, don\\'t hesitate to share it with us!\n\n# Contributing\n\nThen, you can install dependencies and run the test suite:\n\n``` shell\n> bundle install\n> bundle exec rspec\n```\n\n# Disqus Integration\n\nYou can setup [Disqus](https:\u002F\u002Fdisqus.com\u002F) discussion within your\ndocumentation. Just set the credentials in the Apipie configuration:\n\n``` ruby\nconfig.disqus_shortname = \"MyProjectDoc\"\n```\n\n# External References\n\n-   [Getting started tutorial](https:\u002F\u002Fgithub.com\u002FiNecas\u002Fapipie-demo)\n    -including examples of using the tests integration and versioning.\n-   [Real-world application usage](https:\u002F\u002Fgithub.com\u002FKatello\u002Fkatello)\n-   [Read-world application usage with\n    versioning](https:\u002F\u002Fgithub.com\u002Ftheforeman\u002Fforeman)\n-   [Using Apipie API to generate\n    bindings](https:\u002F\u002Fgithub.com\u002FApipie\u002Fapipie-bindings)\n","Apipie-rails 是一个用于 Ruby on Rails 应用程序的 RESTful API 文档生成工具。它通过提供一种领域特定语言（DSL）和 Rails 引擎，允许开发者直接在代码中编写文档，从而避免了学习额外语法的需求，并支持文档数据的多用途复用，如验证等。此外，该工具还具备易于扩展维护、无需字符串解析以及支持多种标记语言的特点。适用于需要为 Rails 项目创建清晰且易于访问的 API 文档场景，特别适合那些希望保持代码与文档同步更新的开发团队。",2,"2026-06-11 03:15:23","top_language"]