api_docs_engine 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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