bullet_train-api 1.2.22 → 1.2.24

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