brainstem 1.0.0.pre.1 → 1.0.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 +4 -4
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +1 -1
- data/README.md +383 -32
- data/bin/brainstem +6 -0
- data/brainstem.gemspec +2 -0
- data/docs/api_doc_generator.markdown +175 -0
- data/docs/brainstem_executable.markdown +32 -0
- data/docs/docgen.png +0 -0
- data/docs/docgen_ascii.txt +63 -0
- data/docs/executable.png +0 -0
- data/docs/executable_ascii.txt +10 -0
- data/lib/brainstem/api_docs.rb +146 -0
- data/lib/brainstem/api_docs/abstract_collection.rb +116 -0
- data/lib/brainstem/api_docs/atlas.rb +158 -0
- data/lib/brainstem/api_docs/builder.rb +167 -0
- data/lib/brainstem/api_docs/controller.rb +122 -0
- data/lib/brainstem/api_docs/controller_collection.rb +40 -0
- data/lib/brainstem/api_docs/endpoint.rb +234 -0
- data/lib/brainstem/api_docs/endpoint_collection.rb +58 -0
- data/lib/brainstem/api_docs/exceptions.rb +8 -0
- data/lib/brainstem/api_docs/formatters/abstract_formatter.rb +64 -0
- data/lib/brainstem/api_docs/formatters/markdown/controller_formatter.rb +76 -0
- data/lib/brainstem/api_docs/formatters/markdown/endpoint_collection_formatter.rb +73 -0
- data/lib/brainstem/api_docs/formatters/markdown/endpoint_formatter.rb +169 -0
- data/lib/brainstem/api_docs/formatters/markdown/helper.rb +76 -0
- data/lib/brainstem/api_docs/formatters/markdown/presenter_formatter.rb +200 -0
- data/lib/brainstem/api_docs/introspectors/abstract_introspector.rb +100 -0
- data/lib/brainstem/api_docs/introspectors/rails_introspector.rb +232 -0
- data/lib/brainstem/api_docs/presenter.rb +225 -0
- data/lib/brainstem/api_docs/presenter_collection.rb +97 -0
- data/lib/brainstem/api_docs/resolver.rb +73 -0
- data/lib/brainstem/api_docs/sinks/abstract_sink.rb +37 -0
- data/lib/brainstem/api_docs/sinks/controller_presenter_multifile_sink.rb +93 -0
- data/lib/brainstem/api_docs/sinks/stdout_sink.rb +44 -0
- data/lib/brainstem/cli.rb +146 -0
- data/lib/brainstem/cli/abstract_command.rb +97 -0
- data/lib/brainstem/cli/generate_api_docs_command.rb +169 -0
- data/lib/brainstem/concerns/controller_dsl.rb +300 -0
- data/lib/brainstem/concerns/controller_param_management.rb +30 -9
- data/lib/brainstem/concerns/formattable.rb +38 -0
- data/lib/brainstem/concerns/inheritable_configuration.rb +3 -2
- data/lib/brainstem/concerns/optional.rb +43 -0
- data/lib/brainstem/concerns/presenter_dsl.rb +76 -15
- data/lib/brainstem/controller_methods.rb +6 -3
- data/lib/brainstem/dsl/association.rb +6 -3
- data/lib/brainstem/dsl/associations_block.rb +6 -3
- data/lib/brainstem/dsl/base_block.rb +2 -4
- data/lib/brainstem/dsl/conditional.rb +7 -3
- data/lib/brainstem/dsl/conditionals_block.rb +4 -4
- data/lib/brainstem/dsl/configuration.rb +184 -8
- data/lib/brainstem/dsl/field.rb +6 -3
- data/lib/brainstem/dsl/fields_block.rb +2 -3
- data/lib/brainstem/help_text.txt +8 -0
- data/lib/brainstem/presenter.rb +27 -6
- data/lib/brainstem/presenter_validator.rb +5 -2
- data/lib/brainstem/time_classes.rb +1 -1
- data/lib/brainstem/version.rb +1 -1
- data/spec/brainstem/api_docs/abstract_collection_spec.rb +156 -0
- data/spec/brainstem/api_docs/atlas_spec.rb +353 -0
- data/spec/brainstem/api_docs/builder_spec.rb +100 -0
- data/spec/brainstem/api_docs/controller_collection_spec.rb +92 -0
- data/spec/brainstem/api_docs/controller_spec.rb +225 -0
- data/spec/brainstem/api_docs/endpoint_collection_spec.rb +144 -0
- data/spec/brainstem/api_docs/endpoint_spec.rb +346 -0
- data/spec/brainstem/api_docs/formatters/abstract_formatter_spec.rb +30 -0
- data/spec/brainstem/api_docs/formatters/markdown/controller_formatter_spec.rb +126 -0
- data/spec/brainstem/api_docs/formatters/markdown/endpoint_collection_formatter_spec.rb +85 -0
- data/spec/brainstem/api_docs/formatters/markdown/endpoint_formatter_spec.rb +261 -0
- data/spec/brainstem/api_docs/formatters/markdown/helper_spec.rb +100 -0
- data/spec/brainstem/api_docs/formatters/markdown/presenter_formatter_spec.rb +485 -0
- data/spec/brainstem/api_docs/introspectors/abstract_introspector_spec.rb +192 -0
- data/spec/brainstem/api_docs/introspectors/rails_introspector_spec.rb +170 -0
- data/spec/brainstem/api_docs/presenter_collection_spec.rb +84 -0
- data/spec/brainstem/api_docs/presenter_spec.rb +519 -0
- data/spec/brainstem/api_docs/resolver_spec.rb +72 -0
- data/spec/brainstem/api_docs/sinks/abstract_sink_spec.rb +16 -0
- data/spec/brainstem/api_docs/sinks/controller_presenter_multifile_sink_spec.rb +56 -0
- data/spec/brainstem/api_docs/sinks/stdout_sink_spec.rb +22 -0
- data/spec/brainstem/api_docs_spec.rb +58 -0
- data/spec/brainstem/cli/abstract_command_spec.rb +91 -0
- data/spec/brainstem/cli/generate_api_docs_command_spec.rb +125 -0
- data/spec/brainstem/cli_spec.rb +67 -0
- data/spec/brainstem/concerns/controller_dsl_spec.rb +471 -0
- data/spec/brainstem/concerns/controller_param_management_spec.rb +36 -16
- data/spec/brainstem/concerns/formattable_spec.rb +30 -0
- data/spec/brainstem/concerns/inheritable_configuration_spec.rb +104 -4
- data/spec/brainstem/concerns/optional_spec.rb +48 -0
- data/spec/brainstem/concerns/presenter_dsl_spec.rb +202 -31
- data/spec/brainstem/dsl/association_spec.rb +18 -2
- data/spec/brainstem/dsl/conditional_spec.rb +25 -2
- data/spec/brainstem/dsl/configuration_spec.rb +1 -1
- data/spec/brainstem/dsl/field_spec.rb +18 -2
- data/spec/brainstem/presenter_collection_spec.rb +10 -2
- data/spec/brainstem/presenter_spec.rb +32 -0
- data/spec/brainstem/presenter_validator_spec.rb +12 -7
- data/spec/dummy/rails.rb +49 -0
- data/spec/shared/atlas_taker.rb +18 -0
- data/spec/shared/formattable.rb +14 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/spec_helpers/db.rb +1 -1
- data/spec/spec_helpers/presenters.rb +20 -14
- metadata +106 -6
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
require 'brainstem/api_docs/formatters/abstract_formatter'
|
|
2
|
+
require 'brainstem/api_docs/formatters/markdown/helper'
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# Responsible for formatting each endpoint.
|
|
6
|
+
#
|
|
7
|
+
module Brainstem
|
|
8
|
+
module ApiDocs
|
|
9
|
+
module Formatters
|
|
10
|
+
module Markdown
|
|
11
|
+
class EndpointCollectionFormatter < AbstractFormatter
|
|
12
|
+
include Helper
|
|
13
|
+
|
|
14
|
+
#####################################################################
|
|
15
|
+
# Public API
|
|
16
|
+
#####################################################################
|
|
17
|
+
|
|
18
|
+
def initialize(endpoint_collection, options = {})
|
|
19
|
+
self.endpoint_collection = endpoint_collection
|
|
20
|
+
self.output = ""
|
|
21
|
+
self.zero_text = "No endpoints were found."
|
|
22
|
+
|
|
23
|
+
super options
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
attr_accessor :endpoint_collection,
|
|
28
|
+
:zero_text,
|
|
29
|
+
:output
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def valid_options
|
|
33
|
+
super | [ :zero_text ]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def call
|
|
38
|
+
format_endpoints!
|
|
39
|
+
format_zero_text! if output.empty?
|
|
40
|
+
output
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
#####################################################################
|
|
45
|
+
private
|
|
46
|
+
#####################################################################
|
|
47
|
+
|
|
48
|
+
def all_formatted_endpoints
|
|
49
|
+
endpoint_collection
|
|
50
|
+
.only_documentable
|
|
51
|
+
.formatted(:markdown)
|
|
52
|
+
.reject(&:empty?)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def format_endpoints!
|
|
57
|
+
output << all_formatted_endpoints.join(md_hr)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def format_zero_text!
|
|
62
|
+
output << zero_text
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
Brainstem::ApiDocs::FORMATTERS[:endpoint_collection][:markdown] = \
|
|
73
|
+
Brainstem::ApiDocs::Formatters::Markdown::EndpointCollectionFormatter.method(:call)
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
require 'brainstem/api_docs/formatters/abstract_formatter'
|
|
2
|
+
require 'brainstem/api_docs/formatters/markdown/helper'
|
|
3
|
+
require 'active_support/core_ext/hash/except'
|
|
4
|
+
require 'forwardable'
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# Responsible for formatting each endpoint.
|
|
8
|
+
#
|
|
9
|
+
module Brainstem
|
|
10
|
+
module ApiDocs
|
|
11
|
+
module Formatters
|
|
12
|
+
module Markdown
|
|
13
|
+
class EndpointFormatter < AbstractFormatter
|
|
14
|
+
include Helper
|
|
15
|
+
extend Forwardable
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
################################################################################
|
|
19
|
+
# Public API
|
|
20
|
+
################################################################################
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def initialize(endpoint, options = {})
|
|
24
|
+
self.endpoint = endpoint
|
|
25
|
+
self.output = ""
|
|
26
|
+
|
|
27
|
+
super options
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
attr_accessor :endpoint,
|
|
32
|
+
:output
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def call
|
|
36
|
+
return output if endpoint.nodoc?
|
|
37
|
+
|
|
38
|
+
format_title!
|
|
39
|
+
format_description!
|
|
40
|
+
format_endpoint!
|
|
41
|
+
format_params!
|
|
42
|
+
format_presents!
|
|
43
|
+
|
|
44
|
+
output
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
################################################################################
|
|
49
|
+
private
|
|
50
|
+
################################################################################
|
|
51
|
+
|
|
52
|
+
delegate :controller => :endpoint
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# Formats the title as given, falling back to the humanized action
|
|
57
|
+
# name.
|
|
58
|
+
#
|
|
59
|
+
def format_title!
|
|
60
|
+
output << md_h4(endpoint.title)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
#
|
|
65
|
+
# Formats the description if given.
|
|
66
|
+
#
|
|
67
|
+
def format_description!
|
|
68
|
+
output << md_p(endpoint.description) unless endpoint.description.empty?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
#
|
|
73
|
+
# Formats the actual URI and stated HTTP methods.
|
|
74
|
+
#
|
|
75
|
+
def format_endpoint!
|
|
76
|
+
http_methods = endpoint.http_methods.map(&:upcase).join(" / ")
|
|
77
|
+
path = endpoint.path.gsub('(.:format)', '.json')
|
|
78
|
+
output << md_code("#{http_methods} #{path}")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
#
|
|
83
|
+
# Formats each parameter.
|
|
84
|
+
#
|
|
85
|
+
def format_params!
|
|
86
|
+
return unless endpoint.root_param_keys.any?
|
|
87
|
+
|
|
88
|
+
output << md_h5("Valid Parameters")
|
|
89
|
+
output << md_ul do
|
|
90
|
+
endpoint.root_param_keys.inject("") do |buff, (root_param_name, child_keys)|
|
|
91
|
+
if child_keys.nil?
|
|
92
|
+
buff += parameter_with_indent_level(
|
|
93
|
+
root_param_name,
|
|
94
|
+
endpoint.valid_params[root_param_name],
|
|
95
|
+
0
|
|
96
|
+
)
|
|
97
|
+
else
|
|
98
|
+
text = md_inline_code(root_param_name) + "\n"
|
|
99
|
+
|
|
100
|
+
child_keys.each do |param_name|
|
|
101
|
+
text += parameter_with_indent_level(
|
|
102
|
+
param_name,
|
|
103
|
+
endpoint.valid_params[param_name],
|
|
104
|
+
1
|
|
105
|
+
)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
buff << md_li(text)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
buff
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# Formats a given parameter with a variable indent level. Useful for
|
|
119
|
+
# indifferently formatting root / nested parameters.
|
|
120
|
+
#
|
|
121
|
+
# @param [String] name the param name
|
|
122
|
+
# @param [Hash] options information pertinent to the param
|
|
123
|
+
# @option [Boolean] options :legacy
|
|
124
|
+
# @option [Boolean] options :recursive
|
|
125
|
+
# @option [String,Symbol] options :only Deprecated: use +actions+
|
|
126
|
+
# block instead
|
|
127
|
+
# @option [String] options :info the doc string for the param
|
|
128
|
+
# @param [Integer] indent how many levels the output should be
|
|
129
|
+
# indented from normal
|
|
130
|
+
#
|
|
131
|
+
def parameter_with_indent_level(title, options = {}, indent = 0)
|
|
132
|
+
options = options.dup
|
|
133
|
+
text = md_inline_code(title)
|
|
134
|
+
|
|
135
|
+
text += " - #{options.delete(:info)}" if options.has_key?(:info)
|
|
136
|
+
|
|
137
|
+
if options.keys.any?
|
|
138
|
+
text += "\n"
|
|
139
|
+
text += md_li("Legacy: #{options[:legacy].to_s}", indent + 1) if options.has_key?(:legacy)
|
|
140
|
+
text += md_li("Recursive: #{options[:recursive].to_s}", indent + 1) if options.has_key?(:recursive)
|
|
141
|
+
text.chomp!
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
md_li(text, indent)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
#
|
|
149
|
+
# Formats the data model for the action.
|
|
150
|
+
#
|
|
151
|
+
def format_presents!
|
|
152
|
+
if endpoint.presenter
|
|
153
|
+
output << md_h5("Data Model")
|
|
154
|
+
|
|
155
|
+
link = md_a(endpoint.presenter_title, endpoint.relative_presenter_path_from_controller(:markdown))
|
|
156
|
+
output << md_ul do
|
|
157
|
+
md_li(link)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
Brainstem::ApiDocs::FORMATTERS[:endpoint][:markdown] = \
|
|
169
|
+
Brainstem::ApiDocs::Formatters::Markdown::EndpointFormatter.method(:call)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# This is a very simple DSL that makes generating a markdown document a bit
|
|
2
|
+
# easier.
|
|
3
|
+
|
|
4
|
+
module Brainstem
|
|
5
|
+
module ApiDocs
|
|
6
|
+
module Formatters
|
|
7
|
+
module Markdown
|
|
8
|
+
module Helper
|
|
9
|
+
def md_h1(text)
|
|
10
|
+
"# #{text}\n\n"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def md_h2(text)
|
|
15
|
+
"## #{text}\n\n"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def md_h3(text)
|
|
20
|
+
"### #{text}\n\n"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def md_h4(text)
|
|
25
|
+
"#### #{text}\n\n"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def md_h5(text)
|
|
30
|
+
"##### #{text}\n\n"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def md_strong(text)
|
|
35
|
+
"**#{text}**"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def md_hr
|
|
40
|
+
"-----\n\n"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def md_p(text)
|
|
45
|
+
text + "\n\n"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def md_code(text, lang = "")
|
|
50
|
+
"```#{lang}\n#{text}\n```\n\n"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def md_inline_code(text)
|
|
55
|
+
"`#{text}`"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def md_ul(&block)
|
|
60
|
+
(instance_eval(&block) || "") + "\n\n"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def md_li(text, indent_level = 0)
|
|
65
|
+
"#{' ' * (indent_level * 4)}- #{text}\n"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def md_a(text, link)
|
|
70
|
+
"[#{text}](#{link})"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
require 'active_support/core_ext/string/inflections'
|
|
2
|
+
require 'brainstem/api_docs/formatters/abstract_formatter'
|
|
3
|
+
require 'brainstem/api_docs/formatters/markdown/helper'
|
|
4
|
+
|
|
5
|
+
module Brainstem
|
|
6
|
+
module ApiDocs
|
|
7
|
+
module Formatters
|
|
8
|
+
module Markdown
|
|
9
|
+
class PresenterFormatter < AbstractFormatter
|
|
10
|
+
include Helper
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def initialize(presenter, options = {})
|
|
14
|
+
self.presenter = presenter
|
|
15
|
+
self.output = ""
|
|
16
|
+
super options
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
attr_accessor :presenter,
|
|
21
|
+
:output
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def call
|
|
25
|
+
return output if presenter.nodoc?
|
|
26
|
+
|
|
27
|
+
format_title!
|
|
28
|
+
format_brainstem_keys!
|
|
29
|
+
format_description!
|
|
30
|
+
format_fields!
|
|
31
|
+
format_filters!
|
|
32
|
+
format_sort_orders!
|
|
33
|
+
format_associations!
|
|
34
|
+
|
|
35
|
+
output
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
#####################################################################
|
|
40
|
+
private
|
|
41
|
+
#####################################################################
|
|
42
|
+
|
|
43
|
+
def format_title!
|
|
44
|
+
output << md_h4(presenter.title)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def format_brainstem_keys!
|
|
49
|
+
text = "Top-level key: "
|
|
50
|
+
text << presenter.brainstem_keys
|
|
51
|
+
.map(&method(:md_inline_code))
|
|
52
|
+
.join(" / ")
|
|
53
|
+
|
|
54
|
+
output << md_p(text)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def format_description!
|
|
59
|
+
output << md_p(presenter.description) unless presenter.description.empty?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def format_field_leaf(field, indent_level)
|
|
64
|
+
text = md_inline_code(field.name.to_s)
|
|
65
|
+
text << " (#{md_inline_code(field.type.to_s.capitalize)})"
|
|
66
|
+
|
|
67
|
+
text << "\n"
|
|
68
|
+
text << md_li(field.description, indent_level + 1) if field.description
|
|
69
|
+
|
|
70
|
+
if field.options[:if]
|
|
71
|
+
conditions = field.options[:if]
|
|
72
|
+
.reject { |cond| presenter.conditionals[cond].options[:nodoc] }
|
|
73
|
+
.map {|cond| presenter.conditionals[cond].description || "" }
|
|
74
|
+
.delete_if(&:empty?)
|
|
75
|
+
.join(" and ")
|
|
76
|
+
|
|
77
|
+
text << md_li("visible when #{conditions}", indent_level + 1) unless conditions.empty?
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
text << md_li("only returned when requested through the #{md_inline_code("optional_fields")} param") if field.optional?
|
|
81
|
+
text.chomp!
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def format_field_branch(branch, indent_level = 0)
|
|
86
|
+
branch.inject("") do |buffer, (name, field)|
|
|
87
|
+
if nested_field?(field)
|
|
88
|
+
sub_fields = md_inline_code(name.to_s) + "\n"
|
|
89
|
+
sub_fields << format_field_branch(field.to_h, indent_level + 1)
|
|
90
|
+
buffer += md_li(sub_fields, indent_level)
|
|
91
|
+
else
|
|
92
|
+
buffer += md_li(format_field_leaf(field, indent_level), indent_level)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def nested_field?(field)
|
|
99
|
+
!field.respond_to?(:options)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def format_fields!
|
|
104
|
+
output << md_h5("Fields")
|
|
105
|
+
|
|
106
|
+
if presenter.valid_fields.any?
|
|
107
|
+
|
|
108
|
+
output << md_ul do
|
|
109
|
+
format_field_branch(presenter.valid_fields)
|
|
110
|
+
end
|
|
111
|
+
else
|
|
112
|
+
output << md_p("No fields were listed.")
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def format_filters!
|
|
118
|
+
if presenter.valid_filters.any?
|
|
119
|
+
output << md_h5("Filters")
|
|
120
|
+
output << md_ul do
|
|
121
|
+
presenter.valid_filters.inject("") do |buffer, (name, opts)|
|
|
122
|
+
text = md_inline_code(name)
|
|
123
|
+
|
|
124
|
+
if opts[:info]
|
|
125
|
+
text << "\n"
|
|
126
|
+
text << md_li(opts[:info], 1)
|
|
127
|
+
text.chomp!
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
buffer += md_li(text)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def format_sort_orders!
|
|
138
|
+
if presenter.valid_sort_orders.any?
|
|
139
|
+
output << md_h5("Sort Orders")
|
|
140
|
+
output << md_ul do
|
|
141
|
+
sorted_orders = presenter.valid_sort_orders.sort_by { |name, _| name.to_s }
|
|
142
|
+
|
|
143
|
+
# Shift the default sort_order to the top
|
|
144
|
+
sorted_orders.unshift sorted_orders.delete_at(sorted_orders.index { |name, _| name.to_s == presenter.default_sort_field })
|
|
145
|
+
|
|
146
|
+
sorted_orders.inject("") do |buffer, (name, opts)|
|
|
147
|
+
text = "#{md_inline_code(name.to_s)}"
|
|
148
|
+
|
|
149
|
+
if presenter.default_sort_field == name.to_s
|
|
150
|
+
text += " - #{md_strong("default")} (#{presenter.default_sort_direction})"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
if opts[:info]
|
|
154
|
+
text += "\n" + md_li(opts[:info], 1)
|
|
155
|
+
text.chomp!
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
buffer += md_li(text)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def format_associations!
|
|
166
|
+
if presenter.valid_associations.any?
|
|
167
|
+
output << md_h5("Associations")
|
|
168
|
+
|
|
169
|
+
output << "Association Name | Associated Class | Description\n"
|
|
170
|
+
output << " -------------- | -------------- | ----------\n"
|
|
171
|
+
|
|
172
|
+
output << presenter.valid_associations.inject("") do |buffer, (_, association)|
|
|
173
|
+
link = presenter.link_for_association(association)
|
|
174
|
+
if link
|
|
175
|
+
link = md_a(association.target_class, link)
|
|
176
|
+
else
|
|
177
|
+
link = association.target_class.to_s
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
desc = association.description.to_s
|
|
181
|
+
if association.options && association.options[:restrict_to_only]
|
|
182
|
+
desc += "." unless desc =~ /\.\s*\z/
|
|
183
|
+
desc += " Restricted to queries using the #{md_inline_code("only")} parameter."
|
|
184
|
+
desc.strip!
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
buffer << md_inline_code(association.name) + " | " + link + " | " + desc + "\n"
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
output << "\n"
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
Brainstem::ApiDocs::FORMATTERS[:presenter][:markdown] = \
|
|
200
|
+
Brainstem::ApiDocs::Formatters::Markdown::PresenterFormatter.method(:call)
|