sober_swag 0.1.0 → 0.2.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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.github/config/rubocop_linter_action.yml +5 -0
  3. data/.github/workflows/lint.yml +15 -0
  4. data/.github/workflows/ruby.yml +23 -1
  5. data/.gitignore +3 -0
  6. data/.rubocop.yml +73 -1
  7. data/.ruby-version +1 -1
  8. data/Gemfile.lock +29 -5
  9. data/README.md +109 -0
  10. data/bin/console +15 -14
  11. data/docs/serializers.md +203 -0
  12. data/example/.rspec +1 -0
  13. data/example/.ruby-version +1 -1
  14. data/example/Gemfile +10 -6
  15. data/example/Gemfile.lock +96 -76
  16. data/example/app/controllers/people_controller.rb +37 -21
  17. data/example/app/controllers/posts_controller.rb +102 -0
  18. data/example/app/models/application_record.rb +3 -0
  19. data/example/app/models/person.rb +6 -0
  20. data/example/app/models/post.rb +9 -0
  21. data/example/app/output_objects/person_errors_output_object.rb +5 -0
  22. data/example/app/output_objects/person_output_object.rb +15 -0
  23. data/example/app/output_objects/post_output_object.rb +10 -0
  24. data/example/bin/bundle +24 -20
  25. data/example/bin/rails +1 -1
  26. data/example/bin/rake +1 -1
  27. data/example/config/application.rb +11 -7
  28. data/example/config/environments/development.rb +0 -1
  29. data/example/config/environments/production.rb +3 -3
  30. data/example/config/puma.rb +5 -5
  31. data/example/config/routes.rb +3 -0
  32. data/example/config/spring.rb +4 -4
  33. data/example/db/migrate/20200311152021_create_people.rb +0 -1
  34. data/example/db/migrate/20200603172347_create_posts.rb +11 -0
  35. data/example/db/schema.rb +16 -7
  36. data/example/spec/rails_helper.rb +64 -0
  37. data/example/spec/requests/people/create_spec.rb +52 -0
  38. data/example/spec/requests/people/get_spec.rb +35 -0
  39. data/example/spec/requests/people/index_spec.rb +69 -0
  40. data/example/spec/spec_helper.rb +94 -0
  41. data/lib/sober_swag.rb +6 -3
  42. data/lib/sober_swag/compiler/error.rb +2 -0
  43. data/lib/sober_swag/compiler/path.rb +2 -5
  44. data/lib/sober_swag/compiler/paths.rb +0 -1
  45. data/lib/sober_swag/compiler/type.rb +28 -15
  46. data/lib/sober_swag/controller.rb +16 -11
  47. data/lib/sober_swag/controller/route.rb +18 -21
  48. data/lib/sober_swag/controller/undefined_body_error.rb +3 -0
  49. data/lib/sober_swag/controller/undefined_path_error.rb +3 -0
  50. data/lib/sober_swag/controller/undefined_query_error.rb +3 -0
  51. data/lib/sober_swag/input_object.rb +28 -0
  52. data/lib/sober_swag/nodes/array.rb +1 -1
  53. data/lib/sober_swag/nodes/base.rb +2 -4
  54. data/lib/sober_swag/nodes/binary.rb +2 -1
  55. data/lib/sober_swag/nodes/enum.rb +4 -2
  56. data/lib/sober_swag/nodes/list.rb +0 -1
  57. data/lib/sober_swag/nodes/primitive.rb +6 -5
  58. data/lib/sober_swag/output_object.rb +102 -0
  59. data/lib/sober_swag/output_object/definition.rb +30 -0
  60. data/lib/sober_swag/{blueprint → output_object}/field.rb +14 -4
  61. data/lib/sober_swag/{blueprint → output_object}/field_syntax.rb +1 -1
  62. data/lib/sober_swag/{blueprint → output_object}/view.rb +15 -6
  63. data/lib/sober_swag/parser.rb +5 -3
  64. data/lib/sober_swag/serializer.rb +5 -2
  65. data/lib/sober_swag/serializer/array.rb +12 -0
  66. data/lib/sober_swag/serializer/base.rb +50 -1
  67. data/lib/sober_swag/serializer/conditional.rb +15 -2
  68. data/lib/sober_swag/serializer/field_list.rb +29 -6
  69. data/lib/sober_swag/serializer/mapped.rb +12 -2
  70. data/lib/sober_swag/serializer/meta.rb +35 -0
  71. data/lib/sober_swag/serializer/optional.rb +17 -2
  72. data/lib/sober_swag/serializer/primitive.rb +4 -1
  73. data/lib/sober_swag/server.rb +83 -0
  74. data/lib/sober_swag/types.rb +3 -0
  75. data/lib/sober_swag/version.rb +1 -1
  76. data/sober_swag.gemspec +6 -4
  77. metadata +77 -44
  78. data/example/person.json +0 -4
  79. data/example/test/controllers/.keep +0 -0
  80. data/example/test/fixtures/.keep +0 -0
  81. data/example/test/fixtures/files/.keep +0 -0
  82. data/example/test/fixtures/people.yml +0 -11
  83. data/example/test/integration/.keep +0 -0
  84. data/example/test/models/.keep +0 -0
  85. data/example/test/models/person_test.rb +0 -7
  86. data/example/test/test_helper.rb +0 -13
  87. data/lib/sober_swag/blueprint.rb +0 -113
  88. data/lib/sober_swag/path.rb +0 -8
  89. data/lib/sober_swag/path/integer.rb +0 -21
  90. data/lib/sober_swag/path/lit.rb +0 -41
  91. data/lib/sober_swag/path/literal.rb +0 -29
  92. data/lib/sober_swag/path/param.rb +0 -33
@@ -1,4 +1,7 @@
1
1
  module SoberSwag
2
+ ##
3
+ # Container for types.
4
+ # You can use constants like SoberSwag::Types::Integer and things as a result of this module existing.
2
5
  class Types
3
6
  include ::Dry::Types()
4
7
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SoberSwag
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
15
15
  spec.homepage = 'https://github.com/SonderMindOrg/sober_swag'
16
16
  spec.license = 'MIT'
17
17
 
18
- spec.metadata['allowed_push_host'] = "https://rubygems.org"
18
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
19
19
 
20
20
  spec.metadata['homepage_uri'] = spec.homepage
21
21
 
@@ -28,13 +28,15 @@ Gem::Specification.new do |spec|
28
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
29
  spec.require_paths = ['lib']
30
30
 
31
+ spec.add_dependency 'activesupport'
31
32
  spec.add_dependency 'dry-struct', '~> 1.0'
32
33
  spec.add_dependency 'dry-types', '~> 1.2'
33
- spec.add_dependency 'activesupport'
34
34
 
35
- spec.add_development_dependency 'pry'
36
- spec.add_development_dependency 'simplecov'
37
35
  spec.add_development_dependency 'bundler', '~> 2.0'
36
+ spec.add_development_dependency 'pry'
38
37
  spec.add_development_dependency 'rake', '~> 13.0'
39
38
  spec.add_development_dependency 'rspec', '~> 3.0'
39
+ spec.add_development_dependency 'rubocop'
40
+ spec.add_development_dependency 'rubocop-rspec'
41
+ spec.add_development_dependency 'simplecov'
40
42
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sober_swag
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Super
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-21 00:00:00.000000000 Z
11
+ date: 2020-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: dry-struct
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -39,19 +53,19 @@ dependencies:
39
53
  - !ruby/object:Gem::Version
40
54
  version: '1.2'
41
55
  - !ruby/object:Gem::Dependency
42
- name: activesupport
56
+ name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - ">="
59
+ - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :runtime
61
+ version: '2.0'
62
+ type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - ">="
66
+ - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '0'
68
+ version: '2.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: pry
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -67,61 +81,75 @@ dependencies:
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
- name: simplecov
84
+ name: rake
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - ">="
87
+ - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '0'
89
+ version: '13.0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - ">="
94
+ - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '0'
96
+ version: '13.0'
83
97
  - !ruby/object:Gem::Dependency
84
- name: bundler
98
+ name: rspec
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: '2.0'
103
+ version: '3.0'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: '2.0'
110
+ version: '3.0'
97
111
  - !ruby/object:Gem::Dependency
98
- name: rake
112
+ name: rubocop
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
- - - "~>"
115
+ - - ">="
102
116
  - !ruby/object:Gem::Version
103
- version: '13.0'
117
+ version: '0'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
- - - "~>"
122
+ - - ">="
109
123
  - !ruby/object:Gem::Version
110
- version: '13.0'
124
+ version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
- name: rspec
126
+ name: rubocop-rspec
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
- - - "~>"
129
+ - - ">="
116
130
  - !ruby/object:Gem::Version
117
- version: '3.0'
131
+ version: '0'
118
132
  type: :development
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
- - - "~>"
136
+ - - ">="
123
137
  - !ruby/object:Gem::Version
124
- version: '3.0'
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
125
153
  description: Parse data, don't write docs
126
154
  email:
127
155
  - asuper@sondermind.com
@@ -129,6 +157,8 @@ executables: []
129
157
  extensions: []
130
158
  extra_rdoc_files: []
131
159
  files:
160
+ - ".github/config/rubocop_linter_action.yml"
161
+ - ".github/workflows/lint.yml"
132
162
  - ".github/workflows/ruby.yml"
133
163
  - ".gitignore"
134
164
  - ".rspec"
@@ -142,7 +172,9 @@ files:
142
172
  - Rakefile
143
173
  - bin/console
144
174
  - bin/setup
175
+ - docs/serializers.md
145
176
  - example/.gitignore
177
+ - example/.rspec
146
178
  - example/.ruby-version
147
179
  - example/Gemfile
148
180
  - example/Gemfile.lock
@@ -151,10 +183,15 @@ files:
151
183
  - example/app/controllers/application_controller.rb
152
184
  - example/app/controllers/concerns/.keep
153
185
  - example/app/controllers/people_controller.rb
186
+ - example/app/controllers/posts_controller.rb
154
187
  - example/app/jobs/application_job.rb
155
188
  - example/app/models/application_record.rb
156
189
  - example/app/models/concerns/.keep
157
190
  - example/app/models/person.rb
191
+ - example/app/models/post.rb
192
+ - example/app/output_objects/person_errors_output_object.rb
193
+ - example/app/output_objects/person_output_object.rb
194
+ - example/app/output_objects/post_output_object.rb
158
195
  - example/bin/bundle
159
196
  - example/bin/rails
160
197
  - example/bin/rake
@@ -181,27 +218,20 @@ files:
181
218
  - example/config/routes.rb
182
219
  - example/config/spring.rb
183
220
  - example/db/migrate/20200311152021_create_people.rb
221
+ - example/db/migrate/20200603172347_create_posts.rb
184
222
  - example/db/schema.rb
185
223
  - example/db/seeds.rb
186
224
  - example/lib/tasks/.keep
187
225
  - example/log/.keep
188
- - example/person.json
189
226
  - example/public/robots.txt
190
- - example/test/controllers/.keep
191
- - example/test/fixtures/.keep
192
- - example/test/fixtures/files/.keep
193
- - example/test/fixtures/people.yml
194
- - example/test/integration/.keep
195
- - example/test/models/.keep
196
- - example/test/models/person_test.rb
197
- - example/test/test_helper.rb
227
+ - example/spec/rails_helper.rb
228
+ - example/spec/requests/people/create_spec.rb
229
+ - example/spec/requests/people/get_spec.rb
230
+ - example/spec/requests/people/index_spec.rb
231
+ - example/spec/spec_helper.rb
198
232
  - example/tmp/.keep
199
233
  - example/vendor/.keep
200
234
  - lib/sober_swag.rb
201
- - lib/sober_swag/blueprint.rb
202
- - lib/sober_swag/blueprint/field.rb
203
- - lib/sober_swag/blueprint/field_syntax.rb
204
- - lib/sober_swag/blueprint/view.rb
205
235
  - lib/sober_swag/compiler.rb
206
236
  - lib/sober_swag/compiler/error.rb
207
237
  - lib/sober_swag/compiler/path.rb
@@ -212,6 +242,7 @@ files:
212
242
  - lib/sober_swag/controller/undefined_body_error.rb
213
243
  - lib/sober_swag/controller/undefined_path_error.rb
214
244
  - lib/sober_swag/controller/undefined_query_error.rb
245
+ - lib/sober_swag/input_object.rb
215
246
  - lib/sober_swag/nodes.rb
216
247
  - lib/sober_swag/nodes/array.rb
217
248
  - lib/sober_swag/nodes/attribute.rb
@@ -224,20 +255,22 @@ files:
224
255
  - lib/sober_swag/nodes/one_of.rb
225
256
  - lib/sober_swag/nodes/primitive.rb
226
257
  - lib/sober_swag/nodes/sum.rb
258
+ - lib/sober_swag/output_object.rb
259
+ - lib/sober_swag/output_object/definition.rb
260
+ - lib/sober_swag/output_object/field.rb
261
+ - lib/sober_swag/output_object/field_syntax.rb
262
+ - lib/sober_swag/output_object/view.rb
227
263
  - lib/sober_swag/parser.rb
228
- - lib/sober_swag/path.rb
229
- - lib/sober_swag/path/integer.rb
230
- - lib/sober_swag/path/lit.rb
231
- - lib/sober_swag/path/literal.rb
232
- - lib/sober_swag/path/param.rb
233
264
  - lib/sober_swag/serializer.rb
234
265
  - lib/sober_swag/serializer/array.rb
235
266
  - lib/sober_swag/serializer/base.rb
236
267
  - lib/sober_swag/serializer/conditional.rb
237
268
  - lib/sober_swag/serializer/field_list.rb
238
269
  - lib/sober_swag/serializer/mapped.rb
270
+ - lib/sober_swag/serializer/meta.rb
239
271
  - lib/sober_swag/serializer/optional.rb
240
272
  - lib/sober_swag/serializer/primitive.rb
273
+ - lib/sober_swag/server.rb
241
274
  - lib/sober_swag/types.rb
242
275
  - lib/sober_swag/version.rb
243
276
  - sober_swag.gemspec
@@ -1,4 +0,0 @@
1
- {
2
- "first_name": "Tony",
3
- "last_name": "Super"
4
- }
File without changes
File without changes
File without changes
@@ -1,11 +0,0 @@
1
- # Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2
-
3
- one:
4
- first_name: MyText
5
- last_name: MyText
6
- date_of_birth: 2020-03-11 09:20:21
7
-
8
- two:
9
- first_name: MyText
10
- last_name: MyText
11
- date_of_birth: 2020-03-11 09:20:21
File without changes
File without changes
@@ -1,7 +0,0 @@
1
- require 'test_helper'
2
-
3
- class PersonTest < ActiveSupport::TestCase
4
- # test "the truth" do
5
- # assert true
6
- # end
7
- end
@@ -1,13 +0,0 @@
1
- ENV['RAILS_ENV'] ||= 'test'
2
- require_relative '../config/environment'
3
- require 'rails/test_help'
4
-
5
- class ActiveSupport::TestCase
6
- # Run tests in parallel with specified workers
7
- parallelize(workers: :number_of_processors)
8
-
9
- # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
10
- fixtures :all
11
-
12
- # Add more helper methods to be used by all tests here...
13
- end
@@ -1,113 +0,0 @@
1
- require 'sober_swag/serializer'
2
-
3
- module SoberSwag
4
- ##
5
- # Create a serializer that is heavily inspired by the "Blueprinter" library.
6
- # This allows you to make "views" and such inside.
7
- #
8
- # Under the hood, this is actually all based on {SoberSwag::Serialzier::Base}.
9
- class Blueprint
10
- autoload(:Field, 'sober_swag/blueprint/field')
11
- autoload(:FieldSyntax, 'sober_swag/blueprint/field_syntax')
12
- autoload(:View, 'sober_swag/blueprint/view')
13
-
14
- ##
15
- # Use a Blueprint to define a new serializer.
16
- # It will be based on {SoberSwag::Serializer::Base}.
17
- #
18
- # An example is illustrative:
19
- #
20
- # PersonSerializer = SoberSwag::Blueprint.define do
21
- # field :id, primitive(:Integer)
22
- # field :name, primtive(:String).optional
23
- #
24
- # view :complex do
25
- # field :age, primitive(:Integer)
26
- # field :title, primitive(:String)
27
- # end
28
- # end
29
- #
30
- # Note: This currently will generate a new *class* that does serialization.
31
- # However, this is only a hack to get rid of the weird naming issue when
32
- # generating swagger from dry structs: their section of the schema area
33
- # is defined by their *Ruby Class Name*. In the future, if we get rid of this,
34
- # we might be able to keep this on the value-level, in which case {#define}
35
- # can simply return an *instance* of SoberSwag::Serializer that does
36
- # the correct thing, with the name you give it. This works for now, though.
37
- def self.define(&block)
38
- self.new.tap { |o|
39
- o.instance_eval(&block)
40
- }.serializer_class
41
- end
42
-
43
- def initialize(base_fields = [])
44
- @fields = base_fields.dup
45
- @views = []
46
- end
47
-
48
- attr_reader :fields, :views
49
-
50
- include FieldSyntax
51
-
52
- def add_field!(field)
53
- @fields << field
54
- end
55
-
56
- def view(name, &block)
57
- @views << View.define(name, fields, &block)
58
- end
59
-
60
- ##
61
- # Instead of generating a new value-level construct,
62
- # this will generate a new *class*. This is so that you can
63
- # name this blueprint, and have the views named as sub-classes.
64
- # This is important as the type compiler uses class names
65
- # for generating refs.
66
- def serializer_class
67
- @serializer_class ||= make_serializer_class!
68
- end
69
-
70
- private
71
-
72
- def make_serializer_class!
73
- # Klass we'll use
74
- klass = Class.new(SoberSwag::Serializer::Base)
75
- # The actual serialization logic is defined in a field list
76
- base_serializer = SoberSwag::Serializer::FieldList.new(fields)
77
- # WhateverBlueprint::Base is now used as the name for a ref
78
- klass.const_set(:Base, base_serializer.type)
79
- final_serializer = views.reduce(base_serializer) do |base, view|
80
- view_serializer = view.serializer
81
- # If we have a view :foo, its type is named
82
- # WhateverBlueprint::Foo
83
- klass.const_set(view.name.to_s.classify, view_serializer.type)
84
- SoberSwag::Serializer::Conditional.new(
85
- proc do |object, options|
86
- if options[:view].to_s == view.name.to_s
87
- [:left, object]
88
- else
89
- [:right, object]
90
- end
91
- end,
92
- view_serializer,
93
- base
94
- )
95
- end
96
- klass.send(:define_method, :serialize) do |object, options = {}|
97
- final_serializer.serialize(object, options)
98
- end
99
- klass.send(:define_method, :type) do
100
- final_serializer.type
101
- end
102
- klass.send(:define_singleton_method, :type) do
103
- final_serializer.type
104
- end
105
- klass.send(:define_singleton_method, :serializer) do
106
- klass.new
107
- end
108
-
109
- klass
110
- end
111
-
112
- end
113
- end