jmoses_apipie-rails 0.0.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. data/.gitignore +11 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +4 -0
  4. data/APACHE-LICENSE-2.0 +202 -0
  5. data/CHANGELOG +55 -0
  6. data/Gemfile +3 -0
  7. data/MIT-LICENSE +20 -0
  8. data/NOTICE +4 -0
  9. data/README.rst +938 -0
  10. data/Rakefile +13 -0
  11. data/apipie-rails.gemspec +26 -0
  12. data/app/controllers/apipie/apipies_controller.rb +105 -0
  13. data/app/public/apipie/javascripts/apipie.js +6 -0
  14. data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +138 -0
  15. data/app/public/apipie/javascripts/bundled/bootstrap.js +1726 -0
  16. data/app/public/apipie/javascripts/bundled/jquery-1.7.2.js +9404 -0
  17. data/app/public/apipie/javascripts/bundled/prettify.js +28 -0
  18. data/app/public/apipie/stylesheets/application.css +20 -0
  19. data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +12 -0
  20. data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +689 -0
  21. data/app/public/apipie/stylesheets/bundled/prettify.css +30 -0
  22. data/app/views/apipie/apipies/_disqus.html.erb +11 -0
  23. data/app/views/apipie/apipies/_params.html.erb +29 -0
  24. data/app/views/apipie/apipies/_params_plain.html.erb +16 -0
  25. data/app/views/apipie/apipies/apipie_404.html.erb +12 -0
  26. data/app/views/apipie/apipies/getting_started.html.erb +4 -0
  27. data/app/views/apipie/apipies/index.html.erb +43 -0
  28. data/app/views/apipie/apipies/method.html.erb +71 -0
  29. data/app/views/apipie/apipies/plain.html.erb +70 -0
  30. data/app/views/apipie/apipies/resource.html.erb +98 -0
  31. data/app/views/apipie/apipies/static.html.erb +101 -0
  32. data/app/views/layouts/apipie/apipie.html.erb +26 -0
  33. data/lib/apipie-rails.rb +15 -0
  34. data/lib/apipie/apipie_module.rb +62 -0
  35. data/lib/apipie/application.rb +334 -0
  36. data/lib/apipie/client/generator.rb +135 -0
  37. data/lib/apipie/configuration.rb +128 -0
  38. data/lib/apipie/dsl_definition.rb +379 -0
  39. data/lib/apipie/error_description.rb +25 -0
  40. data/lib/apipie/errors.rb +38 -0
  41. data/lib/apipie/extractor.rb +151 -0
  42. data/lib/apipie/extractor/collector.rb +113 -0
  43. data/lib/apipie/extractor/recorder.rb +124 -0
  44. data/lib/apipie/extractor/writer.rb +367 -0
  45. data/lib/apipie/helpers.rb +52 -0
  46. data/lib/apipie/markup.rb +48 -0
  47. data/lib/apipie/method_description.rb +191 -0
  48. data/lib/apipie/param_description.rb +204 -0
  49. data/lib/apipie/railtie.rb +9 -0
  50. data/lib/apipie/resource_description.rb +102 -0
  51. data/lib/apipie/routing.rb +15 -0
  52. data/lib/apipie/see_description.rb +39 -0
  53. data/lib/apipie/static_dispatcher.rb +59 -0
  54. data/lib/apipie/validator.rb +310 -0
  55. data/lib/apipie/version.rb +3 -0
  56. data/lib/generators/apipie/install/README +6 -0
  57. data/lib/generators/apipie/install/install_generator.rb +25 -0
  58. data/lib/generators/apipie/install/templates/initializer.rb.erb +7 -0
  59. data/lib/tasks/apipie.rake +166 -0
  60. data/rel-eng/packages/.readme +3 -0
  61. data/rel-eng/packages/rubygem-apipie-rails +1 -0
  62. data/rel-eng/tito.props +5 -0
  63. data/spec/controllers/api/v1/architectures_controller_spec.rb +30 -0
  64. data/spec/controllers/api/v2/architectures_controller_spec.rb +12 -0
  65. data/spec/controllers/api/v2/nested/resources_controller_spec.rb +11 -0
  66. data/spec/controllers/apipies_controller_spec.rb +141 -0
  67. data/spec/controllers/concerns_controller_spec.rb +42 -0
  68. data/spec/controllers/users_controller_spec.rb +473 -0
  69. data/spec/dummy/Rakefile +7 -0
  70. data/spec/dummy/app/controllers/api/base_controller.rb +4 -0
  71. data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +42 -0
  72. data/spec/dummy/app/controllers/api/v1/base_controller.rb +11 -0
  73. data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +30 -0
  74. data/spec/dummy/app/controllers/api/v2/base_controller.rb +11 -0
  75. data/spec/dummy/app/controllers/api/v2/nested/architectures_controller.rb +30 -0
  76. data/spec/dummy/app/controllers/api/v2/nested/resources_controller.rb +33 -0
  77. data/spec/dummy/app/controllers/application_controller.rb +6 -0
  78. data/spec/dummy/app/controllers/concerns/sample_controller.rb +39 -0
  79. data/spec/dummy/app/controllers/concerns_controller.rb +8 -0
  80. data/spec/dummy/app/controllers/twitter_example_controller.rb +302 -0
  81. data/spec/dummy/app/controllers/users_controller.rb +251 -0
  82. data/spec/dummy/app/views/layouts/application.html.erb +21 -0
  83. data/spec/dummy/config.ru +4 -0
  84. data/spec/dummy/config/application.rb +45 -0
  85. data/spec/dummy/config/boot.rb +10 -0
  86. data/spec/dummy/config/database.yml +21 -0
  87. data/spec/dummy/config/environment.rb +8 -0
  88. data/spec/dummy/config/environments/development.rb +25 -0
  89. data/spec/dummy/config/environments/production.rb +49 -0
  90. data/spec/dummy/config/environments/test.rb +35 -0
  91. data/spec/dummy/config/initializers/apipie.rb +102 -0
  92. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  93. data/spec/dummy/config/initializers/inflections.rb +10 -0
  94. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  95. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  96. data/spec/dummy/config/initializers/session_store.rb +8 -0
  97. data/spec/dummy/config/locales/en.yml +5 -0
  98. data/spec/dummy/config/routes.rb +22 -0
  99. data/spec/dummy/db/.gitkeep +0 -0
  100. data/spec/dummy/doc/apipie_examples.yml +28 -0
  101. data/spec/dummy/public/404.html +26 -0
  102. data/spec/dummy/public/422.html +26 -0
  103. data/spec/dummy/public/500.html +26 -0
  104. data/spec/dummy/public/favicon.ico +0 -0
  105. data/spec/dummy/public/javascripts/application.js +2 -0
  106. data/spec/dummy/public/javascripts/controls.js +965 -0
  107. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  108. data/spec/dummy/public/javascripts/effects.js +1123 -0
  109. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  110. data/spec/dummy/public/javascripts/rails.js +202 -0
  111. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  112. data/spec/dummy/script/rails +6 -0
  113. data/spec/lib/application_spec.rb +38 -0
  114. data/spec/lib/method_description_spec.rb +30 -0
  115. data/spec/lib/param_description_spec.rb +174 -0
  116. data/spec/lib/param_group_spec.rb +45 -0
  117. data/spec/lib/resource_description_spec.rb +30 -0
  118. data/spec/lib/validator_spec.rb +46 -0
  119. data/spec/spec_helper.rb +32 -0
  120. metadata +337 -0
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>API documentation</title>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
6
+ <%= Apipie.include_stylesheets %>
7
+ <link type='text/css' rel='stylesheet' href='<%= Apipie.full_url("stylesheets/application.css")%>'/>
8
+ <!-- IE6-8 support of HTML5 elements -->
9
+ <!--[if lt IE 9]>
10
+ <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
11
+ <![endif]-->
12
+ </head>
13
+ <body>
14
+ <div class="container">
15
+ <div class="row">
16
+ <div id='container'>
17
+ <%= yield %>
18
+ <%= render 'disqus' if Apipie.configuration.use_disqus? %>
19
+ </div>
20
+ </div>
21
+ <hr>
22
+ <footer><%= yield :apipie_footer %></footer>
23
+ </div>
24
+ <%= Apipie.include_javascripts %>
25
+ </body>
26
+ </html>
@@ -0,0 +1,15 @@
1
+ require "apipie/routing"
2
+ require "apipie/markup"
3
+ require "apipie/apipie_module"
4
+ require "apipie/dsl_definition"
5
+ require "apipie/configuration"
6
+ require "apipie/method_description"
7
+ require "apipie/resource_description"
8
+ require "apipie/param_description"
9
+ require "apipie/errors"
10
+ require "apipie/error_description"
11
+ require "apipie/see_description"
12
+ require "apipie/validator"
13
+ require "apipie/railtie"
14
+ require 'apipie/extractor'
15
+ require "apipie/version"
@@ -0,0 +1,62 @@
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)
12
+ version ||= Apipie.configuration.default_version
13
+ app.to_json(version, resource_name, method_name)
14
+ end
15
+
16
+ # all calls delegated to Apipie::Application instance
17
+ def self.method_missing(method, *args, &block)
18
+ app.respond_to?(method) ? app.send(method, *args, &block) : super
19
+ end
20
+
21
+ def self.configure
22
+ yield configuration
23
+ end
24
+
25
+ def self.configuration
26
+ @configuration ||= Configuration.new
27
+ end
28
+
29
+ def self.debug(message)
30
+ puts message if Apipie.configuration.debug
31
+ end
32
+
33
+ # get application description for given or default version
34
+ def self.app_info(version = nil)
35
+ if app_info_version_valid? version
36
+ Apipie.markup_to_html(self.configuration.app_info[version])
37
+ elsif app_info_version_valid? Apipie.configuration.default_version
38
+ Apipie.markup_to_html(self.configuration.app_info[Apipie.configuration.default_version])
39
+ else
40
+ "Another API description"
41
+ end
42
+ end
43
+
44
+ def self.api_base_url(version = nil)
45
+ if api_base_url_version_valid? version
46
+ self.configuration.api_base_url[version]
47
+ elsif api_base_url_version_valid? Apipie.configuration.default_version
48
+ self.configuration.api_base_url[Apipie.configuration.default_version]
49
+ else
50
+ "/api"
51
+ end
52
+ end
53
+
54
+ def self.app_info_version_valid?(version)
55
+ version && self.configuration.app_info.has_key?(version)
56
+ end
57
+
58
+ def self.api_base_url_version_valid?(version)
59
+ version && self.configuration.api_base_url.has_key?(version)
60
+ end
61
+
62
+ end
@@ -0,0 +1,334 @@
1
+ require 'apipie/static_dispatcher'
2
+ require 'yaml'
3
+
4
+ module Apipie
5
+
6
+ class Application
7
+
8
+ # we need engine just for serving static assets
9
+ class Engine < Rails::Engine
10
+ initializer "static assets" do |app|
11
+ app.middleware.use ::Apipie::StaticDispatcher, "#{root}/app/public", Apipie.configuration.doc_base_url
12
+ end
13
+ end
14
+
15
+ attr_reader :resource_descriptions
16
+
17
+ def initialize
18
+ super
19
+ init_env
20
+ end
21
+
22
+ def available_versions
23
+ @resource_descriptions.keys.sort
24
+ end
25
+
26
+ def set_resource_id(controller, resource_id)
27
+ @controller_to_resource_id[controller] = resource_id
28
+ end
29
+
30
+ # create new method api description
31
+ def define_method_description(controller, method_name, dsl_data)
32
+ return if ignored?(controller, method_name)
33
+ ret_method_description = nil
34
+
35
+ versions = dsl_data[:api_versions] || []
36
+ versions = controller_versions(controller) if versions.empty?
37
+
38
+ versions.each do |version|
39
+ resource_name_with_version = "#{version}##{get_resource_name(controller)}"
40
+ resource_description = get_resource_description(resource_name_with_version)
41
+
42
+ if resource_description.nil?
43
+ resource_description = define_resource_description(controller, version)
44
+ end
45
+
46
+ method_description = Apipie::MethodDescription.new(method_name, resource_description, dsl_data)
47
+
48
+ # we create separate method description for each version in
49
+ # case the method belongs to more versions. We return just one
50
+ # becuase the version doesn't matter for the purpose it's used
51
+ # (to wrap the original version with validators)
52
+ ret_method_description ||= method_description
53
+ resource_description.add_method_description(method_description)
54
+ end
55
+
56
+ return ret_method_description
57
+ end
58
+
59
+ # create new resource api description
60
+ def define_resource_description(controller, version, dsl_data = nil)
61
+ return if ignored?(controller)
62
+
63
+ resource_name = get_resource_name(controller)
64
+ resource_description = @resource_descriptions[version][resource_name]
65
+ if resource_description
66
+ # we already defined the description somewhere (probably in
67
+ # some method. Updating just meta data from dsl
68
+ resource_description.update_from_dsl_data(dsl_data) if dsl_data
69
+ else
70
+ resource_description = Apipie::ResourceDescription.new(controller, resource_name, dsl_data, version)
71
+
72
+ Apipie.debug("@resource_descriptions[#{version}][#{resource_name}] = #{resource_description}")
73
+ @resource_descriptions[version][resource_name] ||= resource_description
74
+ end
75
+
76
+ return resource_description
77
+ end
78
+
79
+ # recursively searches what versions has the controller specified in
80
+ # resource_description? It's used to derivate the default value of
81
+ # versions for methods.
82
+ def controller_versions(controller)
83
+ ret = @controller_versions[controller]
84
+ return ret unless ret.empty?
85
+ if controller == ActionController::Base || controller.nil?
86
+ return [Apipie.configuration.default_version]
87
+ else
88
+ return controller_versions(controller.superclass)
89
+ end
90
+ end
91
+
92
+ def set_controller_versions(controller, versions)
93
+ @controller_versions[controller] = versions
94
+ end
95
+
96
+ def add_param_group(controller, name, &block)
97
+ key = "#{controller.name}##{name}"
98
+ @param_groups[key] = block
99
+ end
100
+
101
+ def get_param_group(controller, name)
102
+ key = "#{controller.name}##{name}"
103
+ if @param_groups.has_key?(key)
104
+ return @param_groups[key]
105
+ else
106
+ raise "param group #{key} not defined"
107
+ end
108
+ end
109
+
110
+ # get api for given method
111
+ #
112
+ # There are two ways how this method can be used:
113
+ # 1) Specify both parameters
114
+ # resource_name:
115
+ # controller class - UsersController
116
+ # string with resource name (plural) and version - "v1#users"
117
+ # method_name: name of the method (string or symbol)
118
+ #
119
+ # 2) Specify only first parameter:
120
+ # resource_name: string containing both resource and method name joined
121
+ # with '#' symbol.
122
+ # - "users#create" get default version
123
+ # - "v2#users#create" get specific version
124
+ def get_method_description(resource_name, method_name = nil)
125
+ if resource_name.is_a?(String)
126
+ crumbs = resource_name.split('#')
127
+ if method_name.nil?
128
+ method_name = crumbs.pop
129
+ end
130
+ resource_name = crumbs.join("#")
131
+ resource_description = get_resource_description(resource_name)
132
+ elsif resource_name.respond_to? :apipie_resource_descriptions
133
+ resource_description = get_resource_description(resource_name)
134
+ else
135
+ raise ArgumentError.new("Resource #{resource_name} does not exists.")
136
+ end
137
+ unless resource_description.nil?
138
+ resource_description.method_description(method_name.to_sym)
139
+ end
140
+ end
141
+ alias :[] :get_method_description
142
+
143
+ # options:
144
+ # => "users"
145
+ # => "v2#users"
146
+ # => V2::UsersController
147
+ def get_resource_description(resource, version = nil)
148
+ if resource.is_a?(String)
149
+ crumbs = resource.split('#')
150
+ if crumbs.size == 2
151
+ version = crumbs.first
152
+ end
153
+ version ||= Apipie.configuration.default_version
154
+ if @resource_descriptions.has_key?(version)
155
+ return @resource_descriptions[version][crumbs.last]
156
+ end
157
+ else
158
+ resource_name = get_resource_name(resource)
159
+ if version
160
+ resource_name = "#{version}##{resource_name}"
161
+ end
162
+
163
+ if resource_name.nil?
164
+ return nil
165
+ end
166
+ resource_description = get_resource_description(resource_name)
167
+ if resource_description && resource_description.controller == resource
168
+ return resource_description
169
+ end
170
+ end
171
+ end
172
+
173
+ # get all versions of resource description
174
+ def get_resource_descriptions(resource)
175
+ available_versions.map do |version|
176
+ get_resource_description(resource, version)
177
+ end.compact
178
+ end
179
+
180
+ # get all versions of method description
181
+ def get_method_descriptions(resource, method)
182
+ get_resource_descriptions(resource).map do |resource_description|
183
+ resource_description.method_description(method.to_sym)
184
+ end.compact
185
+ end
186
+
187
+ def remove_method_description(resource, versions, method_name)
188
+ versions.each do |version|
189
+ resource = get_resource_name(resource)
190
+ if resource_description = get_resource_description("#{version}##{resource}")
191
+ resource_description.remove_method_description(method_name)
192
+ end
193
+ end
194
+ end
195
+
196
+ # initialize variables for gathering dsl data
197
+ def init_env
198
+ @resource_descriptions = HashWithIndifferentAccess.new { |h, version| h[version] = {} }
199
+ @controller_to_resource_id = {}
200
+ @param_groups = {}
201
+
202
+ # what versions does the controller belong in (specified by resource_description)?
203
+ @controller_versions = Hash.new { |h, controller| h[controller] = [] }
204
+ end
205
+
206
+ def recorded_examples
207
+ return @recorded_examples if @recorded_examples
208
+ tape_file = File.join(Rails.root,"doc","apipie_examples.yml")
209
+ if File.exists?(tape_file)
210
+ #if SafeYAML gem is enabled, it will load examples as an array of Hash, instead of hash
211
+ if defined? SafeYAML
212
+ @recorded_examples = YAML.load_file(tape_file, :safe=>false)
213
+ else
214
+ @recorded_examples = YAML.load_file(tape_file)
215
+ end
216
+ else
217
+ @recorded_examples = {}
218
+ end
219
+ @recorded_examples
220
+ end
221
+
222
+ def reload_examples
223
+ @recorded_examples = nil
224
+ end
225
+
226
+ def to_json(version, resource_name, method_name)
227
+
228
+ _resources = if resource_name.blank?
229
+ # take just resources which have some methods because
230
+ # we dont want to show eg ApplicationController as resource
231
+ resource_descriptions[version].inject({}) do |result, (k,v)|
232
+ result[k] = v.to_json unless v._methods.blank?
233
+ result
234
+ end
235
+ else
236
+ [@resource_descriptions[version][resource_name].to_json(method_name)]
237
+ end
238
+
239
+ url_args = Apipie.configuration.version_in_url ? version : ''
240
+
241
+ {
242
+ :docs => {
243
+ :name => Apipie.configuration.app_name,
244
+ :info => Apipie.app_info(version),
245
+ :copyright => Apipie.configuration.copyright,
246
+ :doc_url => Apipie.full_url(url_args),
247
+ :api_url => Apipie.api_base_url(version),
248
+ :resources => _resources
249
+ }
250
+ }
251
+ end
252
+
253
+ def api_controllers_paths
254
+ Dir[Apipie.configuration.api_controllers_matcher]
255
+ end
256
+
257
+ def reload_documentation
258
+ rails_mark_classes_for_reload
259
+ init_env
260
+ reload_examples
261
+
262
+ api_controllers_paths.each do |f|
263
+ load_controller_from_file f
264
+ end
265
+ end
266
+
267
+ # Is there a reason to interpret the DSL for this run?
268
+ # with specific setting for some environment there is no reason the dsl
269
+ # should be interpreted (e.g. no validations and doc from cache)
270
+ def active_dsl?
271
+ Apipie.configuration.validate? || ! Apipie.configuration.use_cache? || Apipie.configuration.force_dsl?
272
+ end
273
+
274
+ def get_resource_name(klass)
275
+ if klass.class == String
276
+ klass
277
+ elsif @controller_to_resource_id.has_key?(klass)
278
+ @controller_to_resource_id[klass]
279
+ elsif Apipie.configuration.namespaced_resources? && klass.respond_to?(:controller_path)
280
+ return nil if klass == ActionController::Base
281
+ path = klass.controller_path
282
+ path.gsub(version_prefix(klass), "").gsub("/", "-")
283
+ elsif klass.respond_to?(:controller_name)
284
+ return nil if klass == ActionController::Base
285
+ klass.controller_name
286
+ else
287
+ raise "Apipie: Can not resolve resource #{klass} name."
288
+ end
289
+ end
290
+
291
+ private
292
+
293
+ def version_prefix(klass)
294
+ version = controller_versions(klass).first
295
+ base_url = get_base_url(version)
296
+ return "/" if base_url.nil?
297
+ base_url[1..-1] + "/"
298
+ end
299
+
300
+ def get_base_url(version)
301
+ Apipie.configuration.api_base_url[version]
302
+ end
303
+
304
+ def get_resource_version(resource_description)
305
+ if resource_description.respond_to? :_version
306
+ resource_description._version
307
+ else
308
+ Apipie.configuration.default_version
309
+ end
310
+ end
311
+
312
+ def load_controller_from_file(controller_file)
313
+ controller_class_name = controller_file.gsub(/\A.*\/app\/controllers\//,"").gsub(/\.\w*\Z/,"").camelize
314
+ controller_class_name.constantize
315
+ end
316
+
317
+ def ignored?(controller, method = nil)
318
+ ignored = Apipie.configuration.ignored
319
+ return true if ignored.include?(controller.name)
320
+ return true if ignored.include?("#{controller.name}##{method}")
321
+ end
322
+
323
+ # Since Rails 3.2, the classes are reloaded only on file change.
324
+ # We need to reload all the controller classes to rebuild the
325
+ # docs, therefore we just force to reload all the code. This
326
+ # happens only when reload_controllers is set to true and only
327
+ # when showing the documentation.
328
+ def rails_mark_classes_for_reload
329
+ ActiveSupport::DescendantsTracker.clear
330
+ ActiveSupport::Dependencies.clear
331
+ end
332
+
333
+ end
334
+ end
@@ -0,0 +1,135 @@
1
+ #!/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'rubygems'
4
+ require 'thor'
5
+ require 'thor/group'
6
+ require 'fileutils'
7
+ require 'active_support/inflector'
8
+ require 'apipie/client/base'
9
+
10
+ module Apipie
11
+ module Client
12
+
13
+ class Generator < Thor::Group
14
+ include Thor::Actions
15
+
16
+ # Define arguments and options
17
+ argument :name
18
+ argument :subject
19
+ argument :suffix
20
+ argument :version
21
+
22
+ attr_reader :doc, :resource, :resource_key
23
+
24
+ def initialize(*args)
25
+ super
26
+ @doc = Apipie.to_json(version)[:docs]
27
+ end
28
+
29
+ def self.source_root
30
+ File.expand_path("../template", __FILE__)
31
+ end
32
+
33
+ def self.destination_root(name, suffix)
34
+ File.join(FileUtils.pwd, "#{name}#{suffix}")
35
+ end
36
+
37
+ def self.start(client_name, subject = :all, suffix = '_client', version = nil)
38
+ name = client_name.parameterize.underscore
39
+ suffix = suffix.parameterize.underscore
40
+ super([name, subject, suffix, version], :destination_root => destination_root(name, suffix))
41
+ end
42
+
43
+ def all?
44
+ subject == :all
45
+ end
46
+
47
+ def generate_cli
48
+ full_name = "#{name}#{suffix}"
49
+ template("README.tt", "README")
50
+ template("Gemfile.tt", "Gemfile")
51
+ template("Rakefile.tt", "Rakefile")
52
+ template("a_name.gemspec.tt", "#{full_name}.gemspec")
53
+ template("lib/a_name.rb.tt", "lib/#{full_name}.rb")
54
+ template("lib/a_name/version.rb.tt", "lib/#{full_name}/version.rb")
55
+ create_file "lib/#{full_name}/documentation.json", JSON.dump(Apipie.to_json)
56
+ copy_file "lib/a_name/config.yml", "lib/#{full_name}/config.yml"
57
+ if all?
58
+ template("bin/bin.rb.tt", "bin/#{full_name}")
59
+ chmod("bin/#{full_name}", 0755)
60
+ end
61
+ doc[:resources].each do |key, resource|
62
+ @resource_key, @resource = key, resource
63
+ if all?
64
+ template("lib/a_name/commands/cli.rb.tt", "lib/#{full_name}/commands/#{resource_name}.thor")
65
+ end
66
+ template("lib/a_name/resources/resource.rb.tt", "lib/#{full_name}/resources/#{resource_name}.rb")
67
+ end
68
+ end
69
+
70
+ protected
71
+
72
+ def camelizer(string)
73
+ string = string.sub(/^[a-z\d]*/) { $&.capitalize }
74
+ string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$2.capitalize}" }
75
+ end
76
+
77
+ def class_base
78
+ @class_base ||= camelizer(name)
79
+ end
80
+
81
+ def class_suffix
82
+ @class_suffix ||= camelizer(suffix)
83
+ end
84
+
85
+ def plaintext(text)
86
+ text.gsub(/<.*?>/, '').gsub("\n", ' ').strip
87
+ end
88
+
89
+ # Resource related helper methods:
90
+
91
+ def resource_name
92
+ resource[:name].gsub(/\s/, "_").downcase.singularize
93
+ end
94
+
95
+ def api(method)
96
+ method[:apis].first
97
+ end
98
+
99
+ def params_in_path(method)
100
+ api(method)[:api_url].scan(/:([^\/]*)/).map(&:first)
101
+ end
102
+
103
+ def client_args(method)
104
+ params_in_path(method).dup
105
+ end
106
+
107
+ def substituted_url(method)
108
+ params_in_path(method).reduce(api(method)[:api_url]) { |u, p| u.sub(":#{p}", "\#{#{p}}") }
109
+ end
110
+
111
+ def transformation_hash(method)
112
+ method[:params].find_all { |p| p[:expected_type] == "hash" && !p[:params].nil? }.reduce({ }) do |h, p|
113
+ h.update(p[:name] => p[:params].map { |pp| pp[:name] })
114
+ end
115
+ end
116
+
117
+ def validation(method)
118
+ stringify = lambda do |object|
119
+ case object
120
+ when Hash
121
+ clone = object.dup
122
+ object.keys.each { |key| clone[key.to_s] = stringify[clone.delete(key)] }
123
+ clone
124
+ when Array
125
+ object.map { |value| stringify[value] }
126
+ else
127
+ object
128
+ end
129
+ end
130
+ Apipie::Client::Base.construct_validation_hash(stringify[method])
131
+ end
132
+ end
133
+
134
+ end
135
+ end