apipie-rails 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/.autotest +3 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +2 -0
  4. data/.rvmrc +1 -0
  5. data/.travis.yml +5 -0
  6. data/APACHE-LICENSE-2.0 +202 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +115 -0
  9. data/MIT-LICENSE +20 -0
  10. data/NOTICE +4 -0
  11. data/README.rdoc +365 -0
  12. data/Rakefile +13 -0
  13. data/apipie-rails.gemspec +27 -0
  14. data/app/controllers/apipie/apipies_controller.rb +60 -0
  15. data/app/public/apipie/javascripts/apipie.js +6 -0
  16. data/app/public/apipie/javascripts/bundled/bootstrap-collapse.js +138 -0
  17. data/app/public/apipie/javascripts/bundled/bootstrap.js +1726 -0
  18. data/app/public/apipie/javascripts/bundled/jquery-1.7.2.js +9404 -0
  19. data/app/public/apipie/javascripts/bundled/prettify.js +28 -0
  20. data/app/public/apipie/stylesheets/application.css +7 -0
  21. data/app/public/apipie/stylesheets/bundled/bootstrap-responsive.min.css +12 -0
  22. data/app/public/apipie/stylesheets/bundled/bootstrap.min.css +689 -0
  23. data/app/public/apipie/stylesheets/bundled/prettify.css +30 -0
  24. data/app/views/apipie/apipies/_params.html.erb +22 -0
  25. data/app/views/apipie/apipies/_params_plain.html.erb +16 -0
  26. data/app/views/apipie/apipies/index.html.erb +36 -0
  27. data/app/views/apipie/apipies/method.html.erb +63 -0
  28. data/app/views/apipie/apipies/plain.html.erb +70 -0
  29. data/app/views/apipie/apipies/resource.html.erb +82 -0
  30. data/app/views/apipie/apipies/static.html.erb +101 -0
  31. data/app/views/layouts/apipie/apipie.html.erb +37 -0
  32. data/lib/apipie-rails.rb +12 -0
  33. data/lib/apipie/apipie_module.rb +105 -0
  34. data/lib/apipie/application.rb +225 -0
  35. data/lib/apipie/client/generator.rb +105 -0
  36. data/lib/apipie/client/template/Gemfile.tt +5 -0
  37. data/lib/apipie/client/template/README.tt +3 -0
  38. data/lib/apipie/client/template/base.rb.tt +33 -0
  39. data/lib/apipie/client/template/bin.rb.tt +110 -0
  40. data/lib/apipie/client/template/cli.rb.tt +25 -0
  41. data/lib/apipie/client/template/cli_command.rb.tt +129 -0
  42. data/lib/apipie/client/template/client.rb.tt +10 -0
  43. data/lib/apipie/client/template/resource.rb.tt +17 -0
  44. data/lib/apipie/dsl_definition.rb +139 -0
  45. data/lib/apipie/error_description.rb +21 -0
  46. data/lib/apipie/extractor.rb +143 -0
  47. data/lib/apipie/extractor/collector.rb +113 -0
  48. data/lib/apipie/extractor/recorder.rb +122 -0
  49. data/lib/apipie/extractor/writer.rb +356 -0
  50. data/lib/apipie/helpers.rb +24 -0
  51. data/lib/apipie/markup.rb +45 -0
  52. data/lib/apipie/method_description.rb +150 -0
  53. data/lib/apipie/param_description.rb +87 -0
  54. data/lib/apipie/railtie.rb +9 -0
  55. data/lib/apipie/resource_description.rb +83 -0
  56. data/lib/apipie/routing.rb +13 -0
  57. data/lib/apipie/static_dispatcher.rb +60 -0
  58. data/lib/apipie/validator.rb +292 -0
  59. data/lib/apipie/version.rb +3 -0
  60. data/lib/tasks/apipie.rake +156 -0
  61. data/rel-eng/packages/.readme +3 -0
  62. data/rel-eng/tito.props +5 -0
  63. data/rubygem-apipie-rails.spec +72 -0
  64. data/spec/controllers/apipies_controller_spec.rb +132 -0
  65. data/spec/controllers/users_controller_spec.rb +390 -0
  66. data/spec/dummy/Rakefile +7 -0
  67. data/spec/dummy/app/controllers/application_controller.rb +6 -0
  68. data/spec/dummy/app/controllers/twitter_example_controller.rb +302 -0
  69. data/spec/dummy/app/controllers/users_controller.rb +223 -0
  70. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  71. data/spec/dummy/config.ru +4 -0
  72. data/spec/dummy/config/application.rb +45 -0
  73. data/spec/dummy/config/boot.rb +10 -0
  74. data/spec/dummy/config/database.yml +21 -0
  75. data/spec/dummy/config/environment.rb +8 -0
  76. data/spec/dummy/config/environments/development.rb +25 -0
  77. data/spec/dummy/config/environments/production.rb +49 -0
  78. data/spec/dummy/config/environments/test.rb +35 -0
  79. data/spec/dummy/config/initializers/apipie.rb +64 -0
  80. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  81. data/spec/dummy/config/initializers/inflections.rb +10 -0
  82. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  83. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  84. data/spec/dummy/config/initializers/session_store.rb +8 -0
  85. data/spec/dummy/config/locales/en.yml +5 -0
  86. data/spec/dummy/config/routes.rb +21 -0
  87. data/spec/dummy/doc/apipie_examples.yml +28 -0
  88. data/spec/dummy/public/404.html +26 -0
  89. data/spec/dummy/public/422.html +26 -0
  90. data/spec/dummy/public/500.html +26 -0
  91. data/spec/dummy/public/favicon.ico +0 -0
  92. data/spec/dummy/public/javascripts/application.js +2 -0
  93. data/spec/dummy/public/javascripts/controls.js +965 -0
  94. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  95. data/spec/dummy/public/javascripts/effects.js +1123 -0
  96. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  97. data/spec/dummy/public/javascripts/rails.js +202 -0
  98. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  99. data/spec/dummy/script/rails +6 -0
  100. data/spec/spec_helper.rb +32 -0
  101. metadata +312 -0
@@ -0,0 +1,12 @@
1
+ require "apipie/routing"
2
+ require "apipie/markup"
3
+ require "apipie/apipie_module"
4
+ require "apipie/method_description"
5
+ require "apipie/resource_description"
6
+ require "apipie/param_description"
7
+ require "apipie/error_description"
8
+ require "apipie/validator"
9
+ require "apipie/dsl_definition"
10
+ require "apipie/railtie"
11
+ require 'apipie/extractor'
12
+ require "apipie/version"
@@ -0,0 +1,105 @@
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(resource_name = nil, method_name = nil)
12
+ app.to_json(resource_name, method_name)
13
+ end
14
+
15
+ # all calls delegated to Apipie::Application instance
16
+ def self.method_missing(method, *args, &block)
17
+ app.respond_to?(method) ? app.send(method, *args, &block) : super
18
+ end
19
+
20
+ def self.configure
21
+ yield configuration
22
+ end
23
+
24
+ def self.configuration
25
+ @configuration ||= Configuration.new
26
+ end
27
+
28
+ class Configuration
29
+ attr_accessor :app_name, :app_info, :copyright, :markup,
30
+ :validate, :api_base_url, :doc_base_url
31
+
32
+ alias_method :validate?, :validate
33
+
34
+ # matcher to be used in Dir.glob to find controllers to be reloaded e.g.
35
+ #
36
+ # "#{Rails.root}/app/controllers/api/*.rb"
37
+ attr_accessor :api_controllers_matcher
38
+
39
+ # set to true if you want to reload the controllers at each refresh of the
40
+ # documentation. It requires +:api_controllers_matcher+ to be set to work
41
+ # properly.
42
+ attr_writer :reload_controllers
43
+
44
+ def reload_controllers?
45
+ @reload_controllers = Rails.env.development? unless defined? @reload_controllers
46
+ return @reload_controllers && @api_controllers_matcher
47
+ end
48
+
49
+ # set to true if you want to use pregenerated documentation cache and avoid
50
+ # generating the documentation on runtime (usefull for production
51
+ # environment).
52
+ # You can generate the cache by running
53
+ #
54
+ # rake apipie:cache
55
+ attr_accessor :use_cache
56
+ alias_method :use_cache?, :use_cache
57
+
58
+ attr_writer :cache_dir
59
+ def cache_dir
60
+ @cache_dir ||= File.join(Rails.root, "public", "apipie-cache")
61
+ end
62
+
63
+ # if there is not obvious reason why the DSL should be turned on (no
64
+ # validations, cache turned on etc.), it's disabled to avoid unneeded
65
+ # allocation. It you need the DSL for other reasons, you can force the
66
+ # activation.
67
+ attr_writer :force_dsl
68
+ def force_dsl?
69
+ @force_dsl
70
+ end
71
+
72
+ # array of controller names (strings) (might include actions as well)
73
+ # to be ignored # when extracting description form calls.
74
+ # e.g. %w[Api::CommentsController Api::PostsController#post]
75
+ attr_writer :ignored_by_recorder
76
+ def ignored_by_recorder
77
+ @ignored_by_recorder ||= []
78
+ @ignored_by_recorder.map(&:to_s)
79
+ end
80
+
81
+ # comment to put before docs that was generated automatically. It's used to
82
+ # determine if the description should be overwritten next recording.
83
+ # If you want to keep the documentation (prevent from overriding), remove
84
+ # the line above the docs.
85
+ attr_writer :generated_doc_disclaimer
86
+ def generated_doc_disclaimer
87
+ @generated_doc_disclaimer ||= "# DOC GENERATED AUTOMATICALLY: REMOVE THIS LINE TO PREVENT REGENARATING NEXT TIME"
88
+ end
89
+
90
+ def app_info
91
+ Apipie.markup_to_html(@app_info)
92
+ end
93
+
94
+ def initialize
95
+ @markup = Apipie::Markup::RDoc.new
96
+ @app_name = "Another API"
97
+ @app_info = "Another API description"
98
+ @copyright = nil
99
+ @validate = true
100
+ @api_base_url = ""
101
+ @doc_base_url = "/apipie"
102
+ end
103
+ end
104
+
105
+ end
@@ -0,0 +1,225 @@
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_accessor :last_api_args, :last_errors, :last_params, :last_description, :last_examples, :last_see
16
+ attr_reader :method_descriptions, :resource_descriptions
17
+
18
+ def initialize
19
+ super
20
+ @method_descriptions = Hash.new
21
+ @resource_descriptions = Hash.new
22
+ clear_last
23
+ end
24
+
25
+ # create new method api description
26
+ def define_method_description(controller, method_name)
27
+ # create new or get existing api
28
+ resource_name = get_resource_name(controller)
29
+ key = [resource_name, method_name].join('#')
30
+ # add method description key to resource description
31
+ resource = define_resource_description(controller)
32
+
33
+ method_description = Apipie::MethodDescription.new(method_name, resource, self)
34
+
35
+ @method_descriptions[key] ||= method_description
36
+
37
+ @method_descriptions[key]
38
+ end
39
+
40
+ # create new resource api description
41
+ def define_resource_description(controller, &block)
42
+ resource_name = get_resource_name(controller)
43
+
44
+ # puts "defining api for #{resource_name}"
45
+
46
+ @resource_descriptions[resource_name] ||=
47
+ Apipie::ResourceDescription.new(controller, resource_name, &block)
48
+ end
49
+
50
+ def add_method_description_args(method, path, desc)
51
+ @last_api_args << MethodDescription::Api.new(method, path, desc)
52
+ end
53
+
54
+ def add_example(example)
55
+ @last_examples << example.strip_heredoc
56
+ end
57
+
58
+ # check if there is some saved description
59
+ def apipie_provided?
60
+ true unless last_api_args.blank?
61
+ end
62
+
63
+ # get api for given method
64
+ #
65
+ # There are two ways how this method can be used:
66
+ # 1) Specify both parameters
67
+ # resource_name: controller class or string with resource name (plural)
68
+ # method_name: name of the method (string or symbol)
69
+ # 2) Specify only first parameter:
70
+ # resource_name: string containing both resource and method name joined
71
+ # with # (eg. "users#create")
72
+ def get_method_description(resource_name, method_name = nil)
73
+ resource_name = get_resource_name(resource_name)
74
+ key = method_name.blank? ? resource_name : [resource_name, method_name].join('#')
75
+ @method_descriptions[key]
76
+ end
77
+ alias :[] :get_method_description
78
+
79
+ # get api for given resource
80
+ def get_resource_description(resource_name)
81
+ resource_name = get_resource_name(resource_name)
82
+
83
+ @resource_descriptions[resource_name]
84
+ end
85
+
86
+ def remove_method_description(resource_name, method_name)
87
+ resource_name = get_resource_name(resource_name)
88
+
89
+ @method_descriptions.delete [resource_name, method_name].join('#')
90
+ end
91
+
92
+ def remove_resource_description(resource_name)
93
+ resource_name = get_resource_name(resource_name)
94
+
95
+ @resource_descriptions.delete resource_name
96
+ end
97
+
98
+ # Clear all apis in this application.
99
+ def clear
100
+ @resource_descriptions.clear
101
+ @method_descriptions.clear
102
+ end
103
+
104
+ # clear all saved data
105
+ def clear_last
106
+ @last_api_args = []
107
+ @last_errors = []
108
+ @last_params = []
109
+ @last_description = nil
110
+ @last_examples = []
111
+ @last_see = nil
112
+ end
113
+
114
+ # Return the current description, clearing it in the process.
115
+ def get_description
116
+ desc = @last_description
117
+ @last_description = nil
118
+ desc
119
+ end
120
+
121
+ def get_errors
122
+ errors = @last_errors.clone
123
+ @last_errors.clear
124
+ errors
125
+ end
126
+
127
+ def get_api_args
128
+ api_args = @last_api_args.clone
129
+ @last_api_args.clear
130
+ api_args
131
+ end
132
+
133
+ def get_see
134
+ see = @last_see
135
+ @last_see = nil
136
+ see
137
+ end
138
+
139
+ def get_params
140
+ params = @last_params.clone
141
+ @last_params.clear
142
+ params
143
+ end
144
+
145
+ def get_examples
146
+ examples = @last_examples.clone
147
+ @last_examples.clear
148
+ examples
149
+ end
150
+
151
+ def recorded_examples
152
+ return @recorded_examples if @recorded_examples
153
+ tape_file = File.join(Rails.root,"doc","apipie_examples.yml")
154
+ if File.exists?(tape_file)
155
+ @recorded_examples = YAML.load_file(tape_file)
156
+ else
157
+ @recorded_examples = {}
158
+ end
159
+ @recorded_examples
160
+ end
161
+
162
+ def reload_examples
163
+ @recorded_examples = nil
164
+ end
165
+
166
+ def to_json(resource_name, method_name)
167
+
168
+ _resources = if resource_name.blank?
169
+ # take just resources which have some methods because
170
+ # we dont want to show eg ApplicationController as resource
171
+ resource_descriptions.inject({}) do |result, (k,v)|
172
+ result[k] = v.to_json unless v._methods.blank?
173
+ result
174
+ end
175
+ else
176
+ [@resource_descriptions[resource_name].to_json(method_name)]
177
+ end
178
+
179
+ {
180
+ :docs => {
181
+ :name => Apipie.configuration.app_name,
182
+ :info => Apipie.configuration.app_info,
183
+ :copyright => Apipie.configuration.copyright,
184
+ :doc_url => Apipie.full_url(""),
185
+ :api_url => Apipie.configuration.api_base_url,
186
+ :resources => _resources
187
+ }
188
+ }
189
+ end
190
+
191
+ def api_controllers_paths
192
+ Dir[Apipie.configuration.api_controllers_matcher]
193
+ end
194
+
195
+ def reload_documentation
196
+ reload_examples
197
+ api_controllers_paths.each do |f|
198
+ load_controller_from_file f
199
+ end
200
+ end
201
+
202
+ # Is there a reason to interpret the DSL for this run?
203
+ # with specific setting for some environment there is no reason the dsl
204
+ # should be interpreted (e.g. no validations and doc from cache)
205
+ def active_dsl?
206
+ Apipie.configuration.validate? || ! Apipie.configuration.use_cache? || Apipie.configuration.force_dsl?
207
+ end
208
+
209
+ private
210
+
211
+ def get_resource_name(klass)
212
+ if klass.class == String
213
+ klass
214
+ elsif klass.respond_to?(:controller_name)
215
+ klass.controller_name
216
+ end
217
+ end
218
+
219
+ def load_controller_from_file(controller_file)
220
+ controller_class_name = controller_file.gsub(/\A.*\/app\/controllers\//,"").gsub(/\.\w*\Z/,"").camelize
221
+ controller_class_name.constantize
222
+ end
223
+
224
+ end
225
+ end
@@ -0,0 +1,105 @@
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
+
9
+ module Apipie
10
+ module Client
11
+
12
+ class Generator < Thor::Group
13
+ include Thor::Actions
14
+
15
+ # Define arguments and options
16
+ argument :name
17
+
18
+ attr_reader :doc, :resource
19
+
20
+ def initialize(*args)
21
+ super
22
+ @doc = Apipie.to_json()[:docs]
23
+ end
24
+
25
+ def self.source_root
26
+ File.expand_path("../template", __FILE__)
27
+ end
28
+
29
+ def self.destination_root(name)
30
+ File.join(FileUtils.pwd, "#{name}_client")
31
+ end
32
+
33
+ def self.start(client_name)
34
+ name = client_name.parameterize.underscore
35
+ super([name], :destination_root => destination_root(name))
36
+ end
37
+
38
+ def generate_cli
39
+ template("README.tt", "README")
40
+ template("Gemfile.tt", "Gemfile")
41
+ template("bin.rb.tt", "bin/#{name}_client")
42
+ chmod("bin/#{name}_client", 0755)
43
+ template("client.rb.tt", "lib/#{name}_client.rb")
44
+ template("base.rb.tt", "lib/#{name}_client/base.rb")
45
+ template("cli_command.rb.tt", "lib/#{name}_client/cli_command.rb")
46
+ doc[:resources].each do |key, resource|
47
+ @resource = resource
48
+ template("cli.rb.tt", "lib/#{name}_client/commands/#{resource_name}.thor")
49
+ template("resource.rb.tt", "lib/#{name}_client/resources/#{resource_name}.rb")
50
+ end
51
+ end
52
+
53
+ protected
54
+
55
+ def class_base
56
+ name.camelize
57
+ end
58
+
59
+ def plaintext(text)
60
+ text.gsub(/<.*?>/, '').gsub("\n",' ').strip
61
+ end
62
+
63
+ # Resource related helper methods:
64
+
65
+ def resource_name
66
+ resource[:name].gsub(/\s/,"_").downcase.singularize
67
+ end
68
+
69
+ def api(method)
70
+ method[:apis].first
71
+ end
72
+
73
+ def params_in_path(method)
74
+ api(method)[:api_url].scan(/:([^\/]*)/).map(&:first)
75
+ end
76
+
77
+ def client_args(method)
78
+ client_args = params_in_path(method).dup
79
+ client_args << "params = {}" if method[:params].any?
80
+ client_args
81
+ end
82
+
83
+ def validation_hash(method)
84
+ if method[:params].any? { |p| p[:params] }
85
+ method[:params].reduce({}) do |h, p|
86
+ h.update(p[:name] => (p[:params] ? p[:params].map { |pp| pp[:name] } : nil))
87
+ end
88
+ else
89
+ method[:params].map { |p| p[:name] }
90
+ end
91
+ end
92
+
93
+ def substituted_url(method)
94
+ params_in_path(method).reduce(api(method)[:api_url]) { |u, p| u.sub(":#{p}","\#{#{p}}")}
95
+ end
96
+
97
+ def transformation_hash(method)
98
+ method[:params].find_all { |p| p[:expected_type] == "hash" && !p[:params].nil? }.reduce({}) do |h, p|
99
+ h.update(p[:name] => p[:params].map { |pp| pp[:name] })
100
+ end
101
+ end
102
+ end
103
+
104
+ end
105
+ end