forked from Apipie/apipie-rails
/
application.rb
251 lines (205 loc) · 6.76 KB
/
application.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
require 'apipie/static_dispatcher'
require 'yaml'
module Apipie
class Application
# we need engine just for serving static assets
class Engine < Rails::Engine
initializer "static assets" do |app|
app.middleware.use ::Apipie::StaticDispatcher, "#{root}/app/public", Apipie.configuration.doc_base_url
end
end
attr_accessor :last_api_args, :last_errors, :last_params, :last_description, :last_examples, :last_see, :last_formats
attr_reader :method_descriptions, :resource_descriptions
def initialize
super
@method_descriptions = Hash.new
@resource_descriptions = Hash.new
clear_last
end
# create new method api description
def define_method_description(controller, method_name)
# create new or get existing api
resource_name = get_resource_name(controller)
if ignored?(controller, method_name)
clear_last
return
end
key = [resource_name, method_name].join('#')
# add method description key to resource description
resource = define_resource_description(controller)
method_description = Apipie::MethodDescription.new(method_name, resource, self)
@method_descriptions[key] ||= method_description
@method_descriptions[key]
end
# create new resource api description
def define_resource_description(controller, &block)
if ignored?(controller)
clear_last
return
end
resource_name = get_resource_name(controller)
# puts "defining api for #{resource_name}"
@resource_descriptions[resource_name] ||=
Apipie::ResourceDescription.new(controller, resource_name, &block)
end
def add_method_description_args(method, path, desc)
@last_api_args << MethodDescription::Api.new(method, path, desc)
end
def add_example(example)
@last_examples << example.strip_heredoc
end
# check if there is some saved description
def apipie_provided?
true unless last_api_args.blank?
end
# get api for given method
#
# There are two ways how this method can be used:
# 1) Specify both parameters
# resource_name: controller class or string with resource name (plural)
# method_name: name of the method (string or symbol)
# 2) Specify only first parameter:
# resource_name: string containing both resource and method name joined
# with # (eg. "users#create")
def get_method_description(resource_name, method_name = nil)
resource_name = get_resource_name(resource_name)
key = method_name.blank? ? resource_name : [resource_name, method_name].join('#')
@method_descriptions[key]
end
alias :[] :get_method_description
# get api for given resource
def get_resource_description(resource_name)
resource_name = get_resource_name(resource_name)
@resource_descriptions[resource_name]
end
def remove_method_description(resource_name, method_name)
resource_name = get_resource_name(resource_name)
@method_descriptions.delete [resource_name, method_name].join('#')
end
def remove_resource_description(resource_name)
resource_name = get_resource_name(resource_name)
@resource_descriptions.delete resource_name
end
# Clear all apis in this application.
def clear
@resource_descriptions.clear
@method_descriptions.clear
end
# clear all saved data
def clear_last
@last_api_args = []
@last_errors = []
@last_params = []
@last_description = nil
@last_examples = []
@last_see = nil
@last_formats = []
end
# Return the current description, clearing it in the process.
def get_description
desc = @last_description
@last_description = nil
desc
end
def get_errors
errors = @last_errors.clone
@last_errors.clear
errors
end
def get_api_args
api_args = @last_api_args.clone
@last_api_args.clear
api_args
end
def get_see
see = @last_see
@last_see = nil
see
end
def get_formats
formats = @last_formats
@last_formats = nil
formats
end
def get_params
params = @last_params.clone
@last_params.clear
params
end
def get_examples
examples = @last_examples.clone
@last_examples.clear
examples
end
def recorded_examples
return @recorded_examples if @recorded_examples
tape_file = File.join(Rails.root,"doc","apipie_examples.yml")
if File.exists?(tape_file)
@recorded_examples = YAML.load_file(tape_file)
else
@recorded_examples = {}
end
@recorded_examples
end
def reload_examples
@recorded_examples = nil
end
def to_json(resource_name, method_name)
_resources = if resource_name.blank?
# take just resources which have some methods because
# we dont want to show eg ApplicationController as resource
resource_descriptions.inject({}) do |result, (k,v)|
result[k] = v.to_json unless v._methods.blank?
result
end
else
[@resource_descriptions[resource_name].to_json(method_name)]
end
{
:docs => {
:name => Apipie.configuration.app_name,
:info => Apipie.configuration.app_info,
:copyright => Apipie.configuration.copyright,
:doc_url => Apipie.full_url(""),
:api_url => Apipie.configuration.api_base_url,
:resources => _resources
}
}
end
def api_controllers_paths
Dir[Apipie.configuration.api_controllers_matcher]
end
def reload_documentation
reload_examples
api_controllers_paths.each do |f|
load_controller_from_file f
end
end
# Is there a reason to interpret the DSL for this run?
# with specific setting for some environment there is no reason the dsl
# should be interpreted (e.g. no validations and doc from cache)
def active_dsl?
Apipie.configuration.validate? || ! Apipie.configuration.use_cache? || Apipie.configuration.force_dsl?
end
private
def get_resource_name(klass)
if klass.class == String
klass
elsif klass.respond_to?(:controller_path)
klass.controller_path
end
elsif klass.respond_to?(:controller_name)
klass.controller_name
end
end
def load_controller_from_file(controller_file)
controller_class_name = controller_file.gsub(/\A.*\/app\/controllers\//,"").gsub(/\.\w*\Z/,"").camelize
controller_class_name.constantize
end
def ignored?(controller, method = nil)
ignored = Apipie.configuration.ignored
return true if ignored.include?(controller.name)
return true if ignored.include?("#{controller.name}##{method}")
end
end
end