apipie-rails 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/Gemfile.lock +5 -3
  2. data/README.rst +688 -0
  3. data/apipie-rails.gemspec +2 -4
  4. data/app/controllers/apipie/apipies_controller.rb +73 -41
  5. data/app/views/apipie/apipies/index.html.erb +10 -3
  6. data/app/views/apipie/apipies/method.html.erb +5 -2
  7. data/app/views/apipie/apipies/resource.html.erb +10 -3
  8. data/lib/apipie-rails.rb +1 -0
  9. data/lib/apipie/apipie_module.rb +28 -79
  10. data/lib/apipie/application.rb +194 -97
  11. data/lib/apipie/client/generator.rb +5 -4
  12. data/lib/apipie/configuration.rb +112 -0
  13. data/lib/apipie/dsl_definition.rb +93 -16
  14. data/lib/apipie/extractor.rb +12 -5
  15. data/lib/apipie/extractor/collector.rb +1 -1
  16. data/lib/apipie/extractor/recorder.rb +2 -1
  17. data/lib/apipie/extractor/writer.rb +11 -4
  18. data/lib/apipie/helpers.rb +15 -4
  19. data/lib/apipie/markup.rb +3 -4
  20. data/lib/apipie/method_description.rb +28 -22
  21. data/lib/apipie/resource_description.rb +44 -42
  22. data/lib/apipie/routing.rb +3 -1
  23. data/lib/apipie/static_dispatcher.rb +0 -1
  24. data/lib/apipie/version.rb +1 -1
  25. data/lib/generators/apipie/install/README +6 -0
  26. data/lib/generators/apipie/install/install_generator.rb +25 -0
  27. data/lib/generators/apipie/install/templates/initializer.rb.erb +7 -0
  28. data/lib/tasks/apipie.rake +31 -39
  29. data/spec/controllers/api/v1/architectures_controller_spec.rb +30 -0
  30. data/spec/controllers/api/v2/architectures_controller_spec.rb +12 -0
  31. data/spec/controllers/apipies_controller_spec.rb +18 -12
  32. data/spec/controllers/users_controller_spec.rb +56 -19
  33. data/spec/dummy/app/controllers/api/base_controller.rb +4 -0
  34. data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +32 -0
  35. data/spec/dummy/app/controllers/api/v1/base_controller.rb +11 -0
  36. data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +32 -0
  37. data/spec/dummy/app/controllers/api/v2/base_controller.rb +11 -0
  38. data/spec/dummy/app/controllers/twitter_example_controller.rb +1 -1
  39. data/spec/dummy/app/controllers/users_controller.rb +2 -3
  40. data/spec/dummy/config/initializers/apipie.rb +29 -6
  41. data/spec/lib/method_description_spec.rb +29 -0
  42. data/spec/lib/param_description_spec.rb +41 -0
  43. data/spec/lib/resource_description_spec.rb +28 -0
  44. data/spec/spec_helper.rb +1 -1
  45. metadata +99 -164
  46. data/README.rdoc +0 -367
  47. data/lib/apipie/client/base.rb +0 -133
  48. data/lib/apipie/client/cli_command.rb +0 -130
  49. data/lib/apipie/client/main.rb +0 -101
  50. data/lib/apipie/client/rest_client_oauth.rb +0 -19
  51. data/lib/apipie/client/template/Gemfile.tt +0 -3
  52. data/lib/apipie/client/template/README.tt +0 -3
  53. data/lib/apipie/client/template/Rakefile.tt +0 -2
  54. data/lib/apipie/client/template/a_name.gemspec.tt +0 -23
  55. data/lib/apipie/client/template/bin/bin.rb.tt +0 -30
  56. data/lib/apipie/client/template/lib/a_name.rb.tt +0 -27
  57. data/lib/apipie/client/template/lib/a_name/commands/cli.rb.tt +0 -22
  58. data/lib/apipie/client/template/lib/a_name/config.yml +0 -6
  59. data/lib/apipie/client/template/lib/a_name/resources/resource.rb.tt +0 -22
  60. data/lib/apipie/client/template/lib/a_name/version.rb.tt +0 -3
  61. data/lib/apipie/client/thor.rb +0 -21
  62. data/rubygem-apipie-rails.spec +0 -122
  63. data/spec/lib/parameter_description_spec.rb +0 -41
@@ -19,12 +19,11 @@ module Apipie
19
19
  class Markdown
20
20
 
21
21
  def initialize
22
- require 'redcarpet'
23
- @redcarpet ||= ::Redcarpet::Markdown.new(::Redcarpet::Render::HTML.new)
22
+ require 'maruku'
24
23
  end
25
24
 
26
25
  def to_html(text)
27
- @redcarpet.render(text)
26
+ Maruku.new(text).to_html
28
27
  end
29
28
 
30
29
  end
@@ -42,4 +41,4 @@ module Apipie
42
41
  end
43
42
 
44
43
  end
45
- end
44
+ end
@@ -5,39 +5,31 @@ module Apipie
5
5
 
6
6
  class Api
7
7
 
8
- attr_accessor :short_description, :api_url, :http_method
8
+ attr_accessor :short_description, :path, :http_method
9
9
 
10
10
  def initialize(method, path, desc)
11
11
  @http_method = method.to_s
12
- @api_url = create_api_url(path)
12
+ @path = path
13
13
  @short_description = desc
14
14
  end
15
15
 
16
- private
17
-
18
- def create_api_url(path)
19
- path = "#{Apipie.configuration.api_base_url}#{path}"
20
- path = path[0..-2] if path[-1..-1] == '/'
21
- return path
22
- end
23
-
24
16
  end
25
17
 
26
18
  attr_reader :full_description, :method, :resource, :apis, :examples, :see, :formats
27
19
 
28
20
  def initialize(method, resource, app)
29
- @method = method
21
+ @method = method.to_s
30
22
  @resource = resource
31
23
 
32
- @apis = app.get_api_args
33
- @see = app.get_see
34
- @formats = app.get_formats
24
+ @apis = app.last_dsl_data[:api_args]
25
+ @see = app.last_dsl_data[:see]
26
+ @formats = app.last_dsl_data[:formats]
35
27
 
36
- desc = app.get_description || ''
28
+ desc = app.last_dsl_data[:description] || ''
37
29
  @full_description = Apipie.markup_to_html(desc)
38
- @errors = app.get_errors
39
- @params_ordered = app.get_params
40
- @examples = app.get_examples
30
+ @errors = app.last_dsl_data[:errors]
31
+ @params_ordered = app.last_dsl_data[:params]
32
+ @examples = app.last_dsl_data[:examples]
41
33
 
42
34
  @examples += load_recorded_examples
43
35
 
@@ -45,7 +37,6 @@ module Apipie
45
37
  if parent != ActionController::Base
46
38
  @parent_resource = parent.controller_name
47
39
  end
48
- @resource.add_method(id)
49
40
  end
50
41
 
51
42
  def id
@@ -53,7 +44,7 @@ module Apipie
53
44
  end
54
45
 
55
46
  def params
56
- params_ordered.reduce({}) { |h,p| h[p.name] = p; h }
47
+ params_ordered.reduce(ActiveSupport::OrderedHash.new) { |h,p| h[p.name] = p; h }
57
48
  end
58
49
 
59
50
  def params_ordered
@@ -86,14 +77,28 @@ module Apipie
86
77
  return @merged_errors
87
78
  end
88
79
 
80
+ def version
81
+ resource._version
82
+ end
83
+
89
84
  def doc_url
90
- Apipie.full_url("#{@resource._id}/#{@method}")
85
+ crumbs = []
86
+ crumbs << @resource._version if Apipie.configuration.version_in_url
87
+ crumbs << @resource._id
88
+ crumbs << @method
89
+ Apipie.full_url crumbs.join('/')
90
+ end
91
+
92
+ def create_api_url(api)
93
+ path = "#{Apipie.api_base_url(@resource._version)}#{api.path}"
94
+ path = path[0..-2] if path[-1..-1] == '/'
95
+ return path
91
96
  end
92
97
 
93
98
  def method_apis_to_json
94
99
  @apis.each.collect do |api|
95
100
  {
96
- :api_url => api.api_url,
101
+ :api_url => create_api_url(api),
97
102
  :http_method => api.http_method.to_s,
98
103
  :short_description => api.short_description
99
104
  }
@@ -144,6 +149,7 @@ module Apipie
144
149
  def load_recorded_examples
145
150
  (Apipie.recorded_examples[id] || []).
146
151
  find_all { |ex| ex["show_in_doc"].to_i > 0 }.
152
+ find_all { |ex| ex["versions"].nil? || ex["versions"].include?(self.version) }.
147
153
  sort_by { |ex| ex["show_in_doc"] }.
148
154
  map { |ex| format_example(ex.symbolize_keys) }
149
155
  end
@@ -12,72 +12,73 @@ module Apipie
12
12
  class ResourceDescription
13
13
 
14
14
  attr_reader :controller, :_short_description, :_full_description, :_methods, :_id,
15
- :_path, :_version, :_name, :_params_ordered, :_errors_ordered, :_formats
15
+ :_path, :_name, :_params_ordered, :_errors_ordered, :_formats, :_parent
16
16
 
17
- def initialize(controller, resource_name, &block)
18
- @_methods = []
17
+ def initialize(controller, resource_name, dsl_data = nil, version = nil, &block)
18
+
19
+ @_methods = ActiveSupport::OrderedHash.new
19
20
  @_params_ordered = []
20
21
  @_errors_ordered = []
21
22
 
22
23
  @controller = controller
23
24
  @_id = resource_name
24
- @_version = "1"
25
+ @_version = version || Apipie.configuration.default_version
25
26
  @_name = @_id.humanize
26
- @_full_description = ""
27
- @_short_description = ""
28
- @_path = ""
29
- @_formats = []
27
+ @_parent = Apipie.get_resource_description(controller.superclass, version)
30
28
 
31
- block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
29
+ update_from_dsl_data(dsl_data) if dsl_data
32
30
  end
33
31
 
34
- def param(param_name, validator, desc_or_options = nil, options = {}, &block)
35
- param_description = Apipie::ParamDescription.new(param_name, validator, desc_or_options, options, &block)
36
- @_params_ordered << param_description
32
+ def update_from_dsl_data(dsl_data)
33
+ @_name = dsl_data[:resource_name] if dsl_data[:resource_name]
34
+ @_full_description = Apipie.markup_to_html(dsl_data[:description])
35
+ @_short_description = dsl_data[:short_description]
36
+ @_path = dsl_data[:path] || ""
37
+ @_formats = dsl_data[:formats]
38
+ @_errors_ordered = dsl_data[:errors]
39
+ @_params_ordered = dsl_data[:params]
40
+ if dsl_data[:app_info]
41
+ Apipie.configuration.app_info[_version] = dsl_data[:app_info]
42
+ end
43
+ if dsl_data[:api_base_url]
44
+ Apipie.configuration.api_base_url[_version] = dsl_data[:api_base_url]
45
+ end
37
46
  end
38
47
 
39
- def error(*args)
40
- error_description = Apipie::ErrorDescription.new(args)
41
- @_errors_ordered << error_description
48
+ def _version
49
+ @_version || @_parent.try(:_version) || Apipie.configuration.default_version
42
50
  end
43
51
 
52
+ def add_method_description(method_description)
53
+ Apipie.debug "@resource_descriptions[#{self._version}][#{self._name}]._methods[#{method_description.method}] = #{method_description}"
54
+ @_methods[method_description.method.to_sym] = method_description
55
+ end
44
56
 
45
- def path(path); @_path = path; end
46
-
47
- def version(version); @_version = version; end
48
-
49
- def formats(formats); @_formats = formats; end
50
-
51
- def name(name); @_name = name; end
52
-
53
- def short(short); @_short_description = short; end
54
- alias :short_description :short
55
-
56
- def desc(description)
57
- description ||= ''
58
- @_full_description = Apipie.markup_to_html(description)
57
+ def method_description(method_name)
58
+ @_methods[method_name.to_sym]
59
59
  end
60
- alias :description :desc
61
- alias :full_description :desc
62
60
 
63
- # add description of resource method
64
- def add_method(mapi_key)
65
- @_methods << mapi_key
66
- @_methods.uniq!
61
+ def remove_method_description(method_name)
62
+ if @_methods.has_key?(method_name)
63
+ @_methods.delete(method_name)
64
+ end
67
65
  end
68
66
 
69
67
  def doc_url
70
- Apipie.full_url(@_id)
68
+ crumbs = []
69
+ crumbs << _version if Apipie.configuration.version_in_url
70
+ crumbs << @_id
71
+ Apipie.full_url crumbs.join('/')
71
72
  end
72
73
 
73
- def api_url; "#{Apipie.configuration.api_base_url}#{@_path}"; end
74
+ def api_url; "#{Apipie.api_base_url(_version)}#{@_path}"; end
74
75
 
75
76
  def to_json(method_name = nil)
76
77
 
77
- _methods = if method_name.blank?
78
- @_methods.collect { |key| Apipie.method_descriptions[key].to_json }
78
+ methods = if method_name.blank?
79
+ @_methods.collect { |key, method_description| method_description.to_json}
79
80
  else
80
- [Apipie.method_descriptions[[@_id, method_name].join('#')].to_json]
81
+ [@_methods[method_name.to_sym].to_json]
81
82
  end
82
83
 
83
84
  {
@@ -86,10 +87,11 @@ module Apipie
86
87
  :name => @_name,
87
88
  :short_description => @_short_description,
88
89
  :full_description => @_full_description,
89
- :version => @_version,
90
+ :version => _version,
90
91
  :formats => @_formats,
91
- :methods => _methods
92
+ :methods => methods
92
93
  }
93
94
  end
95
+
94
96
  end
95
97
  end
@@ -3,7 +3,9 @@ module Apipie
3
3
  module MapperExtensions
4
4
  def apipie
5
5
  namespace "apipie", :path => Apipie.configuration.doc_base_url do
6
- get("(:resource)/(:method)" => "apipies#index" )
6
+ constraints(:version => /[^\/]+/) do
7
+ get("(:version)/(:resource)/(:method)" => "apipies#index", :as => :apipie)
8
+ end
7
9
  end
8
10
  end
9
11
  end
@@ -46,7 +46,6 @@ module Apipie
46
46
  case env['REQUEST_METHOD']
47
47
  when 'GET', 'HEAD'
48
48
  path = env['PATH_INFO'].sub("#{@baseurl}/","/apipie/").chomp('/')
49
- path.sub!("#{ENV["RAILS_RELATIVE_URL_ROOT"]}",'')
50
49
 
51
50
  if match = @file_handler.match?(path)
52
51
  env["PATH_INFO"] = match
@@ -1,3 +1,3 @@
1
1
  module Apipie
2
- VERSION = '0.0.13'
2
+ VERSION = '0.0.14'
3
3
  end
@@ -0,0 +1,6 @@
1
+ Description:
2
+ Sets up Apipie-rails in your project.
3
+ Examples:
4
+ `rails generate apipie:install`
5
+
6
+ `rails generate apipie:install --help`
@@ -0,0 +1,25 @@
1
+ module Apipie
2
+ class InstallGenerator < ::Rails::Generators::Base
3
+ source_root File.expand_path("../templates", __FILE__)
4
+
5
+ class_option(:route,
6
+ :aliases => "-r",
7
+ :type => :string,
8
+ :desc => "What path should be the doc available on",
9
+ :default => "/apipie")
10
+
11
+ class_option(:api_path,
12
+ :alias => "-a",
13
+ :type => :string,
14
+ :desc => "What path are API requests on",
15
+ :default => "/api")
16
+
17
+ def create_initializer
18
+ template 'initializer.rb.erb', 'config/initializers/apipie.rb'
19
+ end
20
+
21
+ def add_route
22
+ route("apipie")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ Apipie.configure do |config|
2
+ config.app_name = "<%= Rails.application.class.name[/^\w+/] %>"
3
+ config.api_base_url = "<%= options.api_path %>"
4
+ config.doc_base_url = "<%= options.route %>"
5
+ # were is your API defined?
6
+ config.api_controllers_matcher = "#{Rails.root}/app/controllers/*.rb"
7
+ end
@@ -1,6 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'fileutils'
3
- require 'apipie/client/generator'
4
3
 
5
4
  namespace :apipie do
6
5
 
@@ -17,22 +16,22 @@ namespace :apipie do
17
16
  # | - resource2.html
18
17
  #
19
18
  # By default OUT="#{Rails.root}/doc/apidoc"
20
- task :static => :environment do
19
+ task :static, [:version] => :environment do |t, args|
21
20
  with_loaded_documentation do
21
+ args.with_defaults(:version => Apipie.configuration.default_version)
22
22
  out = ENV["OUT"] || File.join(::Rails.root, 'doc', 'apidoc')
23
23
  subdir = File.basename(out)
24
-
25
24
  copy_jscss(out)
26
-
25
+ Apipie.configuration.version_in_url = false
27
26
  Apipie.url_prefix = "./#{subdir}"
28
- doc = Apipie.to_json
27
+ doc = Apipie.to_json(args[:version])
29
28
  generate_one_page(out, doc)
30
29
  generate_plain_page(out, doc)
31
30
  generate_index_page(out, doc)
32
31
  Apipie.url_prefix = "../#{subdir}"
33
- generate_resource_pages(out, doc)
32
+ generate_resource_pages(args[:version], out, doc)
34
33
  Apipie.url_prefix = "../../#{subdir}"
35
- generate_method_pages(out, doc)
34
+ generate_method_pages(args[:version], out, doc)
36
35
  end
37
36
  end
38
37
 
@@ -44,12 +43,18 @@ namespace :apipie do
44
43
 
45
44
  file_base = File.join(cache_dir, Apipie.configuration.doc_base_url)
46
45
  Apipie.url_prefix = "./#{subdir}"
47
- doc = Apipie.to_json
46
+ doc = Apipie.to_json(Apipie.configuration.default_version)
48
47
  generate_index_page(file_base, doc, true)
49
- Apipie.url_prefix = "../#{subdir}"
50
- generate_resource_pages(file_base, doc, true)
51
- Apipie.url_prefix = "../../#{subdir}"
52
- generate_method_pages(file_base, doc, true)
48
+ Apipie.available_versions.each do |version|
49
+ file_base_version = File.join(file_base, version)
50
+ Apipie.url_prefix = "../#{subdir}"
51
+ doc = Apipie.to_json(version)
52
+ generate_index_page(file_base_version, doc, true, true)
53
+ Apipie.url_prefix = "../../#{subdir}"
54
+ generate_resource_pages(version, file_base_version, doc, true)
55
+ Apipie.url_prefix = "../../../#{subdir}"
56
+ generate_method_pages(version, file_base_version, doc, true)
57
+ end
53
58
  end
54
59
  end
55
60
 
@@ -81,33 +86,33 @@ namespace :apipie do
81
86
  render_page("#{file_base}-plain.html", "plain", {:doc => doc[:docs]}, nil)
82
87
  end
83
88
 
84
- def generate_index_page(file_base, doc, include_json = false)
89
+ def generate_index_page(file_base, doc, include_json = false, show_versions = false)
85
90
  FileUtils.mkdir_p(File.dirname(file_base)) unless File.exists?(File.dirname(file_base))
86
-
87
- render_page("#{file_base}.html", "index", {:doc => doc[:docs]})
91
+ versions = show_versions && Apipie.available_versions
92
+ render_page("#{file_base}.html", "index", {:doc => doc[:docs], :versions => versions})
88
93
 
89
94
  File.open("#{file_base}.json", "w") { |f| f << doc.to_json } if include_json
90
95
  end
91
96
 
92
- def generate_resource_pages(file_base, doc, include_json = false)
97
+ def generate_resource_pages(version, file_base, doc, include_json = false)
93
98
  doc[:docs][:resources].each do |resource_name, _|
94
99
  resource_file_base = File.join(file_base, resource_name.to_s)
95
100
  FileUtils.mkdir_p(File.dirname(resource_file_base)) unless File.exists?(File.dirname(resource_file_base))
96
101
 
97
- doc = Apipie.to_json(resource_name)
102
+ doc = Apipie.to_json(version, resource_name)
98
103
  render_page("#{resource_file_base}.html", "resource", {:doc => doc[:docs],
99
104
  :resource => doc[:docs][:resources].first})
100
105
  File.open("#{resource_file_base}.json", "w") { |f| f << doc.to_json } if include_json
101
106
  end
102
107
  end
103
108
 
104
- def generate_method_pages(file_base, doc, include_json = false)
109
+ def generate_method_pages(version, file_base, doc, include_json = false)
105
110
  doc[:docs][:resources].each do |resource_name, resource_params|
106
111
  resource_params[:methods].each do |method|
107
112
  method_file_base = File.join(file_base, resource_name.to_s, method[:name].to_s)
108
113
  FileUtils.mkdir_p(File.dirname(method_file_base)) unless File.exists?(File.dirname(method_file_base))
109
114
 
110
- doc = Apipie.to_json(resource_name, method[:name])
115
+ doc = Apipie.to_json(version, resource_name, method[:name])
111
116
  render_page("#{method_file_base}.html", "method", {:doc => doc[:docs],
112
117
  :resource => doc[:docs][:resources].first,
113
118
  :method => doc[:docs][:resources].first[:methods].first})
@@ -129,28 +134,15 @@ namespace :apipie do
129
134
  FileUtils.cp_r "#{src}/.", dest
130
135
  end
131
136
 
132
- namespace :client do
133
- task :all, [:suffix] => [:environment] do |t, args|
134
- args.with_defaults(:suffix => "_client")
135
- Apipie.configuration.use_cache = false # we don't want to skip DSL evaluation
136
- Apipie.api_controllers_paths.each { |file| require file }
137
-
138
- Apipie::Client::Generator.start(Apipie.configuration.app_name, :all, args[:suffix])
139
- end
140
-
141
- desc "Generate only ruby bindings for API documented with apipie gem."
142
- task :bindings, [:suffix] => [:environment] do |t, args|
143
- args.with_defaults(:suffix => "_client")
144
- Apipie.configuration.use_cache = false # we don't want to skip DSL evaluation
145
- Apipie.api_controllers_paths.each { |file| require file }
146
-
147
- Apipie::Client::Generator.start(Apipie.configuration.app_name, :bindings, args[:suffix])
148
- end
137
+ desc "Generate CLI client for API documented with apipie gem. (deprecated)"
138
+ task :client do
139
+ puts <<MESSAGE
140
+ The apipie gem itself doesn't provide client code generator. See
141
+ https://github.com/Pajk/apipie-rails/wiki/CLI-client for more information on
142
+ how to write your own generator.
143
+ MESSAGE
149
144
  end
150
145
 
151
- desc "Generate CLI client for API documented with apipie gem."
152
- task :client, [:suffix] => 'client:all'
153
-
154
146
  def plaintext(text)
155
147
  text.gsub(/<.*?>/, '').gsub("\n",' ').strip
156
148
  end