api_docs_engine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/app/assets/javascripts/docs.js.coffee +42 -0
  3. data/app/assets/javascripts/highlight.js +1 -0
  4. data/app/assets/stylesheets/docs.css.scss +127 -0
  5. data/app/assets/stylesheets/highlight/styles/github.css +129 -0
  6. data/app/controllers/concerns/docs/manage_resource.rb +98 -0
  7. data/app/controllers/docs/application_controller.rb +24 -0
  8. data/app/controllers/docs/markdown_controller.rb +8 -0
  9. data/app/controllers/docs/missing_docs_controller.rb +7 -0
  10. data/app/controllers/docs/page_categories_controller.rb +27 -0
  11. data/app/controllers/docs/pages_controller.rb +56 -0
  12. data/app/helpers/docs/application_helper.rb +47 -0
  13. data/app/models/docs/missing_collection.rb +11 -0
  14. data/app/models/docs/page.rb +64 -0
  15. data/app/models/docs/page_category.rb +30 -0
  16. data/app/models/docs/routes_collection.rb +71 -0
  17. data/app/views/docs/application/edit.html.slim +2 -0
  18. data/app/views/docs/application/new.html.slim +2 -0
  19. data/app/views/docs/layouts/docs.html.slim +24 -0
  20. data/app/views/docs/markdown/create.json.erb +3 -0
  21. data/app/views/docs/missing_docs/index.html.slim +9 -0
  22. data/app/views/docs/page_categories/_form.html.slim +19 -0
  23. data/app/views/docs/pages/_form.html.slim +35 -0
  24. data/app/views/docs/pages/_page.html.slim +24 -0
  25. data/app/views/docs/pages/index.html.slim +34 -0
  26. data/config/initializers/formtastic.rb +1 -0
  27. data/config/routes.rb +5 -0
  28. data/lib/api_docs_engine/docs.rb +50 -0
  29. data/lib/api_docs_engine.rb +2 -0
  30. data/lib/bootstrap/active_link_to.rb +135 -0
  31. data/lib/bootstrap/markdown_renderer.rb +10 -0
  32. data/lib/docs/core_ext.rb +39 -0
  33. data/lib/docs/engine.rb +9 -0
  34. data/lib/generators/active_record/api_docs_engine_generator.rb +16 -0
  35. data/lib/generators/active_record/templates/migration.rb +27 -0
  36. data/lib/generators/api_docs_engine/api_docs_engine_generator.rb +12 -0
  37. data/lib/generators/api_docs_engine/install_generator.rb +16 -0
  38. data/lib/generators/api_docs_engine/orm_helpers.rb +10 -0
  39. data/lib/generators/templates/api_docs_engine.rb +11 -0
  40. metadata +284 -0
@@ -0,0 +1,30 @@
1
+ module Docs
2
+ class PageCategory < ActiveRecord::Base
3
+ extend FriendlyId
4
+ friendly_id :slug, use: :slugged
5
+ has_many :pages
6
+ alias_attribute :name, :title
7
+
8
+ before_validation :set_missing_title, unless: :title?
9
+
10
+ validates :slug, :title, presence: true
11
+ validates :slug, uniqueness: true, on: :create
12
+
13
+ def weight
14
+ @weight ||= splitted_title[0].to_i.nonzero? || 100
15
+ end
16
+
17
+ def only_title
18
+ @captures ||= splitted_title[1]
19
+ end
20
+
21
+ def splitted_title
22
+ @splitted_title ||= title.match(/^(?:(\d+)\. )?(.+)$/).captures
23
+ end
24
+
25
+ private
26
+ def set_missing_title
27
+ self.title = slug.to_s.titleize
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,71 @@
1
+ module Docs
2
+ class RoutesCollection
3
+ include Enumerable
4
+ attr_reader :routes
5
+
6
+ def initialize(filter = nil)
7
+ filter ||= Docs.missing_routes_filter
8
+ @routes = Inspector.new(Rails.application.routes.routes).enumerate(filter)
9
+ end
10
+
11
+ def [](name)
12
+ routes[name]
13
+ end
14
+
15
+ def each(&block)
16
+ routes.each(&block)
17
+ self
18
+ end
19
+
20
+ def by_controller
21
+ routes.group_by(&:controller)
22
+ end
23
+
24
+ class Item
25
+ attr_accessor :path, :via, :reqs, :pattern, :controller, :action
26
+
27
+ def initialize(route)
28
+ @path = route.path.sub(/\(\.:format\)$/, '.json')
29
+ @via = route.verb
30
+ @reqs = route.reqs
31
+ @pattern = route.json_regexp
32
+ @controller, @action = reqs.split("#")
33
+ end
34
+
35
+ def to_page_attributes
36
+ { path: path, via: via, reqs: reqs, page_category_slug: controller[/^api\/(\w+)/, 1] }
37
+ end
38
+
39
+ def inspect
40
+ "#{via} #{path} => #{reqs}"
41
+ end
42
+ end
43
+
44
+ class Inspector < ::ActionDispatch::Routing::RoutesInspector
45
+ def enumerate(filter = nil)
46
+ routes_to_display = filter_routes(filter)
47
+ collect_routes(routes_to_display)
48
+ end
49
+
50
+ private
51
+ def filter_routes(filter)
52
+ if filter
53
+ @routes.select { |route| route.defaults[:controller] =~ filter }
54
+ else
55
+ @routes
56
+ end
57
+ end
58
+
59
+ def collect_routes(routes)
60
+ routes.collect do |route|
61
+ ActionDispatch::Routing::RouteWrapper.new(route)
62
+ end.reject do |route|
63
+ route.internal?
64
+ end.collect do |route|
65
+ collect_engine_routes(route)
66
+ Item.new(route)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,2 @@
1
+ - content_for :title, "Edit #{controller_name.singularize.humanize} ##{resource.try(:id)}"
2
+ = render "form"
@@ -0,0 +1,2 @@
1
+ - content_for :title, "New #{controller_name.singularize.humanize}"
2
+ = render "form"
@@ -0,0 +1,24 @@
1
+ doctype 5
2
+ html lang="en"
3
+ head
4
+ meta charset="utf-8"
5
+ meta name="viewport" content="width=device-width, initial-scale=1.0"
6
+ title = content_for?(:title) ? yield(:title) : Docs.title
7
+ = csrf_meta_tags
8
+ = stylesheet_link_tag "docs", media: "all"
9
+ = javascript_include_tag "docs"
10
+ body
11
+ .container-fluid
12
+ .row
13
+ #left-sidebar.col-sm-3.col-md-2.sidebar
14
+ ul.nav.nav-sidebar
15
+ - Docs::PageCategory.all.sort_by(&:weight).each do |c|
16
+ = li_active_to c.only_title, page_category_pages_path(c), data: { edit_path: edit_page_category_path(c) }
17
+ .row
18
+ .btn-group.btn-group-xs.pull-right
19
+ = link_to fa_icon(:plus, text: "Add category"), new_page_category_path, class: "btn btn-default"
20
+ = link_to fa_icon(:warning, text: "Missing"), missing_docs_path, class: "btn btn-default"
21
+
22
+ .col-sm-9.col-sm-offset-3.col-md-10.col-md-offset-2.main
23
+ h1.page-header = content_for?(:title) ? yield(:title) : Docs.title
24
+ = yield
@@ -0,0 +1,3 @@
1
+ {
2
+ "result": "<%=j markdown(params[:source]) %>"
3
+ }
@@ -0,0 +1,9 @@
1
+ - content_for :title, "Missing"
2
+ table.table
3
+ tbody
4
+ - @missing_docs.each do |route|
5
+ tr
6
+ td = route.path
7
+ td = route.via
8
+ td = route.reqs
9
+ td = link_to "Create page", new_page_path(page: route.to_page_attributes), class: "btn btn-default btn-sm"
@@ -0,0 +1,19 @@
1
+ = semantic_form_for @page_category do |f|
2
+ .row
3
+ .col-sm-5
4
+ = f.input :title
5
+ .col-sm-5
6
+ = f.input :slug
7
+ .col-sm-2 style="padding-top: 25px;"
8
+ = f.action :submit, button_html: { class: "btn btn-primary btn-block" }
9
+
10
+ ul.nav.nav-tabs role="tablist"
11
+ li.active = link_to "Description", "#desc", role: 'tab', data: { toggle: 'tab' }
12
+ li = link_to "Preview", "#preview", role: 'tab', data: { toggle: 'tab' }
13
+
14
+ = f.inputs do
15
+ .tab-content
16
+ #desc.tab-pane.fade.in.active
17
+ = f.input :body, input_html: { rows: 30, class: "process-markdown" }, label: false
18
+ #preview.tab-pane
19
+ .preview-markdown data-source=".process-markdown"
@@ -0,0 +1,35 @@
1
+ = semantic_form_for @page do |f|
2
+ .row
3
+ .col-sm-6
4
+ = f.input :title
5
+ .col-sm-4
6
+ = f.input :page_category_slug
7
+ .col-sm-2 style="padding-top: 25px;"
8
+ = f.action :submit, button_html: { class: "btn btn-primary btn-block" }
9
+ .row
10
+ .col-sm-2
11
+ = f.input :via
12
+ .col-sm-4
13
+ = f.input :path
14
+ .col-sm-4
15
+ = f.input :reqs
16
+ .col-sm-2
17
+ = f.input :weight
18
+
19
+ ul.nav.nav-tabs role="tablist"
20
+ li.active
21
+ = link_to "Description", "#desc", role: 'tab', data: { toggle: 'tab' }
22
+ li
23
+ = link_to fa_icon(:eye, text: "Preview"), "#preview", role: 'tab', data: { toggle: 'tab' }
24
+ li
25
+ = link_to fa_icon(:code, text: "Example"), "#example", role: 'tab', data: { toggle: 'tab' }
26
+
27
+
28
+ = f.inputs do
29
+ .tab-content
30
+ #desc.tab-pane.fade.in.active
31
+ = f.input :body, input_html: { rows: 30, class: "process-markdown" }, label: false
32
+ #preview.tab-pane
33
+ .preview-markdown data-source=".process-markdown"
34
+ #example.tab-pane
35
+ = f.input :example, input_html: { rows: 20 }, label: false
@@ -0,0 +1,24 @@
1
+ .action
2
+ h3 id=page.anchor = page.title
3
+
4
+ .panel.panel-default
5
+ .panel-heading
6
+ code == "#{content_tag :strong, page.via} #{page.only_path}#{content_tag :span, page.only_query, class: 'text-muted'}"
7
+ .navbar.navbar-default.navbar-static-top.panel-navbar
8
+ ul.nav.navbar-nav role="tablist"
9
+ li class=( "active" if page.body.present? )
10
+ = link_to fa_icon('info-circle'), "##{page.anchor}-desc", role: "tab", data: { toggle: "tab" }
11
+ li class=( "active" unless page.body.present? )
12
+ = link_to fa_icon(:code, text: "Example"), "##{page.anchor}-example", role: "tab", data: { toggle: "tab" }
13
+ li
14
+ = link_to fa_icon(:edit), edit_page_path(page)
15
+
16
+ .tab-content.panel-body
17
+ .tab-pane id="#{page.anchor}-desc" class=( "active" if page.body.present? )
18
+ p
19
+ - if page.body?
20
+ == markdown(page.body)
21
+ .tab-pane id="#{page.anchor}-example" class=( "active" unless page.body.present? )
22
+ p
23
+ - if page.example?
24
+ pre: samp.json == page.example
@@ -0,0 +1,34 @@
1
+ - content_for :title, @page_category.only_title
2
+
3
+ .row
4
+ .col-md-9
5
+ - if @pages.any?
6
+ .panel.panel-default
7
+ .panel-heading: h4.panel-title Методы
8
+ table.table.table-condensed
9
+ tbody
10
+ - @pages.each do |page|
11
+ tr
12
+ td
13
+ code == "#{content_tag :strong, page.via} #{page.only_path}"
14
+ td
15
+ = link_to page.title, "##{page.anchor}"
16
+ td
17
+ small.text-muted = page.reqs
18
+
19
+ - if @page_category.body?
20
+ == markdown(@page_category.body)
21
+
22
+ - if @pages.any?
23
+ .actions
24
+ = render @pages
25
+
26
+ .col-md-3
27
+ .navbar-spyscroll
28
+ ul.nav.nav-right-spy role="tablist"
29
+ - @pages.each do |page|
30
+ li = link_to "#{content_tag(:strong, page.via)} #{page.only_path}".html_safe, "##{page.anchor}"
31
+ hr /
32
+ .btn-group.btn-group-xs
33
+ = link_to fa_icon(:edit, text: "Edit"), [:edit, @page_category], class: "btn btn-default"
34
+ = link_to fa_icon(:plus, text: "Add page"), [:new, @page_category, :page], class: "btn btn-default"
@@ -0,0 +1 @@
1
+ Formtastic::Helpers::FormHelper.builder = FormtasticBootstrap::FormBuilder
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ Docs::Engine.routes.draw do
2
+ scope "docs" do
3
+ Docs.route(self)
4
+ end
5
+ end
@@ -0,0 +1,50 @@
1
+ require 'slim-rails'
2
+ require 'sass-rails'
3
+ require 'jquery-rails'
4
+ require 'coffee-rails'
5
+ require 'bootstrap-sass'
6
+ require 'font-awesome-rails'
7
+ require 'redcarpet'
8
+ require 'friendly_id'
9
+ require 'formtastic'
10
+ require 'formtastic-bootstrap'
11
+ require 'turbolinks'
12
+
13
+ module Docs
14
+ mattr_accessor :title
15
+ @@title = "API documentation"
16
+
17
+ mattr_accessor :root_path
18
+ @@root_path = "missing_docs#index"
19
+
20
+ mattr_accessor :missing_routes_filter
21
+ @@missing_routes_filter = /api\/.*/
22
+
23
+ mattr_accessor :api_docs_prefix
24
+ @@api_docs_prefix = "api"
25
+
26
+ mattr_accessor :auth
27
+ @@auth = nil
28
+
29
+ class << self
30
+ def setup
31
+ yield self
32
+ end
33
+
34
+ def route(router)
35
+ router.instance_exec do
36
+ root Docs.root_path
37
+
38
+ resources :missing_docs, only: [:index]
39
+ resources :page_categories, except: [:index, :show, :edit]
40
+ resources :pages, except: [:index, :show]
41
+
42
+ resources :page_categories, shallow: true, path: Docs.api_docs_prefix, only: [:edit] do
43
+ resources :pages, only: [:index, :new, :create], path: "", path_names: { new: "new_page" }
44
+ end
45
+
46
+ resources :markdown, only: "create"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,2 @@
1
+ require "api_docs_engine/docs"
2
+ require "docs/engine"
@@ -0,0 +1,135 @@
1
+ require "docs/core_ext"
2
+
3
+ module Bootstrap
4
+ module ActiveLinkTo
5
+ class ActiveLink
6
+ ACTIVE_OPTIONS = [:active, :class_active, :class_inactive, :active_disable]
7
+
8
+ def initialize(context)
9
+ @context = context
10
+ end
11
+
12
+ def render(*args, &block)
13
+ @name = block_given? ? capture(&block) : args.shift
14
+ @link_options = args.extract_options!
15
+ @url = h.url_for(args.shift)
16
+ @active_options = @link_options.extract!(*ACTIVE_OPTIONS).only_presented
17
+ @after_link = @link_options.delete(:after_link).to_s
18
+
19
+ if is_wrap?
20
+ provide_wrap_with_content!
21
+ else
22
+ @link_options.smart_append_to :class, active_class
23
+ content
24
+ end
25
+ end
26
+
27
+ private
28
+ def content
29
+ "#{link}#{@after_link}".html_safe
30
+ end
31
+
32
+ def h
33
+ @context
34
+ end
35
+
36
+ def link
37
+ return @name if is_active? && is_active_disable?
38
+ h.link_to @name, @url, @link_options
39
+ end
40
+
41
+ def is_active?
42
+ @is_active = h.is_active_link?(@url, @active_options[:active]) if @is_active.nil?
43
+ @is_active
44
+ end
45
+
46
+ def is_wrap?
47
+ !@link_options[:wrap_tag].nil?
48
+ end
49
+
50
+ def is_dropdown?
51
+ !@link_options[:dropdown].nil?
52
+ end
53
+
54
+ def is_active_disable?
55
+ !!@active_options[:active_disable]
56
+ end
57
+
58
+ def provide_wrap_with_content!
59
+ @link_options[:wrap_options] ||= {}
60
+ @wrap_options, wrap_tag = @link_options.extract!(:wrap_options, :wrap_tag).values
61
+ @wrap_options.smart_append_to :class, active_class
62
+
63
+ provide_dropdown! if is_dropdown?
64
+
65
+ h.content_tag wrap_tag, content, @wrap_options
66
+ end
67
+
68
+ def provide_dropdown!
69
+ dropdown_html, dropdown = @link_options.extract!(:dropdown_html, :dropdown).values
70
+ @wrap_options.smart_append_to :class, 'dropdown'
71
+ @link_options.smart_update class: ['dropdown-toggle'], id: dropdown, data: {toggle: 'dropdown', hover: 'dropdown'}
72
+ @after_link << dropdown_html.to_s
73
+ end
74
+
75
+ def active_class
76
+ h.active_link_to_class(@url, @active_options, is_active?)
77
+ end
78
+ end
79
+
80
+ # Wrapper around link_to. Accepts following params:
81
+ # :active => Boolean | Symbol | Regex | Controller/Action Pair
82
+ # :class_active => String
83
+ # :class_inactive => String
84
+ # :disable_active => Boolean
85
+ # :wrap_tag => Symbol
86
+ # Example usage:
87
+ # active_link_to('/users', :class_active => 'enabled')
88
+ # active_link_to(users_path, :active => :exclusive, :wrap_tag => :li)
89
+ def active_link_to(*args, &block)
90
+ ActiveLink.new(self).render(*args, &block)
91
+ end
92
+
93
+ # Returns css class name. Takes the link's URL and its params
94
+ # Example usage:
95
+ # active_link_to_class('/root', :class_active => 'on', :class_inactive => 'off')
96
+ #
97
+ def active_link_to_class(url, options={}, is_active=nil)
98
+ is_active = is_active_link?(url, options[:active]) if is_active.nil?
99
+ is_active ? (options[:class_active] ||= 'active') : options[:class_inactive]
100
+ end
101
+
102
+ # Returns true or false based on the provided path and condition
103
+ # Possible condition values are:
104
+ # Boolean -> true | false
105
+ # Symbol -> :exclusive | :inclusive
106
+ # Regex -> /regex/
107
+ # Controller/Action Pair -> [[:controller], [:action_a, :action_b]]
108
+ # Example usage:
109
+ # is_active_link?('/root', true)
110
+ # is_active_link?('/root', :exclusive)
111
+ # is_active_link?('/root', /^\/root/)
112
+ # is_active_link?('/root', ['users', ['show', 'edit']])
113
+ #
114
+ def is_active_link?(url, condition = nil)
115
+ url = url_for(url).sub(/\?.*/, '') # ignore GET params
116
+ case condition
117
+ when :inclusive, nil
118
+ !request.fullpath.match(/^#{Regexp.escape(url)}(\/.*|\?.*)?$/).blank?
119
+ when :exclusive
120
+ !request.fullpath.match(/^#{Regexp.escape(url)}\/?(\?.*)?$/).blank?
121
+ when Regexp
122
+ !request.fullpath.match(condition).blank?
123
+ when Array
124
+ controllers = [*condition[0]]
125
+ actions = [*condition[1]]
126
+ (controllers.blank? || controllers.member?(params[:controller])) &&
127
+ (actions.blank? || actions.member?(params[:action]))
128
+ when TrueClass
129
+ true
130
+ when FalseClass
131
+ false
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,10 @@
1
+ module Bootstrap
2
+ class MarkdownRenderer < Redcarpet::Render::HTML
3
+ def table(header, body)
4
+ %{<table class="table table-bordered">
5
+ #{header}
6
+ #{body}
7
+ </table>}
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,39 @@
1
+ class Hash
2
+ def smart_append_to(key, value, delimeter=' ')
3
+ if self[key].nil?
4
+ self[key] ||= value
5
+ else
6
+ self[key] << delimeter if self[key].is_a?(String)
7
+ self[key] << value
8
+ end
9
+ end
10
+
11
+ def smart_merge(other)
12
+ return self unless other.is_a? Hash and other.any?
13
+ return other unless self.any?
14
+
15
+ self.merge other do |key, left, right|
16
+ case left
17
+ when Hash
18
+ right.is_a?(Hash) ? left.smart_merge(right) : right
19
+ when Array
20
+ (left | [right]).flatten
21
+ when String
22
+ right.is_a?(Array) ? ([left]|right).flatten : right
23
+ else right
24
+ end
25
+ end
26
+ end
27
+
28
+ def smart_merge!(other_hash)
29
+ self.replace(empty? ? other_hash : smart_merge(other_hash))
30
+ end
31
+
32
+ def smart_update(other_hash)
33
+ self.replace(other_hash.smart_merge(self))
34
+ end
35
+
36
+ def only_presented
37
+ select {|_, v| v.present? }
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ module Docs
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Docs
4
+
5
+ initializer "docs.asset_precompile_paths" do |app|
6
+ app.config.assets.precompile += %w(docs.*)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails/generators/active_record'
2
+ require 'generators/api_docs_engine/orm_helpers'
3
+
4
+ module ActiveRecord
5
+ module Generators
6
+ class ApiDocsEngine < ActiveRecord::Generators::Base
7
+ source_root File.expand_path("../templates", __FILE__)
8
+
9
+ include ::ApiDocsEngine::Generators::OrmHelpers
10
+
11
+ def copy_api_docs_engine_migration
12
+ migration_template "migration.rb", "db/migrate/api_docs_create.rb"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ class ApiDocsCreate < ActiveRecord::Migration
2
+ def up
3
+ enable_extension :hstore
4
+
5
+ create_table :docs_page_categories do |t|
6
+ t.string :slug, index: { unique: true }
7
+ t.string :title
8
+ t.text :body
9
+ end
10
+
11
+ create_table :docs_pages do |t|
12
+ t.belongs_to :page_category, index: true
13
+ t.string :path
14
+ t.string :via
15
+ t.string :title
16
+ t.text :body
17
+ t.text :example
18
+ t.hstore :data
19
+ end
20
+ end
21
+
22
+ def down
23
+ drop_table :docs_pages
24
+ drop_table :docs_page_categories
25
+ disable_extension :hstore
26
+ end
27
+ end
@@ -0,0 +1,12 @@
1
+ require 'rails/generators/base'
2
+
3
+ module ApiDocsEngine
4
+ module Generators
5
+ class ApiDocsEngineGenerator < Rails::Generators::Base
6
+ hook_for :orm
7
+
8
+ namespace "api_docs_engine"
9
+ source_root File.expand_path("../templates", __FILE__)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails/generators/base'
2
+ require 'securerandom'
3
+
4
+ module ApiDocsEngine
5
+ module Generators
6
+ class InstallGenerator < Rails::Generators::Base
7
+ source_root File.expand_path("../../templates", __FILE__)
8
+
9
+ class_option :orm
10
+
11
+ def copy_initializer
12
+ template "api_docs_engine.rb", "config/initializers/api_docs_engine.rb"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ module ApiDocsEngine
2
+ module Generators
3
+ module OrmHelpers
4
+ private
5
+ def migration_path
6
+ @migration_path ||= File.join("db", "migrate")
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ Docs.setup do |config|
2
+ # config.title = "API documentation"
3
+ # config.root_path = { to: "pages#index", defaults: { page_category_id: "common" }}
4
+ # config.missing_routes_filter = /api\/.*/
5
+ # config.api_docs_prefix = "api"
6
+ # config.auth = Proc.new do |controller|
7
+ # controller.class_eval do
8
+ # http_basic_authenticate_with name: "admin", password: "admin", only: nil
9
+ # end
10
+ # end
11
+ end