dictum 0.0.5 → 0.0.6

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