bullet_train-api 1.2.22 → 1.2.24

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
  SHA256:
3
- metadata.gz: b698e3c1efb4baded431f9971fd5102a93b4a582b3c23626a4c287d1f2158a53
4
- data.tar.gz: 6e44423ed7d5f4698372f7def585fbb5cf81c5caf1be0e64b315a1d21f443a1d
3
+ metadata.gz: 87ee8b24dbab751228f331fe26950afa6fe93f3525092767831bd9659ed5d6f5
4
+ data.tar.gz: 1f5f064679487f87b01e5d5940efc121b72f5dbe86586b8bd07e63b83406b3f9
5
5
  SHA512:
6
- metadata.gz: 9a53a06ce3d7620876c38ff9b4ddd89c7c19c18f044faf4158f276369a42fd7e1eec06df2f8ad58a52affb30f3fd88ce2aacfb6c2c7c96c03a4c2ff267d90119
7
- data.tar.gz: 83b4321431b744891209b52754499e796fb64ae6a8a1466d5bcf4482c79aad6f3a733d8f83abea15b1e6d425e9f497543db9bd21886a4f40aa730aa3957ff93e
6
+ metadata.gz: 897ae05b0fd124b0418ee6e242e570d7f20b76aafdc29b1ebcae3a44b76621f095f319ad00a7306edcf01f99b87b9b830289f38834dd3e7ab5aee92276629477
7
+ data.tar.gz: a5a7f22e19bb8137c60b814343a79a11905cc9e26c76f45691e5d9edb07d1cd13b18f2cd540f6d41f114d21c4c7f2761680f624bc39a378009d9a8772e0f180e
@@ -1,128 +1,5 @@
1
- module OpenApiHelper
2
- def indent(string, count)
3
- lines = string.lines
4
- first_line = lines.shift
5
- lines = lines.map { |line| (" " * count).to_s + line }
6
- lines.unshift(first_line).join.html_safe
7
- end
8
-
9
- # TODO: Remove this method? It's not being used anywhere
10
- def components_for(model)
11
- for_model model do
12
- indent(render("api/#{@version}/open_api/#{model.name.underscore.pluralize}/components"), 2)
13
- end
14
- end
15
-
16
- def current_model
17
- @model_stack.last
18
- end
19
-
20
- def for_model(model)
21
- @model_stack ||= []
22
- @model_stack << model
23
- result = yield
24
- @model_stack.pop
25
- result
26
- end
27
-
28
- def gem_paths
29
- @gem_paths ||= `bundle show --paths`.lines.map { |gem_path| gem_path.chomp }
30
- end
31
-
32
- def automatic_paths_for(model, parent, except: [])
33
- output = render("api/#{@version}/open_api/shared/paths", except: except)
34
- output = Scaffolding::Transformer.new(model.name, [parent&.name]).transform_string(output).html_safe
35
- indent(output, 1)
36
- end
37
-
38
- def automatic_components_for(model, locals: {})
39
- path = "app/views/api/#{@version}"
40
- paths = ([path] + gem_paths.map { |gem_path| "#{gem_path}/#{path}" })
41
- jbuilder = Jbuilder::Schema.renderer(paths, locals: {
42
- # If we ever get to the point where we need a real model here, we should implement an example team in seeds that we can source it from.
43
- model.name.underscore.split("/").last.to_sym => model.new,
44
- # Same here, if we ever need this to be a real object, this should be `test@example.com` with an `SecureRandom.hex` password.
45
- :current_user => User.new
46
- }.merge(locals))
47
-
48
- schema_json = jbuilder.json(
49
- model.new,
50
- title: I18n.t("#{model.name.underscore.pluralize}.label"),
51
- # TODO Improve this. We don't have a generic description for models we can use here.
52
- description: I18n.t("#{model.name.underscore.pluralize}.label"),
53
- )
54
-
55
- attributes_output = JSON.parse(schema_json)
56
-
57
- # Rails attachments aren't technically attributes in a model,
58
- # so we add the attributes manually to make them available in the API.
59
- if model.attachment_reflections.any?
60
- model.attachment_reflections.each do |reflection|
61
- attribute_name = reflection.first
62
-
63
- attributes_output["properties"][attribute_name] = {
64
- "type" => "object",
65
- "description" => attribute_name.titleize.to_s
66
- }
67
-
68
- attributes_output["example"].merge!({attribute_name.to_s => nil})
69
- end
70
- end
71
-
72
- if has_strong_parameters?("Api::#{@version.upcase}::#{model.name.pluralize}Controller".constantize)
73
- strong_params_module = "Api::#{@version.upcase}::#{model.name.pluralize}Controller::StrongParameters".constantize
74
- strong_parameter_keys = BulletTrain::Api::StrongParametersReporter.new(model, strong_params_module).report
75
- if strong_parameter_keys.last.is_a?(Hash)
76
- strong_parameter_keys += strong_parameter_keys.pop.keys
77
- end
78
-
79
- parameters_output = JSON.parse(schema_json)
80
- parameters_output["required"].select! { |key| strong_parameter_keys.include?(key.to_sym) }
81
- parameters_output["properties"].select! { |key, value| strong_parameter_keys.include?(key.to_sym) }
82
-
83
- (
84
- indent(attributes_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Attributes:"), 3) +
85
- indent(" " + parameters_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Parameters:"), 3)
86
- ).html_safe
87
- else
88
-
89
- indent(attributes_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Attributes:"), 3)
90
- .html_safe
91
- end
92
- end
93
-
94
- def paths_for(model)
95
- for_model model do
96
- indent(render("api/#{@version}/open_api/#{model.name.underscore.pluralize}/paths"), 1)
97
- end
98
- end
99
-
100
- def attribute(attribute)
101
- heading = t("#{current_model.name.underscore.pluralize}.fields.#{attribute}.heading")
102
- attribute_data = current_model.columns_hash[attribute.to_s]
103
-
104
- # Default to `string` when the type returns nil.
105
- type = attribute_data.nil? ? "string" : attribute_data.type
106
-
107
- attribute_block = <<~YAML
108
- #{attribute}:
109
- description: "#{heading}"
110
- type: #{type}
111
- YAML
112
- indent(attribute_block.chomp, 2)
113
- end
114
- alias_method :parameter, :attribute
115
-
116
- private
117
-
118
- def has_strong_parameters?(controller)
119
- methods = controller.action_methods
120
- methods.include?("create") || methods.include?("update")
121
- end
122
- end
123
-
124
1
  class Api::OpenApiController < ApplicationController
125
- helper :open_api
2
+ helper "api/open_api"
126
3
 
127
4
  def set_default_response_format
128
5
  request.format = :yaml
@@ -0,0 +1,148 @@
1
+ module Api
2
+ module OpenApiHelper
3
+ def indent(string, count)
4
+ lines = string.lines
5
+ first_line = lines.shift
6
+ lines = lines.map { |line| (" " * count).to_s + line }
7
+ lines.unshift(first_line).join.html_safe
8
+ end
9
+
10
+ # TODO: Remove this method? It's not being used anywhere
11
+ def components_for(model)
12
+ for_model model do
13
+ indent(render("api/#{@version}/open_api/#{model.name.underscore.pluralize}/components"), 2)
14
+ end
15
+ end
16
+
17
+ def current_model
18
+ @model_stack.last
19
+ end
20
+
21
+ def for_model(model)
22
+ @model_stack ||= []
23
+ @model_stack << model
24
+ result = yield
25
+ @model_stack.pop
26
+ result
27
+ end
28
+
29
+ def gem_paths
30
+ @gem_paths ||= `bundle show --paths`.lines.map { |gem_path| gem_path.chomp }
31
+ end
32
+
33
+ def automatic_paths_for(model, parent, except: [])
34
+ output = render("api/#{@version}/open_api/shared/paths", except: except)
35
+ output = Scaffolding::Transformer.new(model.name, [parent&.name]).transform_string(output).html_safe
36
+
37
+ # There are some placeholders specific to this method that we still need to transform.
38
+ model_symbol = model.name.underscore.tr("/", "_")
39
+
40
+ if (get_example = FactoryBot.get_example(model_symbol, version: @version))
41
+ output.gsub!("🚅 get_example", get_example)
42
+ end
43
+
44
+ if (post_parameters = FactoryBot.post_parameters(model_symbol, version: @version))
45
+ output.gsub!("🚅 post_parameters", post_parameters)
46
+ end
47
+
48
+ if (post_examples = FactoryBot.post_examples(model_symbol, version: @version))
49
+ output.gsub!("🚅 post_examples", post_examples)
50
+ end
51
+
52
+ if (put_parameters = FactoryBot.put_parameters(model_symbol, version: @version))
53
+ output.gsub!("🚅 put_parameters", put_parameters)
54
+ end
55
+
56
+ if (put_example = FactoryBot.put_example(model_symbol, version: @version))
57
+ output.gsub!("🚅 put_example", put_example)
58
+ end
59
+
60
+ indent(output, 1)
61
+ end
62
+
63
+ def automatic_components_for(model, locals: {})
64
+ path = "app/views/api/#{@version}"
65
+ paths = ([path] + gem_paths.map { |gem_path| "#{gem_path}/#{path}" })
66
+ jbuilder = Jbuilder::Schema.renderer(paths, locals: {
67
+ # If we ever get to the point where we need a real model here, we should implement an example team in seeds that we can source it from.
68
+ model.name.underscore.split("/").last.to_sym => model.new,
69
+ # Same here, if we ever need this to be a real object, this should be `test@example.com` with an `SecureRandom.hex` password.
70
+ :current_user => User.new
71
+ }.merge(locals))
72
+
73
+ schema_json = jbuilder.json(
74
+ model.new,
75
+ title: I18n.t("#{model.name.underscore.pluralize}.label"),
76
+ # TODO Improve this. We don't have a generic description for models we can use here.
77
+ description: I18n.t("#{model.name.underscore.pluralize}.label"),
78
+ )
79
+
80
+ attributes_output = JSON.parse(schema_json)
81
+
82
+ # Rails attachments aren't technically attributes in a model,
83
+ # so we add the attributes manually to make them available in the API.
84
+ if model.attachment_reflections.any?
85
+ model.attachment_reflections.each do |reflection|
86
+ attribute_name = reflection.first
87
+
88
+ attributes_output["properties"][attribute_name] = {
89
+ "type" => "object",
90
+ "description" => attribute_name.titleize.to_s
91
+ }
92
+
93
+ attributes_output["example"].merge!({attribute_name.to_s => nil})
94
+ end
95
+ end
96
+
97
+ if has_strong_parameters?("Api::#{@version.upcase}::#{model.name.pluralize}Controller".constantize)
98
+ strong_params_module = "Api::#{@version.upcase}::#{model.name.pluralize}Controller::StrongParameters".constantize
99
+ strong_parameter_keys = BulletTrain::Api::StrongParametersReporter.new(model, strong_params_module).report
100
+ if strong_parameter_keys.last.is_a?(Hash)
101
+ strong_parameter_keys += strong_parameter_keys.pop.keys
102
+ end
103
+
104
+ parameters_output = JSON.parse(schema_json)
105
+ parameters_output["required"].select! { |key| strong_parameter_keys.include?(key.to_sym) }
106
+ parameters_output["properties"].select! { |key, value| strong_parameter_keys.include?(key.to_sym) }
107
+
108
+ (
109
+ indent(attributes_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Attributes:"), 3) +
110
+ indent(" " + parameters_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Parameters:"), 3)
111
+ ).html_safe
112
+ else
113
+
114
+ indent(attributes_output.to_yaml.gsub("---", "#{model.name.gsub("::", "")}Attributes:"), 3)
115
+ .html_safe
116
+ end
117
+ end
118
+
119
+ def paths_for(model)
120
+ for_model model do
121
+ indent(render("api/#{@version}/open_api/#{model.name.underscore.pluralize}/paths"), 1)
122
+ end
123
+ end
124
+
125
+ def attribute(attribute)
126
+ heading = t("#{current_model.name.underscore.pluralize}.fields.#{attribute}.heading")
127
+ attribute_data = current_model.columns_hash[attribute.to_s]
128
+
129
+ # Default to `string` when the type returns nil.
130
+ type = attribute_data.nil? ? "string" : attribute_data.type
131
+
132
+ attribute_block = <<~YAML
133
+ #{attribute}:
134
+ description: "#{heading}"
135
+ type: #{type}
136
+ YAML
137
+ indent(attribute_block.chomp, 2)
138
+ end
139
+ alias_method :parameter, :attribute
140
+
141
+ private
142
+
143
+ def has_strong_parameters?(controller)
144
+ methods = controller.action_methods
145
+ methods.include?("create") || methods.include?("update")
146
+ end
147
+ end
148
+ end
@@ -4,7 +4,7 @@
4
4
  <% unless except.include?(:index) %>
5
5
  get:
6
6
  tags:
7
- - "Scaffolding/Completely Concrete/Tangible Things"
7
+ - Scaffolding::CompletelyConcrete::TangibleThing
8
8
  summary: "List Tangible Things"
9
9
  operationId: listScaffoldingCompletelyConcreteTangibleThings
10
10
  parameters:
@@ -30,11 +30,13 @@
30
30
  type: array
31
31
  items:
32
32
  $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingAttributes"
33
+ example:
34
+ 🚅 get_example
33
35
  <% end %>
34
36
  <% unless except.include?(:create) %>
35
37
  post:
36
38
  tags:
37
- - "Scaffolding/Completely Concrete/Tangible Things"
39
+ - Scaffolding::CompletelyConcrete::TangibleThing
38
40
  summary: "Create Tangible Thing"
39
41
  operationId: createScaffoldingCompletelyConcreteTangibleThings
40
42
  parameters:
@@ -54,6 +56,8 @@
54
56
  scaffolding_completely_concrete_tangible_thing:
55
57
  type: object
56
58
  $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingParameters"
59
+ example:
60
+ 🚅 post_parameters
57
61
  responses:
58
62
  "404":
59
63
  description: "Not Found"
@@ -63,6 +67,8 @@
63
67
  application/json:
64
68
  schema:
65
69
  $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingAttributes"
70
+ example:
71
+ 🚅 post_examples
66
72
  <% end %>
67
73
  <% end %>
68
74
  <% unless except.include?(:show) && except.include?(:update) && except.include?(:destroy) %>
@@ -70,7 +76,7 @@
70
76
  <% unless except.include?(:show) %>
71
77
  get:
72
78
  tags:
73
- - "Scaffolding/Completely Concrete/Tangible Things"
79
+ - Scaffolding::CompletelyConcrete::TangibleThing
74
80
  summary: "Fetch Tangible Thing"
75
81
  operationId: getScaffoldingCompletelyConcreteTangibleThings
76
82
  parameters:
@@ -84,11 +90,13 @@
84
90
  application/json:
85
91
  schema:
86
92
  $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingAttributes"
93
+ example:
94
+ 🚅 get_example
87
95
  <% end %>
88
96
  <% unless except.include?(:update) %>
89
97
  put:
90
98
  tags:
91
- - "Scaffolding/Completely Concrete/Tangible Things"
99
+ - Scaffolding::CompletelyConcrete::TangibleThing
92
100
  summary: "Update Tangible Thing"
93
101
  operationId: updateScaffoldingCompletelyConcreteTangibleThings
94
102
  parameters:
@@ -104,6 +112,8 @@
104
112
  scaffolding_completely_concrete_tangible_thing:
105
113
  type: object
106
114
  $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingParameters"
115
+ example:
116
+ 🚅 put_parameters
107
117
  responses:
108
118
  "404":
109
119
  description: "Not Found"
@@ -113,11 +123,13 @@
113
123
  application/json:
114
124
  schema:
115
125
  $ref: "#/components/schemas/ScaffoldingCompletelyConcreteTangibleThingAttributes"
126
+ example:
127
+ 🚅 put_example
116
128
  <% end %>
117
129
  <% unless except.include?(:destroy) %>
118
130
  delete:
119
131
  tags:
120
- - "Scaffolding/Completely Concrete/Tangible Things"
132
+ - Scaffolding::CompletelyConcrete::TangibleThing
121
133
  summary: "Remove Tangible Thing"
122
134
  operationId: removeScaffoldingCompletelyConcreteTangibleThings
123
135
  parameters:
@@ -1,7 +1,7 @@
1
1
  /teams:
2
2
  get:
3
3
  tags:
4
- - Teams
4
+ - Team
5
5
  summary: "List Teams"
6
6
  operationId: listTeams
7
7
  parameters:
@@ -22,10 +22,13 @@
22
22
  type: array
23
23
  items:
24
24
  $ref: "#/components/schemas/TeamAttributes"
25
+ example:
26
+ <%= FactoryBot.get_examples(:team, version: @version) %>
27
+
25
28
  /teams/{id}:
26
29
  get:
27
30
  tags:
28
- - Teams
31
+ - Team
29
32
  summary: "Fetch Team"
30
33
  operationId: fetchTeam
31
34
  parameters:
@@ -39,9 +42,11 @@
39
42
  application/json:
40
43
  schema:
41
44
  $ref: "#/components/schemas/TeamAttributes"
45
+ example:
46
+ <%= FactoryBot.get_example(:team, version: @version) %>
42
47
  put:
43
48
  tags:
44
- - Teams
49
+ - Team
45
50
  summary: "Update Team"
46
51
  operationId: updateTeam
47
52
  parameters:
@@ -57,6 +62,8 @@
57
62
  team:
58
63
  type: object
59
64
  $ref: "#/components/schemas/TeamParameters"
65
+ example:
66
+ <%= FactoryBot.put_parameters(:team, version: @version) %>
60
67
  responses:
61
68
  "404":
62
69
  description: "Not Found"
@@ -66,3 +73,5 @@
66
73
  application/json:
67
74
  schema:
68
75
  $ref: "#/components/schemas/TeamAttributes"
76
+ example:
77
+ <%= FactoryBot.put_example(:team, version: @version) %>
@@ -1,7 +1,7 @@
1
1
  /users:
2
2
  get:
3
3
  tags:
4
- - Users
4
+ - User
5
5
  summary: "List Users"
6
6
  operationId: listUsers
7
7
  parameters:
@@ -22,10 +22,12 @@
22
22
  type: array
23
23
  items:
24
24
  $ref: "#/components/schemas/UserAttributes"
25
+ example:
26
+ <%= FactoryBot.get_examples(:user, version: @version) %>
25
27
  /users/{id}:
26
28
  get:
27
29
  tags:
28
- - Users
30
+ - User
29
31
  summary: "Fetch User"
30
32
  operationId: fetchUser
31
33
  parameters:
@@ -39,9 +41,11 @@
39
41
  application/json:
40
42
  schema:
41
43
  $ref: "#/components/schemas/UserAttributes"
44
+ example:
45
+ <%= FactoryBot.get_example(:user, version: @version) %>
42
46
  put:
43
47
  tags:
44
- - Users
48
+ - User
45
49
  summary: "Update User"
46
50
  operationId: updateUser
47
51
  parameters:
@@ -57,6 +61,8 @@
57
61
  user:
58
62
  type: object
59
63
  $ref: "#/components/schemas/UserParameters"
64
+ example:
65
+ <%= FactoryBot.put_parameters(:user, version: @version) %>
60
66
  responses:
61
67
  "404":
62
68
  description: "Not Found"
@@ -66,3 +72,5 @@
66
72
  application/json:
67
73
  schema:
68
74
  $ref: "#/components/schemas/UserAttributes"
75
+ example:
76
+ <%= FactoryBot.put_example(:user, version: @version) %>
@@ -0,0 +1,151 @@
1
+ require_relative "../../../app/helpers/api/open_api_helper"
2
+
3
+ module FactoryBot
4
+ module ExampleBot
5
+ attr_accessor :tables_to_reset
6
+
7
+ def example(model, **options)
8
+ @tables_to_reset = [model.to_s.pluralize]
9
+
10
+ object = nil
11
+
12
+ ActiveRecord::Base.transaction do
13
+ instance = FactoryBot.create(factory(model), **options)
14
+ object = deep_clone(instance)
15
+
16
+ raise ActiveRecord::Rollback
17
+ end
18
+
19
+ reset_tables!
20
+ object
21
+ end
22
+
23
+ def example_list(model, quantity, **options)
24
+ @tables_to_reset = [model.to_s.pluralize]
25
+
26
+ objects = []
27
+
28
+ ActiveRecord::Base.transaction do
29
+ instances = FactoryBot.create_list(factory(model), quantity, **options)
30
+
31
+ instances.each do |instance|
32
+ objects << deep_clone(instance)
33
+ end
34
+
35
+ raise ActiveRecord::Rollback
36
+ end
37
+
38
+ reset_tables!
39
+ objects
40
+ end
41
+
42
+ %i[get_examples get_example post_examples post_parameters put_example put_parameters patch_example patch_parameters].each do |method|
43
+ define_method(method) do |model, **options|
44
+ _path_examples(method.to_s, model, **options)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def factory(model)
51
+ # TODO Why do we sometimes get a real object here and sometimes just a model name as a symbol?
52
+ unless model.is_a?(String)
53
+ model = model.name.underscore.tr("/", "_").to_sym
54
+ end
55
+
56
+ factories = FactoryBot.factories.instance_variable_get(:@items).keys
57
+ factories.include?("#{model}_example") ? "#{model}_example".to_sym : model
58
+ end
59
+
60
+ def reset_tables!
61
+ @tables_to_reset.each do |name|
62
+ ActiveRecord::Base.connection.reset_pk_sequence!(name) if ActiveRecord::Base.connection.table_exists?(name)
63
+ end
64
+ end
65
+
66
+ def deep_clone(instance)
67
+ clone = instance.clone
68
+
69
+ instance.class.reflections.each do |name, reflection|
70
+ if reflection.macro == :has_many
71
+ associations = instance.send(name).map { |association| association.clone }
72
+ clone.send("#{name}=", associations)
73
+ @tables_to_reset << name
74
+ elsif %i[belongs_to has_one].include?(reflection.macro)
75
+ clone.send("#{name}=", instance.send(name).clone)
76
+ @tables_to_reset << name.pluralize
77
+ end
78
+ end
79
+
80
+ clone
81
+ end
82
+
83
+ include ::Api::OpenApiHelper
84
+ def _path_examples(method, model, **options)
85
+ version = options.delete(:version) || "v1"
86
+
87
+ case method.split("_").first
88
+ when "get"
89
+ count = (options.delete(:count) || method == "get_examples") ? 2 : 1
90
+ template, class_name, var_name, values = _set_values(method, model, count)
91
+ else
92
+ template, class_name, var_name, values = _set_values("get_example", model)
93
+
94
+ unless %w[example examples].include?(method.split("_").last)
95
+ if has_strong_parameters?("::Api::#{version.upcase}::#{class_name.pluralize}Controller".constantize)
96
+ strong_params_module = "::Api::#{version.upcase}::#{class_name.pluralize}Controller::StrongParameters".constantize
97
+ strong_parameter_keys = BulletTrain::Api::StrongParametersReporter.new(class_name.constantize, strong_params_module).report
98
+ if strong_parameter_keys.last.is_a?(Hash)
99
+ strong_parameter_keys += strong_parameter_keys.pop.keys
100
+ end
101
+
102
+ output = _json_output(template, version, class_name, var_name, values)
103
+
104
+ parameters_output = JSON.parse(output)
105
+ parameters_output&.select! { |key| strong_parameter_keys.include?(key.to_sym) }
106
+
107
+ return indent(parameters_output.to_yaml.delete_prefix("---\n"), 6).html_safe
108
+ end
109
+ return nil
110
+ end
111
+ end
112
+
113
+ _yaml_output(template, version, class_name, var_name, values)
114
+ end
115
+
116
+ def _set_values(method, model, count = 1)
117
+ if count > 1
118
+ values = FactoryBot.example_list(model, count)
119
+ class_name = values.first.class.name
120
+ var_name = class_name.demodulize.underscore.pluralize
121
+ else
122
+ values = FactoryBot.example(model)
123
+ class_name = values.class.name
124
+ var_name = class_name.demodulize.underscore
125
+ end
126
+
127
+ template = (method == "get_examples") ? "index" : "show"
128
+
129
+ [template, class_name, var_name, values]
130
+ end
131
+
132
+ def _json_output(template, version, class_name, var_name, values)
133
+ ActionController::Base.render(
134
+ template: "api/#{version}/#{class_name.underscore.pluralize}/#{template}",
135
+ assigns: {"#{var_name}": values},
136
+ formats: :json
137
+ )
138
+ end
139
+
140
+ def _yaml_output(template, version, class_name, var_name, values)
141
+ indent(
142
+ JSON.parse(
143
+ _json_output(template, version, class_name, var_name, values)
144
+ ).to_yaml
145
+ .delete_prefix("---\n"), 7
146
+ ).html_safe
147
+ end
148
+ end
149
+
150
+ extend ExampleBot
151
+ end
@@ -1,5 +1,5 @@
1
1
  module BulletTrain
2
2
  module Api
3
- VERSION = "1.2.22"
3
+ VERSION = "1.2.24"
4
4
  end
5
5
  end
@@ -1,6 +1,7 @@
1
1
  require "bullet_train/api/version"
2
2
  require "bullet_train/api/engine"
3
3
  require "bullet_train/api/strong_parameters_reporter"
4
+ require "bullet_train/api/example_bot"
4
5
  require "bullet_train/platform/connection_workflow"
5
6
 
6
7
  # require "wine_bouncer"
@@ -1,6 +1,9 @@
1
1
  require "scaffolding"
2
2
  require "scaffolding/file_manipulator"
3
3
 
4
+ require "faraday"
5
+ require "tempfile"
6
+
4
7
  namespace :bullet_train do
5
8
  namespace :api do
6
9
  desc "Bump the current version of application's API"
@@ -88,5 +91,42 @@ namespace :bullet_train do
88
91
 
89
92
  puts "Finished bumping to #{new_version}"
90
93
  end
94
+
95
+ desc "Bump the current version of application's API"
96
+ task push_to_redocly: :environment do
97
+ include Rails.application.routes.url_helpers
98
+
99
+ raise "You need to set REDOCLY_ORGANIZATION_ID in your environment. You can fetch it from the URL when you're on your Redocly dashboard." unless ENV["REDOCLY_ORGANIZATION_ID"].present?
100
+ raise "You need to set REDOCLY_API_KEY in your environment. You can create one at https://app.redocly.com/org/#{ENV["REDOCLY_ORGANIZATION_ID"]}/settings/api-keys ." unless ENV["REDOCLY_API_KEY"].present?
101
+
102
+ # Create a new Faraday connection
103
+ conn = Faraday.new(api_url(version: BulletTrain::Api.current_version))
104
+
105
+ # Fetch the file
106
+ response = conn.get
107
+
108
+ # Check if the request was successful
109
+ if response.status == 200
110
+ # Create a temp file
111
+ temp_file = Tempfile.new(["openapi-", ".yaml"])
112
+
113
+ # Write the file content to the temp file
114
+ temp_file.binmode
115
+ temp_file.write(response.body)
116
+ temp_file.rewind
117
+
118
+ # Close and delete the temp file when the script exits
119
+ temp_file.close
120
+ puts "File downloaded and saved to: #{temp_file.path}"
121
+
122
+ puts `echo "#{ENV["REDOCLY_API_KEY"]}" | redocly login`
123
+
124
+ puts `redocly push #{temp_file.path} "@#{ENV["REDOCLY_ORGANIZATION_ID"]}/#{I18n.t("application.name")}@#{BulletTrain::Api.current_version}" --public --upsert`
125
+
126
+ temp_file.unlink
127
+ else
128
+ puts "Failed to download the OpenAPI Document. Status code: #{response.status}"
129
+ end
130
+ end
91
131
  end
92
132
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bullet_train-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.22
4
+ version: 1.2.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Culver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-24 00:00:00.000000000 Z
11
+ date: 2023-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: standard
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: 2.0.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: factory_bot
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: bullet_train
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -141,6 +155,7 @@ files:
141
155
  - app/controllers/concerns/api/controllers/base.rb
142
156
  - app/controllers/concerns/api/v1/teams/controller_base.rb
143
157
  - app/controllers/concerns/api/v1/users/controller_base.rb
158
+ - app/helpers/api/open_api_helper.rb
144
159
  - app/models/platform/access_token.rb
145
160
  - app/models/platform/application.rb
146
161
  - app/views/account/platform/access_tokens/_breadcrumbs.html.erb
@@ -188,6 +203,7 @@ files:
188
203
  - config/routes.rb
189
204
  - lib/bullet_train/api.rb
190
205
  - lib/bullet_train/api/engine.rb
206
+ - lib/bullet_train/api/example_bot.rb
191
207
  - lib/bullet_train/api/strong_parameters_reporter.rb
192
208
  - lib/bullet_train/api/version.rb
193
209
  - lib/bullet_train/platform.rb
@@ -215,7 +231,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
215
231
  - !ruby/object:Gem::Version
216
232
  version: '0'
217
233
  requirements: []
218
- rubygems_version: 3.3.7
234
+ rubygems_version: 3.4.6
219
235
  signing_key:
220
236
  specification_version: 4
221
237
  summary: Bullet Train API