sober_swag 0.1.0 → 0.6.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 +4 -4
- data/.github/config/rubocop_linter_action.yml +4 -0
- data/.github/workflows/lint.yml +15 -0
- data/.github/workflows/ruby.yml +33 -2
- data/.gitignore +4 -0
- data/.rubocop.yml +75 -1
- data/.ruby-version +1 -1
- data/README.md +154 -1
- data/bin/console +16 -15
- data/docs/serializers.md +203 -0
- data/example/.rspec +1 -0
- data/example/.ruby-version +1 -1
- data/example/Gemfile +9 -7
- data/example/Gemfile.lock +96 -79
- data/example/app/controllers/people_controller.rb +41 -23
- data/example/app/controllers/posts_controller.rb +110 -0
- data/example/app/models/application_record.rb +3 -0
- data/example/app/models/person.rb +6 -0
- data/example/app/models/post.rb +9 -0
- data/example/app/output_objects/person_errors_output_object.rb +5 -0
- data/example/app/output_objects/person_output_object.rb +15 -0
- data/example/app/output_objects/post_output_object.rb +10 -0
- data/example/bin/bundle +24 -20
- data/example/bin/rails +1 -1
- data/example/bin/rake +1 -1
- data/example/config/application.rb +11 -7
- data/example/config/environments/development.rb +0 -1
- data/example/config/environments/production.rb +3 -3
- data/example/config/puma.rb +5 -5
- data/example/config/routes.rb +3 -0
- data/example/config/spring.rb +4 -4
- data/example/db/migrate/20200311152021_create_people.rb +0 -1
- data/example/db/migrate/20200603172347_create_posts.rb +11 -0
- data/example/db/schema.rb +16 -7
- data/example/spec/rails_helper.rb +64 -0
- data/example/spec/requests/people/create_spec.rb +52 -0
- data/example/spec/requests/people/get_spec.rb +35 -0
- data/example/spec/requests/people/index_spec.rb +69 -0
- data/example/spec/spec_helper.rb +94 -0
- data/lib/sober_swag.rb +6 -3
- data/lib/sober_swag/compiler/error.rb +2 -0
- data/lib/sober_swag/compiler/path.rb +2 -5
- data/lib/sober_swag/compiler/paths.rb +0 -1
- data/lib/sober_swag/compiler/type.rb +86 -56
- data/lib/sober_swag/controller.rb +16 -11
- data/lib/sober_swag/controller/route.rb +18 -21
- data/lib/sober_swag/controller/undefined_body_error.rb +3 -0
- data/lib/sober_swag/controller/undefined_path_error.rb +3 -0
- data/lib/sober_swag/controller/undefined_query_error.rb +3 -0
- data/lib/sober_swag/input_object.rb +28 -0
- data/lib/sober_swag/nodes/array.rb +1 -1
- data/lib/sober_swag/nodes/base.rb +5 -3
- data/lib/sober_swag/nodes/binary.rb +2 -1
- data/lib/sober_swag/nodes/enum.rb +4 -2
- data/lib/sober_swag/nodes/list.rb +0 -1
- data/lib/sober_swag/nodes/primitive.rb +6 -5
- data/lib/sober_swag/output_object.rb +102 -0
- data/lib/sober_swag/output_object/definition.rb +30 -0
- data/lib/sober_swag/{blueprint → output_object}/field.rb +14 -4
- data/lib/sober_swag/{blueprint → output_object}/field_syntax.rb +2 -2
- data/lib/sober_swag/{blueprint → output_object}/view.rb +15 -6
- data/lib/sober_swag/parser.rb +9 -4
- data/lib/sober_swag/serializer.rb +5 -2
- data/lib/sober_swag/serializer/array.rb +12 -0
- data/lib/sober_swag/serializer/base.rb +50 -1
- data/lib/sober_swag/serializer/conditional.rb +19 -2
- data/lib/sober_swag/serializer/field_list.rb +29 -6
- data/lib/sober_swag/serializer/mapped.rb +15 -3
- data/lib/sober_swag/serializer/meta.rb +35 -0
- data/lib/sober_swag/serializer/optional.rb +17 -2
- data/lib/sober_swag/serializer/primitive.rb +4 -1
- data/lib/sober_swag/server.rb +83 -0
- data/lib/sober_swag/types.rb +3 -0
- data/lib/sober_swag/version.rb +1 -1
- data/sober_swag.gemspec +8 -4
- metadata +79 -47
- data/Gemfile.lock +0 -92
- data/example/person.json +0 -4
- data/example/test/controllers/.keep +0 -0
- data/example/test/fixtures/.keep +0 -0
- data/example/test/fixtures/files/.keep +0 -0
- data/example/test/fixtures/people.yml +0 -11
- data/example/test/integration/.keep +0 -0
- data/example/test/models/.keep +0 -0
- data/example/test/models/person_test.rb +0 -7
- data/example/test/test_helper.rb +0 -13
- data/lib/sober_swag/blueprint.rb +0 -113
- data/lib/sober_swag/path.rb +0 -8
- data/lib/sober_swag/path/integer.rb +0 -21
- data/lib/sober_swag/path/lit.rb +0 -41
- data/lib/sober_swag/path/literal.rb +0 -29
- data/lib/sober_swag/path/param.rb +0 -33
data/Gemfile.lock
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
sober_swag (0.1.0)
|
5
|
-
activesupport
|
6
|
-
dry-struct (~> 1.0)
|
7
|
-
dry-types (~> 1.2)
|
8
|
-
|
9
|
-
GEM
|
10
|
-
remote: https://rubygems.org/
|
11
|
-
specs:
|
12
|
-
activesupport (6.0.2.1)
|
13
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
14
|
-
i18n (>= 0.7, < 2)
|
15
|
-
minitest (~> 5.1)
|
16
|
-
tzinfo (~> 1.1)
|
17
|
-
zeitwerk (~> 2.2)
|
18
|
-
coderay (1.1.2)
|
19
|
-
concurrent-ruby (1.1.6)
|
20
|
-
diff-lcs (1.3)
|
21
|
-
docile (1.3.2)
|
22
|
-
dry-configurable (0.11.3)
|
23
|
-
concurrent-ruby (~> 1.0)
|
24
|
-
dry-core (~> 0.4, >= 0.4.7)
|
25
|
-
dry-equalizer (~> 0.2)
|
26
|
-
dry-container (0.7.2)
|
27
|
-
concurrent-ruby (~> 1.0)
|
28
|
-
dry-configurable (~> 0.1, >= 0.1.3)
|
29
|
-
dry-core (0.4.9)
|
30
|
-
concurrent-ruby (~> 1.0)
|
31
|
-
dry-equalizer (0.3.0)
|
32
|
-
dry-inflector (0.2.0)
|
33
|
-
dry-logic (1.0.6)
|
34
|
-
concurrent-ruby (~> 1.0)
|
35
|
-
dry-core (~> 0.2)
|
36
|
-
dry-equalizer (~> 0.2)
|
37
|
-
dry-struct (1.3.0)
|
38
|
-
dry-core (~> 0.4, >= 0.4.4)
|
39
|
-
dry-equalizer (~> 0.3)
|
40
|
-
dry-types (~> 1.3)
|
41
|
-
ice_nine (~> 0.11)
|
42
|
-
dry-types (1.4.0)
|
43
|
-
concurrent-ruby (~> 1.0)
|
44
|
-
dry-container (~> 0.3)
|
45
|
-
dry-core (~> 0.4, >= 0.4.4)
|
46
|
-
dry-equalizer (~> 0.3)
|
47
|
-
dry-inflector (~> 0.1, >= 0.1.2)
|
48
|
-
dry-logic (~> 1.0, >= 1.0.2)
|
49
|
-
i18n (1.8.2)
|
50
|
-
concurrent-ruby (~> 1.0)
|
51
|
-
ice_nine (0.11.2)
|
52
|
-
method_source (0.9.2)
|
53
|
-
minitest (5.14.0)
|
54
|
-
pry (0.12.2)
|
55
|
-
coderay (~> 1.1.0)
|
56
|
-
method_source (~> 0.9.0)
|
57
|
-
rake (13.0.1)
|
58
|
-
rspec (3.9.0)
|
59
|
-
rspec-core (~> 3.9.0)
|
60
|
-
rspec-expectations (~> 3.9.0)
|
61
|
-
rspec-mocks (~> 3.9.0)
|
62
|
-
rspec-core (3.9.1)
|
63
|
-
rspec-support (~> 3.9.1)
|
64
|
-
rspec-expectations (3.9.0)
|
65
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
66
|
-
rspec-support (~> 3.9.0)
|
67
|
-
rspec-mocks (3.9.1)
|
68
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
69
|
-
rspec-support (~> 3.9.0)
|
70
|
-
rspec-support (3.9.2)
|
71
|
-
simplecov (0.18.5)
|
72
|
-
docile (~> 1.1)
|
73
|
-
simplecov-html (~> 0.11)
|
74
|
-
simplecov-html (0.12.2)
|
75
|
-
thread_safe (0.3.6)
|
76
|
-
tzinfo (1.2.6)
|
77
|
-
thread_safe (~> 0.1)
|
78
|
-
zeitwerk (2.3.0)
|
79
|
-
|
80
|
-
PLATFORMS
|
81
|
-
ruby
|
82
|
-
|
83
|
-
DEPENDENCIES
|
84
|
-
bundler (~> 2.0)
|
85
|
-
pry
|
86
|
-
rake (~> 13.0)
|
87
|
-
rspec (~> 3.0)
|
88
|
-
simplecov
|
89
|
-
sober_swag!
|
90
|
-
|
91
|
-
BUNDLED WITH
|
92
|
-
2.1.2
|
data/example/person.json
DELETED
File without changes
|
data/example/test/fixtures/.keep
DELETED
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
|
data/example/test/models/.keep
DELETED
File without changes
|
data/example/test/test_helper.rb
DELETED
@@ -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
|
data/lib/sober_swag/blueprint.rb
DELETED
@@ -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
|
data/lib/sober_swag/path.rb
DELETED
data/lib/sober_swag/path/lit.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
module SoberSwag
|
2
|
-
class Path
|
3
|
-
class Lit
|
4
|
-
##
|
5
|
-
# Parse a literal path fragment
|
6
|
-
def initialize(lit)
|
7
|
-
@lit = lit
|
8
|
-
end
|
9
|
-
|
10
|
-
attr_reader :lit
|
11
|
-
|
12
|
-
def param?
|
13
|
-
false
|
14
|
-
end
|
15
|
-
|
16
|
-
def param_type
|
17
|
-
nil
|
18
|
-
end
|
19
|
-
|
20
|
-
def param_key
|
21
|
-
nil
|
22
|
-
end
|
23
|
-
|
24
|
-
##
|
25
|
-
# Constant to avoid a bunch of array allocation
|
26
|
-
MATCH_SUCC = [:match, nil].freeze
|
27
|
-
##
|
28
|
-
# Constant to avoid a bunch of array allocation
|
29
|
-
MATHC_FAIL = [:fail].freeze
|
30
|
-
|
31
|
-
def match(param)
|
32
|
-
if param == lit
|
33
|
-
MATCH_SUCC
|
34
|
-
else
|
35
|
-
MATCH_FAIL
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module SoberSwag
|
2
|
-
module Path
|
3
|
-
##
|
4
|
-
# One literal text fragment, basically
|
5
|
-
class Literal < Node
|
6
|
-
##
|
7
|
-
# Make a new text node
|
8
|
-
# @param text [String]
|
9
|
-
def initialize(text)
|
10
|
-
@text = text
|
11
|
-
end
|
12
|
-
|
13
|
-
attr_reader :text
|
14
|
-
|
15
|
-
##
|
16
|
-
# We can make a jump table out of this node!
|
17
|
-
def jumpable?
|
18
|
-
true
|
19
|
-
end
|
20
|
-
|
21
|
-
##
|
22
|
-
# This doesn't read a parameter type.
|
23
|
-
def param?
|
24
|
-
false
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
module SoberSwag
|
2
|
-
class Path
|
3
|
-
##
|
4
|
-
# Parse a parameter
|
5
|
-
class Param
|
6
|
-
def initialize(name, type)
|
7
|
-
@name = name
|
8
|
-
@type = type
|
9
|
-
end
|
10
|
-
|
11
|
-
def param?
|
12
|
-
true
|
13
|
-
end
|
14
|
-
|
15
|
-
def param_key
|
16
|
-
@name
|
17
|
-
end
|
18
|
-
|
19
|
-
def param_type
|
20
|
-
@type
|
21
|
-
end
|
22
|
-
|
23
|
-
def match(param)
|
24
|
-
if (m = @type.try(param)).success?
|
25
|
-
[:match, m]
|
26
|
-
else
|
27
|
-
[:fail]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|