apipie-rails 0.0.13 → 0.0.14

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 (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