apipierails3 0.0.1

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.
Files changed (171) hide show
  1. checksums.yaml +17 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +27 -0
  5. data/APACHE-LICENSE-2.0 +202 -0
  6. data/CHANGELOG.md +469 -0
  7. data/Gemfile +1 -0
  8. data/Gemfile.rails32 +6 -0
  9. data/Gemfile.rails41 +6 -0
  10. data/Gemfile.rails42 +11 -0
  11. data/Gemfile.rails50 +6 -0
  12. data/Gemfile.rails51 +7 -0
  13. data/MIT-LICENSE +20 -0
  14. data/NOTICE +4 -0
  15. data/PROPOSAL_FOR_RESPONSE_DESCRIPTIONS.md +244 -0
  16. data/README.rst +1874 -0
  17. data/Rakefile +13 -0
  18. data/apipierails3.gemspec +27 -0
  19. data/app/controllers/apipie/apipies_controller.rb +199 -0
  20. data/app/helpers/apipie_helper.rb +10 -0
  21. data/app/public/apipie/javascripts/apipie.js +6 -0
  22. data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +138 -0
  23. data/app/public/apipie/javascripts/bundled/bootstrap.js +1726 -0
  24. data/app/public/apipie/javascripts/bundled/jquery.js +5 -0
  25. data/app/public/apipie/javascripts/bundled/prettify.js +28 -0
  26. data/app/public/apipie/stylesheets/application.css +7 -0
  27. data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +12 -0
  28. data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +689 -0
  29. data/app/public/apipie/stylesheets/bundled/prettify.css +30 -0
  30. data/app/views/apipie/apipies/_disqus.html.erb +13 -0
  31. data/app/views/apipie/apipies/_errors.html.erb +23 -0
  32. data/app/views/apipie/apipies/_headers.html.erb +26 -0
  33. data/app/views/apipie/apipies/_languages.erb +6 -0
  34. data/app/views/apipie/apipies/_metadata.erb +1 -0
  35. data/app/views/apipie/apipies/_method_detail.erb +61 -0
  36. data/app/views/apipie/apipies/_params.html.erb +42 -0
  37. data/app/views/apipie/apipies/_params_plain.html.erb +20 -0
  38. data/app/views/apipie/apipies/apipie_404.html.erb +17 -0
  39. data/app/views/apipie/apipies/apipie_checksum.json.erb +1 -0
  40. data/app/views/apipie/apipies/getting_started.html.erb +6 -0
  41. data/app/views/apipie/apipies/index.html.erb +56 -0
  42. data/app/views/apipie/apipies/method.html.erb +41 -0
  43. data/app/views/apipie/apipies/plain.html.erb +77 -0
  44. data/app/views/apipie/apipies/resource.html.erb +80 -0
  45. data/app/views/apipie/apipies/static.html.erb +103 -0
  46. data/app/views/layouts/apipie/apipie.html.erb +27 -0
  47. data/config/locales/de.yml +28 -0
  48. data/config/locales/en.yml +32 -0
  49. data/config/locales/es.yml +28 -0
  50. data/config/locales/fr.yml +31 -0
  51. data/config/locales/it.yml +31 -0
  52. data/config/locales/ja.yml +31 -0
  53. data/config/locales/pl.yml +28 -0
  54. data/config/locales/pt-BR.yml +28 -0
  55. data/config/locales/ru.yml +28 -0
  56. data/config/locales/tr.yml +28 -0
  57. data/config/locales/zh-CN.yml +28 -0
  58. data/config/locales/zh-TW.yml +28 -0
  59. data/images/screenshot-1.png +0 -0
  60. data/images/screenshot-2.png +0 -0
  61. data/lib/apipie/apipie_module.rb +83 -0
  62. data/lib/apipie/application.rb +462 -0
  63. data/lib/apipie/configuration.rb +186 -0
  64. data/lib/apipie/dsl_definition.rb +607 -0
  65. data/lib/apipie/error_description.rb +44 -0
  66. data/lib/apipie/errors.rb +86 -0
  67. data/lib/apipie/extractor.rb +177 -0
  68. data/lib/apipie/extractor/collector.rb +117 -0
  69. data/lib/apipie/extractor/recorder.rb +166 -0
  70. data/lib/apipie/extractor/writer.rb +454 -0
  71. data/lib/apipie/helpers.rb +73 -0
  72. data/lib/apipie/markup.rb +48 -0
  73. data/lib/apipie/method_description.rb +273 -0
  74. data/lib/apipie/middleware/checksum_in_headers.rb +35 -0
  75. data/lib/apipie/param_description.rb +280 -0
  76. data/lib/apipie/railtie.rb +9 -0
  77. data/lib/apipie/resource_description.rb +124 -0
  78. data/lib/apipie/response_description.rb +131 -0
  79. data/lib/apipie/response_description_adapter.rb +200 -0
  80. data/lib/apipie/routes_formatter.rb +33 -0
  81. data/lib/apipie/routing.rb +16 -0
  82. data/lib/apipie/rspec/response_validation_helper.rb +192 -0
  83. data/lib/apipie/see_description.rb +39 -0
  84. data/lib/apipie/static_dispatcher.rb +69 -0
  85. data/lib/apipie/swagger_generator.rb +707 -0
  86. data/lib/apipie/tag_list_description.rb +11 -0
  87. data/lib/apipie/validator.rb +526 -0
  88. data/lib/apipie/version.rb +3 -0
  89. data/lib/apipierails3.rb +25 -0
  90. data/lib/generators/apipie/install/README +6 -0
  91. data/lib/generators/apipie/install/install_generator.rb +25 -0
  92. data/lib/generators/apipie/install/templates/initializer.rb.erb +7 -0
  93. data/lib/generators/apipie/views_generator.rb +11 -0
  94. data/lib/tasks/apipie.rake +345 -0
  95. data/rel-eng/packages/.readme +3 -0
  96. data/rel-eng/packages/rubygem-apipie-rails +1 -0
  97. data/rel-eng/tito.props +5 -0
  98. data/spec/controllers/api/v1/architectures_controller_spec.rb +29 -0
  99. data/spec/controllers/api/v2/architectures_controller_spec.rb +12 -0
  100. data/spec/controllers/api/v2/nested/resources_controller_spec.rb +11 -0
  101. data/spec/controllers/apipies_controller_spec.rb +273 -0
  102. data/spec/controllers/concerns_controller_spec.rb +42 -0
  103. data/spec/controllers/extended_controller_spec.rb +11 -0
  104. data/spec/controllers/users_controller_spec.rb +740 -0
  105. data/spec/dummy/Rakefile +7 -0
  106. data/spec/dummy/app/controllers/api/base_controller.rb +4 -0
  107. data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +43 -0
  108. data/spec/dummy/app/controllers/api/v1/base_controller.rb +11 -0
  109. data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +30 -0
  110. data/spec/dummy/app/controllers/api/v2/base_controller.rb +11 -0
  111. data/spec/dummy/app/controllers/api/v2/nested/architectures_controller.rb +32 -0
  112. data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +33 -0
  113. data/spec/dummy/app/controllers/application_controller.rb +18 -0
  114. data/spec/dummy/app/controllers/concerns/extending_concern.rb +11 -0
  115. data/spec/dummy/app/controllers/concerns/sample_controller.rb +41 -0
  116. data/spec/dummy/app/controllers/concerns_controller.rb +8 -0
  117. data/spec/dummy/app/controllers/extended_controller.rb +14 -0
  118. data/spec/dummy/app/controllers/files_controller.rb +5 -0
  119. data/spec/dummy/app/controllers/overridden_concerns_controller.rb +31 -0
  120. data/spec/dummy/app/controllers/pets_controller.rb +408 -0
  121. data/spec/dummy/app/controllers/pets_using_auto_views_controller.rb +73 -0
  122. data/spec/dummy/app/controllers/pets_using_self_describing_classes_controller.rb +95 -0
  123. data/spec/dummy/app/controllers/tagged_cats_controller.rb +32 -0
  124. data/spec/dummy/app/controllers/tagged_dogs_controller.rb +15 -0
  125. data/spec/dummy/app/controllers/twitter_example_controller.rb +307 -0
  126. data/spec/dummy/app/controllers/users_controller.rb +297 -0
  127. data/spec/dummy/app/views/layouts/application.html.erb +21 -0
  128. data/spec/dummy/config.ru +4 -0
  129. data/spec/dummy/config/application.rb +49 -0
  130. data/spec/dummy/config/boot.rb +10 -0
  131. data/spec/dummy/config/database.yml +21 -0
  132. data/spec/dummy/config/environment.rb +8 -0
  133. data/spec/dummy/config/environments/development.rb +28 -0
  134. data/spec/dummy/config/environments/production.rb +52 -0
  135. data/spec/dummy/config/environments/test.rb +38 -0
  136. data/spec/dummy/config/initializers/apipie.rb +110 -0
  137. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  138. data/spec/dummy/config/initializers/inflections.rb +10 -0
  139. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  140. data/spec/dummy/config/initializers/secret_token.rb +8 -0
  141. data/spec/dummy/config/initializers/session_store.rb +8 -0
  142. data/spec/dummy/config/locales/en.yml +5 -0
  143. data/spec/dummy/config/routes.rb +51 -0
  144. data/spec/dummy/db/.gitkeep +0 -0
  145. data/spec/dummy/doc/apipie_examples.json +1 -0
  146. data/spec/dummy/doc/users/desc_from_file.md +1 -0
  147. data/spec/dummy/public/404.html +26 -0
  148. data/spec/dummy/public/422.html +26 -0
  149. data/spec/dummy/public/500.html +26 -0
  150. data/spec/dummy/public/favicon.ico +0 -0
  151. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  152. data/spec/dummy/script/rails +6 -0
  153. data/spec/lib/application_spec.rb +49 -0
  154. data/spec/lib/extractor/extractor_spec.rb +9 -0
  155. data/spec/lib/extractor/middleware_spec.rb +44 -0
  156. data/spec/lib/extractor/writer_spec.rb +110 -0
  157. data/spec/lib/file_handler_spec.rb +18 -0
  158. data/spec/lib/method_description_spec.rb +98 -0
  159. data/spec/lib/param_description_spec.rb +345 -0
  160. data/spec/lib/param_group_spec.rb +60 -0
  161. data/spec/lib/rake_spec.rb +71 -0
  162. data/spec/lib/resource_description_spec.rb +48 -0
  163. data/spec/lib/swagger/openapi_2_0_schema.json +1607 -0
  164. data/spec/lib/swagger/rake_swagger_spec.rb +139 -0
  165. data/spec/lib/swagger/response_validation_spec.rb +104 -0
  166. data/spec/lib/swagger/swagger_dsl_spec.rb +658 -0
  167. data/spec/lib/validator_spec.rb +113 -0
  168. data/spec/lib/validators/array_validator_spec.rb +85 -0
  169. data/spec/spec_helper.rb +109 -0
  170. data/spec/support/rake.rb +21 -0
  171. metadata +415 -0
@@ -0,0 +1,28 @@
1
+ 'zh-TW':
2
+ apipie:
3
+ resources: 資源
4
+ resource: 資源
5
+ description: 描述
6
+ no_docs_found: 沒有找到文檔
7
+ no_docs_found_descr: 沒有找到文檔。
8
+ follow_instructions_html: 點擊 %{href} 查看描述。
9
+ follow_instructions_href: 高級指導
10
+ oops: Oops!!
11
+ resource_not_found_html: 沒有找到資源 %{resource} 。
12
+ method_not_found_html: 沒有找到資源 %{resource} 的方法 %{method} 。
13
+ goto_homepage_html: 試圖訪問 %{href}
14
+ goto_homepage_href: "%{app_name} API 文檔主頁"
15
+ required: 必填
16
+ optional: 選填
17
+ nil_allowed: 允許空值
18
+ param_name: 參數名字
19
+ params: 參數
20
+ examples: 示例
21
+ metadata: 元數據
22
+ errors: 錯誤
23
+ supported_formats: 支持格式
24
+ enable_javascript_html: 瀏覽 %{comments_href}前請允許執行 JavaScript 。
25
+ comments_powered_by_disqus: 評論技術支持 %{disqus}
26
+ api_documentation: API 文檔
27
+ headers: 頭部
28
+ header_name: 頭部名字
Binary file
Binary file
@@ -0,0 +1,83 @@
1
+ require "apipie/helpers"
2
+ require "apipie/application"
3
+
4
+ module Apipie
5
+ extend Apipie::Helpers
6
+
7
+ def self.app
8
+ @application ||= Apipie::Application.new
9
+ end
10
+
11
+ def self.to_json(version = nil, resource_name = nil, method_name = nil, lang = nil)
12
+ version ||= Apipie.configuration.default_version
13
+ app.to_json(version, resource_name, method_name, lang)
14
+ end
15
+
16
+ def self.to_swagger_json(version = nil, resource_name = nil, method_name = nil, lang = nil, clear_warnings=true)
17
+ version ||= Apipie.configuration.default_version
18
+ app.to_swagger_json(version, resource_name, method_name, lang, clear_warnings)
19
+ end
20
+
21
+ def self.json_schema_for_method_response(controller_name, method_name, return_code, allow_nulls)
22
+ # note: this does not support versions (only the default version is queried)!
23
+ version ||= Apipie.configuration.default_version
24
+ app.json_schema_for_method_response(version, controller_name, method_name, return_code, allow_nulls)
25
+ end
26
+
27
+ def self.json_schema_for_self_describing_class(cls, allow_nulls=true)
28
+ app.json_schema_for_self_describing_class(cls, allow_nulls)
29
+ end
30
+
31
+
32
+ # all calls delegated to Apipie::Application instance
33
+ def self.method_missing(method, *args, &block)
34
+ app.respond_to?(method) ? app.send(method, *args, &block) : super
35
+ end
36
+
37
+ def self.configure
38
+ yield configuration
39
+ end
40
+
41
+ def self.configuration
42
+ @configuration ||= Configuration.new
43
+ end
44
+
45
+ def self.debug(message)
46
+ puts message if Apipie.configuration.debug
47
+ end
48
+
49
+ # get application description for given or default version
50
+ def self.app_info(version = nil, lang = nil)
51
+ info = if app_info_version_valid? version
52
+ translate(self.configuration.app_info[version], lang)
53
+ elsif app_info_version_valid? Apipie.configuration.default_version
54
+ translate(self.configuration.app_info[Apipie.configuration.default_version], lang)
55
+ else
56
+ "Another API description"
57
+ end
58
+
59
+ Apipie.markup_to_html info
60
+ end
61
+
62
+ def self.api_base_url(version = nil)
63
+ if api_base_url_version_valid? version
64
+ self.configuration.api_base_url[version]
65
+ elsif api_base_url_version_valid? Apipie.configuration.default_version
66
+ self.configuration.api_base_url[Apipie.configuration.default_version]
67
+ else
68
+ "/api"
69
+ end
70
+ end
71
+
72
+ def self.app_info_version_valid?(version)
73
+ version && self.configuration.app_info.has_key?(version)
74
+ end
75
+
76
+ def self.api_base_url_version_valid?(version)
77
+ version && self.configuration.api_base_url.has_key?(version)
78
+ end
79
+
80
+ def self.record(record)
81
+ Apipie::Extractor.start record
82
+ end
83
+ end
@@ -0,0 +1,462 @@
1
+ require 'apipie/static_dispatcher'
2
+ require 'apipie/routes_formatter'
3
+ require 'yaml'
4
+ require 'digest/sha1'
5
+ require 'json'
6
+
7
+ module Apipie
8
+
9
+ class Application
10
+ # we need engine just for serving static assets
11
+ class Engine < Rails::Engine
12
+ initializer "static assets", :before => :build_middleware_stack do |app|
13
+ app.middleware.use ::Apipie::StaticDispatcher, "#{root}/app/public"
14
+ end
15
+ end
16
+
17
+ attr_reader :resource_descriptions
18
+
19
+ def initialize
20
+ super
21
+ init_env
22
+ end
23
+
24
+ def available_versions
25
+ @resource_descriptions.keys.sort
26
+ end
27
+
28
+ def set_resource_id(controller, resource_id)
29
+ @controller_to_resource_id[controller] = resource_id
30
+ end
31
+
32
+ def rails_routes(route_set = nil)
33
+ if route_set.nil? && @rails_routes
34
+ return @rails_routes
35
+ end
36
+ route_set ||= Rails.application.routes
37
+ # ensure routes are loaded
38
+ Rails.application.reload_routes! unless Rails.application.routes.routes.any?
39
+
40
+ flatten_routes = []
41
+
42
+ route_set.routes.each do |route|
43
+ if route.app.respond_to?(:routes) && route.app.routes.is_a?(ActionDispatch::Routing::RouteSet)
44
+ # recursively go though the moutned engines
45
+ flatten_routes.concat(rails_routes(route.app.routes))
46
+ else
47
+ flatten_routes << route
48
+ end
49
+ end
50
+
51
+ @rails_routes = flatten_routes
52
+ end
53
+
54
+ # the app might be nested when using contraints, namespaces etc.
55
+ # this method does in depth search for the route controller
56
+ def route_app_controller(app, route, visited_apps = [])
57
+ if route.defaults[:controller]
58
+ controller_name = "#{route.defaults[:controller]}_controller".camelize
59
+ controller_name.safe_constantize
60
+ end
61
+ end
62
+
63
+ def routes_for_action(controller, method, args)
64
+ routes = rails_routes.select do |route|
65
+ controller == route_app_controller(route.app, route) &&
66
+ method.to_s == route.defaults[:action]
67
+ end
68
+
69
+ Apipie.configuration.routes_formatter.format_routes(routes, args)
70
+ end
71
+
72
+ # create new method api description
73
+ def define_method_description(controller, method_name, dsl_data)
74
+ return if ignored?(controller, method_name)
75
+ ret_method_description = nil
76
+
77
+ versions = dsl_data[:api_versions] || []
78
+ versions = controller_versions(controller) if versions.empty?
79
+
80
+ versions.each do |version|
81
+ resource_name_with_version = "#{version}##{get_resource_name(controller)}"
82
+ resource_description = get_resource_description(resource_name_with_version)
83
+
84
+ if resource_description.nil?
85
+ resource_description = define_resource_description(controller, version)
86
+ end
87
+
88
+ method_description = Apipie::MethodDescription.new(method_name, resource_description, dsl_data)
89
+
90
+ # we create separate method description for each version in
91
+ # case the method belongs to more versions. We return just one
92
+ # becuase the version doesn't matter for the purpose it's used
93
+ # (to wrap the original version with validators)
94
+ ret_method_description ||= method_description
95
+ resource_description.add_method_description(method_description)
96
+ end
97
+
98
+ return ret_method_description
99
+ end
100
+
101
+ # create new resource api description
102
+ def define_resource_description(controller, version, dsl_data = nil)
103
+ return if ignored?(controller)
104
+
105
+ resource_name = get_resource_name(controller)
106
+ resource_description = @resource_descriptions[version][resource_name]
107
+ if resource_description
108
+ # we already defined the description somewhere (probably in
109
+ # some method. Updating just meta data from dsl
110
+ resource_description.update_from_dsl_data(dsl_data) if dsl_data
111
+ else
112
+ resource_description = Apipie::ResourceDescription.new(controller, resource_name, dsl_data, version)
113
+
114
+ Apipie.debug("@resource_descriptions[#{version}][#{resource_name}] = #{resource_description}")
115
+ @resource_descriptions[version][resource_name] ||= resource_description
116
+ end
117
+
118
+ return resource_description
119
+ end
120
+
121
+ # recursively searches what versions has the controller specified in
122
+ # resource_description? It's used to derivate the default value of
123
+ # versions for methods.
124
+ def controller_versions(controller)
125
+ ret = @controller_versions[controller.to_s]
126
+ return ret unless ret.empty?
127
+ if controller == ActionController::Base || controller.nil?
128
+ return [Apipie.configuration.default_version]
129
+ else
130
+ return controller_versions(controller.to_s.constantize.superclass)
131
+ end
132
+ end
133
+
134
+ def set_controller_versions(controller, versions)
135
+ @controller_versions[controller.to_s] = versions
136
+ end
137
+
138
+ def add_param_group(controller, name, &block)
139
+ key = "#{controller.name}##{name}"
140
+ @param_groups[key] = block
141
+ end
142
+
143
+ def get_param_group(controller, name)
144
+ key = "#{controller.name}##{name}"
145
+ if @param_groups.has_key?(key)
146
+ return @param_groups[key]
147
+ else
148
+ raise "param group #{key} not defined"
149
+ end
150
+ end
151
+
152
+ # get api for given method
153
+ #
154
+ # There are two ways how this method can be used:
155
+ # 1) Specify both parameters
156
+ # resource_name:
157
+ # controller class - UsersController
158
+ # string with resource name (plural) and version - "v1#users"
159
+ # method_name: name of the method (string or symbol)
160
+ #
161
+ # 2) Specify only first parameter:
162
+ # resource_name: string containing both resource and method name joined
163
+ # with '#' symbol.
164
+ # - "users#create" get default version
165
+ # - "v2#users#create" get specific version
166
+ def get_method_description(resource_name, method_name = nil)
167
+ if resource_name.is_a?(String)
168
+ crumbs = resource_name.split('#')
169
+ if method_name.nil?
170
+ method_name = crumbs.pop
171
+ end
172
+ resource_name = crumbs.join("#")
173
+ resource_description = get_resource_description(resource_name)
174
+ elsif resource_name.respond_to? :apipie_resource_descriptions
175
+ resource_description = get_resource_description(resource_name)
176
+ else
177
+ raise ArgumentError.new("Resource #{resource_name} does not exists.")
178
+ end
179
+ unless resource_description.nil?
180
+ resource_description.method_description(method_name.to_sym)
181
+ end
182
+ end
183
+ alias :[] :get_method_description
184
+
185
+ # options:
186
+ # => "users"
187
+ # => "v2#users"
188
+ # => V2::UsersController
189
+ def get_resource_description(resource, version = nil)
190
+ if resource.is_a?(String)
191
+ crumbs = resource.split('#')
192
+ if crumbs.size == 2
193
+ version = crumbs.first
194
+ end
195
+ version ||= Apipie.configuration.default_version
196
+ if @resource_descriptions.has_key?(version)
197
+ return @resource_descriptions[version][crumbs.last]
198
+ end
199
+ else
200
+ resource_name = get_resource_name(resource)
201
+ if version
202
+ resource_name = "#{version}##{resource_name}"
203
+ end
204
+
205
+ if resource_name.nil?
206
+ return nil
207
+ end
208
+ resource_description = get_resource_description(resource_name)
209
+ if resource_description && resource_description.controller.to_s == resource.to_s
210
+ return resource_description
211
+ end
212
+ end
213
+ end
214
+
215
+ # get all versions of resource description
216
+ def get_resource_descriptions(resource)
217
+ available_versions.map do |version|
218
+ get_resource_description(resource, version)
219
+ end.compact
220
+ end
221
+
222
+ # get all versions of method description
223
+ def get_method_descriptions(resource, method)
224
+ get_resource_descriptions(resource).map do |resource_description|
225
+ resource_description.method_description(method.to_sym)
226
+ end.compact
227
+ end
228
+
229
+ def remove_method_description(resource, versions, method_name)
230
+ versions.each do |version|
231
+ resource = get_resource_name(resource)
232
+ if resource_description = get_resource_description("#{version}##{resource}")
233
+ resource_description.remove_method_description(method_name)
234
+ end
235
+ end
236
+ end
237
+
238
+ # initialize variables for gathering dsl data
239
+ def init_env
240
+ @resource_descriptions ||= HashWithIndifferentAccess.new { |h, version| h[version] = {} }
241
+ @controller_to_resource_id ||= {}
242
+ @param_groups ||= {}
243
+ @swagger_generator = Apipie::SwaggerGenerator.new(self)
244
+
245
+ # what versions does the controller belong in (specified by resource_description)?
246
+ @controller_versions ||= Hash.new { |h, controller| h[controller.to_s] = [] }
247
+ end
248
+
249
+ def recorded_examples
250
+ return @recorded_examples if @recorded_examples
251
+ @recorded_examples = Apipie::Extractor::Writer.load_recorded_examples
252
+ end
253
+
254
+ def reload_examples
255
+ @recorded_examples = nil
256
+ end
257
+
258
+ def json_schema_for_method_response(version, controller_name, method_name, return_code, allow_nulls)
259
+ method = @resource_descriptions[version][controller_name].method_description(method_name)
260
+ raise NoDocumentedMethod.new(controller_name, method_name) if method.nil?
261
+ @swagger_generator.json_schema_for_method_response(method, return_code, allow_nulls)
262
+ end
263
+
264
+ def json_schema_for_self_describing_class(cls, allow_nulls)
265
+ @swagger_generator.json_schema_for_self_describing_class(cls, allow_nulls)
266
+ end
267
+
268
+ def to_swagger_json(version, resource_name, method_name, lang, clear_warnings=false)
269
+ return unless valid_search_args?(version, resource_name, method_name)
270
+
271
+ # if resource_name is blank, take just resources which have some methods because
272
+ # we dont want to show eg ApplicationController as resource
273
+ # otherwise, take only the specified resource
274
+ _resources = resource_descriptions[version].inject({}) do |result, (k,v)|
275
+ if resource_name.blank?
276
+ result[k] = v unless v._methods.blank?
277
+ else
278
+ result[k] = v if k == resource_name
279
+ end
280
+ result
281
+ end
282
+
283
+ @swagger_generator.generate_from_resources(version,_resources, method_name, lang, clear_warnings)
284
+ end
285
+
286
+ def to_json(version, resource_name, method_name, lang)
287
+
288
+ return unless valid_search_args?(version, resource_name, method_name)
289
+
290
+ _resources = if resource_name.blank?
291
+ # take just resources which have some methods because
292
+ # we dont want to show eg ApplicationController as resource
293
+ resource_descriptions[version].inject({}) do |result, (k,v)|
294
+ result[k] = v.to_json(nil, lang) unless v._methods.blank?
295
+ result
296
+ end
297
+ else
298
+ [@resource_descriptions[version][resource_name].to_json(method_name, lang)]
299
+ end
300
+
301
+ url_args = Apipie.configuration.version_in_url ? version : ''
302
+
303
+ {
304
+ :docs => {
305
+ :name => Apipie.configuration.app_name,
306
+ :info => Apipie.app_info(version, lang),
307
+ :copyright => Apipie.configuration.copyright,
308
+ :doc_url => Apipie.full_url(url_args),
309
+ :api_url => Apipie.api_base_url(version),
310
+ :resources => _resources
311
+ }
312
+ }
313
+ end
314
+
315
+ def api_controllers_paths
316
+ Dir.glob(Apipie.configuration.api_controllers_matcher)
317
+ end
318
+
319
+ def reload_documentation
320
+ # don't load translated strings, we'll translate them later
321
+ old_locale = locale
322
+ locale = Apipie.configuration.default_locale
323
+
324
+ rails_mark_classes_for_reload
325
+
326
+ api_controllers_paths.each do |f|
327
+ load_controller_from_file f
328
+ end
329
+ @checksum = nil if Apipie.configuration.update_checksum
330
+
331
+ locale = old_locale
332
+ end
333
+
334
+ def load_documentation
335
+ if !@documentation_loaded || Apipie.configuration.reload_controllers?
336
+ Apipie.reload_documentation
337
+ @documentation_loaded = true
338
+ end
339
+ end
340
+
341
+ def compute_checksum
342
+ if Apipie.configuration.use_cache?
343
+ file_base = File.join(Apipie.configuration.cache_dir, Apipie.configuration.doc_base_url)
344
+ all_docs = {}
345
+ Dir.glob(file_base + '/*.json').sort.each do |f|
346
+ all_docs[File.basename(f, '.json')] = JSON.parse(File.read(f))
347
+ end
348
+ else
349
+ load_documentation if available_versions == []
350
+ all_docs = Apipie.available_versions.inject({}) do |all, version|
351
+ all.update(version => Apipie.to_json(version))
352
+ end
353
+ end
354
+ Digest::SHA1.hexdigest(JSON.dump(all_docs))
355
+ end
356
+
357
+ def checksum
358
+ @checksum ||= compute_checksum
359
+ end
360
+
361
+ # Is there a reason to interpret the DSL for this run?
362
+ # with specific setting for some environment there is no reason the dsl
363
+ # should be interpreted (e.g. no validations and doc from cache)
364
+ def active_dsl?
365
+ Apipie.configuration.validate? || ! Apipie.configuration.use_cache? || Apipie.configuration.force_dsl?
366
+ end
367
+
368
+ def get_resource_name(klass)
369
+ if klass.class == String
370
+ klass
371
+ elsif @controller_to_resource_id.has_key?(klass)
372
+ @controller_to_resource_id[klass]
373
+ elsif Apipie.configuration.namespaced_resources? && klass.respond_to?(:controller_path)
374
+ return nil if klass == ActionController::Base
375
+ path = klass.controller_path
376
+ path.gsub(version_prefix(klass), "").gsub("/", "-")
377
+ elsif klass.respond_to?(:controller_name)
378
+ return nil if klass == ActionController::Base
379
+ klass.controller_name
380
+ else
381
+ raise "Apipie: Can not resolve resource #{klass} name."
382
+ end
383
+ end
384
+
385
+ def locale
386
+ Apipie.configuration.locale.call(nil) if Apipie.configuration.locale
387
+ end
388
+
389
+ def locale=(locale)
390
+ Apipie.configuration.locale.call(locale) if Apipie.configuration.locale
391
+ end
392
+
393
+ def translate(str, locale)
394
+ if Apipie.configuration.translate
395
+ Apipie.configuration.translate.call(str, locale)
396
+ else
397
+ str
398
+ end
399
+ end
400
+
401
+ private
402
+
403
+ # Make sure that the version/resource_name/method_name are valid combination
404
+ # resource_name and method_name can be nil
405
+ def valid_search_args?(version, resource_name, method_name)
406
+ return false unless self.resource_descriptions.has_key?(version)
407
+ if resource_name
408
+ return false unless self.resource_descriptions[version].has_key?(resource_name)
409
+ if method_name
410
+ resource_description = self.resource_descriptions[version][resource_name]
411
+ return false unless resource_description.valid_method_name?(method_name)
412
+ end
413
+ end
414
+ return true
415
+ end
416
+
417
+ def version_prefix(klass)
418
+ version = controller_versions(klass.to_s).first
419
+ base_url = get_base_url(version)
420
+ return "/" if base_url.blank?
421
+ base_url[1..-1] + "/"
422
+ end
423
+
424
+ def get_base_url(version)
425
+ Apipie.configuration.api_base_url[version]
426
+ end
427
+
428
+ def get_resource_version(resource_description)
429
+ if resource_description.respond_to? :_version
430
+ resource_description._version
431
+ else
432
+ Apipie.configuration.default_version
433
+ end
434
+ end
435
+
436
+ def load_controller_from_file(controller_file)
437
+ controller_class_name = controller_file.gsub(/\A.*\/app\/controllers\//,"").gsub(/\.\w*\Z/,"").camelize
438
+ controller_class_name.constantize
439
+ end
440
+
441
+ def ignored?(controller, method = nil)
442
+ ignored = Apipie.configuration.ignored
443
+ return true if ignored.include?(controller.name)
444
+ return true if ignored.include?("#{controller.name}##{method}")
445
+ end
446
+
447
+ # Since Rails 3.2, the classes are reloaded only on file change.
448
+ # We need to reload all the controller classes to rebuild the
449
+ # docs, therefore we just force to reload all the code. This
450
+ # happens only when reload_controllers is set to true and only
451
+ # when showing the documentation.
452
+ #
453
+ # If cache_classes is set to false, it does nothing,
454
+ # as this would break loading of the controllers.
455
+ def rails_mark_classes_for_reload
456
+ init_env
457
+ reload_examples
458
+ end
459
+
460
+
461
+ end
462
+ end