apress-documentation 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.drone.yml +28 -0
- data/.gitignore +10 -0
- data/Appraisals +30 -0
- data/CHANGELOG.md +34 -0
- data/Gemfile +4 -0
- data/README.md +101 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/package/documentation.js +18 -0
- data/app/assets/javascripts/shared/dependency_switcher.js +10 -0
- data/app/assets/javascripts/swagger_binder.js +19 -0
- data/app/assets/javascripts/swagger_ui.js +24 -0
- data/app/assets/javascripts/templates/document.hamlbars +25 -0
- data/app/assets/stylesheets/document/base.scss +112 -0
- data/app/assets/stylesheets/document/document.scss +19 -0
- data/app/assets/stylesheets/document/layout.scss +9 -0
- data/app/assets/stylesheets/document/sidebar.scss +19 -0
- data/app/assets/stylesheets/document/swagger.scss +3 -0
- data/app/assets/stylesheets/document/switch.scss +46 -0
- data/app/assets/stylesheets/document/variables.scss +26 -0
- data/app/assets/stylesheets/package/documentation.css +9 -0
- data/app/assets/stylesheets/package/swagger_print.css +4 -0
- data/app/assets/stylesheets/package/swagger_screen.css +4 -0
- data/app/controllers/apress/documentation/documents_controller.rb +14 -0
- data/app/controllers/apress/documentation/swagger_controller.rb +22 -0
- data/app/controllers/apress/documentation/swagger_ui_controller.rb +11 -0
- data/app/controllers/concerns/apress/documentation/preload_docs.rb +20 -0
- data/app/helpers/apress/documentation/documents_helper.rb +14 -0
- data/app/presenters/apress/documentation/dependency_presenter.rb +75 -0
- data/app/services/apress/documentation/swagger_json_builder.rb +22 -0
- data/app/views/apress/documentation/documents/_document.html.haml +32 -0
- data/app/views/apress/documentation/documents/_swagger.html.haml +10 -0
- data/app/views/apress/documentation/documents/show.html.haml +13 -0
- data/app/views/apress/documentation/presenters/dependency_presenter/_dependencies.html.haml +21 -0
- data/app/views/apress/documentation/presenters/dependency_presenter/_links.html.haml +17 -0
- data/app/views/apress/documentation/swagger_ui/show.html.haml +26 -0
- data/app/views/layouts/apress/documentation/_menu.html.haml +6 -0
- data/app/views/layouts/apress/documentation/_menu_item.html.haml +7 -0
- data/app/views/layouts/apress/documentation/_sidebar.html.haml +2 -0
- data/app/views/layouts/documentation.html.haml +17 -0
- data/apress-documentation.gemspec +35 -0
- data/config/routes.rb +16 -0
- data/dip.yml +48 -0
- data/docker-compose.development.yml +18 -0
- data/docker-compose.drone.yml +7 -0
- data/docker-compose.yml +10 -0
- data/lib/apress/documentation.rb +48 -0
- data/lib/apress/documentation/dsl/compilers/base_compiler.rb +32 -0
- data/lib/apress/documentation/dsl/compilers/document_compiler.rb +111 -0
- data/lib/apress/documentation/dsl/compilers/mixins/dependable.rb +31 -0
- data/lib/apress/documentation/dsl/compilers/mixins/publicity.rb +34 -0
- data/lib/apress/documentation/dsl/compilers/swagger_compiler.rb +25 -0
- data/lib/apress/documentation/dsl/document.rb +14 -0
- data/lib/apress/documentation/dsl/modules.rb +40 -0
- data/lib/apress/documentation/dsl/swagger_document.rb +14 -0
- data/lib/apress/documentation/dsl/utils/swagger_bind_point_extractor.rb +37 -0
- data/lib/apress/documentation/engine.rb +16 -0
- data/lib/apress/documentation/extensions/rgl/adjacency.rb +18 -0
- data/lib/apress/documentation/storage/base_storage.rb +88 -0
- data/lib/apress/documentation/storage/dependency_graph.rb +96 -0
- data/lib/apress/documentation/storage/document.rb +52 -0
- data/lib/apress/documentation/storage/modules.rb +83 -0
- data/lib/apress/documentation/storage/swagger_document.rb +62 -0
- data/lib/apress/documentation/swagger/schema.rb +39 -0
- data/lib/apress/documentation/version.rb +5 -0
- data/spec/app/controllers/documents_controller_spec.rb +42 -0
- data/spec/app/controllers/swagger_controller_spec.rb +46 -0
- data/spec/app/controllers/swagger_ui_controller_spec.rb +11 -0
- data/spec/app/services/swagger_json_builder_spec.rb +41 -0
- data/spec/apress/documentation_spec.rb +342 -0
- data/spec/helpers/apress/documentation/documents_helper_spec.rb +17 -0
- data/spec/internal/app/docs/swagger/root.rb +7 -0
- data/spec/internal/config/database.yml +7 -0
- data/spec/internal/config/environments/test.rb +1 -0
- data/spec/internal/config/hosts.rb +1 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/lib/stub_docs/module.rb +3 -0
- data/spec/internal/lib/stub_docs/module/document/child_document.rb +7 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/presenters/apress/documentation/dependency_presenter_spec.rb +139 -0
- data/spec/spec_helper.rb +27 -0
- metadata +335 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'compilers/document_compiler'
|
2
|
+
|
3
|
+
module Apress
|
4
|
+
module Documentation
|
5
|
+
module Dsl
|
6
|
+
module Document
|
7
|
+
# Public: Подключает DSL в класс данных документа
|
8
|
+
def compile(fields = {}, &block)
|
9
|
+
Apress::Documentation::Dsl::Compilers::DocumentCompiler.new(self).compile(fields, &block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Apress
|
2
|
+
module Documentation
|
3
|
+
module Dsl
|
4
|
+
module Modules
|
5
|
+
# Protected: Точка входа для построения DS
|
6
|
+
# используется через делегацию в модуле Apress::Documentation
|
7
|
+
#
|
8
|
+
#
|
9
|
+
# module_slug - Symbol - слаг модуля
|
10
|
+
# fields - Hash(optional, default - {}) - поля для установки в короткой записи
|
11
|
+
# (например, Apress::Documentation.build(:slug, title: 'name'))
|
12
|
+
# &block - Proc(optional) - вызовы DSL методов
|
13
|
+
#
|
14
|
+
# Examples
|
15
|
+
#
|
16
|
+
# Apress::Documentation.build(:module) do
|
17
|
+
# name 'some module'
|
18
|
+
# description 'tests'
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Apress::Documentation.build(:module) do
|
22
|
+
# document(:some, title: 'Some doc') do
|
23
|
+
# description 'Тут вставить описание'
|
24
|
+
# publicity 'Публичное'
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
def build(module_slug, fields = {}, &block)
|
29
|
+
module_slug = module_slug.to_s
|
30
|
+
document = self[module_slug]
|
31
|
+
document ||= Apress::Documentation::Storage::Document.new(module_slug)
|
32
|
+
Apress::Documentation::Storage::DependencyGraph.instance.add_document(document)
|
33
|
+
self << document
|
34
|
+
|
35
|
+
document.compile(fields, &block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'compilers/swagger_compiler'
|
2
|
+
|
3
|
+
module Apress
|
4
|
+
module Documentation
|
5
|
+
module Dsl
|
6
|
+
module SwaggerDocument
|
7
|
+
# Public: Подключает DSL в класс данных swagger-описания
|
8
|
+
def compile(fields = {}, &block)
|
9
|
+
Apress::Documentation::Dsl::Compilers::SwaggerCompiler.new(self).compile(fields, &block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Apress
|
2
|
+
module Documentation
|
3
|
+
module Dsl
|
4
|
+
module Utils
|
5
|
+
# Private: "Распознает" идентификатор html-tag'а в SwaggerUI по переданному блоку Swagger::Blocks,
|
6
|
+
# в который будет вставлена дополнительная информация из SwaggerDocument.
|
7
|
+
#
|
8
|
+
# Идея: Выполнить блок DSL swagger_path из Swagger::Blocks без вызовов реальных методов.
|
9
|
+
#
|
10
|
+
# Алгоритм:
|
11
|
+
# - Выполняем переданный блок от swagger_path, пропуская неизвестные методы
|
12
|
+
# - как только нашли первый вызов "key :operationId, value", запоминаем value
|
13
|
+
# - тоже самое для key :tags, [value]
|
14
|
+
# - если после выполнения блока оба значения заданы (@tag, @operation_id) возвращаем результат
|
15
|
+
class SwaggerBindPointExtractor
|
16
|
+
def extract(&block)
|
17
|
+
instance_eval(&block)
|
18
|
+
"#{@tag}_#{@operation_id}" if @tag && @operation_id
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(name, *args, &block)
|
22
|
+
if block_given?
|
23
|
+
instance_eval(&block)
|
24
|
+
elsif name.to_s == 'key'
|
25
|
+
case args[0]
|
26
|
+
when :operationId
|
27
|
+
@operation_id ||= args[1]
|
28
|
+
when :tags
|
29
|
+
@tag ||= args[1].try(:first)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Apress
|
2
|
+
module Documentation
|
3
|
+
class Engine < Rails::Engine
|
4
|
+
config.autoload_paths += [
|
5
|
+
config.root.join('app', 'controllers', 'concerns'),
|
6
|
+
config.root.join('app', 'presenters')
|
7
|
+
]
|
8
|
+
|
9
|
+
config.documentation = {path_scope: nil, routes_constraints: {domain: :current}}
|
10
|
+
|
11
|
+
initializer "apress-documentation", before: :load_init_rb do |app|
|
12
|
+
RGL::DirectedAdjacencyGraph.include Apress::Documentation::Extensions::RGL::Adjacency
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Apress
|
2
|
+
module Documentation
|
3
|
+
module Extensions
|
4
|
+
module RGL
|
5
|
+
module Adjacency
|
6
|
+
# Private: Расширение графа для замены вершины на новую
|
7
|
+
def replace_vertex(old_v, new_v)
|
8
|
+
@vertices_dict[new_v] = @vertices_dict.delete(old_v)
|
9
|
+
|
10
|
+
@vertices_dict.each_value do |list|
|
11
|
+
list.add(new_v) if list.delete?(old_v)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Apress
|
2
|
+
module Documentation
|
3
|
+
module Storage
|
4
|
+
# Private: AbstractClass, Базовый класс хранилища
|
5
|
+
#
|
6
|
+
# описывает методы аттрибутов для сериализации в json формата:
|
7
|
+
# {
|
8
|
+
# {
|
9
|
+
# "attr_0": send(:attr_0),
|
10
|
+
# "attr_1": send(:attr_1),
|
11
|
+
# ....
|
12
|
+
# }
|
13
|
+
# }
|
14
|
+
class BaseStorage
|
15
|
+
# Public: Составной слаг, используется как URL
|
16
|
+
attr_reader :slug
|
17
|
+
|
18
|
+
def self.json_attr_names
|
19
|
+
@json_attr_names ||= []
|
20
|
+
end
|
21
|
+
|
22
|
+
# Public: Задает аттрибуты для сериализации в json
|
23
|
+
def self.json_attr(*method_names)
|
24
|
+
json_attr_names.concat(method_names.map(&:to_s))
|
25
|
+
|
26
|
+
attr_accessor(*method_names)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Public: Сериализует объект в JSON
|
30
|
+
def as_json(options = {})
|
31
|
+
self.class.json_attr_names.each_with_object({}) do |attr_name, json|
|
32
|
+
value = send(attr_name)
|
33
|
+
|
34
|
+
json[attr_name] = value if value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Public: задает аттрибуты на основе хеша
|
39
|
+
def assign(options = {})
|
40
|
+
options.each do |key, value|
|
41
|
+
unless self.class.json_attr_names.include?(key.to_s)
|
42
|
+
raise "Undefined attribute #{key}, allowed attributes are #{self.class.json_attr_names}"
|
43
|
+
end
|
44
|
+
|
45
|
+
send("#{key}=", value)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def eql?(other)
|
50
|
+
slug == other.to_s
|
51
|
+
end
|
52
|
+
alias_method :==, :eql?
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
slug.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
def hash
|
59
|
+
slug.hash
|
60
|
+
end
|
61
|
+
|
62
|
+
def inspect
|
63
|
+
"<#{self.class} slug = #{slug}>"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Public: находит зависимости для текущего документа
|
67
|
+
#
|
68
|
+
# Arguments:
|
69
|
+
# reverse - флаг для отпеределения какой тип зависимостей нужно вернуть
|
70
|
+
# возможные значения
|
71
|
+
# - false (default) - документы, от которых зависит текущий документ (AKA зависимости self)
|
72
|
+
# - true - документы, которые зависят от текущего (AKA потребители self)
|
73
|
+
#
|
74
|
+
# Returns Array of Pairs - [[doc1, doc2], [doc1, doc2]]
|
75
|
+
def dependencies(reverse: false)
|
76
|
+
@dependencies ||= Hash.new do |hash, key|
|
77
|
+
hash[key] = Storage::DependencyGraph.instance.dependencies(
|
78
|
+
self,
|
79
|
+
reverse: key
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
@dependencies[reverse]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Apress
|
4
|
+
module Documentation
|
5
|
+
module Storage
|
6
|
+
# Private: Основное хранилище всех зависимостей между документами
|
7
|
+
# Инкапсулирует орентированный граф, вершины которого документы (Document или SwaggerDocument)
|
8
|
+
class DependencyGraph
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
# Public: добавление документа
|
12
|
+
#
|
13
|
+
# Arguments:
|
14
|
+
# document - (String or Document) - документ или его слаг(если документ еще не был создан)
|
15
|
+
#
|
16
|
+
# Note:
|
17
|
+
# Данный метод позволяет ""лениво"" создавать документы в графе,
|
18
|
+
# подменяя слаг документа, вставленного в граф до создания самого документа, на сам документ
|
19
|
+
# Returns nothing
|
20
|
+
def add_document(document)
|
21
|
+
if graph.has_vertex?(document)
|
22
|
+
graph.replace_vertex(document, document)
|
23
|
+
else
|
24
|
+
graph.add_vertex(document)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Public: добавление связи между документами, создает ребро в графе, если оно не было создано
|
29
|
+
#
|
30
|
+
# Arguments:
|
31
|
+
# document_from - (Document) - документ от который зависит
|
32
|
+
# document_to - (String or Document) - документ или его слаг(если документ еще не был создан)
|
33
|
+
#
|
34
|
+
# Returns nothing
|
35
|
+
def add_dependency(document_from, document_to)
|
36
|
+
graph.add_edge(document_from, document_to) unless graph.has_edge?(document_from, document_to)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Public: находит все зависимости для заданного документа
|
40
|
+
#
|
41
|
+
# Arguments:
|
42
|
+
# contract - (Document) - документ для которого определяем зависимости
|
43
|
+
# reverse - (boolean) - флаг, различает тип определяемых зависимостей
|
44
|
+
# возможные значения
|
45
|
+
# - false (default) - документы, от которых зависит текущий документ (AKA зависимости contract)
|
46
|
+
# - true - документы, которые зависят от текущего (AKA потребители contract)
|
47
|
+
#
|
48
|
+
# Returns Array of Pairs - [[doc_from, doc_to], [doc_from_other, doc_to_other]]
|
49
|
+
def dependencies(contract, reverse:)
|
50
|
+
dep = []
|
51
|
+
|
52
|
+
condition =
|
53
|
+
if reverse
|
54
|
+
lambda { |doc, _, to| doc == to }
|
55
|
+
else
|
56
|
+
lambda { |doc, from, _| doc == from }
|
57
|
+
end
|
58
|
+
|
59
|
+
graph.each_edge do |from, to|
|
60
|
+
next unless condition.call(contract, from, to)
|
61
|
+
|
62
|
+
dep << (reverse ? [to, from] : [from, to])
|
63
|
+
end
|
64
|
+
|
65
|
+
dep
|
66
|
+
end
|
67
|
+
|
68
|
+
# Public: валидирует зависимости
|
69
|
+
#
|
70
|
+
# Throws RuntimeError если найдена вершина неверного типа
|
71
|
+
#
|
72
|
+
# Returns nothing
|
73
|
+
def validate!
|
74
|
+
graph.each_vertex do |v|
|
75
|
+
unless v.is_a?(Apress::Documentation::Storage::BaseStorage)
|
76
|
+
raise "Несуществующий документ - #{v}, объявлен в - #{dependencies(v, reverse: true).map(&:last)}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Public: очищает все текущие зависисмости
|
82
|
+
#
|
83
|
+
# Returns nothing
|
84
|
+
def reset!
|
85
|
+
@graph = RGL::DirectedAdjacencyGraph.new
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def graph
|
91
|
+
@graph ||= RGL::DirectedAdjacencyGraph.new
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'base_storage'
|
2
|
+
require_relative '../dsl/document'
|
3
|
+
|
4
|
+
module Apress
|
5
|
+
module Documentation
|
6
|
+
module Storage
|
7
|
+
# Protected
|
8
|
+
#
|
9
|
+
# Внутренний класс системы документации
|
10
|
+
# Описывает отдельный документ
|
11
|
+
class Document < BaseStorage
|
12
|
+
include Apress::Documentation::Dsl::Document
|
13
|
+
# Public: Заголовок документа
|
14
|
+
json_attr :title
|
15
|
+
# Public: Описание документа
|
16
|
+
json_attr :description
|
17
|
+
# Public: Бизнесс описание - заполняется менаджером
|
18
|
+
json_attr :business_desc
|
19
|
+
# Public: Наличие тестов, ссылка на задачу с тестами
|
20
|
+
json_attr :tests
|
21
|
+
# Public: Публичность описываемого функционала - (Защищенный, Публичный)
|
22
|
+
json_attr :publicity
|
23
|
+
|
24
|
+
def initialize(slug)
|
25
|
+
@slug = slug
|
26
|
+
end
|
27
|
+
|
28
|
+
# Public: проверка, необходимо ли для данного документа отображать SwaggerUI
|
29
|
+
def swagger?
|
30
|
+
!swagger_documents.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Public: Хранит дочерние документы
|
34
|
+
def documents
|
35
|
+
@documents ||= {}
|
36
|
+
end
|
37
|
+
|
38
|
+
# Public: Хранит объекты SwaggerDocument для отображения на одной старнице через SwaggerUI
|
39
|
+
def swagger_documents
|
40
|
+
@swagger_documents ||= {}
|
41
|
+
end
|
42
|
+
|
43
|
+
# Public: находит документ верхнего уровня - модуль
|
44
|
+
#
|
45
|
+
# Returns Document
|
46
|
+
def current_module
|
47
|
+
Apress::Documentation::Storage::Modules.instance[slug.to_s.split('/').first]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require_relative '../dsl/modules'
|
3
|
+
|
4
|
+
module Apress
|
5
|
+
module Documentation
|
6
|
+
module Storage
|
7
|
+
# Protected
|
8
|
+
#
|
9
|
+
# Класс хранения документов верхнего уровня (модулей)
|
10
|
+
class Modules
|
11
|
+
include Apress::Documentation::Dsl::Modules
|
12
|
+
include Singleton
|
13
|
+
|
14
|
+
# Public
|
15
|
+
#
|
16
|
+
# Хеш модулей
|
17
|
+
def data
|
18
|
+
@data ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
# Public
|
22
|
+
#
|
23
|
+
# Добавление модуля
|
24
|
+
#
|
25
|
+
# Arguments
|
26
|
+
# document - Document
|
27
|
+
#
|
28
|
+
# Example usage:
|
29
|
+
# Apress::Documentation::Modules.instance << document
|
30
|
+
def <<(document)
|
31
|
+
data[document.slug.to_s] = document
|
32
|
+
end
|
33
|
+
|
34
|
+
# Public
|
35
|
+
#
|
36
|
+
# Поиск модуля
|
37
|
+
#
|
38
|
+
# Arguments
|
39
|
+
# slug - String (или любой совместимый объект) - слаг документа
|
40
|
+
#
|
41
|
+
# Example usage:
|
42
|
+
# Apress::Documentation::Modules.instance[slug]
|
43
|
+
#
|
44
|
+
# Returns Document
|
45
|
+
def [](slug)
|
46
|
+
data[slug.to_s]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Public
|
50
|
+
#
|
51
|
+
# Получение документа по его URL
|
52
|
+
#
|
53
|
+
# Arguments
|
54
|
+
# path - String - строка разделенная '/' (пример "/module/document/some_function")
|
55
|
+
#
|
56
|
+
# Example usage:
|
57
|
+
# Apress::Documentation.fetch_document('module_name/document/test')
|
58
|
+
def fetch_document(path)
|
59
|
+
keys = path.split('/')
|
60
|
+
doc = data[keys.shift]
|
61
|
+
return unless doc
|
62
|
+
|
63
|
+
keys.each do |key|
|
64
|
+
doc = doc.documents[key] || (doc.respond_to?(:swagger_documents) && doc.swagger_documents[key])
|
65
|
+
break unless doc
|
66
|
+
end
|
67
|
+
|
68
|
+
doc
|
69
|
+
end
|
70
|
+
|
71
|
+
# Public
|
72
|
+
#
|
73
|
+
# Удаление всех документов, используется для тестирования
|
74
|
+
#
|
75
|
+
# Example usage:
|
76
|
+
# Apress::Documentation.reset!
|
77
|
+
def reset!
|
78
|
+
@data = {}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|