dictum 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1abfdfd254c6440dd20d29a1f76339d413512ee5
4
- data.tar.gz: 01f93d8ee750b724a6c93e4a9beabab729cadfbe
3
+ metadata.gz: c7497e8af6c6c8ca44b6d22efcc8d35c2e7fdced
4
+ data.tar.gz: 4035ae72c64eeb23ba13ca9e6cceca97750f889f
5
5
  SHA512:
6
- metadata.gz: 43e9db9a4c534ffb44e4a648fff63f44a5c38565e716708dc2beff30d8cd6b31046f487f8769ccf1ebd89d74aff15145e4b51b861f5ad9847a001955c784b621
7
- data.tar.gz: 96012528a2372d4bc8879367c4f64462e2209b6e9138f6ee7f5d40969910a1706e269a3e39a1d6973cdee088b6c2b4ab9c8d9c206473cb7066b6ae9af21fe591
6
+ metadata.gz: ba691003c2487a7871b7a2ce6af0782bb1b8655a22adddbb25fe33eba196fb4d3dc8905b291cf6dfd12781fd3c1a57adc92d2161940582fbc276c099f347bdeb
7
+ data.tar.gz: 42c8d20e80ca2b825e87812d208800a0406f863d255cb4ddc4d3f1646cd131bb949f51846901d361c2b1be7369a1f20357c3b9c5d666f7863c4a6ea65363f32e
@@ -1,6 +1,7 @@
1
1
  AllCops:
2
2
  Exclude:
3
3
  - dictum.gemspec
4
+ - lib/tasks/dictum.rake
4
5
  - spec/spec_helper.rb
5
6
 
6
7
  Documentation:
data/Gemfile CHANGED
@@ -3,9 +3,10 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in crf.gemspec
4
4
  gemspec
5
5
 
6
- gem 'rake', '~> 11.1'
7
- gem 'json', '~> 1.8'
6
+ gem 'rake', '~> 12.0'
7
+ gem 'json', '~> 2.0'
8
8
 
9
9
  group :test do
10
- gem 'codeclimate-test-reporter', require: false
10
+ gem 'simplecov'
11
+ gem 'codeclimate-test-reporter', '~> 1.0.0'
11
12
  end
data/README.md CHANGED
@@ -128,6 +128,25 @@ And voilà, Dictum will create a document like this in '/docs/Documentation' (se
128
128
  "no_content"
129
129
  ```
130
130
 
131
+ # Error codes
132
+
133
+ Dictum supports the documentation of the custom error codes of your API. In order to do this you need to send an array of errors with a specific format, like the following:
134
+
135
+ ```ruby
136
+ ERROR_CODES = [
137
+ {
138
+ code: 1234,
139
+ message: 'This is a short description of the error, usually what is returned in the body of the response.',
140
+ description: 'This is a larger and more detailed description of the error, usually you want to show this only in the documentation'
141
+ }
142
+ ]
143
+
144
+ # spec_helper.rb
145
+ Dictum.error_codes(ERROR_CODES)
146
+ ```
147
+
148
+ We recommend you to define your error codes in a module or class with useful methods like get(error_code) and get_all, [like this one](https://gist.github.com/alebian/1b925151b6a6acd3e4bb2ef4b5148324).
149
+
131
150
  # Advanced usage
132
151
 
133
152
  If you pay attention to the basic usage, you will notice that it is a lot of boilerplate if your API has a lot of endpoints, this is not DRY. Luckily you can work around it using some Rspec tricks:
data/TODO.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # List of TODOs
2
2
  - Don't generate documentation while running normal tests
3
3
  - Improve HTML style and generator
4
- - Try it for Unit Test
4
+ - Try it for Unit Test and minitest
5
5
  - Make it more general, not only for REST APIs
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
20
  spec.test_files = spec.files.grep(%r{^(test|spec)/})
21
21
 
22
- spec.add_dependency 'nokogiri', '~> 1.6'
22
+ spec.add_dependency 'nokogiri', '~> 1.7'
23
23
 
24
24
  spec.add_development_dependency 'bundler', '>= 1.3.0', '< 2.0'
25
25
  spec.add_development_dependency 'rspec', '~> 3.4', '>= 3.4.0'
@@ -8,6 +8,8 @@ require 'tmpdir'
8
8
  module Dictum
9
9
  load 'tasks/dictum.rake' if defined?(Rails)
10
10
 
11
+ TEMPFILE_PATH = "#{Dir.tmpdir}/dictum_temp.json".freeze
12
+
11
13
  @config = {
12
14
  output_format: :markdown,
13
15
  output_path: "#{Dir.tmpdir}/docs",
@@ -73,6 +75,14 @@ module Dictum
73
75
  Documenter.instance.endpoint(arguments)
74
76
  end
75
77
 
78
+ ##
79
+ # Method used to add a new error code.
80
+ # @param codes_list is an array of hashes representing the code, message and description
81
+ #
82
+ def self.error_codes(codes_list)
83
+ codes_list.each { |error| Documenter.instance.error_code(error) }
84
+ end
85
+
76
86
  ##
77
87
  # Method that will execute tests and then save the results in the selected format
78
88
  #
@@ -88,13 +98,12 @@ module Dictum
88
98
  def self.save_to_file
89
99
  writer = nil
90
100
  output_filename = "#{@config[:output_path]}/#{@config[:output_filename]}"
91
- tempfile_path = Documenter.instance.tempfile_path
92
101
 
93
102
  case @config[:output_format]
94
103
  when :markdown
95
- writer = MarkdownWriter.new(output_filename, tempfile_path, @config)
104
+ writer = MarkdownWriter.new(output_filename, TEMPFILE_PATH, @config)
96
105
  when :html
97
- writer = HtmlWriter.new(output_filename, tempfile_path, @config)
106
+ writer = HtmlWriter.new(output_filename, TEMPFILE_PATH, @config)
98
107
  end
99
108
 
100
109
  writer.write
@@ -0,0 +1,3 @@
1
+ module Dictum
2
+ MISSING_MESSAGE = 'Dictum error: data not provided.'.freeze
3
+ end
@@ -1,5 +1,6 @@
1
1
  require 'singleton'
2
2
  require 'tmpdir'
3
+ require_relative 'constants'
3
4
 
4
5
  module Dictum
5
6
  ##
@@ -7,13 +8,11 @@ module Dictum
7
8
  #
8
9
  class Documenter
9
10
  include Singleton
10
-
11
11
  attr_reader :data, :tempfile_path
12
- TEMPFILE_NAME = 'dictum_temp.json'.freeze
13
12
 
14
13
  def initialize
15
14
  reset_data
16
- @tempfile_path = "#{Dir.tmpdir}/#{TEMPFILE_NAME}"
15
+ @tempfile_path = Dictum::TEMPFILE_PATH
17
16
  end
18
17
 
19
18
  def resource(arguments = {})
@@ -36,9 +35,21 @@ module Dictum
36
35
  update_temp
37
36
  end
38
37
 
38
+ def error_code(error = {})
39
+ return if error.nil? || !error.is_a?(Hash)
40
+ error_hash = {
41
+ code: error[:code] || Dictum::MISSING_MESSAGE,
42
+ message: error[:message] || '',
43
+ description: error[:description] || ''
44
+ }
45
+ error_codes << error_hash
46
+ update_temp
47
+ end
48
+
39
49
  def reset_data
40
50
  @data = {
41
- resources: {}
51
+ resources: {},
52
+ error_codes: []
42
53
  }
43
54
  end
44
55
 
@@ -48,6 +59,10 @@ module Dictum
48
59
  @data[:resources]
49
60
  end
50
61
 
62
+ def error_codes
63
+ @data[:error_codes]
64
+ end
65
+
51
66
  def update_temp
52
67
  File.delete(tempfile_path) if File.exist?(tempfile_path)
53
68
  file = File.open(tempfile_path, 'w+')
@@ -1,4 +1,5 @@
1
1
  module Dictum
2
+ # rubocop:disable ClassLength
2
3
  class HtmlHelpers
3
4
  BOOTSTRAP_JS = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js'.freeze
4
5
  BOOTSTRAP_CSS = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css'.freeze
@@ -111,6 +112,29 @@ module Dictum
111
112
  end
112
113
  answer += ">#{content}</#{name}>"
113
114
  end
115
+
116
+ def table(headers, rows)
117
+ return '' unless headers
118
+ answer = table_headers(headers)
119
+ answer += table_rows(rows)
120
+ tag('table', answer, class: 'table')
121
+ end
122
+
123
+ private
124
+
125
+ def table_headers(headers)
126
+ answer = ''
127
+ headers.each { |header| answer += tag('th', header) }
128
+ tag('tr', answer)
129
+ end
130
+
131
+ def table_rows(rows)
132
+ answer = ''
133
+ rows.each do |row|
134
+ answer += tag('tr', tag('td', row[0]) + tag('td', row[1]) + tag('td', row[2]))
135
+ end
136
+ answer
137
+ end
114
138
  end
115
139
  end
116
140
  end
@@ -3,7 +3,13 @@ require 'json'
3
3
  require 'nokogiri'
4
4
 
5
5
  module Dictum
6
+ # rubocop:disable ClassLength
6
7
  class HtmlWriter
8
+ ERROR_CODE_URL = 'error_codes'.freeze
9
+ ERROR_CODE_TEXT = 'Error codes'.freeze
10
+ RESOURCES_TEXT = 'Resources'.freeze
11
+ BACK_TEXT = 'Back'.freeze
12
+
7
13
  attr_reader :temp_path, :temp_json, :output_dir, :output_file, :header_title
8
14
 
9
15
  def initialize(output_dir, temp_path, config)
@@ -28,10 +34,14 @@ module Dictum
28
34
  index.close
29
35
  end
30
36
 
37
+ # rubocop:disable LineLength
38
+ # rubocop:disable AbcSize
31
39
  def write_index
32
40
  html = HtmlHelpers.build do |b|
33
41
  content = b.jumbotron(b.title(@config[:index_title], 'title'))
42
+ content += b.title(RESOURCES_TEXT)
34
43
  content += b.unordered_list(resources.keys)
44
+ content += b.link("#{ERROR_CODE_URL}.html", b.subtitle(ERROR_CODE_TEXT)) unless error_codes.empty?
35
45
  container = b.container(b.row(content))
36
46
  b.html_header(header_title, container, @config[:inline_css])
37
47
  end
@@ -42,18 +52,23 @@ module Dictum
42
52
  resources.each do |resource_name, information|
43
53
  write_page(resource_name, information)
44
54
  end
55
+ write_error_codes_page unless error_codes.empty?
45
56
  end
46
57
 
47
58
  def resources
48
59
  temp_json['resources']
49
60
  end
50
61
 
62
+ def error_codes
63
+ temp_json['error_codes']
64
+ end
65
+
51
66
  def write_page(resource_name, information)
52
67
  html = HtmlHelpers.build do |b|
53
68
  content = resource_header_and_endpoints(
54
69
  resource_name, information['description'], information['endpoints'], b
55
70
  )
56
- container = b.container(b.row(content) + b.row(b.button('Back')))
71
+ container = b.container(b.row(content) + b.row(b.button(BACK_TEXT)))
57
72
  b.html_header(header_title, container, @config[:inline_css])
58
73
  end
59
74
  write_to_file("#{output_dir}/#{resource_name.downcase}.html", html)
@@ -83,10 +98,7 @@ module Dictum
83
98
 
84
99
  def write_response(endpoint, builder)
85
100
  answer = builder.code_block('Status', endpoint['response_status'])
86
- answer += write_codeblock(
87
- 'Response headers', endpoint['response_headers'], builder
88
- ) if endpoint['response_headers']
89
-
101
+ answer += write_codeblock('Response headers', endpoint['response_headers'], builder) if endpoint['response_headers']
90
102
  if endpoint['response_body']
91
103
  param = endpoint['response_body'] == 'no_content' ? {} : endpoint['response_body']
92
104
  answer += write_codeblock('Response body', param, builder)
@@ -99,5 +111,23 @@ module Dictum
99
111
  sanitized_json = json.empty? ? {} : json
100
112
  builder.code_block(text, JSON.pretty_generate(sanitized_json))
101
113
  end
114
+
115
+ def write_error_codes_page
116
+ html = HtmlHelpers.build do |b|
117
+ content = b.title(ERROR_CODE_TEXT, 'title')
118
+ content += b.table(error_code_table_header, error_codes_as_rows)
119
+ container = b.container(b.row(content) + b.row(b.button(BACK_TEXT)))
120
+ b.html_header(header_title, container, @config[:inline_css])
121
+ end
122
+ write_to_file("#{output_dir}/#{ERROR_CODE_URL}.html", html)
123
+ end
124
+
125
+ def error_code_table_header
126
+ %w(Code Description Message)
127
+ end
128
+
129
+ def error_codes_as_rows
130
+ error_codes.map { |a| [a['code'], a['description'], a['message']] }
131
+ end
102
132
  end
103
133
  end
@@ -16,6 +16,7 @@ module Dictum
16
16
  @output_file = File.open(output_path, 'a+')
17
17
  write_index
18
18
  write_temp_path
19
+ write_error_codes
19
20
  output_file.close
20
21
  end
21
22
 
@@ -37,6 +38,17 @@ module Dictum
37
38
  end
38
39
  end
39
40
 
41
+ def write_error_codes
42
+ return if error_codes.empty?
43
+ output_file.puts "# Error codes"
44
+ output_file.puts "|Code|Message|Description|"
45
+ output_file.puts "|----|----|----|"
46
+ error_codes.each do |error|
47
+ output_file.puts "|#{error['code']}|#{error['message']}|#{error['description']}|"
48
+ end
49
+ output_file.puts "\n"
50
+ end
51
+
40
52
  def write_endpoints(endpoints)
41
53
  endpoints.each do |endpoint|
42
54
  output_file.puts "## #{endpoint['http_verb']} #{endpoint['endpoint']}\n\n"
@@ -70,5 +82,9 @@ module Dictum
70
82
  output_file.puts "\#\#\# #{subtitle}:"
71
83
  output_file.puts "```json\n#{JSON.pretty_generate(sanitized_contents)}\n```\n\n"
72
84
  end
85
+
86
+ def error_codes
87
+ temp_json['error_codes']
88
+ end
73
89
  end
74
90
  end
@@ -1,3 +1,3 @@
1
1
  module Dictum
2
- VERSION = '0.0.5'.freeze
2
+ VERSION = '0.0.6'.freeze
3
3
  end
@@ -3,4 +3,5 @@ Dictum.configure do |config|
3
3
  config.root_path = Rails.root
4
4
  config.output_filename = 'Documentation'
5
5
  config.output_format = :markdown
6
+ config.index_title = 'MYAPP API documentation'
6
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dictum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alejandro Bezdjian
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-26 00:00:00.000000000 Z
11
+ date: 2017-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
19
+ version: '1.7'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.6'
26
+ version: '1.7'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -124,6 +124,7 @@ files:
124
124
  - example.gif
125
125
  - example.md
126
126
  - lib/dictum.rb
127
+ - lib/dictum/constants.rb
127
128
  - lib/dictum/documenter.rb
128
129
  - lib/dictum/html_helpers.rb
129
130
  - lib/dictum/html_writer.rb