swagger_autogenerate 1.2.8 → 2.0.0

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
  SHA256:
3
- metadata.gz: 7edebbaf56232cc63c6ba0084ae9536053f6b45f18763bc6718952da9e4b7e95
4
- data.tar.gz: 91f05f795c8b81451d25c4997a08f176bc034a576e6a5db6c20782ae9c805cb2
3
+ metadata.gz: b2c5c12b58edcd185c9831efb1c2e2f01053281858e6ec0ae85c149a3f3a2f71
4
+ data.tar.gz: 1c6e7a1d15457fd89837315cbfaf5b41631047def4df33a5ba382d6c5382b3c3
5
5
  SHA512:
6
- metadata.gz: 56e031eacfa7c2f47e2f35d652a68e059a56de0862b90a3af09574d186fddeef100becc70b52333a087209fe288d52adf3c54663f40c1caa5e4c3677057ef997
7
- data.tar.gz: e7d9bcdc321318de22bed1f26af8119c27411254d47213bb86e01d29ac297853d9aa84f8caf797b3647235ed37c4b2e37778ea81791ee1e24902828fbce84c87
6
+ metadata.gz: 96261e06a8de505e0513f89c0aec39ca76ddf054412c117c29510310581312f5ca957184250e750f29a9b88674dc7ffa5e3a5abfa43d8f0e537504a078b3fe7f
7
+ data.tar.gz: 1f11a7ae9e1551f88fa2e4739f49edd4e3a1c5c7dc11004dc5a79721428622eee7dd05a10bfe7649f2863d4781efb1cf6d15915d2de16d90484774463eb8495c
data/CHANGELOG.md CHANGED
@@ -1,24 +1,43 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.1] - 2024-05-27
4
- ## [1.0.2] - 2024-05-31
5
- ## [1.0.3] - 2024-05-31
6
- ## [1.0.4] - 2024-06-01
7
- ## [1.0.5] - 2024-06-01
8
- ## [1.0.6] - 2024-06-01
9
- ## [1.0.7] - 2024-06-01
10
- ## [1.0.8] - 2024-06-03
11
- ## [1.0.9] - 2024-06-04
12
- ## [1.1.0] - 2024-06-23
13
- ## [1.1.1] - 2024-06-26
14
- ## [1.1.2] - 2024-08-17
15
- ## [1.2.0] - 2024-09-08
16
- ## [1.2.1] - 2024-09-08
17
- ## [1.2.2] - 2024-09-12
18
- ## [1.2.3] - 2024-09-12
19
- ## [1.2.4] - 2024-09-15
20
- ## [1.2.5] - 2024-09-15
21
- ## [1.2.6] - 2024-11-05
3
+ ## [2.0.0] - 2026-09-03
4
+
5
+ ### Breaking
6
+ - Default `security` is now `[]` (no project-specific `org_slug` / `locale` schemes)
7
+ - Default OpenAPI document is built from app name + empty `securitySchemes`
8
+ - Env-gated generation helpers renamed conceptually to `SwaggerAutogenerate.generate?` (`allow_swagger?` still works)
9
+ - Internal code split into focused classes (public configure API unchanged in spirit)
10
+
11
+ ### Added
12
+ - Railtie auto-includes into `ApplicationController` in the configured test environment
13
+ - RSpec test suite for configuration, helpers, schema/params/responses, and YAML generation
14
+ - rswag-friendly `default_path` resolution (`swagger` / `swagger/v1`)
15
+ - Ergonomic config: `info_title`, `servers`, `security_schemes`, `auto_include`
16
+
17
+ ### Improved
18
+ - README for rswag-api / rswag-ui usage
19
+ - Clearer module layout under `lib/swagger_autogenerate/`
20
+
21
+ ## [1.2.9] - 2025-11-24
22
22
  ## [1.2.8] - 2024-11-05
23
+ ## [1.2.6] - 2024-11-05
24
+ ## [1.2.5] - 2024-09-15
25
+ ## [1.2.4] - 2024-09-15
26
+ ## [1.2.3] - 2024-09-12
27
+ ## [1.2.2] - 2024-09-12
28
+ ## [1.2.1] - 2024-09-08
29
+ ## [1.2.0] - 2024-09-08
30
+ ## [1.1.2] - 2024-08-17
31
+ ## [1.1.1] - 2024-06-26
32
+ ## [1.1.0] - 2024-06-23
33
+ ## [1.0.9] - 2024-06-04
34
+ ## [1.0.8] - 2024-06-03
35
+ ## [1.0.7] - 2024-06-01
36
+ ## [1.0.6] - 2024-06-01
37
+ ## [1.0.5] - 2024-06-01
38
+ ## [1.0.4] - 2024-06-01
39
+ ## [1.0.3] - 2024-05-31
40
+ ## [1.0.2] - 2024-05-31
41
+ ## [0.1.1] - 2024-05-27
23
42
 
24
43
  - Initial release
data/README.md CHANGED
@@ -1,77 +1,193 @@
1
- # SwaggerAutogenerate
2
- automating Swagger YAML generation in Ruby on Rails offers a range of benefits for API documentation. By leveraging the power of the swagger_autogenerate gem, developers can:
3
- 1) save time and effort
4
- 2) (up to date) reducing the chances of inconsistencies between the actual API implementation and its documentation.
5
- 3) improves the overall development workflow by providing a seamless integration with testing frameworks like RSpec.
6
- 4) resulting in better communication and understanding of the APIs.
1
+ # Swagger Autogenerate
7
2
 
8
- The gem automatically observes the request/response patterns during the execution of test scenarios, generating accurate Swagger YAML files that reflect the API's behavior. developers and consumers can better understand and interact with the APIs.
3
+ Generate **OpenAPI / Swagger YAML** from your existing Rails RSpec request (or controller) specs.
4
+
5
+ Designed to drop into projects that already use **`rswag-api`** and **`rswag-ui`**: run specs → YAML lands under `swagger/` (or `swagger/v1/`) → rswag serves and renders it.
6
+
7
+ ## Why
8
+
9
+ - Keep docs in sync with real request/response behavior from tests
10
+ - No hand-maintained path definitions for happy-path coverage
11
+ - Works with any Rails app; rswag-friendly defaults out of the box
9
12
 
10
13
  ## Dependencies
11
14
 
12
- The SwaggerAutogenerate gem depends on the rspec-rails gem, which brings the RSpec testing framework to Ruby on Rails.
13
- Please install rspec-rails first: https://github.com/rspec/rspec-rails
14
- Then continue the installation process.
15
+ - Ruby `>= 2.7`
16
+ - Rails `>= 5.2`
17
+ - [rspec-rails](https://github.com/rspec/rspec-rails) in the host app
18
+ - Optional but recommended: [`rswag-api`](https://github.com/rswag/rswag) + [`rswag-ui`](https://github.com/rswag/rswag)
15
19
 
16
20
  ## Installation
17
21
 
18
- 1) Open your Gemfile located at ./Gemfile
19
- 2) Add the following line to the Gemfile within the appropriate group (e.g., :test):
22
+ Add to the test group:
20
23
 
21
- ```
22
- group :test do
23
- gem 'swagger_autogenerate'
24
- end
25
- ```
26
- 3) Install the gem and add to the application's Gemfile by executing:
27
- ```
28
- bundle install
29
- ```
24
+ ```ruby
25
+ group :test do
26
+ gem 'swagger_autogenerate'
27
+ end
28
+ ```
30
29
 
31
- ## Configuration
30
+ ```bash
31
+ bundle install
32
+ ```
33
+
34
+ ### With rswag
35
+
36
+ Typical Gemfile:
32
37
 
33
- To configure the swagger_autogenerate gem in your Rails application, follow these steps:
38
+ ```ruby
39
+ gem 'rswag-api'
40
+ gem 'rswag-ui'
34
41
 
35
- ### Step 1:
36
- 1) Open the app/controllers/application_controller.rb
37
- 2) Inside the class ApplicationController block.
38
- 3) Add the following code:
42
+ group :test do
43
+ gem 'rspec-rails'
44
+ gem 'swagger_autogenerate'
45
+ end
39
46
  ```
40
- include SwaggerAutogenerate if Rails.env.test?
47
+
48
+ Point rswag at the same folder this gem writes to (default `swagger` or `swagger/v1` when that directory exists).
49
+
50
+ ## Quick start
51
+
52
+ ### 1. Auto-include (default)
53
+
54
+ In **test**, the gem Railtie includes itself into `ApplicationController` automatically.
55
+
56
+ You can still include manually if you prefer:
57
+
58
+ ```ruby
59
+ # app/controllers/application_controller.rb
60
+ include SwaggerAutogenerate if Rails.env.test?
61
+ ```
62
+
63
+ Disable auto-include:
64
+
65
+ ```ruby
66
+ # config/initializers/swagger_autogenerate.rb
67
+ SwaggerAutogenerate.configure do |config|
68
+ config.auto_include = false
69
+ end
70
+ ```
71
+
72
+ ### 2. Generate docs from specs
73
+
74
+ Write a normal file path (recommended with rswag):
75
+
76
+ ```bash
77
+ SWAGGER_GENERATE_PATH='swagger/v1/swagger.yaml' bundle exec rspec spec/requests/users_spec.rb
41
78
  ```
42
79
 
43
- ### Step 2 (optional)
44
- 1) Create a file called swagger_autogenerate.rb in the ./config/initializers
45
- 2) Open the ./config/initializers/swagger_autogenerate.rb
46
- 3) Add the following code to the swagger_autogenerate.rb
80
+ Or generate one YAML file per controller tag under the default directory:
81
+
82
+ ```bash
83
+ SWAGGER_GENERATE=1 bundle exec rspec spec/requests/
84
+ # => swagger/users.yaml (or swagger/v1/users.yaml when that folder exists / is configured)
47
85
  ```
86
+
87
+ Generation only runs when:
88
+
89
+ 1. `SWAGGER_GENERATE_PATH` or `SWAGGER_GENERATE` is set, and
90
+ 2. `Rails.env` matches `config.environment_name` (default `:test`)
91
+
92
+ Without those env vars, specs run normally and nothing is written.
93
+
94
+ ## Configuration
95
+
96
+ Optional initializer — **only override what you need**. Defaults are project-agnostic (empty security, app name as title, `swagger` output path).
97
+
98
+ ```ruby
99
+ # config/initializers/swagger_autogenerate.rb
48
100
  SwaggerAutogenerate.configure do |config|
49
- config.with_config = true
50
- config.with_multiple_examples = true
51
- action_for_old_examples = :append # :replace or :append
52
- config.with_response_description = true
101
+ # Where SWAGGER_GENERATE writes files (rswag default layout)
102
+ config.default_path = 'swagger/v1'
103
+
104
+ # OpenAPI info (auto title = Rails app module name when unset)
105
+ config.info_title = 'My API'
106
+ config.info_description = 'Public HTTP API'
107
+ config.info_version = '1.0.0'
108
+ config.openapi_version = '3.0.1'
109
+ config.servers = [{ 'url' => 'https://api.example.com' }]
110
+
111
+ # Auth for rswag / OpenAPI
112
+ config.security_schemes = {
113
+ 'bearerAuth' => {
114
+ 'type' => 'http',
115
+ 'scheme' => 'bearer',
116
+ 'bearerFormat' => 'JWT'
117
+ }
118
+ }
119
+ config.security = [{ 'bearerAuth' => [] }]
120
+
121
+ # Behavior flags
122
+ config.with_config = true # write openapi/info/components header
123
+ config.with_multiple_examples = true # keep several response examples per status
124
+ config.with_rspec_examples = true # use RSpec example group description as example name
125
+ config.with_response_description = true # human-readable status descriptions
126
+ config.with_payload_properties = true # document request payload shapes per example
127
+ config.action_for_old_examples = :append # or :replace
128
+
129
+ # Env var names / environment gate (rarely changed)
130
+ config.swagger_path_environment_variable = 'SWAGGER_GENERATE_PATH'
131
+ config.generate_swagger_environment_variable = 'SWAGGER_GENERATE'
132
+ config.environment_name = :test
133
+ config.auto_include = true
53
134
  end
135
+ ```
136
+
137
+ ### Full document override
54
138
 
139
+ If you already maintain a root OpenAPI hash (or want zero magic):
140
+
141
+ ```ruby
142
+ SwaggerAutogenerate.configure do |config|
143
+ config.swagger_config = {
144
+ 'openapi' => '3.0.1',
145
+ 'info' => { 'title' => 'Custom', 'version' => '1.0.0' },
146
+ 'components' => { 'securitySchemes' => {} }
147
+ }
148
+ end
55
149
  ```
56
- $ This file is optional and allows you to customize the behavior of the gem by providing additional options.
150
+
151
+ ### Environment variables
152
+
153
+ | Variable | Purpose |
154
+ |---|---|
155
+ | `SWAGGER_GENERATE_PATH` | Exact `.yaml`/`.yml` file **or** a directory (one file per tag) |
156
+ | `SWAGGER_GENERATE` | Write under `config.default_path` (rswag-aware) |
157
+ | `tag` | Optional override for the OpenAPI tag / filename stem |
57
158
 
58
159
  ## Example
59
- To generate Swagger YAML documentation for the APIs implemented in the EmployeesController class, you can follow these steps:
60
- 1) Ensure that you have the swagger_autogenerate gem installed and configured in your Rails application, as described later.
61
- 2) Create a spec file for the EmployeesController class at the path:
62
- $ spec/your_path/employees_controller_spec.rb
63
- This file should contain the test scenarios for each action (e.g., index, show, create) of the controller.
64
160
 
65
- 3) Run the spec code using the rspec command and set the environment variable SWAGGER to the desired YAML file name. For example:
161
+ ```bash
162
+ SWAGGER_GENERATE_PATH='swagger/v1/swagger.yaml' \
163
+ bundle exec rspec spec/requests/employees_spec.rb
66
164
  ```
67
- SWAGGER_GENERATE_PATH='employee_apis.yaml' rspec spec/your_path/employees_controller_spec.rb
165
+
166
+ Coverage in the YAML matches what your examples actually hit (paths, statuses, bodies, query/path params). Prefer request specs that exercise real routes.
167
+
168
+ ## Library layout
169
+
170
+ ```
171
+ lib/swagger_autogenerate/
172
+ configuration.rb # defaults + customization
173
+ swagger_trace.rb # orchestrates one request/response
174
+ path_normalizer.rb # /users/1 → /users/{id}
175
+ parameter_builder.rb # parameters + requestBody
176
+ response_builder.rb # responses + examples
177
+ schema_builder.rb # type inference
178
+ document_writer.rb # read/write YAML
179
+ yaml_merger.rb # merge into existing document
180
+ helpers.rb
181
+ railtie.rb # auto-include in test
68
182
  ```
69
- 4) This command runs the spec file and instructs the swagger_autogenerate gem to generate Swagger YAML documentation and save it to the file named employee_apis.yaml.
70
- 5) Once the command finishes executing, you will have the Swagger YAML documentation generated based on the test scenarios in the employees_controller_spec.rb file.
71
183
 
72
- ### Please note
73
- that the generated documentation will depend on the test scenarios defined in your employees_controller_spec.rb file. Make sure to have comprehensive test scenarios that cover different scenarios and expected responses for accurate and detailed Swagger documentation.
184
+ ## Development
185
+
186
+ ```bash
187
+ bundle install
188
+ bundle exec rspec
189
+ ```
74
190
 
75
191
  ## License
76
192
 
77
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
193
+ MIT see [LICENSE.txt](LICENSE.txt).
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copy to config/initializers/swagger_autogenerate.rb and adjust as needed.
4
+ # Everything is optional — omit this file to use project-agnostic defaults.
5
+
6
+ SwaggerAutogenerate.configure do |config|
7
+ # rswag-api / rswag-ui usually serve files from swagger/v1
8
+ config.default_path = 'swagger/v1'
9
+
10
+ config.info_title = 'My API'
11
+ config.info_description = 'API documentation generated from request specs'
12
+ config.info_version = '1.0.0'
13
+ config.servers = [{ 'url' => 'http://localhost:3000' }]
14
+
15
+ # Example JWT security for OpenAPI / rswag-ui "Authorize"
16
+ # config.security_schemes = {
17
+ # 'bearerAuth' => {
18
+ # 'type' => 'http',
19
+ # 'scheme' => 'bearer',
20
+ # 'bearerFormat' => 'JWT'
21
+ # }
22
+ # }
23
+ # config.security = [{ 'bearerAuth' => [] }]
24
+
25
+ config.with_multiple_examples = true
26
+ config.with_rspec_examples = true
27
+ config.action_for_old_examples = :append # :replace
28
+ end
@@ -1,31 +1,118 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SwaggerAutogenerate
4
+ # Holds gem settings. Defaults work with any Rails app and rswag-api / rswag-ui.
5
+ #
6
+ # Override only what you need:
7
+ #
8
+ # SwaggerAutogenerate.configure do |config|
9
+ # config.default_path = 'swagger/v1'
10
+ # config.info_title = 'My API'
11
+ # config.security = [{ 'bearerAuth' => [] }]
12
+ # end
13
+ #
2
14
  class Configuration
3
- attr_accessor :with_config, :with_multiple_examples, :with_rspec_examples, :with_example_description,
4
- :with_response_description, :with_payload_properties, :swagger_path_environment_variable, :generate_swagger_environment_variable,
5
- :default_path, :environment_name, :security, :swagger_config, :response_status, :action_for_old_examples
15
+ ATTRS = %i[
16
+ with_config
17
+ with_multiple_examples
18
+ with_rspec_examples
19
+ with_example_description
20
+ with_response_description
21
+ with_payload_properties
22
+ swagger_path_environment_variable
23
+ generate_swagger_environment_variable
24
+ default_path
25
+ environment_name
26
+ security
27
+ swagger_config
28
+ response_status
29
+ action_for_old_examples
30
+ auto_include
31
+ info_title
32
+ info_description
33
+ info_version
34
+ openapi_version
35
+ servers
36
+ security_schemes
37
+ ].freeze
38
+
39
+ attr_accessor(*ATTRS)
6
40
 
7
41
  def initialize
42
+ apply_defaults!
43
+ end
44
+
45
+ def apply_defaults!
8
46
  @with_config = true
9
47
  @with_multiple_examples = true
10
48
  @with_rspec_examples = true
11
- # remove this when we do not need it any more
12
49
  @with_example_description = true
13
50
  @with_payload_properties = true
14
51
  @with_response_description = true
15
52
  @action_for_old_examples = :append # :replace or :append
16
53
  @swagger_path_environment_variable = 'SWAGGER_GENERATE_PATH'
17
54
  @generate_swagger_environment_variable = 'SWAGGER_GENERATE'
18
- @default_path = 'swagger'
55
+ @default_path = nil # resolved lazily (rswag-aware)
19
56
  @environment_name = :test
20
- @security = default_security
21
- @swagger_config = default_swagger_config
57
+ @auto_include = true
58
+ @security = []
22
59
  @response_status = default_response_status
60
+ @swagger_config = nil # resolved lazily
61
+ @info_title = nil
62
+ @info_description = 'API documentation generated from request specs'
63
+ @info_version = '1.0.0'
64
+ @openapi_version = '3.0.1'
65
+ @servers = []
66
+ @security_schemes = {}
67
+ end
68
+
69
+ # Directory under Rails.root where YAML files are written.
70
+ # Prefers rswag swagger root when available, otherwise "swagger".
71
+ def resolved_default_path
72
+ explicit = @default_path
73
+ return explicit if explicit.present?
74
+
75
+ rswag_path || 'swagger'
76
+ end
77
+
78
+ def resolved_swagger_config
79
+ return @swagger_config if @swagger_config.present?
80
+
81
+ {
82
+ 'openapi' => openapi_version,
83
+ 'info' => {
84
+ 'title' => resolved_info_title,
85
+ 'description' => info_description,
86
+ 'version' => info_version
87
+ },
88
+ 'servers' => servers,
89
+ 'components' => {
90
+ 'securitySchemes' => security_schemes
91
+ }
92
+ }
93
+ end
94
+
95
+ def resolved_info_title
96
+ return info_title if info_title.present?
97
+
98
+ app_class = defined?(Rails) && Rails.respond_to?(:application) && Rails.application&.class
99
+ return 'API' unless app_class
100
+
101
+ if app_class.respond_to?(:module_parent_name)
102
+ app_class.module_parent_name
103
+ elsif app_class.respond_to?(:parent_name)
104
+ app_class.parent_name
105
+ else
106
+ 'API'
107
+ end
108
+ rescue StandardError
109
+ 'API'
23
110
  end
24
111
 
25
112
  def default_response_status
26
113
  {
27
114
  100 => 'The initial part of the request has been received, and the client should proceed with sending the remainder of the request',
28
- 101 => 'The server agrees to switch protocols and is acknowledging the client\'s request to change the protocol being used',
115
+ 101 => "The server agrees to switch protocols and is acknowledging the client's request to change the protocol being used",
29
116
  200 => 'The request has succeeded',
30
117
  201 => 'The request has been fulfilled, and a new resource has been created as a result. The newly created resource is returned in the response body',
31
118
  202 => 'The request has been accepted for processing, but the processing has not been completed. The response may contain an estimated completion time or other status information',
@@ -48,32 +135,18 @@ module SwaggerAutogenerate
48
135
  }
49
136
  end
50
137
 
51
- def default_swagger_config
52
- {
53
- 'openapi' => '3.0.0',
54
- 'info' => {
55
- 'title' => 'title',
56
- 'description' => 'description',
57
- 'version' => '1.0.0'
58
- },
59
- 'servers' => [],
60
- 'components' => {
61
- 'securitySchemes' => {
62
- 'locale' => {
63
- 'type' => 'apiKey',
64
- 'in' => 'query',
65
- 'name' => 'locale'
66
- }
67
- }
68
- }
69
- }
70
- end
138
+ private
139
+
140
+ def rswag_path
141
+ return unless defined?(Rails) && Rails.root
71
142
 
72
- def default_security
73
- [
74
- { 'org_slug' => [] },
75
- { 'locale' => [] }
76
- ]
143
+ # Common rswag layout: swagger/v1/swagger.yaml
144
+ return 'swagger/v1' if Rails.root.join('swagger/v1').directory?
145
+ return 'swagger' if Rails.root.join('swagger').directory?
146
+
147
+ nil
148
+ rescue StandardError
149
+ nil
77
150
  end
78
151
  end
79
152
 
@@ -84,4 +157,8 @@ module SwaggerAutogenerate
84
157
  def self.configure
85
158
  yield(configuration)
86
159
  end
160
+
161
+ def self.reset_configuration!
162
+ @configuration = Configuration.new
163
+ end
87
164
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module SwaggerAutogenerate
6
+ # Resolves output path and reads/writes Swagger YAML documents.
7
+ class DocumentWriter
8
+ def initialize(config:, tags:, request:)
9
+ @config = config
10
+ @tags = tags
11
+ @request = request
12
+ end
13
+
14
+ def location
15
+ return @location if defined?(@location)
16
+
17
+ generate_env = config.generate_swagger_environment_variable
18
+ path_env = config.swagger_path_environment_variable
19
+
20
+ @location =
21
+ if ENV[generate_env].present?
22
+ directory = Rails.root.join(config.resolved_default_path).to_s
23
+ FileUtils.mkdir_p(directory)
24
+ File.join(directory, "#{Helpers.snake_case(tags&.first)}.yaml")
25
+ elsif ENV[path_env].to_s.match?(/\.(ya?ml)\z/i)
26
+ Rails.root.join(ENV.fetch(path_env)).to_s
27
+ else
28
+ directory = Rails.root.join(ENV.fetch(path_env, config.resolved_default_path)).to_s
29
+ FileUtils.mkdir_p(directory)
30
+ File.join(directory, "#{Helpers.snake_case(tags&.first)}.yaml")
31
+ end
32
+ end
33
+
34
+ def exist?
35
+ File.exist?(location)
36
+ end
37
+
38
+ def read
39
+ return nil unless exist?
40
+
41
+ Helpers.load_yaml(location)
42
+ end
43
+
44
+ def write(data)
45
+ File.write(location, Helpers.dump_yaml(data))
46
+ end
47
+
48
+ def ensure_exists!
49
+ write({ 'paths' => {} }) unless exist?
50
+ end
51
+
52
+ private
53
+
54
+ attr_reader :config, :tags, :request
55
+ end
56
+ end