sober_swag 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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