rails_api_documentation 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +58 -3
- data/app/views/rails_api_doc/api_docs/_request_api_table.slim +1 -1
- data/app/views/rails_api_doc/api_docs/_response_api_table.slim +1 -1
- data/app/views/shared/_table.slim +1 -1
- data/lib/rails_api_doc/controller/request/dsl.rb +32 -3
- data/lib/rails_api_doc/controller/request/factory.rb +4 -4
- data/lib/rails_api_doc/controller/request/param.rb +3 -3
- data/lib/rails_api_doc/controller/response/factory.rb +1 -12
- data/lib/rails_api_doc/controller/response/headers.rb +0 -1
- data/lib/rails_api_doc/controller/response/repository.rb +11 -1
- data/lib/rails_api_doc/controller/strong_params/dsl.rb +9 -4
- data/lib/rails_api_doc/controller/strong_params/permitted_params.rb +6 -4
- data/lib/rails_api_doc/model/attribute_merger.rb +34 -29
- data/lib/rails_api_doc/model/attribute_parser.rb +1 -0
- data/lib/rails_api_doc/version.rb +1 -1
- data/lib/rails_api_doc.rb +3 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a72e86cdcaefec61dd47079acd6df5eb7ad88762
|
4
|
+
data.tar.gz: dc2ee37bbed89765494a3b697ab337db746aaefb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a1d84265c02e6c7c588078cb27790bb1a231a6451aa35c3c24210b41a2ec62237deb611be3408346f66dbcd8e68fb6a44f8473194eedb77acc0f4e5e528a085
|
7
|
+
data.tar.gz: 43e6fb0376be3a10f0da24cf170bc42110b79869308e5d3b7ebaf19e59104b872e2c34365bc2647ba5e50ab6fb803e38115382579e704f56d4d6692153aeb1d7
|
data/README.md
CHANGED
@@ -22,7 +22,7 @@ Or install it yourself as:
|
|
22
22
|
+ displaying application api if used in one of correct ways
|
23
23
|
![alt tag](https://raw.githubusercontent.com/vshaveyko/rails_api_doc/master/preview.png)
|
24
24
|
+ Integration with Rabl if it is bundled
|
25
|
-
+ ```
|
25
|
+
+ ```strong_params``` method that will filter incoming params for you
|
26
26
|
|
27
27
|
## Usage
|
28
28
|
|
@@ -56,7 +56,16 @@ To display api documentation on route '/api_doc' you need to:
|
|
56
56
|
parameter :comment, type: :string
|
57
57
|
end
|
58
58
|
end
|
59
|
-
parameter :test, type:
|
59
|
+
parameter :test, type: :string, required: true
|
60
|
+
|
61
|
+
parameter({
|
62
|
+
articles_attributes: { model: 'Article', type: :ary_object },
|
63
|
+
data_attributes: { model: 'Datum' },
|
64
|
+
comments_attributes: { model: 'Comment', type: :ary_object }
|
65
|
+
}, type: :object) do
|
66
|
+
parameter :id
|
67
|
+
parameter :name
|
68
|
+
end
|
60
69
|
|
61
70
|
end
|
62
71
|
```
|
@@ -75,7 +84,7 @@ To display api documentation on route '/api_doc' you need to:
|
|
75
84
|
|
76
85
|
# controller action
|
77
86
|
def create
|
78
|
-
Comment.create!(
|
87
|
+
Comment.create!(strong_params)
|
79
88
|
end
|
80
89
|
|
81
90
|
```
|
@@ -84,6 +93,52 @@ To display api documentation on route '/api_doc' you need to:
|
|
84
93
|
|
85
94
|
Comment will be created with: `Comment(body='Comment body', title='Comment title', age=nil)`
|
86
95
|
|
96
|
+
## Value
|
97
|
+
|
98
|
+
You can pass optional value argument to every parameter:
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
parameter :val, type: :integer, value: -> (request_value) { 5 }
|
102
|
+
```
|
103
|
+
|
104
|
+
on every matching request value in this field will be overriden by value returned by proc.
|
105
|
+
|
106
|
+
value field expecting anything that will respond to `:call` and can accept one argument(param value from request)
|
107
|
+
|
108
|
+
you should expect that value passed can be `nil`
|
109
|
+
|
110
|
+
This can be used to force values on some fields, or modify values passed to request in some ways.
|
111
|
+
|
112
|
+
E.g. you want to force current_user_id on model creation instead of passing it from frontend.
|
113
|
+
|
114
|
+
## Enum
|
115
|
+
|
116
|
+
When you defined parameter type as `:enum` you can pass `enum:` option. This will filter parameter by values provided.
|
117
|
+
|
118
|
+
## Group common blocks
|
119
|
+
|
120
|
+
You can define parameters that have common fields this way:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
parameter({
|
124
|
+
articles_attributes: { model: 'Article', type: :ary_object },
|
125
|
+
data_attributes: { model: 'Datum' },
|
126
|
+
comments_attributes: { model: 'Comment', type: :ary_object }
|
127
|
+
}, type: :object) do
|
128
|
+
parameter :id
|
129
|
+
parameter :name
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
Pass common values as last optional arguments and uniq definitions as hash value.
|
134
|
+
All nesting parameters are applied to elements in blocks.
|
135
|
+
|
136
|
+
Something with same type can be defined like this:
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
parameter :name, :desc, type: :string
|
140
|
+
```
|
141
|
+
|
87
142
|
## Types
|
88
143
|
|
89
144
|
Parameter type may be one of these:
|
@@ -2,4 +2,4 @@
|
|
2
2
|
|
3
3
|
div[id="#{ctrl}.request" style="--row-count: #{request_headers.length}"]
|
4
4
|
|
5
|
-
= render 'shared/table', model: ctrl, rows: repo[ctrl], headers: request_headers, nesting: [], params: { api_type: :request }
|
5
|
+
= render 'shared/table', model: ctrl, rows: repo[ctrl.name], headers: request_headers, nesting: [], params: { api_type: :request }
|
@@ -11,6 +11,6 @@ div.response-table[id="#{ctrl}.response" style="--row-count: #{response_headers
|
|
11
11
|
div.request-action-title
|
12
12
|
= render 'shared/title', locals: { blue_title: route[:method], yellow_title: route[:url]}
|
13
13
|
|
14
|
-
- if rows = repo.
|
14
|
+
- if rows = repo.load_attrs(ctrl, action)
|
15
15
|
|
16
16
|
= render 'shared/table', model: ctrl, rows: rows, headers: response_headers, nesting: [], params: { api_action: action, api_type: :response }
|
@@ -29,7 +29,7 @@ div.flex-table
|
|
29
29
|
- if index.zero?
|
30
30
|
span.ico ✏
|
31
31
|
/ = submit_tag ,name: 'destroy', class: 'ico destroy'
|
32
|
-
= link_to '❌' , api_doc_url(construct_destroy_param(row_values, params, nesting)), method: :delete,
|
32
|
+
= link_to '❌' , api_doc_url(construct_destroy_param(row_values, params, nesting)), method: :delete,data: { confirm: 'Are you sure?' }, class: 'destroy ico'
|
33
33
|
span.exit.ico ❌
|
34
34
|
= submit_tag '✔'
|
35
35
|
|
@@ -5,19 +5,48 @@ module RailsApiDoc
|
|
5
5
|
module Request
|
6
6
|
module DSL
|
7
7
|
|
8
|
+
#
|
8
9
|
# Use parameter in controller to define REQUEST parameter.
|
9
10
|
# Adds it to repository: RailsApiDoc::Controller::Request::Repository
|
10
|
-
|
11
|
+
# Params can be defined in several ways:
|
12
|
+
# 1. parameter :name, type: :string
|
13
|
+
#
|
14
|
+
# 2. parameter {
|
15
|
+
# dose_form_attributes: { model: 'Rxnorm::RxDoseForm' },
|
16
|
+
# input_method_attributes: { model: 'TreatmentInfo::InputMethod' },
|
17
|
+
# input_condition_attributes: { model: 'Drugs::InputCondition' },
|
18
|
+
# input_duration_attributes: { model: 'Drugs::InputDuration' }
|
19
|
+
# }, type: :object do
|
20
|
+
# parameter :id
|
21
|
+
# parameter :name
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# 3. parameter :name, :code, type: :string
|
25
|
+
#
|
26
|
+
def parameter(*arguments, &block)
|
27
|
+
options = arguments.extract_options!
|
28
|
+
|
11
29
|
raise ArgumentError, 'Parameter already defined.' if repo.key?(name)
|
12
30
|
|
13
31
|
validate_options(options, block_given?)
|
14
32
|
|
15
|
-
|
33
|
+
arguments.each do |param|
|
34
|
+
# 2)
|
35
|
+
if param.is_a?(Hash)
|
36
|
+
param.each do |param_name, additional_options|
|
37
|
+
_options = options.merge(additional_options)
|
38
|
+
|
39
|
+
define_parameter(param_name, _options, &block)
|
40
|
+
end
|
41
|
+
else # 1), 3)
|
42
|
+
define_parameter(param, options, &block)
|
43
|
+
end
|
44
|
+
end
|
16
45
|
end
|
17
46
|
|
18
47
|
private
|
19
48
|
|
20
|
-
def validate_options(options,
|
49
|
+
def validate_options(options, _block_given)
|
21
50
|
options.assert_valid_keys(RailsApiDoc::Controller::Param::VALID_KEYS)
|
22
51
|
|
23
52
|
RailsApiDoc::Controller::Request::Param.valid_type?(options[:type])
|
@@ -4,11 +4,11 @@ class RailsApiDoc::Controller::Request::Factory
|
|
4
4
|
class << self
|
5
5
|
|
6
6
|
def repo
|
7
|
-
|
7
|
+
repo = RailsApiDoc::Controller::Request::Repository.new
|
8
8
|
|
9
|
-
|
9
|
+
repo.repo = merge_attributes_from_model repo.repo
|
10
10
|
|
11
|
-
|
11
|
+
repo
|
12
12
|
end
|
13
13
|
|
14
14
|
def registered_controllers
|
@@ -21,7 +21,7 @@ class RailsApiDoc::Controller::Request::Factory
|
|
21
21
|
# do not mutate attributes
|
22
22
|
#
|
23
23
|
def merge_attributes_from_model(attributes)
|
24
|
-
RailsApiDoc::Model::AttributeMerger.new(attributes
|
24
|
+
RailsApiDoc::Model::AttributeMerger.new(attributes, 'request').call
|
25
25
|
end
|
26
26
|
|
27
27
|
end
|
@@ -8,11 +8,7 @@ class RailsApiDoc::Controller::Response::Factory
|
|
8
8
|
# TODO: add more options later depending on app settings
|
9
9
|
# TODO: rename to :load_repo
|
10
10
|
def repo
|
11
|
-
|
12
|
-
|
13
|
-
attributes = merge_attributes_from_model attributes
|
14
|
-
|
15
|
-
attributes
|
11
|
+
RailsApiDoc::Controller::Response::Repository.new(repository.repo)
|
16
12
|
end
|
17
13
|
|
18
14
|
def controllers
|
@@ -25,13 +21,6 @@ class RailsApiDoc::Controller::Response::Factory
|
|
25
21
|
@repo ||= ::RailsApiDoc::Controller::Response::Rabl.new(controllers)
|
26
22
|
end
|
27
23
|
|
28
|
-
#
|
29
|
-
# do not mutate attributes
|
30
|
-
#
|
31
|
-
def merge_attributes_from_model(attributes)
|
32
|
-
RailsApiDoc::Model::AttributeMerger.new(attributes).call(api_type: 'response')
|
33
|
-
end
|
34
|
-
|
35
24
|
end
|
36
25
|
|
37
26
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# author: Vadim Shaveiko <@vshaveyko>
|
1
3
|
# :nodoc:
|
2
4
|
class RailsApiDoc::Controller::Response::Repository
|
3
5
|
|
@@ -5,7 +7,15 @@ class RailsApiDoc::Controller::Response::Repository
|
|
5
7
|
include RailsApiDoc::Controller::Response::Headers
|
6
8
|
|
7
9
|
def initialize(repo)
|
8
|
-
@repo = repo.clone.transform_values
|
10
|
+
@repo = repo.clone.transform_values(&:deep_dup)
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_attrs(ctrl, action)
|
14
|
+
at = load_template(ctrl, action)&.nodes || {}
|
15
|
+
|
16
|
+
at = RailsApiDoc::Model::AttributeMerger.new(at, 'response').merge_action(action: action, ctrl: ctrl)
|
17
|
+
|
18
|
+
at
|
9
19
|
end
|
10
20
|
|
11
21
|
def load_template(ctrl, action)
|
@@ -1,14 +1,19 @@
|
|
1
|
-
# :
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# author: Vadim Shaveiko <@vshaveyko>
|
2
3
|
module RailsApiDoc
|
3
4
|
module Controller
|
4
5
|
module ResourceParams
|
5
|
-
module DSL
|
6
|
+
module DSL # :nodoc:
|
6
7
|
|
7
8
|
include RailsApiDoc::Controller::ResourceParams::PermittedParams # implements params_to_permit
|
8
9
|
|
9
|
-
def
|
10
|
+
def strong_params(pars = params)
|
11
|
+
#
|
10
12
|
# accepted_params for permit
|
11
|
-
|
13
|
+
#
|
14
|
+
permitted = params_to_permit(pars)
|
15
|
+
|
16
|
+
pars.permit(permitted)
|
12
17
|
end
|
13
18
|
|
14
19
|
end
|
@@ -7,8 +7,8 @@ module RailsApiDoc
|
|
7
7
|
|
8
8
|
private
|
9
9
|
|
10
|
-
def params_to_permit
|
11
|
-
_next_nesting_level(
|
10
|
+
def params_to_permit(pars = params)
|
11
|
+
_next_nesting_level(pars, param_data: _permitted_params)
|
12
12
|
end
|
13
13
|
|
14
14
|
def _permitted_params
|
@@ -32,7 +32,6 @@ module RailsApiDoc
|
|
32
32
|
level_accepted_params
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
35
|
#
|
37
36
|
# loop through current level of params and add to permit level if all requirements are met
|
38
37
|
#
|
@@ -47,6 +46,10 @@ module RailsApiDoc
|
|
47
46
|
#
|
48
47
|
def loop_params(params, level_permitted_params, accepted_params)
|
49
48
|
level_permitted_params.each do |param_name, api_param_data|
|
49
|
+
if api_param_data.value&.respond_to?(:call)
|
50
|
+
params[param_name] = api_param_data.value.call(params[param_name])
|
51
|
+
end
|
52
|
+
|
50
53
|
controller_param = params[param_name]
|
51
54
|
|
52
55
|
_check_required(param_name, controller_param, api_param_data) # raise if required and no value
|
@@ -63,7 +66,6 @@ module RailsApiDoc
|
|
63
66
|
param_data: api_param_data.nested,
|
64
67
|
current_accepted_params: accepted_params,
|
65
68
|
param_name: param_name)
|
66
|
-
|
67
69
|
end
|
68
70
|
elsif api_param_data.nested? # value should be nested object
|
69
71
|
_next_nesting_level(controller_param,
|
@@ -6,53 +6,58 @@ class RailsApiDoc::Model::AttributeMerger
|
|
6
6
|
MODEL = RailsApiDoc::ApiDatum
|
7
7
|
MERGABLE_FIELDS = [:type, :desc, :action_type].freeze
|
8
8
|
|
9
|
+
@@data = MODEL.all
|
10
|
+
|
9
11
|
#
|
10
12
|
# do not mutate attributes
|
11
13
|
#
|
12
14
|
# please - impossible
|
13
15
|
#
|
14
|
-
def initialize(attributes)
|
15
|
-
@attrs = attributes
|
16
|
+
def initialize(attributes, api_type)
|
17
|
+
@attrs = attributes.stringify_keys
|
18
|
+
@api_type = api_type
|
16
19
|
end
|
17
20
|
|
18
|
-
def
|
19
|
-
@api_type
|
21
|
+
def merge_action(action:, ctrl:)
|
22
|
+
merge_data = @@data.select { |d| d.api_type == @api_type && d.api_action == action.to_s && d.nesting.first == ctrl.name }
|
20
23
|
|
21
|
-
|
22
|
-
_add_nested_param(param)
|
24
|
+
merge_data.each do |param|
|
25
|
+
_add_nested_param(param, param.nesting[1..-1], @attrs)
|
23
26
|
end
|
24
27
|
|
25
28
|
@attrs
|
26
29
|
end
|
27
30
|
|
28
|
-
|
31
|
+
def call
|
32
|
+
api_params = @@data.select { |d| d.api_type == @api_type }.each do |param|
|
33
|
+
#
|
34
|
+
# nesting should be present for parameter to appear
|
35
|
+
#
|
36
|
+
next unless param.name && param.nesting.present?
|
29
37
|
|
30
|
-
|
31
|
-
# nesting should be present for parameter to appear
|
32
|
-
return if param.nesting.blank?
|
38
|
+
attrs, nesting, name = _parse_settings(param)
|
33
39
|
|
34
|
-
|
40
|
+
_add_nested_param(param, nesting, attrs)
|
41
|
+
end
|
35
42
|
|
36
|
-
|
43
|
+
@attrs
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
37
47
|
|
38
|
-
|
48
|
+
def _add_nested_param(param, nesting, attrs)
|
49
|
+
ctrl_param = _find_param(nesting, param.name, attrs)
|
39
50
|
|
40
51
|
ctrl_param.param = param
|
41
52
|
# _merge_data_to_param(ctrl_param, param)
|
42
53
|
end
|
43
54
|
|
44
55
|
def _parse_settings(param)
|
45
|
-
ctrl = param.nesting[0]
|
56
|
+
ctrl = param.nesting[0]
|
46
57
|
nesting = param.nesting[1..-1]
|
47
58
|
name = param.name&.to_sym
|
48
59
|
attrs = @attrs[ctrl]
|
49
60
|
|
50
|
-
#
|
51
|
-
# making exception
|
52
|
-
# until request parameters are not split by actions
|
53
|
-
#
|
54
|
-
attrs = attrs[param.api_action] if @api_type == 'response'
|
55
|
-
|
56
61
|
[attrs, nesting, name]
|
57
62
|
end
|
58
63
|
|
@@ -82,18 +87,18 @@ class RailsApiDoc::Model::AttributeMerger
|
|
82
87
|
end
|
83
88
|
end
|
84
89
|
|
85
|
-
def _find_param(
|
86
|
-
|
87
|
-
|
90
|
+
def _find_param(nest, name, attrs)
|
91
|
+
nest.each do |model|
|
92
|
+
#
|
93
|
+
# model on different fields because of wrong nesting sturcture for request
|
94
|
+
# TODO: fix this later
|
95
|
+
#
|
96
|
+
nested_attrs = attrs.detect { |k, v| v.nested? && (v.model == model || k.to_s == model) }
|
88
97
|
|
89
98
|
attrs = nested_attrs ? nested_attrs : _define_nesting_level(attrs, name, model)
|
90
99
|
end
|
91
100
|
|
92
|
-
|
93
|
-
attrs[name]
|
94
|
-
else
|
95
|
-
attrs[name] = _init_param_for_api_type(name)
|
96
|
-
end
|
101
|
+
attrs[name] ||= _init_param_for_api_type(name, {})
|
97
102
|
end
|
98
103
|
|
99
104
|
def _define_nesting_level(attrs, name, model)
|
@@ -123,7 +128,7 @@ class RailsApiDoc::Model::AttributeMerger
|
|
123
128
|
if @api_type == 'request'
|
124
129
|
RailsApiDoc::Controller::Request::Param.new(name, options, is_new: true)
|
125
130
|
elsif @api_type == 'response'
|
126
|
-
RailsApiDoc::Controller::Response::Param.new(name, name, options[:nested], options[:model],
|
131
|
+
RailsApiDoc::Controller::Response::Param.new(name, name, options[:nested], options[:model], nil, options[:type], is_new: true)
|
127
132
|
end
|
128
133
|
end
|
129
134
|
|
data/lib/rails_api_doc.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# author: Vadim Shaveiko <@vshaveyko>
|
2
2
|
# frozen_string_literal: true
|
3
3
|
module RailsApiDoc
|
4
|
-
|
4
|
+
|
5
|
+
NESTED_TYPES = [:ary_object, :object, :json].freeze
|
5
6
|
|
6
|
-
STRAIGHT_TYPES = [:bool, :string, :integer, :array, :datetime, :enum].freeze
|
7
|
+
STRAIGHT_TYPES = [:bool, :string, :integer, :array, :datetime, :enum, :model].freeze
|
7
8
|
|
8
9
|
ACCEPTED_TYPES = (NESTED_TYPES + STRAIGHT_TYPES).freeze
|
9
10
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_api_documentation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- vs
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|