schemable 0.1.2 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +16 -2
- data/Gemfile +7 -6
- data/Gemfile.lock +21 -13
- data/README.md +165 -9
- data/Rakefile +3 -3
- data/lib/generators/schemable/install_generator.rb +2 -2
- data/lib/generators/schemable/model_generator.rb +8 -4
- data/lib/schemable/version.rb +1 -1
- data/lib/schemable.rb +394 -317
- data/schemable.gemspec +16 -17
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f34e140b93c601b0fa6d0baa7bb43d8e77e4276c7419077abad2fce6cbeae820
|
4
|
+
data.tar.gz: b9755ec8abe9cfd3c432945831009410bc256acc82d4ea1efb0a87b72c98e538
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f05de6d4ead3c1ab197b9160e1b97ef0330af0055af54663e02e7e64fe6d91d8b61da67addf75a394e1e1794577618411e5ecd36e0b34ddd9415e3d260d2a731
|
7
|
+
data.tar.gz: 806b59dd5e21d936ca3000445325416caabda85b6788fc8f2cb2a60dfa333037ab75dba40880755bcf6c5632aa95bcb109d26550cea95ca00706820486917a0f
|
data/.rubocop.yml
CHANGED
@@ -108,10 +108,24 @@ Metrics/AbcSize:
|
|
108
108
|
Metrics/MethodLength:
|
109
109
|
Enabled: false
|
110
110
|
Metrics/CyclomaticComplexity:
|
111
|
-
|
111
|
+
Enabled: false
|
112
112
|
Metrics/PerceivedComplexity:
|
113
|
-
|
113
|
+
Enabled: false
|
114
114
|
Lint/DuplicateMethods: # Disables duplicate methods warning
|
115
115
|
Enabled: false
|
116
116
|
Gemspec/RequiredRubyVersion: # Disables required ruby version warning
|
117
117
|
Enabled: false
|
118
|
+
Metrics/ParameterLists: # Disables parameter lists warning
|
119
|
+
Enabled: false
|
120
|
+
Lint/NextWithoutAccumulator: # Disables next without accumulator warning
|
121
|
+
Enabled: false
|
122
|
+
Lint/ShadowingOuterLocalVariable: # Disables shadowing outer local variable warning
|
123
|
+
Enabled: false
|
124
|
+
Metrics/ModuleLength: # Disables module length warning
|
125
|
+
Enabled: false
|
126
|
+
Layout/EmptyLinesAroundClassBody: # Disables empty lines around class body warning
|
127
|
+
Enabled: false
|
128
|
+
Layout/HeredocIndentation: # Disables heredoc indentation warning
|
129
|
+
Enabled: false
|
130
|
+
Layout/ClosingHeredocIndentation: # Disables closing heredoc indentation warning
|
131
|
+
Enabled: false
|
data/Gemfile
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
source
|
3
|
+
source 'https://rubygems.org'
|
4
4
|
|
5
5
|
gemspec
|
6
6
|
|
7
|
-
gem
|
8
|
-
gem
|
9
|
-
gem
|
7
|
+
gem 'rake', '~> 13.0.6'
|
8
|
+
gem 'rspec', '~> 3.12'
|
9
|
+
gem 'rubocop', '~> 1.55'
|
10
|
+
gem 'rubocop-rails', '~> 2.20.2'
|
10
11
|
|
11
12
|
group :development, :test do
|
12
|
-
gem 'jsonapi-rails', '~> 0.4.1'
|
13
13
|
gem 'factory_bot_rails', '~> 6.2'
|
14
|
-
|
14
|
+
gem 'jsonapi-rails', '~> 0.4.1'
|
15
|
+
end
|
data/Gemfile.lock
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
schemable (0.1.
|
5
|
-
factory_bot_rails (
|
6
|
-
jsonapi-rails (
|
4
|
+
schemable (0.1.4)
|
5
|
+
factory_bot_rails (~> 6.2.0)
|
6
|
+
jsonapi-rails (~> 0.4.1)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
@@ -51,6 +51,7 @@ GEM
|
|
51
51
|
jsonapi-renderer (0.2.2)
|
52
52
|
jsonapi-serializable (0.3.1)
|
53
53
|
jsonapi-renderer (~> 0.2.0)
|
54
|
+
language_server-protocol (3.17.0.3)
|
54
55
|
loofah (2.21.2)
|
55
56
|
crass (~> 1.0.2)
|
56
57
|
nokogiri (>= 1.12.0)
|
@@ -59,8 +60,9 @@ GEM
|
|
59
60
|
nokogiri (1.14.4-x86_64-linux)
|
60
61
|
racc (~> 1.4)
|
61
62
|
parallel (1.23.0)
|
62
|
-
parser (3.2.2.
|
63
|
+
parser (3.2.2.3)
|
63
64
|
ast (~> 2.4.1)
|
65
|
+
racc
|
64
66
|
racc (1.6.2)
|
65
67
|
rack (2.2.7)
|
66
68
|
rack-test (2.1.0)
|
@@ -79,8 +81,8 @@ GEM
|
|
79
81
|
zeitwerk (~> 2.5)
|
80
82
|
rainbow (3.1.1)
|
81
83
|
rake (13.0.6)
|
82
|
-
regexp_parser (2.8.
|
83
|
-
rexml (3.2.
|
84
|
+
regexp_parser (2.8.1)
|
85
|
+
rexml (3.2.6)
|
84
86
|
rspec (3.12.0)
|
85
87
|
rspec-core (~> 3.12.0)
|
86
88
|
rspec-expectations (~> 3.12.0)
|
@@ -94,18 +96,23 @@ GEM
|
|
94
96
|
diff-lcs (>= 1.2.0, < 2.0)
|
95
97
|
rspec-support (~> 3.12.0)
|
96
98
|
rspec-support (3.12.0)
|
97
|
-
rubocop (1.
|
99
|
+
rubocop (1.55.0)
|
98
100
|
json (~> 2.3)
|
101
|
+
language_server-protocol (>= 3.17.0)
|
99
102
|
parallel (~> 1.10)
|
100
|
-
parser (>= 3.2.
|
103
|
+
parser (>= 3.2.2.3)
|
101
104
|
rainbow (>= 2.2.2, < 4.0)
|
102
105
|
regexp_parser (>= 1.8, < 3.0)
|
103
106
|
rexml (>= 3.2.5, < 4.0)
|
104
|
-
rubocop-ast (>= 1.28.
|
107
|
+
rubocop-ast (>= 1.28.1, < 2.0)
|
105
108
|
ruby-progressbar (~> 1.7)
|
106
109
|
unicode-display_width (>= 2.4.0, < 3.0)
|
107
|
-
rubocop-ast (1.
|
110
|
+
rubocop-ast (1.29.0)
|
108
111
|
parser (>= 3.2.1.0)
|
112
|
+
rubocop-rails (2.20.2)
|
113
|
+
activesupport (>= 4.2.0)
|
114
|
+
rack (>= 1.1)
|
115
|
+
rubocop (>= 1.33.0, < 2.0)
|
109
116
|
ruby-progressbar (1.13.0)
|
110
117
|
thor (1.2.2)
|
111
118
|
tzinfo (2.0.6)
|
@@ -119,9 +126,10 @@ PLATFORMS
|
|
119
126
|
DEPENDENCIES
|
120
127
|
factory_bot_rails (~> 6.2)
|
121
128
|
jsonapi-rails (~> 0.4.1)
|
122
|
-
rake (~> 13.0)
|
123
|
-
rspec (~> 3.
|
124
|
-
rubocop (~> 1.
|
129
|
+
rake (~> 13.0.6)
|
130
|
+
rspec (~> 3.12)
|
131
|
+
rubocop (~> 1.55)
|
132
|
+
rubocop-rails (~> 2.20.2)
|
125
133
|
schemable!
|
126
134
|
|
127
135
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -1,24 +1,180 @@
|
|
1
1
|
# Schemable
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/schemable`. To experiment with that code, run `bin/console` for an interactive prompt.
|
3
|
+
The Schemable gem provides a simple way to define a schema for a Rails model in [JSONAPI](https://jsonapi.org/) format. It can automatically generate a schema for a model based on the model's factory and the model's attributes. It is also highly customizable, allowing you to modify the schema to your liking by overriding the default methods.
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
9
|
-
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'schemable'
|
11
|
+
```
|
10
12
|
|
11
|
-
|
13
|
+
And then execute:
|
12
14
|
|
13
|
-
$ bundle
|
15
|
+
$ bundle install
|
14
16
|
|
15
|
-
|
17
|
+
Or install it yourself as:
|
16
18
|
|
17
|
-
$ gem install
|
19
|
+
$ gem install schemable
|
18
20
|
|
19
21
|
## Usage
|
20
22
|
|
21
|
-
|
23
|
+
The installation command above will install the Schemable gem and its dependencies. However, in order for Schemable to work, you must also add the following files to your Rails application:
|
24
|
+
|
25
|
+
- `app/helpers/serializers_helper.rb` - This file contains the `serializers_map` helper method, which is used to map a model to its serializer.
|
26
|
+
- `spec/swagger/common_definitions.rb` - This file contains the `aggregate` method, which is used to aggregate the schemas of all the models in your application into a single place. This file is recommeded, but not required. If you do not use this file, you will need to manually aggregate the schemas of all the models in your application into a single place.
|
27
|
+
|
28
|
+
To generate these files, run the following command:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
rails g schemable:install
|
32
|
+
```
|
33
|
+
|
34
|
+
### Generating Definition Files
|
35
|
+
|
36
|
+
The Schemable gem provides a generator that can be used to generate definition files for your models. To generate a definition file for a model, run the following command:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
rails g schemable:model --model_name <model_name>
|
40
|
+
```
|
41
|
+
|
42
|
+
This will generate a definition file for the specified model in the `lib/swagger/definitions` directory. The definition file will be named `<model_name>.rb`. This file will have the bare minimum code required to generate a schema for the model. You can then modify the definition file to your liking by overriding the default methods. For example, you can add or remove attributes from the schema, or you can add or remove relationships from the schema. You can also add custom attributes to the schema. For more information on how to customize the schema, see the [Customizing the Schema](#customizing-the-schema) section below.
|
43
|
+
|
44
|
+
## Customizing the Schema
|
45
|
+
|
46
|
+
The Schemable gem provides a number of methods that can be used to customize the schema. These methods are defined in the `Schemable` module of the gem. To customize the schema, simply override the default methods in the definition file for the model. The following is a list of the methods that can be overridden:
|
47
|
+
|
48
|
+
| WARNING: please read the method inline documentation before overriding to avoid any unexpected behavior. |
|
49
|
+
| -------------------------------------------------------------------------------------------------------- |
|
50
|
+
|
51
|
+
The list of methods that can be overridden are as follows:
|
52
|
+
|
53
|
+
| Method Name | Description |
|
54
|
+
| -------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
55
|
+
| `serializer` | Returns the serializer class. |
|
56
|
+
| `attributes` | Returns the attributes that are auto generated from the model. |
|
57
|
+
| `relationships` | Returns the relationships in the format of { belongs_to: {}, has_many: {} }. |
|
58
|
+
| `array_type` | Returns the type of arrays in the model that needs to be manually defined. |
|
59
|
+
| `optional_request_attributes` | Returns the attributes that are optional in the request schema. |
|
60
|
+
| `nullable_attributes` | Returns the attributes that are nullable in the request/response schema. |
|
61
|
+
| `additional_request_attributes` | Returns the attributes that are additional in the request schema. |
|
62
|
+
| `additional_response_attributes` | Returns the attributes that are additional in the response schema. |
|
63
|
+
| `additional_response_relations` | Returns the relationships that are additional in the response schema (Appended to relationships). |
|
64
|
+
| `additional_response_included` | Returns the included that are additional in the response schema (Appended to included). |
|
65
|
+
| `excluded_request_attributes` | Returns the attributes that are excluded from the request schema. |
|
66
|
+
| `excluded_response_attributes` | Returns the attributes that are excluded from the response schema. |
|
67
|
+
| `excluded_response_relations` | Returns the relationships that are excluded from the response schema. |
|
68
|
+
| `excluded_response_included` | (not implemented yet) Returns the included that are excluded from the response schema. |
|
69
|
+
| `nested_relationships` | Returns the relationships to be further expanded in the response schema. |
|
70
|
+
| `model` | Returns the model class (Constantized from the definition class name). |
|
71
|
+
| `model_name` | Returns the model name. Used for schema type naming. |
|
72
|
+
| `definitions` | Returns the generated schemas in JSONAPI format (It is recommended to override this method to your liking) |
|
73
|
+
|
74
|
+
The following is an example of a definition file for a model that has been customized:
|
75
|
+
|
76
|
+
<Details>
|
77
|
+
<Summary>Click to view the example</Summary>
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
module Swagger
|
81
|
+
module Definitions
|
82
|
+
class UserApplication
|
83
|
+
|
84
|
+
include Schemable
|
85
|
+
include SerializersHelper
|
86
|
+
|
87
|
+
attr_accessor :instance
|
88
|
+
|
89
|
+
def initialize
|
90
|
+
@instance ||= JSONAPI::Serializable::Renderer.new.render(FactoryBot.create(:user, :with_user_application_applicants), class: serializers_map, include: [])
|
91
|
+
end
|
92
|
+
|
93
|
+
def serializer
|
94
|
+
V1::UserApplicationSerializer
|
95
|
+
end
|
96
|
+
|
97
|
+
def relationships
|
98
|
+
{
|
99
|
+
belongs_to: {
|
100
|
+
category: Swagger::Definitions::Category,
|
101
|
+
},
|
102
|
+
has_many: {
|
103
|
+
applicants: Swagger::Definitions::Applicant,
|
104
|
+
}
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
def array_types
|
109
|
+
{
|
110
|
+
applicant_ids:
|
111
|
+
{
|
112
|
+
type: :array,
|
113
|
+
items:
|
114
|
+
{
|
115
|
+
type: :string
|
116
|
+
},
|
117
|
+
nullable: true
|
118
|
+
}
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
def excluded_request_attributes
|
123
|
+
%i[id updated_at created_at applicant_ids comment]
|
124
|
+
end
|
125
|
+
|
126
|
+
def additional_request_attributes
|
127
|
+
{
|
128
|
+
applicants_attributes:
|
129
|
+
{
|
130
|
+
type: :array,
|
131
|
+
items: {
|
132
|
+
anyOf: [
|
133
|
+
{
|
134
|
+
type: :object,
|
135
|
+
properties: Swagger::Definitions::Applicant.new.request_schema.as_json['properties']['data']['properties']
|
136
|
+
}
|
137
|
+
]
|
138
|
+
}
|
139
|
+
}
|
140
|
+
}
|
141
|
+
end
|
142
|
+
|
143
|
+
def additional_response_attributes
|
144
|
+
{
|
145
|
+
comment: { type: :object, properties: {}, nullable: true }
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
def nested_relationships
|
150
|
+
{
|
151
|
+
applicants: {
|
152
|
+
belongs_to: {
|
153
|
+
district: Swagger::Definitions::District,
|
154
|
+
province: Swagger::Definitions::Province,
|
155
|
+
},
|
156
|
+
has_many: {
|
157
|
+
attachments: Swagger::Definitions::Upload,
|
158
|
+
}
|
159
|
+
}
|
160
|
+
}
|
161
|
+
end
|
162
|
+
|
163
|
+
def self.definitions
|
164
|
+
schema_instance = self.new
|
165
|
+
[
|
166
|
+
"#{schema_instance.model}Request": schema_instance.camelize_keys(schema_instance.request_schema),
|
167
|
+
"#{schema_instance.model}Response": schema_instance.camelize_keys(schema_instance.response_schema(expand: true, exclude_from_expansion: [:category], multi: true)),
|
168
|
+
"#{schema_instance.model}ResponseExpanded": schema_instance.camelize_keys(schema_instance.response_schema(expand: true, nested: true))
|
169
|
+
]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
```
|
176
|
+
|
177
|
+
</Details>
|
22
178
|
|
23
179
|
## Development
|
24
180
|
|
data/Rakefile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
5
|
|
6
6
|
RSpec::Core::RakeTask.new(:spec)
|
7
7
|
|
8
|
-
require
|
8
|
+
require 'rubocop/rake_task'
|
9
9
|
|
10
10
|
RuboCop::RakeTask.new
|
11
11
|
|
@@ -4,8 +4,8 @@ module Schemable
|
|
4
4
|
source_root File.expand_path('../../templates', __dir__)
|
5
5
|
class_option :model_name, type: :string, default: 'Model', desc: 'Name of the model'
|
6
6
|
|
7
|
-
def initialize(*)
|
8
|
-
super(*)
|
7
|
+
def initialize(*args)
|
8
|
+
super(*args)
|
9
9
|
end
|
10
10
|
|
11
11
|
def copy_initializer
|
@@ -4,8 +4,8 @@ module Schemable
|
|
4
4
|
source_root File.expand_path('../../templates', __dir__)
|
5
5
|
class_option :model_name, type: :string, default: 'Model', desc: 'Name of the model'
|
6
6
|
|
7
|
-
def initialize(*)
|
8
|
-
super(*)
|
7
|
+
def initialize(*args)
|
8
|
+
super(*args)
|
9
9
|
|
10
10
|
@model_name = options[:model_name]
|
11
11
|
@model_name != 'Model' || raise('Model name is required')
|
@@ -36,8 +36,12 @@ module Swagger
|
|
36
36
|
V1::#{@model_name.classify}Serializer
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
40
|
-
%i[
|
39
|
+
def excluded_create_request_attributes
|
40
|
+
%i[updated_at created_at]
|
41
|
+
end
|
42
|
+
|
43
|
+
def excluded_update_request_attributes
|
44
|
+
%i[updated_at created_at]
|
41
45
|
end
|
42
46
|
end
|
43
47
|
end
|
data/lib/schemable/version.rb
CHANGED