brainstem 1.0.0.pre.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,116 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'brainstem/concerns/optional'
|
3
|
+
require 'brainstem/concerns/formattable'
|
4
|
+
|
5
|
+
module Brainstem
|
6
|
+
module ApiDocs
|
7
|
+
class AbstractCollection
|
8
|
+
include Enumerable
|
9
|
+
extend Forwardable
|
10
|
+
include Concerns::Optional
|
11
|
+
include Concerns::Formattable
|
12
|
+
|
13
|
+
#
|
14
|
+
# Creates a new collection with all passed members. Very handy for
|
15
|
+
# reduce operations which should return a subset of members but retain
|
16
|
+
# the same utility.
|
17
|
+
#
|
18
|
+
def self.with_members(atlas, *members)
|
19
|
+
new(atlas).tap {|n| members.flatten.each { |m| n << m } }
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def initialize(atlas, options = {})
|
24
|
+
self.atlas = atlas
|
25
|
+
self.members = []
|
26
|
+
super options
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
attr_accessor :atlas
|
31
|
+
|
32
|
+
delegate :find_by_class => :atlas
|
33
|
+
|
34
|
+
|
35
|
+
#
|
36
|
+
# Handy accessor for extracting the last member of the collection.
|
37
|
+
#
|
38
|
+
def last
|
39
|
+
members[-1]
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
#
|
44
|
+
# Appends a pre-existing object to the collection.
|
45
|
+
#
|
46
|
+
def <<(*objects)
|
47
|
+
members.push(*objects.flatten)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
#
|
52
|
+
# Iterates over each controller in the collection.
|
53
|
+
#
|
54
|
+
def each(&block)
|
55
|
+
members.each(&block)
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
#
|
60
|
+
# Returns a map of each member formatted as specified.
|
61
|
+
#
|
62
|
+
def formatted(format, options = {})
|
63
|
+
map { |member| member.formatted_as(format, options) }
|
64
|
+
.reject(&:empty?)
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
#
|
69
|
+
# Returns a list of each member's filename.
|
70
|
+
#
|
71
|
+
# We internally refer to `formatted_with_filename` here because we don't
|
72
|
+
# want to include any filenames of empty files (i.e. nodoc).
|
73
|
+
#
|
74
|
+
def filenames(format)
|
75
|
+
formatted_with_filename(format).map { |arr| arr[1] }
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
#
|
80
|
+
# Returns a map of each formatted member and its suggested filename.
|
81
|
+
#
|
82
|
+
def formatted_with_filename(format, options = {})
|
83
|
+
map { |member| [
|
84
|
+
member.formatted_as(format, options),
|
85
|
+
member.suggested_filename(format)
|
86
|
+
] }
|
87
|
+
.reject { |(buffer, _)| buffer.empty? }
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
def each_formatted_with_filename(format, options = {}, &block)
|
92
|
+
formatted_with_filename(format, options)
|
93
|
+
.each { |args| block.call(*args) }
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def each_formatted(format, options = {}, &block)
|
98
|
+
formatted(format, options)
|
99
|
+
.each { |args| block.call(*args) }
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def each_filename(format, &block)
|
104
|
+
filenames(format).each { |args| block.call(*args) }
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
#########################################################################
|
110
|
+
protected
|
111
|
+
#########################################################################
|
112
|
+
|
113
|
+
attr_accessor :members
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'brainstem/api_docs/resolver'
|
3
|
+
require 'brainstem/api_docs/exceptions'
|
4
|
+
require 'brainstem/api_docs/endpoint_collection'
|
5
|
+
require 'brainstem/api_docs/controller_collection'
|
6
|
+
require 'brainstem/api_docs/presenter_collection'
|
7
|
+
require 'brainstem/concerns/optional'
|
8
|
+
|
9
|
+
#
|
10
|
+
#
|
11
|
+
# The Atlas is an object that makes the information from an introspector
|
12
|
+
# available in formatted and raw format.
|
13
|
+
#
|
14
|
+
module Brainstem
|
15
|
+
module ApiDocs
|
16
|
+
class Atlas
|
17
|
+
extend Forwardable
|
18
|
+
include Concerns::Optional
|
19
|
+
|
20
|
+
|
21
|
+
def initialize(introspector, options = {})
|
22
|
+
self.endpoints = EndpointCollection.new(self)
|
23
|
+
self.controllers = ControllerCollection.new(self)
|
24
|
+
self.presenters = ::Brainstem::ApiDocs::PresenterCollection.new(self)
|
25
|
+
self.resolver = Resolver.new(self)
|
26
|
+
|
27
|
+
self.controller_matches = []
|
28
|
+
self.introspector = introspector
|
29
|
+
|
30
|
+
super options
|
31
|
+
|
32
|
+
parse_routes!
|
33
|
+
extract_presenters!
|
34
|
+
validate!
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
attr_accessor :endpoints,
|
39
|
+
:controllers,
|
40
|
+
:presenters,
|
41
|
+
:resolver
|
42
|
+
|
43
|
+
|
44
|
+
delegate :find_by_class => :resolver
|
45
|
+
|
46
|
+
|
47
|
+
#########################################################################
|
48
|
+
private
|
49
|
+
#########################################################################
|
50
|
+
|
51
|
+
|
52
|
+
#
|
53
|
+
# Lists valid options that may be passed on instantiation.
|
54
|
+
#
|
55
|
+
def valid_options
|
56
|
+
super | [ :controller_matches ]
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
#
|
61
|
+
# Ensures the atlas is valid before allowing consumers to make requests
|
62
|
+
# of it.
|
63
|
+
#
|
64
|
+
def validate!
|
65
|
+
raise InvalidAtlasError, "Atlas is not valid." unless valid?
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
#
|
70
|
+
# Set and read the introspector.
|
71
|
+
#
|
72
|
+
attr_accessor :introspector
|
73
|
+
|
74
|
+
|
75
|
+
#
|
76
|
+
# Holds +Regexp+s which each controller name must match in order to be
|
77
|
+
# included in the list of endpoints.
|
78
|
+
#
|
79
|
+
attr_accessor :controller_matches
|
80
|
+
|
81
|
+
|
82
|
+
#
|
83
|
+
# Returns a list of all routes that pass the user's filtering.
|
84
|
+
#
|
85
|
+
def allowed_routes
|
86
|
+
introspector.routes.keep_if(&method(:allow_route?))
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
#
|
91
|
+
# Constructs +Endpoint+ and +Controller wrappers per route.
|
92
|
+
#
|
93
|
+
def parse_routes!
|
94
|
+
allowed_routes.each do |route|
|
95
|
+
if (endpoint = endpoints.find_from_route(route))
|
96
|
+
endpoint.merge_http_methods!(route[:http_methods])
|
97
|
+
else
|
98
|
+
controller = controllers.find_or_create_from_route(route)
|
99
|
+
endpoint = endpoints.create_from_route(route, controller)
|
100
|
+
|
101
|
+
controller.add_endpoint(endpoint)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
#
|
108
|
+
# Extracts declared presents for each endpoint and converts it into a
|
109
|
+
# Presenter wrapper object.
|
110
|
+
#
|
111
|
+
def extract_presenters!
|
112
|
+
valid_presenter_pairs.each do |target_class, const|
|
113
|
+
presenter = presenters.find_or_create_from_presenter_collection(target_class, const)
|
114
|
+
|
115
|
+
endpoints
|
116
|
+
.select do |ep|
|
117
|
+
declared_presented_class = ep.declared_presented_class
|
118
|
+
!declared_presented_class.nil? && declared_presented_class.to_s == target_class
|
119
|
+
end
|
120
|
+
.each {|ep| ep.presenter = presenter }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
#
|
126
|
+
# Returns a list of valid +target_class_to_s => PresenterConst+ pairs,
|
127
|
+
# determining validity by whether they descend from the base presenter.
|
128
|
+
#
|
129
|
+
# @return [Hash{String => Class}] valid pairs
|
130
|
+
#
|
131
|
+
def valid_presenter_pairs
|
132
|
+
Brainstem.presenter_collection.presenters.select do |target_class, const|
|
133
|
+
introspector.presenters.include? const
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
#
|
139
|
+
# Whether this Atlas is valid (i.e. if it has at least one endpoint).
|
140
|
+
#
|
141
|
+
# @return [Boolean] if the atlas is valid
|
142
|
+
#
|
143
|
+
def valid?
|
144
|
+
endpoints.count > 0
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
#
|
149
|
+
# Returns whether a route's controller passes the limiting regexp passed to the
|
150
|
+
# generation command.
|
151
|
+
#
|
152
|
+
def allow_route?(route)
|
153
|
+
introspector.controllers.include?(route[:controller]) &&
|
154
|
+
controller_matches.all? { |regexp| route[:controller].to_s =~ regexp }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'brainstem/api_docs/introspectors/rails_introspector'
|
2
|
+
require 'brainstem/concerns/optional'
|
3
|
+
require 'brainstem/api_docs/atlas'
|
4
|
+
require 'active_support/core_ext/hash/slice'
|
5
|
+
|
6
|
+
#
|
7
|
+
# This class describes the main API surface for generating API documentation.
|
8
|
+
# The command-line utility provided with Brainstem is basically just a thin
|
9
|
+
# veneer over top of this class.
|
10
|
+
#
|
11
|
+
# You can use this to programmatically generate the API docs, or to browse them
|
12
|
+
# while inside a REPL.
|
13
|
+
#
|
14
|
+
module Brainstem
|
15
|
+
module ApiDocs
|
16
|
+
class Builder
|
17
|
+
include Brainstem::Concerns::Optional
|
18
|
+
|
19
|
+
|
20
|
+
def valid_options
|
21
|
+
[
|
22
|
+
:introspector_method,
|
23
|
+
:atlas_method,
|
24
|
+
|
25
|
+
:args_for_introspector,
|
26
|
+
:args_for_atlas
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
#
|
32
|
+
# @param [Hash] options
|
33
|
+
# @option options [Proc] :introspector_method Proc of arity one that
|
34
|
+
# returns an Introspector (an object that introspects into
|
35
|
+
# the host application, seeking its routes, controllers, and
|
36
|
+
# presenters).
|
37
|
+
# @option options [Hash] :args_for_introspector Additional arguments to
|
38
|
+
# be passed to the introspector on creation.
|
39
|
+
# @option options [Hash] :args_for_atlas Additional arguments to be passed
|
40
|
+
# to the atlas on creation.
|
41
|
+
# @option options [Proc,Object] :introspector_method A method that
|
42
|
+
# returns an introspector when called.
|
43
|
+
# @option options [Proc,Object] :atlas_method A method that returns an Atlas-like
|
44
|
+
# object when called.
|
45
|
+
#
|
46
|
+
# @see Brainstem::ApiDocs::Introspectors::AbstractIntrospector
|
47
|
+
# @see Brainstem::ApiDocs::Introspectors::RailsIntrospector
|
48
|
+
#
|
49
|
+
def initialize(options = {})
|
50
|
+
super
|
51
|
+
|
52
|
+
build_introspector!
|
53
|
+
build_atlas!
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
#
|
58
|
+
# Builds an introspector.
|
59
|
+
#
|
60
|
+
def build_introspector!
|
61
|
+
self.introspector = introspector_method.call(args_for_introspector)
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
#
|
66
|
+
# Builds an atlas.
|
67
|
+
#
|
68
|
+
def build_atlas!
|
69
|
+
self.atlas = atlas_method.call(introspector, args_for_atlas)
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
#
|
74
|
+
# Arguments to be passed to the introspector on creation.
|
75
|
+
#
|
76
|
+
# @see Brainstem::ApiDocs::Introspectors::AbstractIntrospector
|
77
|
+
# @see Brainstem::ApiDocs::Introspectors::RailsIntrospector
|
78
|
+
#
|
79
|
+
def args_for_introspector
|
80
|
+
@args_for_introspector ||= {}
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
#
|
85
|
+
# Allows passing args to the introspector if - for example - you are
|
86
|
+
# using a custom base controller class.
|
87
|
+
#
|
88
|
+
attr_writer :args_for_introspector
|
89
|
+
|
90
|
+
|
91
|
+
#
|
92
|
+
# Arguments to be passed to the atlas on creation.
|
93
|
+
#
|
94
|
+
# @see Brainstem::ApiDocs::Atlas
|
95
|
+
#
|
96
|
+
def args_for_atlas
|
97
|
+
@args_for_atlas ||= {}
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
#
|
102
|
+
# Allows passing args to the atlas if - for example - you are
|
103
|
+
# specifying match terms for the allowable controller set.
|
104
|
+
#
|
105
|
+
attr_writer :args_for_atlas
|
106
|
+
|
107
|
+
|
108
|
+
#
|
109
|
+
# A method which returns the introspector which extracts information
|
110
|
+
# about the Brainstem-powered API from the host application.
|
111
|
+
#
|
112
|
+
# Stored as a proc because it's impossible to inject an instantiated
|
113
|
+
# object and have it receive args from this class. This is less important
|
114
|
+
# in this specific circumstance but is kept for uniformity with
|
115
|
+
# +atlas_method+.
|
116
|
+
#
|
117
|
+
# @return [Proc] a proc of arity 1 which takes an options hash and
|
118
|
+
# returns an introspector
|
119
|
+
#
|
120
|
+
def introspector_method
|
121
|
+
@introspector_method ||=
|
122
|
+
Introspectors::RailsIntrospector.method(:with_loaded_environment)
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
#
|
127
|
+
# Allows setting the introspector_method if - for example - you are using
|
128
|
+
# Brainstem on a Sinatra app and you need to customize how lookups for
|
129
|
+
# presenters, controllers, and routes are performed.
|
130
|
+
#
|
131
|
+
attr_writer :introspector_method
|
132
|
+
|
133
|
+
|
134
|
+
#
|
135
|
+
# Holds a reference to the constructed introspector.
|
136
|
+
#
|
137
|
+
attr_accessor :introspector
|
138
|
+
|
139
|
+
|
140
|
+
#
|
141
|
+
# A proc of arity 1..2 which takes an introspector and optional options,
|
142
|
+
# and which returns a new Atlas.
|
143
|
+
#
|
144
|
+
# Passed an introspector.
|
145
|
+
#
|
146
|
+
# @return [Proc] a method to return an atlas
|
147
|
+
#
|
148
|
+
def atlas_method
|
149
|
+
@atlas_method ||= Atlas.method(:new)
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
#
|
154
|
+
# Allows setting the introspector_method if - for example - you are using
|
155
|
+
# an alternative formatter and the requisite information is not present
|
156
|
+
# in the +Endpoint+ objects.
|
157
|
+
#
|
158
|
+
attr_writer :atlas_method
|
159
|
+
|
160
|
+
|
161
|
+
#
|
162
|
+
# Holds a reference to the constructed atlas.
|
163
|
+
#
|
164
|
+
attr_accessor :atlas
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'brainstem/concerns/optional'
|
2
|
+
require 'brainstem/concerns/formattable'
|
3
|
+
require 'active_support/inflector'
|
4
|
+
require 'brainstem/api_docs/endpoint_collection'
|
5
|
+
require 'forwardable'
|
6
|
+
|
7
|
+
module Brainstem
|
8
|
+
module ApiDocs
|
9
|
+
class Controller
|
10
|
+
extend Forwardable
|
11
|
+
include Concerns::Optional
|
12
|
+
include Concerns::Formattable
|
13
|
+
|
14
|
+
|
15
|
+
def initialize(atlas, options = {})
|
16
|
+
self.atlas = atlas
|
17
|
+
self.endpoints = EndpointCollection.new(atlas)
|
18
|
+
super options
|
19
|
+
yield self if block_given?
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
attr_accessor :const,
|
24
|
+
:name,
|
25
|
+
:endpoints,
|
26
|
+
:filename_pattern,
|
27
|
+
:atlas
|
28
|
+
|
29
|
+
|
30
|
+
attr_writer :filename_pattern,
|
31
|
+
:filename_link_pattern
|
32
|
+
|
33
|
+
|
34
|
+
def valid_options
|
35
|
+
super | [
|
36
|
+
:const,
|
37
|
+
:name,
|
38
|
+
:formatters,
|
39
|
+
:filename_pattern,
|
40
|
+
:filename_link_pattern
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
#
|
46
|
+
# Adds an existing endpoint to its endpoint collection.
|
47
|
+
#
|
48
|
+
def add_endpoint(endpoint)
|
49
|
+
self.endpoints << endpoint
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def suggested_filename(format)
|
54
|
+
filename_pattern
|
55
|
+
.gsub('{{namespace}}', const.to_s.deconstantize.underscore)
|
56
|
+
.gsub('{{name}}', name.to_s.split("/").last)
|
57
|
+
.gsub('{{extension}}', extension)
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def suggested_filename_link(format)
|
62
|
+
filename_link_pattern
|
63
|
+
.gsub('{{name}}', name.to_s)
|
64
|
+
.gsub('{{extension}}', extension)
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def extension
|
69
|
+
@extension ||= Brainstem::ApiDocs.output_extension
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def filename_pattern
|
74
|
+
@filename_pattern ||= Brainstem::ApiDocs.controller_filename_pattern
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def filename_link_pattern
|
79
|
+
@filename_link_pattern ||= Brainstem::ApiDocs.controller_filename_link_pattern
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
delegate :configuration => :const
|
84
|
+
delegate :find_by_class => :atlas
|
85
|
+
|
86
|
+
|
87
|
+
def default_configuration
|
88
|
+
configuration[:_default]
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def nodoc?
|
93
|
+
default_configuration[:nodoc]
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def title
|
98
|
+
contextual_documentation(:title) || const.to_s.demodulize
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
def description
|
103
|
+
contextual_documentation(:description) || ""
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
#
|
108
|
+
# Returns a key if it exists and is documentable.
|
109
|
+
#
|
110
|
+
def contextual_documentation(key)
|
111
|
+
default_configuration.has_key?(key) &&
|
112
|
+
!default_configuration[key][:nodoc] &&
|
113
|
+
default_configuration[key][:info]
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
def valid_sorted_endpoints
|
118
|
+
endpoints.sorted_with_actions_in_controller(const)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|