rest-api-generator 0.1.1 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -1
- data/Gemfile.lock +191 -43
- data/README.md +173 -7
- data/Rakefile +1 -1
- data/lib/generators/rest_api_generator/helpers.rb +72 -0
- data/lib/generators/rest_api_generator/resource_generator.rb +33 -16
- data/lib/generators/rest_api_generator/spec/rspec_generator.rb +36 -0
- data/lib/generators/rest_api_generator/spec/rswag_generator.rb +54 -0
- data/lib/generators/rest_api_generator/spec/templates/rspec/nested_resource_controller_spec.rb.tt +62 -0
- data/lib/generators/rest_api_generator/{templates/rest_api_spec.rb.tt → spec/templates/rspec/resource_controller_spec.rb.tt} +5 -5
- data/lib/generators/rest_api_generator/spec/templates/rswag/nested_resource_controller_spec.rb.tt +116 -0
- data/lib/generators/rest_api_generator/spec/templates/rswag/resource_controller_spec.rb.tt +111 -0
- data/lib/generators/rest_api_generator/templates/child_api_controller.rb.tt +10 -9
- data/lib/generators/rest_api_generator/templates/implicit_child_resource_controller.rb.tt +4 -0
- data/lib/generators/rest_api_generator/templates/implicit_resource_controller.rb.tt +4 -0
- data/lib/generators/rest_api_generator/templates/rest_api_controller.rb.tt +2 -0
- data/lib/rest-api-generator.rb +3 -0
- data/lib/rest_api_generator/application_controller.rb +8 -0
- data/lib/rest_api_generator/child_resource_controller.rb +97 -0
- data/lib/rest_api_generator/filterable.rb +30 -0
- data/lib/rest_api_generator/helpers/render.rb +1 -1
- data/lib/rest_api_generator/orderable.rb +30 -0
- data/lib/rest_api_generator/resource_controller.rb +73 -0
- data/lib/rest_api_generator/version.rb +1 -1
- data/lib/rest_api_generator.rb +11 -1
- data/rest-api-generator.gemspec +11 -4
- metadata +90 -8
- data/lib/generators/rest_api_generator/templates/child_api_spec.rb.tt +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3c84db27490fa76b76096f10ba351092bfb42479890a2a279d725f579c4edb7
|
4
|
+
data.tar.gz: 25e537cd496a09eb3b5755fadf4d04bbcaad38c941bf54af60e230ed7a1ccd13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a0f07b832a6373ed5197f114a0bdc54c6a6c2088d712e3641b8d55d717a5d5b019bba3427907b73495ac6a97de2bfbdd68ee48de267651808cf3d6adbe9f2547
|
7
|
+
data.tar.gz: 565c3cc7797794a6c59008990e58727173c5fa472ef8a8a188cb2a2ba60789cf03994ba8feaff7d8d5dfcf3443333412ece5dbb926f5a44156fa71ad240531b0
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,107 +1,255 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rest-api-generator (0.1.
|
5
|
-
|
4
|
+
rest-api-generator (0.1.3)
|
5
|
+
rails (>= 5.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
|
11
|
-
|
12
|
-
activesupport (=
|
13
|
-
|
10
|
+
actioncable (7.0.4)
|
11
|
+
actionpack (= 7.0.4)
|
12
|
+
activesupport (= 7.0.4)
|
13
|
+
nio4r (~> 2.0)
|
14
|
+
websocket-driver (>= 0.6.1)
|
15
|
+
actionmailbox (7.0.4)
|
16
|
+
actionpack (= 7.0.4)
|
17
|
+
activejob (= 7.0.4)
|
18
|
+
activerecord (= 7.0.4)
|
19
|
+
activestorage (= 7.0.4)
|
20
|
+
activesupport (= 7.0.4)
|
21
|
+
mail (>= 2.7.1)
|
22
|
+
net-imap
|
23
|
+
net-pop
|
24
|
+
net-smtp
|
25
|
+
actionmailer (7.0.4)
|
26
|
+
actionpack (= 7.0.4)
|
27
|
+
actionview (= 7.0.4)
|
28
|
+
activejob (= 7.0.4)
|
29
|
+
activesupport (= 7.0.4)
|
30
|
+
mail (~> 2.5, >= 2.5.4)
|
31
|
+
net-imap
|
32
|
+
net-pop
|
33
|
+
net-smtp
|
34
|
+
rails-dom-testing (~> 2.0)
|
35
|
+
actionpack (7.0.4)
|
36
|
+
actionview (= 7.0.4)
|
37
|
+
activesupport (= 7.0.4)
|
38
|
+
rack (~> 2.0, >= 2.2.0)
|
14
39
|
rack-test (>= 0.6.3)
|
15
40
|
rails-dom-testing (~> 2.0)
|
16
41
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
17
|
-
|
18
|
-
|
42
|
+
actiontext (7.0.4)
|
43
|
+
actionpack (= 7.0.4)
|
44
|
+
activerecord (= 7.0.4)
|
45
|
+
activestorage (= 7.0.4)
|
46
|
+
activesupport (= 7.0.4)
|
47
|
+
globalid (>= 0.6.0)
|
48
|
+
nokogiri (>= 1.8.5)
|
49
|
+
actionview (7.0.4)
|
50
|
+
activesupport (= 7.0.4)
|
19
51
|
builder (~> 3.1)
|
20
52
|
erubi (~> 1.4)
|
21
53
|
rails-dom-testing (~> 2.0)
|
22
54
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
23
|
-
|
55
|
+
activejob (7.0.4)
|
56
|
+
activesupport (= 7.0.4)
|
57
|
+
globalid (>= 0.3.6)
|
58
|
+
activemodel (7.0.4)
|
59
|
+
activesupport (= 7.0.4)
|
60
|
+
activerecord (7.0.4)
|
61
|
+
activemodel (= 7.0.4)
|
62
|
+
activesupport (= 7.0.4)
|
63
|
+
activestorage (7.0.4)
|
64
|
+
actionpack (= 7.0.4)
|
65
|
+
activejob (= 7.0.4)
|
66
|
+
activerecord (= 7.0.4)
|
67
|
+
activesupport (= 7.0.4)
|
68
|
+
marcel (~> 1.0)
|
69
|
+
mini_mime (>= 1.1.0)
|
70
|
+
activesupport (7.0.4)
|
24
71
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
25
72
|
i18n (>= 1.6, < 2)
|
26
73
|
minitest (>= 5.1)
|
27
74
|
tzinfo (~> 2.0)
|
28
|
-
|
75
|
+
addressable (2.8.1)
|
76
|
+
public_suffix (>= 2.0.2, < 6.0)
|
77
|
+
ammeter (1.1.5)
|
78
|
+
activesupport (>= 3.0)
|
79
|
+
railties (>= 3.0)
|
80
|
+
rspec-rails (>= 2.2)
|
29
81
|
ast (2.4.2)
|
30
82
|
builder (3.2.4)
|
31
83
|
concurrent-ruby (1.1.10)
|
32
84
|
crass (1.0.6)
|
85
|
+
database_cleaner (2.0.1)
|
86
|
+
database_cleaner-active_record (~> 2.0.0)
|
87
|
+
database_cleaner-active_record (2.0.1)
|
88
|
+
activerecord (>= 5.a)
|
89
|
+
database_cleaner-core (~> 2.0.0)
|
90
|
+
database_cleaner-core (2.0.1)
|
91
|
+
date (3.3.3)
|
33
92
|
diff-lcs (1.5.0)
|
34
|
-
erubi (1.
|
35
|
-
|
93
|
+
erubi (1.12.0)
|
94
|
+
globalid (1.0.0)
|
95
|
+
activesupport (>= 5.0)
|
96
|
+
i18n (1.12.0)
|
36
97
|
concurrent-ruby (~> 1.0)
|
37
|
-
|
98
|
+
json (2.6.3)
|
99
|
+
json-schema (3.0.0)
|
100
|
+
addressable (>= 2.8)
|
101
|
+
loofah (2.19.1)
|
38
102
|
crass (~> 1.0.2)
|
39
103
|
nokogiri (>= 1.5.9)
|
104
|
+
mail (2.8.0)
|
105
|
+
mini_mime (>= 0.1.1)
|
106
|
+
net-imap
|
107
|
+
net-pop
|
108
|
+
net-smtp
|
109
|
+
marcel (1.0.2)
|
40
110
|
method_source (1.0.0)
|
41
|
-
|
42
|
-
|
111
|
+
mini_mime (1.1.2)
|
112
|
+
minitest (5.16.3)
|
113
|
+
net-imap (0.3.4)
|
114
|
+
date
|
115
|
+
net-protocol
|
116
|
+
net-pop (0.1.2)
|
117
|
+
net-protocol
|
118
|
+
net-protocol (0.2.1)
|
119
|
+
timeout
|
120
|
+
net-smtp (0.3.3)
|
121
|
+
net-protocol
|
122
|
+
nio4r (2.5.8)
|
123
|
+
nokogiri (1.13.10-x86_64-linux)
|
43
124
|
racc (~> 1.4)
|
44
125
|
parallel (1.22.1)
|
45
|
-
parser (3.1.
|
126
|
+
parser (3.1.3.0)
|
46
127
|
ast (~> 2.4.1)
|
47
|
-
|
128
|
+
public_suffix (5.0.1)
|
129
|
+
racc (1.6.2)
|
48
130
|
rack (2.2.4)
|
49
131
|
rack-test (2.0.2)
|
50
132
|
rack (>= 1.3)
|
133
|
+
rails (7.0.4)
|
134
|
+
actioncable (= 7.0.4)
|
135
|
+
actionmailbox (= 7.0.4)
|
136
|
+
actionmailer (= 7.0.4)
|
137
|
+
actionpack (= 7.0.4)
|
138
|
+
actiontext (= 7.0.4)
|
139
|
+
actionview (= 7.0.4)
|
140
|
+
activejob (= 7.0.4)
|
141
|
+
activemodel (= 7.0.4)
|
142
|
+
activerecord (= 7.0.4)
|
143
|
+
activestorage (= 7.0.4)
|
144
|
+
activesupport (= 7.0.4)
|
145
|
+
bundler (>= 1.15.0)
|
146
|
+
railties (= 7.0.4)
|
51
147
|
rails-dom-testing (2.0.3)
|
52
148
|
activesupport (>= 4.2.0)
|
53
149
|
nokogiri (>= 1.6)
|
54
|
-
rails-html-sanitizer (1.4.
|
55
|
-
loofah (~> 2.
|
56
|
-
railties (
|
57
|
-
actionpack (=
|
58
|
-
activesupport (=
|
150
|
+
rails-html-sanitizer (1.4.4)
|
151
|
+
loofah (~> 2.19, >= 2.19.1)
|
152
|
+
railties (7.0.4)
|
153
|
+
actionpack (= 7.0.4)
|
154
|
+
activesupport (= 7.0.4)
|
59
155
|
method_source
|
60
156
|
rake (>= 12.2)
|
61
157
|
thor (~> 1.0)
|
158
|
+
zeitwerk (~> 2.5)
|
62
159
|
rainbow (3.1.1)
|
63
160
|
rake (13.0.6)
|
64
|
-
regexp_parser (2.
|
161
|
+
regexp_parser (2.6.1)
|
65
162
|
rexml (3.2.5)
|
66
|
-
rspec (3.
|
67
|
-
rspec-core (~> 3.
|
68
|
-
rspec-expectations (~> 3.
|
69
|
-
rspec-mocks (~> 3.
|
70
|
-
rspec-core (3.
|
71
|
-
rspec-support (~> 3.
|
72
|
-
rspec-expectations (3.
|
163
|
+
rspec (3.12.0)
|
164
|
+
rspec-core (~> 3.12.0)
|
165
|
+
rspec-expectations (~> 3.12.0)
|
166
|
+
rspec-mocks (~> 3.12.0)
|
167
|
+
rspec-core (3.12.0)
|
168
|
+
rspec-support (~> 3.12.0)
|
169
|
+
rspec-expectations (3.12.1)
|
73
170
|
diff-lcs (>= 1.2.0, < 2.0)
|
74
|
-
rspec-support (~> 3.
|
75
|
-
rspec-mocks (3.
|
171
|
+
rspec-support (~> 3.12.0)
|
172
|
+
rspec-mocks (3.12.1)
|
76
173
|
diff-lcs (>= 1.2.0, < 2.0)
|
77
|
-
rspec-support (~> 3.
|
78
|
-
rspec-
|
79
|
-
|
174
|
+
rspec-support (~> 3.12.0)
|
175
|
+
rspec-rails (6.0.1)
|
176
|
+
actionpack (>= 6.1)
|
177
|
+
activesupport (>= 6.1)
|
178
|
+
railties (>= 6.1)
|
179
|
+
rspec-core (~> 3.11)
|
180
|
+
rspec-expectations (~> 3.11)
|
181
|
+
rspec-mocks (~> 3.11)
|
182
|
+
rspec-support (~> 3.11)
|
183
|
+
rspec-support (3.12.0)
|
184
|
+
rswag (2.8.0)
|
185
|
+
rswag-api (= 2.8.0)
|
186
|
+
rswag-specs (= 2.8.0)
|
187
|
+
rswag-ui (= 2.8.0)
|
188
|
+
rswag-api (2.8.0)
|
189
|
+
railties (>= 3.1, < 7.1)
|
190
|
+
rswag-specs (2.8.0)
|
191
|
+
activesupport (>= 3.1, < 7.1)
|
192
|
+
json-schema (>= 2.2, < 4.0)
|
193
|
+
railties (>= 3.1, < 7.1)
|
194
|
+
rspec-core (>= 2.14)
|
195
|
+
rswag-ui (2.8.0)
|
196
|
+
actionpack (>= 3.1, < 7.1)
|
197
|
+
railties (>= 3.1, < 7.1)
|
198
|
+
rubocop (1.40.0)
|
199
|
+
json (~> 2.3)
|
80
200
|
parallel (~> 1.10)
|
81
|
-
parser (>= 3.1.
|
201
|
+
parser (>= 3.1.2.1)
|
82
202
|
rainbow (>= 2.2.2, < 4.0)
|
83
203
|
regexp_parser (>= 1.8, < 3.0)
|
84
|
-
rexml
|
85
|
-
rubocop-ast (>= 1.
|
204
|
+
rexml (>= 3.2.5, < 4.0)
|
205
|
+
rubocop-ast (>= 1.23.0, < 2.0)
|
86
206
|
ruby-progressbar (~> 1.7)
|
87
207
|
unicode-display_width (>= 1.4.0, < 3.0)
|
88
|
-
rubocop-ast (1.
|
208
|
+
rubocop-ast (1.24.0)
|
89
209
|
parser (>= 3.1.1.0)
|
210
|
+
rubocop-performance (1.15.2)
|
211
|
+
rubocop (>= 1.7.0, < 2.0)
|
212
|
+
rubocop-ast (>= 0.4.0)
|
213
|
+
rubocop-rails (2.17.4)
|
214
|
+
activesupport (>= 4.2.0)
|
215
|
+
rack (>= 1.1)
|
216
|
+
rubocop (>= 1.33.0, < 2.0)
|
217
|
+
rubocop-rspec (2.16.0)
|
218
|
+
rubocop (~> 1.33)
|
219
|
+
rubocop-shopify (2.10.1)
|
220
|
+
rubocop (~> 1.35)
|
90
221
|
ruby-progressbar (1.11.0)
|
222
|
+
sqlite3 (1.5.4-x86_64-linux)
|
223
|
+
switchcop (0.1.2)
|
224
|
+
rubocop (~> 1.40.0)
|
225
|
+
rubocop-performance (~> 1.15.1)
|
226
|
+
rubocop-rails (~> 2.17.3)
|
227
|
+
rubocop-rspec (~> 2.16.0)
|
228
|
+
rubocop-shopify (~> 2.10.1)
|
91
229
|
thor (1.2.1)
|
92
|
-
|
230
|
+
timeout (0.3.1)
|
231
|
+
tzinfo (2.0.5)
|
93
232
|
concurrent-ruby (~> 1.0)
|
94
|
-
unicode-display_width (2.
|
95
|
-
|
233
|
+
unicode-display_width (2.3.0)
|
234
|
+
websocket-driver (0.7.5)
|
235
|
+
websocket-extensions (>= 0.1.0)
|
236
|
+
websocket-extensions (0.1.5)
|
237
|
+
zeitwerk (2.6.6)
|
96
238
|
|
97
239
|
PLATFORMS
|
98
240
|
x86_64-linux
|
99
241
|
|
100
242
|
DEPENDENCIES
|
243
|
+
ammeter (~> 1.1.5)
|
244
|
+
database_cleaner
|
101
245
|
rake (~> 13.0)
|
102
246
|
rest-api-generator!
|
103
247
|
rspec (~> 3.0)
|
104
|
-
|
248
|
+
rspec-rails (~> 6.0.0)
|
249
|
+
rswag
|
250
|
+
rswag-specs
|
251
|
+
sqlite3
|
252
|
+
switchcop
|
105
253
|
|
106
254
|
BUNDLED WITH
|
107
255
|
2.3.3
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ practices.
|
|
5
5
|
|
6
6
|
## How it works?
|
7
7
|
|
8
|
-
The gems use vanilla Rails generators
|
8
|
+
The gems use vanilla Rails generators in combination with our templates to create all the resources needed to build a
|
9
9
|
REST API.
|
10
10
|
|
11
11
|
Following [Switch Dreams's](https://www.switchdreams.com.br/]) coding practices, the controllers are built with:
|
@@ -16,14 +16,31 @@ Following [Switch Dreams's](https://www.switchdreams.com.br/]) coding practices,
|
|
16
16
|
|
17
17
|
- For tests, we use RSpec and FactoryBot.
|
18
18
|
|
19
|
+
## Current Features
|
20
|
+
|
21
|
+
- [Automatic rest api crud generation](#example)
|
22
|
+
- [Nested Resource](#nested-resource)
|
23
|
+
- :goal_net: [Modular error handler](#modular-error-handler)
|
24
|
+
- :memo: [Automated documentation](#specsdocs)
|
25
|
+
- [Resource ordering](#ordering)
|
26
|
+
- [Resource filter](#filtering)
|
27
|
+
|
28
|
+
## Next Features
|
29
|
+
|
30
|
+
- Serialization https://github.com/SwitchDreams/rest-api-generator/issues/14
|
31
|
+
https://github.com/SwitchDreams/rest-api-generator/issues/11
|
32
|
+
- Pagination https://github.com/SwitchDreams/rest-api-generator/issues/15
|
33
|
+
- Integration with AVO
|
34
|
+
- Select fields
|
35
|
+
- User auth module
|
36
|
+
|
19
37
|
## Installation
|
20
38
|
|
21
39
|
Add this line to your application's Gemfile:
|
22
40
|
|
23
41
|
```ruby
|
24
|
-
|
25
|
-
|
26
|
-
end
|
42
|
+
# Build a Ruby on Rails REST API faster
|
43
|
+
gem 'rest-api-generator'
|
27
44
|
```
|
28
45
|
|
29
46
|
And then execute:
|
@@ -61,13 +78,15 @@ This error handler will rescue from: `ActiveRecord::RecordNotFound`
|
|
61
78
|
### Generate Resource
|
62
79
|
|
63
80
|
```bash
|
64
|
-
$ rails g
|
81
|
+
$ rails g rest_api_generator:resource table_name attributes
|
65
82
|
```
|
66
83
|
|
67
84
|
This command will create:
|
68
85
|
|
69
86
|
- **Model and Migration**: Using rails default model generator
|
70
|
-
- **Controller**: A controller
|
87
|
+
- **Controller**: A controller that implementes CRUD by inheritance of `RestApiGenerator::ResourceController`, or you
|
88
|
+
can use eject option for create a controller
|
89
|
+
that implements index, show, create, update and destroy methods.
|
71
90
|
- **Specs for the created controller**
|
72
91
|
- **Factory bot factory for created model**
|
73
92
|
- **Routes**: with rails resources
|
@@ -75,11 +94,97 @@ This command will create:
|
|
75
94
|
### Example
|
76
95
|
|
77
96
|
```bash
|
78
|
-
$ rails g
|
97
|
+
$ rails g rest_api_generator:resource car name:string color:string
|
79
98
|
```
|
80
99
|
|
81
100
|
Will generate following controller and the other files:
|
82
101
|
|
102
|
+
```ruby
|
103
|
+
# app/controllers/cars_controller.rb
|
104
|
+
class CarsController < RestApiGenerator::ResourceController
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
For a better experience you can override some methods from the
|
109
|
+
[default controller](https://github.com/SwitchDreams/rest-api-generator/blob/main/lib/rest_api_generator/resource_controller.rb)
|
110
|
+
|
111
|
+
### Options
|
112
|
+
|
113
|
+
| Option | Goal | Default | Usage Example |
|
114
|
+
|--------|--------------------------------------------------------------|---------|-----------------|
|
115
|
+
| father | Generate nested resource | nil | --father Users |
|
116
|
+
| scope | Scope the resource for other route or namespace organization | nil | --scope Api::V1 |
|
117
|
+
| eject | Eject the controller to high customization | false | true |
|
118
|
+
| spec | Choose the spec format. Current options: "rspec" or "rswag" | rspec | --spec rswag |
|
119
|
+
|
120
|
+
#### Scope
|
121
|
+
|
122
|
+
In REST api one of the best practices is versioning the end-points, and you can achieve this using scope options,
|
123
|
+
example:
|
124
|
+
|
125
|
+
```bash
|
126
|
+
# Command
|
127
|
+
rails g rest_api_generator:resource car name:string color:string --scope Api::V1
|
128
|
+
```
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
# GET api/v1/cars
|
132
|
+
module Api::V1
|
133
|
+
class CarsController < RestApiGenerator::ResourceController
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
For this option you need to manually setup routes, for this example:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
# routes.rb
|
142
|
+
namespace :api do
|
143
|
+
namespace :v1 do
|
144
|
+
resources :cars
|
145
|
+
end
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
#### Nested resource
|
150
|
+
|
151
|
+
In REST api sometimes we need to build a nested resource, for example when we need to get all devices from a user, for
|
152
|
+
this we have nested resource option:
|
153
|
+
|
154
|
+
```bash
|
155
|
+
# Command
|
156
|
+
rails g rest_api_generator:resource Devices name:string color:string users:references --scope Users
|
157
|
+
```
|
158
|
+
|
159
|
+
```ruby
|
160
|
+
# GET users/:user_id/devices
|
161
|
+
module Users
|
162
|
+
class DevicesController < RestApiGenerator::ChildResourceController
|
163
|
+
end
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
167
|
+
For this option you need to manually setup routes, for this example:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
# routes.rb
|
171
|
+
resources :users do
|
172
|
+
resources :devices, controller: 'users/devices'
|
173
|
+
end
|
174
|
+
```
|
175
|
+
|
176
|
+
Considerations:
|
177
|
+
|
178
|
+
- The children model needs to belongs_to parent model and parent model needs to have has_many children model
|
179
|
+
|
180
|
+
#### Eject
|
181
|
+
|
182
|
+
Or you can use the `eject` option for create the controller with the implemented methods:
|
183
|
+
|
184
|
+
```bash
|
185
|
+
rails g rest_api_generator:resource car name:string color:string --eject true
|
186
|
+
```
|
187
|
+
|
83
188
|
```ruby
|
84
189
|
|
85
190
|
class CarsController < ApplicationController
|
@@ -118,9 +223,70 @@ class CarsController < ApplicationController
|
|
118
223
|
params.require(:car).permit(:name, :color)
|
119
224
|
end
|
120
225
|
end
|
226
|
+
```
|
227
|
+
|
228
|
+
#### Specs/Docs
|
229
|
+
|
230
|
+
The default generated spec for this gem is using plain rspec, but you can choose rswag, for scaffold you specs and docs
|
231
|
+
at the same time:
|
232
|
+
|
233
|
+
For this you need to setup https://github.com/rswag/rswag and you the following flag when generating resources.
|
234
|
+
|
235
|
+
```shell
|
236
|
+
rails g rest_api_generator:resource Car name:string color:string --spec rswag
|
237
|
+
```
|
238
|
+
|
239
|
+
This spec options work as generators too, so you can call them individually:
|
240
|
+
|
241
|
+
```shell
|
242
|
+
# rest_api_generator:spec:rswag or rest_api_generator:spec:rspec
|
243
|
+
rails g rest_api_generator:spec:rswag Car name:string color:string
|
244
|
+
```
|
245
|
+
|
246
|
+
### Resource Features
|
247
|
+
|
248
|
+
#### Modular Error Handler
|
121
249
|
|
250
|
+
The error module will return a json in this following format when any active record or custom error raises.
|
251
|
+
|
252
|
+
```json
|
253
|
+
{
|
254
|
+
"status": 422,
|
255
|
+
"error": "",
|
256
|
+
"message": ""
|
257
|
+
}
|
122
258
|
```
|
123
259
|
|
260
|
+
This is good to padronize the error handler in front-end too.
|
261
|
+
|
262
|
+
#### Ordering
|
263
|
+
|
264
|
+
For ordering use this format:
|
265
|
+
|
266
|
+
- Ordering asc: `GET /cars?sort=+name or GET /cars?sort=name`
|
267
|
+
- Ordering desc: `GET /card?sort=-name`
|
268
|
+
|
269
|
+
By default, every resource column can be the key for ordering.
|
270
|
+
|
271
|
+
#### Filtering
|
272
|
+
|
273
|
+
For filter is needed to add some scopes in Model file, example:
|
274
|
+
|
275
|
+
```ruby
|
276
|
+
# app/models/car.rb
|
277
|
+
|
278
|
+
class Car < ApplicationRecord
|
279
|
+
include RestApiGenerator::Filterable
|
280
|
+
|
281
|
+
filter_scope :filter_by_color, ->(color) { where(color: color) }
|
282
|
+
filter_scope :filter_by_name, ->(name) { where("name LIKE ?", "%#{name}%") }
|
283
|
+
end
|
284
|
+
```
|
285
|
+
|
286
|
+
And It's done, you can filter your index end-point:
|
287
|
+
|
288
|
+
- `GET /cars?color=blue or GET /cars?color=red&name=Ferrari`
|
289
|
+
|
124
290
|
## Development
|
125
291
|
|
126
292
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can
|
data/Rakefile
CHANGED
@@ -4,8 +4,12 @@ module RestApiGenerator
|
|
4
4
|
module Helpers
|
5
5
|
attr_accessor :options, :attributes
|
6
6
|
|
7
|
+
API_CONTROLLER_DIR_PATH = "app/controllers"
|
8
|
+
API_TEST_DIR_PATH = "spec/requests"
|
9
|
+
|
7
10
|
private
|
8
11
|
|
12
|
+
# Columns handlers
|
9
13
|
def model_columns_for_attributes
|
10
14
|
class_name.singularize.constantize.columns.reject do |column|
|
11
15
|
column.name.to_s =~ /^(id|user_id|created_at|updated_at)$/
|
@@ -17,5 +21,73 @@ module RestApiGenerator
|
|
17
21
|
Rails::Generators::GeneratedAttribute.new(column.name.to_s, column.type.to_s)
|
18
22
|
end
|
19
23
|
end
|
24
|
+
|
25
|
+
# Namespace scope
|
26
|
+
|
27
|
+
def scope_namespacing(&block)
|
28
|
+
content = capture(&block)
|
29
|
+
content = wrap_with_scope(content) if options["scope"].present? || options["father"].present?
|
30
|
+
concat(content)
|
31
|
+
end
|
32
|
+
|
33
|
+
def module_namespace
|
34
|
+
if options["scope"].present? && options["father"].present?
|
35
|
+
options["scope"] + "::" + options["father"]
|
36
|
+
else
|
37
|
+
options["scope"] + options["father"]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def wrap_with_scope(content)
|
42
|
+
content = indent(content).chomp
|
43
|
+
"module #{module_namespace}\n#{content}\nend\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
# Paths handlers
|
47
|
+
def controller_path
|
48
|
+
"#{API_CONTROLLER_DIR_PATH}#{scope_path}/#{file_name.pluralize}_controller.rb"
|
49
|
+
end
|
50
|
+
|
51
|
+
def scope_path
|
52
|
+
return "" if options["scope"].blank? && options["father"].blank?
|
53
|
+
|
54
|
+
if options["scope"].present? && options["father"].present?
|
55
|
+
"/" + option_to_path(options["scope"]) + "/" + option_to_path(options["father"])
|
56
|
+
else
|
57
|
+
"/" + option_to_path(options["scope"]) + option_to_path(options["father"])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def option_to_path(option)
|
62
|
+
option.downcase.split("::").join("/")
|
63
|
+
end
|
64
|
+
|
65
|
+
def scope_route_path
|
66
|
+
return "" if options["scope"].blank?
|
67
|
+
|
68
|
+
option_to_path(options["scope"])
|
69
|
+
end
|
70
|
+
|
71
|
+
def nested_routes
|
72
|
+
return "" if options["father"].blank?
|
73
|
+
|
74
|
+
"#{options["father"].downcase.pluralize}/\#{#{options["father"].singularize.downcase}.id}/#{plural_name}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def initial_route
|
78
|
+
return "/#{plural_name}" if options["father"].blank? && options["scope"].blank?
|
79
|
+
|
80
|
+
scope_route_path + "/" + nested_routes
|
81
|
+
end
|
82
|
+
|
83
|
+
def spec_routes
|
84
|
+
{
|
85
|
+
index: initial_route,
|
86
|
+
show: initial_route + "\#{#{singular_name}.id}",
|
87
|
+
create: initial_route,
|
88
|
+
update: initial_route + "\#{#{singular_name}.id}",
|
89
|
+
delete: initial_route + "\#{#{singular_name}.id}",
|
90
|
+
}
|
91
|
+
end
|
20
92
|
end
|
21
93
|
end
|