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.
- checksums.yaml +7 -0
- data/app/assets/javascripts/docs.js.coffee +42 -0
- data/app/assets/javascripts/highlight.js +1 -0
- data/app/assets/stylesheets/docs.css.scss +127 -0
- data/app/assets/stylesheets/highlight/styles/github.css +129 -0
- data/app/controllers/concerns/docs/manage_resource.rb +98 -0
- data/app/controllers/docs/application_controller.rb +24 -0
- data/app/controllers/docs/markdown_controller.rb +8 -0
- data/app/controllers/docs/missing_docs_controller.rb +7 -0
- data/app/controllers/docs/page_categories_controller.rb +27 -0
- data/app/controllers/docs/pages_controller.rb +56 -0
- data/app/helpers/docs/application_helper.rb +47 -0
- data/app/models/docs/missing_collection.rb +11 -0
- data/app/models/docs/page.rb +64 -0
- data/app/models/docs/page_category.rb +30 -0
- data/app/models/docs/routes_collection.rb +71 -0
- data/app/views/docs/application/edit.html.slim +2 -0
- data/app/views/docs/application/new.html.slim +2 -0
- data/app/views/docs/layouts/docs.html.slim +24 -0
- data/app/views/docs/markdown/create.json.erb +3 -0
- data/app/views/docs/missing_docs/index.html.slim +9 -0
- data/app/views/docs/page_categories/_form.html.slim +19 -0
- data/app/views/docs/pages/_form.html.slim +35 -0
- data/app/views/docs/pages/_page.html.slim +24 -0
- data/app/views/docs/pages/index.html.slim +34 -0
- data/config/initializers/formtastic.rb +1 -0
- data/config/routes.rb +5 -0
- data/lib/api_docs_engine/docs.rb +50 -0
- data/lib/api_docs_engine.rb +2 -0
- data/lib/bootstrap/active_link_to.rb +135 -0
- data/lib/bootstrap/markdown_renderer.rb +10 -0
- data/lib/docs/core_ext.rb +39 -0
- data/lib/docs/engine.rb +9 -0
- data/lib/generators/active_record/api_docs_engine_generator.rb +16 -0
- data/lib/generators/active_record/templates/migration.rb +27 -0
- data/lib/generators/api_docs_engine/api_docs_engine_generator.rb +12 -0
- data/lib/generators/api_docs_engine/install_generator.rb +16 -0
- data/lib/generators/api_docs_engine/orm_helpers.rb +10 -0
- data/lib/generators/templates/api_docs_engine.rb +11 -0
- 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,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,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,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,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,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
|
data/lib/docs/engine.rb
ADDED
@@ -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,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
|