grape-starter 1.6.2 → 2.0.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/workflows/pipeline.yml +5 -2
- data/.gitignore +4 -0
- data/.rubocop.yml +9 -2
- data/CHANGELOG.md +36 -4
- data/README.md +38 -6
- data/bin/grape-starter +18 -1
- data/grape-starter.gemspec +1 -1
- data/lib/starter/build.rb +6 -6
- data/lib/starter/builder/activerecord.rb +1 -1
- data/lib/starter/{templates → builder}/endpoints.rb +1 -1
- data/lib/starter/{templates → builder}/files.rb +1 -1
- data/lib/starter/builder/sequel.rb +1 -1
- data/lib/starter/import.rb +52 -0
- data/lib/starter/importer/namespace.rb +73 -0
- data/lib/starter/importer/nested_params.rb +14 -0
- data/lib/starter/importer/parameter.rb +180 -0
- data/lib/starter/importer/specification.rb +71 -0
- data/lib/starter/names.rb +87 -0
- data/lib/starter/{builder → shared}/base_file.rb +11 -6
- data/lib/starter/version.rb +1 -1
- data/lib/starter.rb +1 -2
- data/template/.rubocop.yml +3 -0
- data/template/Dockerfile +1 -1
- data/template/Gemfile +1 -1
- data/template/config/boot.rb +1 -1
- metadata +13 -8
- data/lib/starter/builder/names.rb +0 -86
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8d9f7ca7efc30bff48e6f765786b43a6cfd6d2c1c68d93063bbab89c4042bb5d
|
|
4
|
+
data.tar.gz: 1ecd2c9a8ce6eeebd94ed79a5e08bb81328c327a361750ca6ae1aff8578281ef
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: baa02a26a233adc4f6edd6afe687356b99d29ef59071a170cf6183fb257be59254d7c2bb2e04bcf63bd67e8978e46c6a261cbb71319340ebeedacee3a8427f22
|
|
7
|
+
data.tar.gz: 43a5e2557d01d84bccc0cf91e5d7c52446b86572a2343d19ce2d905172b01b5c83bbf085d04d646e7cf6faf01b5466e0f47912323c32433981b693b5ff1bfad1
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
name: Pipeline
|
|
2
2
|
on:
|
|
3
3
|
pull_request:
|
|
4
|
-
|
|
4
|
+
branches:
|
|
5
|
+
- 'master'
|
|
5
6
|
push:
|
|
6
7
|
branches:
|
|
7
8
|
- 'master'
|
|
@@ -23,9 +24,11 @@ jobs:
|
|
|
23
24
|
rspec:
|
|
24
25
|
runs-on: ubuntu-latest
|
|
25
26
|
needs: ['rubocop']
|
|
27
|
+
env:
|
|
28
|
+
RACK_ENV: test
|
|
26
29
|
strategy:
|
|
27
30
|
matrix:
|
|
28
|
-
ruby-version: ['3.
|
|
31
|
+
ruby-version: ['3.1', '3.2', head]
|
|
29
32
|
|
|
30
33
|
steps:
|
|
31
34
|
- uses: actions/checkout@v3
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -12,6 +12,7 @@ AllCops:
|
|
|
12
12
|
- '**/template/api/**'
|
|
13
13
|
- grape-starter.gemspec
|
|
14
14
|
- template/spec/spec-helper.rb
|
|
15
|
+
- api/**/*
|
|
15
16
|
UseCache: true
|
|
16
17
|
NewCops: enable
|
|
17
18
|
TargetRubyVersion: 3.2
|
|
@@ -25,6 +26,9 @@ Layout/IndentationWidth:
|
|
|
25
26
|
Layout/LineLength:
|
|
26
27
|
Max: 120
|
|
27
28
|
|
|
29
|
+
Lint/MissingSuper:
|
|
30
|
+
Enabled: false
|
|
31
|
+
|
|
28
32
|
Metrics/BlockLength:
|
|
29
33
|
Exclude:
|
|
30
34
|
- 'spec/**/*'
|
|
@@ -32,13 +36,16 @@ Metrics/BlockLength:
|
|
|
32
36
|
Metrics/AbcSize:
|
|
33
37
|
Max: 20
|
|
34
38
|
|
|
39
|
+
Metrics/ClassLength:
|
|
40
|
+
Max: 120
|
|
41
|
+
|
|
35
42
|
Metrics/MethodLength:
|
|
36
43
|
Max: 20
|
|
37
44
|
|
|
38
45
|
Naming/AccessorMethodName:
|
|
39
46
|
Exclude:
|
|
40
|
-
- 'lib/starter/
|
|
41
|
-
- 'lib/starter/
|
|
47
|
+
- 'lib/starter/builder/files.rb'
|
|
48
|
+
- 'lib/starter/builder/endpoints.rb'
|
|
42
49
|
|
|
43
50
|
Style/AsciiComments:
|
|
44
51
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,38 @@
|
|
|
1
1
|
### NEXT
|
|
2
2
|
|
|
3
|
-
-
|
|
3
|
+
- contributions
|
|
4
|
+
|
|
5
|
+
### v2.0.0 / 2023-10-21 Imports OApi specs
|
|
6
|
+
|
|
7
|
+
- [(#38)](https://github.com/LeFnord/grape-starter/pull/38) Handles nested body [LeFnord](https://github.com/LeFnord)
|
|
8
|
+
- [(#38)](https://github.com/LeFnord/grape-starter/pull/38) Handle parameters from request body [LeFnord](https://github.com/LeFnord)
|
|
9
|
+
- [(#37)](https://github.com/LeFnord/grape-starter/pull/37) Ignores possible version segments in path [LeFnord](https://github.com/LeFnord)
|
|
10
|
+
- Sets min ruby to 3.1 [LeFnord](https://github.com/LeFnord)
|
|
11
|
+
- [(#36)](https://github.com/LeFnord/grape-starter/pull/36) Handle Parameters [LeFnord](https://github.com/LeFnord)
|
|
12
|
+
- Avoids duplicated mount points. [LeFnord](https://github.com/LeFnord)
|
|
13
|
+
- Small code smells [LeFnord](https://github.com/LeFnord)
|
|
14
|
+
- Sets next version to 2.0.0 [LeFnord](https://github.com/LeFnord)
|
|
15
|
+
- [(#31)](https://github.com/LeFnord/grape-starter/pull/31) Import OAPI spec [LeFnord](https://github.com/LeFnord)
|
|
16
|
+
- Fix for Dockerfile smell DL3020 [#35](https://github.com/LeFnord/grape-starter/pull/35) [Giovanni Rosa](https://github.com/grosa1)
|
|
17
|
+
|
|
18
|
+
### v1.6.2 / 2023-03-12
|
|
19
|
+
|
|
20
|
+
- [(#34)](https://github.com/LeFnord/grape-starter/pull/34) Makes Names a class [LeFnord](https://github.com/LeFnord)
|
|
21
|
+
- Re-organises libe files. [LeFnord](https://github.com/LeFnord)
|
|
22
|
+
- Minor clean up. [LeFnord](https://github.com/LeFnord)
|
|
23
|
+
|
|
24
|
+
### v1.6.1 / 2023-02-17 -> yanked
|
|
25
|
+
|
|
26
|
+
### v1.6.0 / 2023-02-13
|
|
27
|
+
|
|
28
|
+
- [(#33)](https://github.com/LeFnord/grape-starter/pull/33) Replaces Thin by Puma [LeFnord](https://github.com/LeFnord)
|
|
29
|
+
- Minor lint fix. [LeFnord](https://github.com/LeFnord)
|
|
30
|
+
- [(#32)](https://github.com/LeFnord/grape-starter/pull/32) Uses Zeitwerk for loading [LeFnord](https://github.com/LeFnord)
|
|
31
|
+
|
|
32
|
+
### v1.5.2 / 2023-02-11
|
|
33
|
+
|
|
34
|
+
- Upgrades action. [LeFnord](https://github.com/LeFnord)
|
|
35
|
+
- Uses ruby 3.2 [LeFnord](https://github.com/LeFnord)
|
|
4
36
|
|
|
5
37
|
### v1.5.1 / 2021-12-28
|
|
6
38
|
|
|
@@ -47,7 +79,7 @@
|
|
|
47
79
|
- Changes ruby.yml to use 2.7 [LeFnord](https://github.com/LeFnord)
|
|
48
80
|
- Prepare release 1.2.4 [LeFnord](https://github.com/LeFnord)
|
|
49
81
|
- Respects froozen string stuff. [LeFnord](https://github.com/LeFnord)
|
|
50
|
-
- Updates Ruby and deps
|
|
82
|
+
- [(#23)](https://github.com/LeFnord/grape-starter/pull/23) Updates Ruby and deps [LeFnord](https://github.com/LeFnord)
|
|
51
83
|
- Create ruby.yml [LeFnord](https://github.com/LeFnord)
|
|
52
84
|
|
|
53
85
|
- Fixes gems for sequel. [LeFnord](https://github.com/LeFnord)
|
|
@@ -55,8 +87,8 @@
|
|
|
55
87
|
|
|
56
88
|
### v1.2.3 / 2019-12-15
|
|
57
89
|
|
|
58
|
-
- Removes require pry. [LeFnord](LeFnord) closes [!21](https://github.com/LeFnord/grape-starter/issues/21)
|
|
59
|
-
- [#22](https://github.com/LeFnord/grape-starter/pull/22) - accomodate activerecord 6.0
|
|
90
|
+
- Removes require pry. [LeFnord](https://github.com/LeFnord) closes [!21](https://github.com/LeFnord/grape-starter/issues/21)
|
|
91
|
+
- [#22](https://github.com/LeFnord/grape-starter/pull/22) - accomodate activerecord 6.0 [#22](https://github.com/LeFnord/grape-starter/pull/22) [Ignacio Carrera](https://github.com/nachokb)
|
|
60
92
|
|
|
61
93
|
### v1.2.2 / 2019-02-28
|
|
62
94
|
|
data/README.md
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
[](https://github.com/LeFnord/grape-starter/actions/workflows/pipeline.yml)
|
|
2
2
|
[](https://badge.fury.io/rb/grape-starter)
|
|
3
3
|
|
|
4
|
+
- [Why the next one?](#why-the-next-one)
|
|
5
|
+
- [Usage](#usage)
|
|
6
|
+
- [Install it](#install-it)
|
|
7
|
+
- [Create a new project](#create-a-new-project)
|
|
8
|
+
- [Add resources](#add-resources)
|
|
9
|
+
- [Import OAPI spec \[WIP\]](#import-oapi-spec-wip)
|
|
10
|
+
- [Remove a resource](#remove-a-resource)
|
|
11
|
+
- [Contributing](#contributing)
|
|
12
|
+
- [Adding a new ORM template](#adding-a-new-orm-template)
|
|
13
|
+
- [License](#license)
|
|
14
|
+
|
|
4
15
|
|
|
5
16
|
# Grape Starter
|
|
6
17
|
|
|
@@ -9,20 +20,24 @@ Is a tool to help you to build up a skeleton for a [Grape](http://github.com/rub
|
|
|
9
20
|
|
|
10
21
|

|
|
11
22
|
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
12
26
|
## Why the next one?
|
|
13
27
|
|
|
14
28
|
- build up a playground for your ideas, prototypes, testing behaviour … whatever
|
|
15
29
|
- ~~no assumtions about~~ you can choose, if you want to use a backend/ORM, ergo no restrictions, only a pure grape/rack skeleton with a nice documentation
|
|
16
30
|
|
|
31
|
+
|
|
17
32
|
## Usage
|
|
18
33
|
|
|
19
|
-
|
|
34
|
+
### Install it
|
|
20
35
|
```
|
|
21
36
|
$ gem install grape-starter
|
|
22
37
|
```
|
|
23
38
|
|
|
24
39
|
|
|
25
|
-
|
|
40
|
+
### Create a new project
|
|
26
41
|
```
|
|
27
42
|
$ grape-starter new awesome_api
|
|
28
43
|
```
|
|
@@ -32,9 +47,7 @@ with following options:
|
|
|
32
47
|
-p foobar, --prefix=foobar # sets the prefix of the API (default: none)
|
|
33
48
|
-o sequel, --orm=sequel # create files for the specified ORM, available: sequel, activerecord (ar) (default: none)
|
|
34
49
|
```
|
|
35
|
-
|
|
36
50
|
This command creates a folder named `awesome_api` containing the skeleton. With following structure:
|
|
37
|
-
|
|
38
51
|
```
|
|
39
52
|
├── <Standards>
|
|
40
53
|
├── api
|
|
@@ -88,7 +101,7 @@ the documentation of it under: [http://localhost:9292/doc](http://localhost:9292
|
|
|
88
101
|
More could be found in [README](template/README.md).
|
|
89
102
|
|
|
90
103
|
|
|
91
|
-
|
|
104
|
+
### Add resources
|
|
92
105
|
```
|
|
93
106
|
$ grape-starter add foo [http methods]
|
|
94
107
|
```
|
|
@@ -117,7 +130,24 @@ If the `orm` switch `true`, the lib class would be created as child class of a s
|
|
|
117
130
|
so for example for Sequel, it would be wirtten: `Foo < Sequel::Model` instead of `Foo`, hereby the using ORM would be taken from the configuration, which was stored by project creation.
|
|
118
131
|
|
|
119
132
|
|
|
120
|
-
|
|
133
|
+
### Import OAPI spec [WIP]
|
|
134
|
+
```
|
|
135
|
+
$ grape-starter import path/to/spec
|
|
136
|
+
```
|
|
137
|
+
to create an API based on the spec.
|
|
138
|
+
|
|
139
|
+
##### To Dos:
|
|
140
|
+
|
|
141
|
+
- [x] read spec an create per namespace a file with defined endpoint
|
|
142
|
+
- [x] read path parameter
|
|
143
|
+
- [x] requires it in param block
|
|
144
|
+
- [x] specify it
|
|
145
|
+
- [x] handle query parameter -> check it
|
|
146
|
+
- [x] handle body parameter -> check it
|
|
147
|
+
- [ ] add description block
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
### Remove a resource
|
|
121
151
|
```
|
|
122
152
|
$ grape-starter rm foo
|
|
123
153
|
```
|
|
@@ -128,6 +158,7 @@ to remove previous generated files for a resource.
|
|
|
128
158
|
|
|
129
159
|
Any contributions are welcome on GitHub at https://github.com/LeFnord/grape-starter.
|
|
130
160
|
|
|
161
|
+
|
|
131
162
|
### Adding a new ORM template
|
|
132
163
|
|
|
133
164
|
To add an new ORM, it needs following steps:
|
|
@@ -168,6 +199,7 @@ To add an new ORM, it needs following steps:
|
|
|
168
199
|
2. An additional switch in the [`Starter::Orms.build`](https://github.com/LeFnord/grape-starter/blob/ef45133e6d2254efee06ae4f17ede2fc5c06bebb/lib/starter/builder/orms.rb#L7-L18) and [`Starter::Names.lib_klass_name`](https://github.com/LeFnord/grape-starter/blob/ef45133e6d2254efee06ae4f17ede2fc5c06bebb/lib/starter/builder/names.rb#L13-L24) methods to choose the right template.
|
|
169
200
|
3. An entry in the description of the [`new` command](https://github.com/LeFnord/grape-starter/blob/fa62c8a2ff72f984144b2336859d3e0b397398bd/bin/grape-starter#L28), when it would be called with `-h`
|
|
170
201
|
|
|
202
|
+
|
|
171
203
|
## License
|
|
172
204
|
|
|
173
205
|
The gem is available as open source under the terms of the [MIT License](LICENSE).
|
data/bin/grape-starter
CHANGED
|
@@ -73,7 +73,7 @@ command :add do |c|
|
|
|
73
73
|
builder_options = global_options.merge(set: set).merge(options)
|
|
74
74
|
created_files = Starter::Build.add!(resource, builder_options)
|
|
75
75
|
|
|
76
|
-
`bundle exec rubocop -a #{created_files.join(' ')}`
|
|
76
|
+
`bundle exec rubocop --only Layout -a #{created_files.join(' ')}`
|
|
77
77
|
$stdout.puts "added resource: #{resource}"
|
|
78
78
|
rescue => e
|
|
79
79
|
exit_now! e
|
|
@@ -97,6 +97,23 @@ command :rm do |c|
|
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
+
desc 'Adds resources from given OAPI spec'
|
|
101
|
+
long_desc 'Import YAML or JSON OAPI specification given by path argument'
|
|
102
|
+
arg_name 'path'
|
|
103
|
+
command :import do |c|
|
|
104
|
+
c.action do |_global_options, _options, args|
|
|
105
|
+
path = args.first
|
|
106
|
+
exit_now! 'no path given' if path.blank?
|
|
107
|
+
exit_now! "file under #{path} not exists" unless File.exist?(path)
|
|
108
|
+
|
|
109
|
+
created_files = Starter::Import.do_it!(path)
|
|
110
|
+
|
|
111
|
+
`bundle exec rubocop --only Layout -a #{created_files.join(' ')}`
|
|
112
|
+
rescue => e
|
|
113
|
+
exit_now! e
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
100
117
|
|
|
101
118
|
pre do |_global, _command, _options, _args|
|
|
102
119
|
# Pre logic here
|
data/grape-starter.gemspec
CHANGED
|
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
23
23
|
spec.require_paths = ['lib']
|
|
24
24
|
|
|
25
|
-
spec.required_ruby_version = '>=
|
|
25
|
+
spec.required_ruby_version = '>= 3.1'
|
|
26
26
|
|
|
27
27
|
spec.add_dependency 'gli', '~> 2.20'
|
|
28
28
|
spec.add_dependency 'activesupport', '>= 6', '< 8'
|
data/lib/starter/build.rb
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Starter
|
|
4
4
|
class Build
|
|
5
|
-
extend
|
|
6
|
-
extend
|
|
7
|
-
extend
|
|
5
|
+
extend Shared::BaseFile
|
|
6
|
+
extend Builder::Files
|
|
7
|
+
extend Builder::Endpoints
|
|
8
8
|
|
|
9
9
|
class << self
|
|
10
10
|
attr_reader :prefix, :resource, :entity,
|
|
@@ -28,7 +28,7 @@ module Starter
|
|
|
28
28
|
@resource = name
|
|
29
29
|
@destination = destination
|
|
30
30
|
@prefix = options[:p] # can be nil
|
|
31
|
-
@naming = Starter::
|
|
31
|
+
@naming = Starter::Names.new(@resource)
|
|
32
32
|
|
|
33
33
|
FileUtils.copy_entry source, destination
|
|
34
34
|
|
|
@@ -64,7 +64,7 @@ module Starter
|
|
|
64
64
|
@force = options[:force]
|
|
65
65
|
@entity = options[:entity]
|
|
66
66
|
@orm = options[:orm]
|
|
67
|
-
@naming = Starter::
|
|
67
|
+
@naming = Starter::Names.new(@resource)
|
|
68
68
|
|
|
69
69
|
Orms.add_migration(@naming.klass_name, resource.downcase) if @orm
|
|
70
70
|
save_resource
|
|
@@ -115,7 +115,7 @@ module Starter
|
|
|
115
115
|
#
|
|
116
116
|
# creates a new file in lib folder as namespace, includind the version
|
|
117
117
|
def add_namespace_with_version
|
|
118
|
-
new_lib = File.join(destination, 'lib', @naming.
|
|
118
|
+
new_lib = File.join(destination, 'lib', @naming.resource_file)
|
|
119
119
|
FileOps.write_file(new_lib, base_namespace_file.strip_heredoc)
|
|
120
120
|
end
|
|
121
121
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'yaml'
|
|
5
|
+
|
|
6
|
+
module Starter
|
|
7
|
+
class Import
|
|
8
|
+
extend Shared::BaseFile
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
def do_it!(path)
|
|
12
|
+
spec = load_spec(path)
|
|
13
|
+
create_files_from(spec)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def load_spec(path)
|
|
17
|
+
return nil if path.blank?
|
|
18
|
+
|
|
19
|
+
spec = case File.extname(path)[1..]
|
|
20
|
+
when 'yaml', 'yml'
|
|
21
|
+
YAML.load_file(path)
|
|
22
|
+
when 'json'
|
|
23
|
+
JSON.load_file(path)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
Importer::Specification.new(spec:)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def create_files_from(spec)
|
|
30
|
+
spec.namespaces.each_with_object([]) do |(name_of, paths), memo|
|
|
31
|
+
@naming = Starter::Names.new(name_of)
|
|
32
|
+
|
|
33
|
+
# 1. build content for file
|
|
34
|
+
namespace = Starter::Importer::Namespace.new(
|
|
35
|
+
naming: @naming,
|
|
36
|
+
paths: paths,
|
|
37
|
+
components: spec.components
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
break if ENV['RACK_ENV'] == 'test'
|
|
41
|
+
|
|
42
|
+
# 2. create endpoint file
|
|
43
|
+
FileOps.write_file(@naming.api_file_name, namespace.content)
|
|
44
|
+
memo << @naming.api_file_name
|
|
45
|
+
|
|
46
|
+
# 3. add mountpoint
|
|
47
|
+
add_mount_point
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: false
|
|
2
|
+
|
|
3
|
+
module Starter
|
|
4
|
+
module Importer
|
|
5
|
+
class Namespace
|
|
6
|
+
attr_accessor :naming, :paths, :components
|
|
7
|
+
|
|
8
|
+
def initialize(naming:, paths:, components:)
|
|
9
|
+
@naming = naming
|
|
10
|
+
@paths = paths
|
|
11
|
+
@components = components
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def content
|
|
15
|
+
<<-FILE.strip_heredoc
|
|
16
|
+
# frozen_string_literal: true
|
|
17
|
+
|
|
18
|
+
module Api
|
|
19
|
+
module Endpoints
|
|
20
|
+
class #{@naming.klass_name} < Grape::API
|
|
21
|
+
namespace #{namespace} do
|
|
22
|
+
#{endpoints.join("\n")}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
FILE
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def namespace
|
|
33
|
+
@namespace ||= naming.version_klass ? "'#{naming.origin}'" : ":#{naming.resource.downcase}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def endpoints
|
|
37
|
+
paths.map do |path, verbs|
|
|
38
|
+
segment = prepare_route(path)
|
|
39
|
+
verbs.keys.each_with_object([]) do |verb, memo|
|
|
40
|
+
next unless allowed_verbs.include?(verb)
|
|
41
|
+
|
|
42
|
+
if (parameters = verbs[verb]['parameters'].presence)
|
|
43
|
+
params_block = params_block(parameters)
|
|
44
|
+
memo << params_block
|
|
45
|
+
end
|
|
46
|
+
memo << "#{verb} '#{segment}' do\n # your code comes here\nend\n"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def prepare_route(path)
|
|
52
|
+
params = path.scan(/\{(\w+)\}/)
|
|
53
|
+
if params.empty?
|
|
54
|
+
path
|
|
55
|
+
else
|
|
56
|
+
path.gsub('{', ':').gsub('}', '')
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def params_block(params)
|
|
61
|
+
params_block = "params do\n"
|
|
62
|
+
params.each_value do |param|
|
|
63
|
+
params_block << " #{param.to_s}\n" # rubocop:disable Lint/RedundantStringCoercion
|
|
64
|
+
end
|
|
65
|
+
params_block << 'end'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def allowed_verbs
|
|
69
|
+
%w[get put post delete]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/ClassLength
|
|
2
|
+
# frozen_string_literal: false
|
|
3
|
+
|
|
4
|
+
module Starter
|
|
5
|
+
module Importer
|
|
6
|
+
class Parameter
|
|
7
|
+
class Error < StandardError; end
|
|
8
|
+
|
|
9
|
+
attr_accessor :kind, :name, :definition, :nested
|
|
10
|
+
|
|
11
|
+
def initialize(definition:, components: {})
|
|
12
|
+
@nested = []
|
|
13
|
+
@kind = validate_parameters(definition:, components:)
|
|
14
|
+
prepare_attributes(definition:, components:)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_s
|
|
18
|
+
return serialized_object if nested?
|
|
19
|
+
|
|
20
|
+
serialized
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def nested?
|
|
24
|
+
@nested.present?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# initialize helper
|
|
28
|
+
#
|
|
29
|
+
def validate_parameters(definition:, components:)
|
|
30
|
+
return :direct if definition.key?('name')
|
|
31
|
+
return :ref if definition.key?('$ref') && components.key?('parameters')
|
|
32
|
+
return :body if definition.key?('content')
|
|
33
|
+
|
|
34
|
+
raise Error, 'no valid combination given'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def prepare_attributes(definition:, components:) # rubocop:disable Metrics/MethodLength
|
|
38
|
+
case kind
|
|
39
|
+
when :direct
|
|
40
|
+
@name = definition['name']
|
|
41
|
+
@definition = definition.except('name')
|
|
42
|
+
when :ref
|
|
43
|
+
found = components.dig(*definition['$ref'].split('/')[2..])
|
|
44
|
+
@name = found['name']
|
|
45
|
+
@definition = found.except('name')
|
|
46
|
+
|
|
47
|
+
if (value = @definition.dig('schema', '$ref').presence)
|
|
48
|
+
@definition['schema'] = components.dig(*value.split('/')[2..])
|
|
49
|
+
end
|
|
50
|
+
when :body
|
|
51
|
+
definition['in'] = 'body'
|
|
52
|
+
schema = definition['content'] ? definition['content'].values.first['schema'] : definition
|
|
53
|
+
if schema.key?('$ref')
|
|
54
|
+
path = schema['$ref'].split('/')[2..]
|
|
55
|
+
|
|
56
|
+
@name, @definition = handle_body(definition:, properties: components.dig(*path))
|
|
57
|
+
@name ||= path.last
|
|
58
|
+
else
|
|
59
|
+
@name, @definition = handle_body(definition:, properties: schema)
|
|
60
|
+
@name = nested.map(&:name).join('_') if @name.nil? && nested?
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def handle_body(definition:, properties:) # rubocop:disable Metrics/MethodLength
|
|
66
|
+
if simple_object?(properties:)
|
|
67
|
+
name = properties['properties'].keys.first
|
|
68
|
+
type = properties.dig('properties', name, 'type') || 'array'
|
|
69
|
+
subtype = properties.dig('properties', name, 'items', 'type')
|
|
70
|
+
definition['type'] = subtype.nil? ? type : "#{type}[#{subtype}]"
|
|
71
|
+
|
|
72
|
+
properties.dig('properties', name).except('type').each { |k, v| definition[k] = v }
|
|
73
|
+
definition['type'] = 'file' if definition['format'].presence == 'binary'
|
|
74
|
+
|
|
75
|
+
[name, definition]
|
|
76
|
+
elsif object?(definition:) # a nested object -> JSON
|
|
77
|
+
definition['type'] = properties['type'].presence || 'JSON'
|
|
78
|
+
return [nil, definition] if properties.nil? || properties['properties'].nil?
|
|
79
|
+
|
|
80
|
+
properties['properties'].each do |nested_name, nested_definition|
|
|
81
|
+
nested_definition['required'] = required?(properties, nested_name)
|
|
82
|
+
nested = NestedParams.new(name: nested_name, definition: nested_definition)
|
|
83
|
+
nested.prepare_attributes(definition: nested.definition, components: {})
|
|
84
|
+
nested.name = nested_name
|
|
85
|
+
@nested << nested
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
[self.name, definition]
|
|
89
|
+
else # others
|
|
90
|
+
[nil, properties ? definition.merge(properties) : definition]
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# handle_body helper, check/find/define types
|
|
95
|
+
#
|
|
96
|
+
def object?(definition:)
|
|
97
|
+
definition['type'] == 'object' ||
|
|
98
|
+
definition['content']&.keys&.first&.include?('application/json')
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def simple_object?(properties:)
|
|
102
|
+
list_of_object?(properties:) &&
|
|
103
|
+
properties['properties'].length == 1
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def list_of_object?(properties:)
|
|
107
|
+
properties&.key?('properties')
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def required?(property, name)
|
|
111
|
+
return false unless property['required']
|
|
112
|
+
|
|
113
|
+
property['required'].is_a?(Array) ? property['required'].include?(name) : property['required']
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# to_s helper
|
|
117
|
+
#
|
|
118
|
+
def serialized_object
|
|
119
|
+
definition.tap do |foo|
|
|
120
|
+
foo['type'] = foo['type'] == 'object' ? 'JSON' : foo['type']
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
parent = NestedParams.new(name: name, definition: definition)
|
|
124
|
+
entry = "#{parent} do\n"
|
|
125
|
+
nested.each { |n| entry << " #{n}\n" }
|
|
126
|
+
entry << ' end'
|
|
127
|
+
if entry.include?("format: 'binary', type: 'File'")
|
|
128
|
+
entry.sub!('type: JSON', 'type: Hash')
|
|
129
|
+
entry.sub!(", documentation: { in: 'body' }", '')
|
|
130
|
+
entry.gsub!(", in: 'body'", '')
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
entry
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def serialized
|
|
137
|
+
type = definition['type'] || definition['schema']['type']
|
|
138
|
+
type.scan(/\w+/).each { |x| type.match?('JSON') ? type : type.sub!(x, x.capitalize) }
|
|
139
|
+
|
|
140
|
+
if type == 'Array' && definition.key?('items')
|
|
141
|
+
sub = definition.dig('items', 'type').to_s.capitalize
|
|
142
|
+
type = "#{type}[#{sub}]"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
entry = definition['required'] ? 'requires' : 'optional'
|
|
146
|
+
entry << " :#{name}"
|
|
147
|
+
entry << ", type: #{type}"
|
|
148
|
+
doc = documentation
|
|
149
|
+
entry << ", #{doc}" if doc
|
|
150
|
+
|
|
151
|
+
entry
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def documentation
|
|
155
|
+
@documentation ||= begin
|
|
156
|
+
tmp = {}
|
|
157
|
+
tmp['desc'] = definition['description'] if definition.key?('description')
|
|
158
|
+
if definition.key?('in') && !(definition['type'] == 'File' && definition['format'] == 'binary')
|
|
159
|
+
tmp['in'] = definition['in']
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
if definition.key?('format')
|
|
163
|
+
tmp['format'] = definition['format']
|
|
164
|
+
tmp['type'] = 'File' if definition['format'] == 'binary'
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
documentation = 'documentation:'
|
|
168
|
+
documentation.tap do |doc|
|
|
169
|
+
doc << ' { '
|
|
170
|
+
content = tmp.map { |k, v| "#{k}: '#{v}'" }
|
|
171
|
+
doc << content.join(', ')
|
|
172
|
+
doc << ' }'
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/ClassLength
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Starter
|
|
4
|
+
module Importer
|
|
5
|
+
class Specification
|
|
6
|
+
class Error < StandardError; end
|
|
7
|
+
|
|
8
|
+
attr_accessor :openapi, :info,
|
|
9
|
+
:paths, :components, :webhooks
|
|
10
|
+
|
|
11
|
+
def initialize(spec:)
|
|
12
|
+
# mandatory
|
|
13
|
+
@openapi = spec.fetch('openapi')
|
|
14
|
+
@info = spec.fetch('info')
|
|
15
|
+
|
|
16
|
+
# in contrast to the spec, paths are required
|
|
17
|
+
@paths = spec.fetch('paths').except('/').sort.to_h
|
|
18
|
+
|
|
19
|
+
# optional -> not used atm
|
|
20
|
+
@components = spec.fetch('components', false)
|
|
21
|
+
@webhooks = spec.fetch('webhooks', false)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def namespaces
|
|
25
|
+
validate_paths
|
|
26
|
+
|
|
27
|
+
@namespaces ||= paths.keys.each_with_object({}) do |path, memo|
|
|
28
|
+
namespace, rest_path = segmentize(path)
|
|
29
|
+
|
|
30
|
+
memo[namespace] ||= {}
|
|
31
|
+
memo[namespace][rest_path] = prepare_verbs(paths[path])
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def validate_paths
|
|
38
|
+
raise Error, '`paths` empty … nothings to do' if paths.empty?
|
|
39
|
+
raise Error, 'only template given' if paths.keys.one? && paths.keys.first.match?(%r{/\{\w*\}})
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def segmentize(path)
|
|
43
|
+
segments = path.split('/').delete_if(&:empty?)
|
|
44
|
+
ignore = segments.take_while { |x| x =~ /(v)*(\.\d)+/ || x =~ /(v\d)+/ || x == 'api' }
|
|
45
|
+
rest = segments - ignore
|
|
46
|
+
|
|
47
|
+
[rest.shift, rest.empty? ? '/' : "/#{rest.join('/')}"]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def prepare_verbs(spec) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
51
|
+
path_params = nil
|
|
52
|
+
spec.each_with_object({}) do |(verb, content), memo|
|
|
53
|
+
if verb == 'parameters'
|
|
54
|
+
path_params = content
|
|
55
|
+
next
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
memo[verb] = content
|
|
59
|
+
next unless content.key?('parameters') || content.key?('requestBody') || path_params
|
|
60
|
+
|
|
61
|
+
parameters = ((content['parameters'] || path_params || []) + [content['requestBody']]).compact
|
|
62
|
+
|
|
63
|
+
memo[verb]['parameters'] = parameters.each_with_object({}) do |definition, para|
|
|
64
|
+
parameter = Parameter.new(definition:, components:)
|
|
65
|
+
para[parameter.name] = parameter
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Starter
|
|
4
|
+
class Names
|
|
5
|
+
attr_accessor :resource, :origin, :version_klass
|
|
6
|
+
|
|
7
|
+
def initialize(resource)
|
|
8
|
+
@version_klass = false
|
|
9
|
+
@origin = resource
|
|
10
|
+
@resource = if resource.match?(/([[:digit:]][[:punct:]])+/)
|
|
11
|
+
@version_klass = true
|
|
12
|
+
digit = resource.scan(/\d/).first.to_i - 1
|
|
13
|
+
letter = ('a'..'z').to_a[digit]
|
|
14
|
+
"#{letter}_#{resource.tr('.', '_')}"
|
|
15
|
+
else
|
|
16
|
+
resource
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def klass_name
|
|
21
|
+
return @resource.classify if version_klass
|
|
22
|
+
|
|
23
|
+
for_klass = @resource.tr('-', '/')
|
|
24
|
+
singular? ? for_klass.classify : for_klass.classify.pluralize
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# rubocop:disable Style/StringConcatenation
|
|
28
|
+
def resource_file
|
|
29
|
+
@resource.tr('/', '-').downcase + '.rb'
|
|
30
|
+
end
|
|
31
|
+
# rubocop:enable Style/StringConcatenation
|
|
32
|
+
|
|
33
|
+
def resource_spec
|
|
34
|
+
resource_file.gsub(/.rb$/, '_spec.rb')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# entry in api/base.rb
|
|
38
|
+
def mount_point
|
|
39
|
+
" mount Endpoints::#{klass_name}\n"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# endpoints file
|
|
43
|
+
def api_file_name
|
|
44
|
+
File.join(Dir.getwd, 'api', 'endpoints', resource_file)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# entities file
|
|
48
|
+
def entity_file_name
|
|
49
|
+
File.join(Dir.getwd, 'api', 'entities', resource_file)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# lib file
|
|
53
|
+
def lib_file_name
|
|
54
|
+
File.join(Dir.getwd, 'lib', 'models', resource_file)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# model entry in lib file
|
|
58
|
+
def lib_klass_name
|
|
59
|
+
return klass_name unless @orm
|
|
60
|
+
|
|
61
|
+
case Starter::Config.read[:orm]
|
|
62
|
+
when 'sequel'
|
|
63
|
+
extend(Starter::Builder::Sequel)
|
|
64
|
+
"#{klass_name} < #{model_klass}"
|
|
65
|
+
when 'activerecord', 'ar'
|
|
66
|
+
extend(Starter::Builder::ActiveRecord)
|
|
67
|
+
"#{klass_name} < #{model_klass}"
|
|
68
|
+
else
|
|
69
|
+
klass_name
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# resource spec
|
|
74
|
+
def api_spec_name
|
|
75
|
+
File.join(Dir.getwd, 'spec', 'requests', resource_spec)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# lib spec
|
|
79
|
+
def lib_spec_name
|
|
80
|
+
File.join(Dir.getwd, 'spec', 'lib', 'models', resource_spec)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def singular?
|
|
84
|
+
@resource.singularize.inspect == @resource.inspect
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Starter
|
|
4
|
-
module
|
|
4
|
+
module Shared
|
|
5
5
|
module BaseFile
|
|
6
6
|
# add it in api base
|
|
7
7
|
def add_mount_point
|
|
8
|
-
FileOps.call!(
|
|
8
|
+
FileOps.call!(base_file_path) { |content| add_to_base(content) }
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
# adding mount point to base class
|
|
12
12
|
def add_to_base(file)
|
|
13
|
-
occurence = file.scan(/(\s+mount\s.*?\n)/).
|
|
13
|
+
occurence = file.scan(/(\s+mount\s.*?\n)/).map(&:first).join
|
|
14
|
+
return if occurence.include?(@naming.mount_point.strip)
|
|
15
|
+
|
|
14
16
|
replacement = occurence + @naming.mount_point
|
|
15
17
|
file.sub!(occurence, replacement)
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
# removes in api base
|
|
19
21
|
def remove_mount_point
|
|
20
|
-
FileOps.call!(
|
|
22
|
+
FileOps.call!(base_file_path) { |content| remove_from_base(content) }
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
# removes mount point from base class
|
|
@@ -39,8 +41,11 @@ module Starter
|
|
|
39
41
|
|
|
40
42
|
# get api base file as string
|
|
41
43
|
def base_file
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
FileOps.read_file(base_file_path)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def base_file_path
|
|
48
|
+
File.join(Dir.getwd, 'api', 'base.rb')
|
|
44
49
|
end
|
|
45
50
|
end
|
|
46
51
|
end
|
data/lib/starter/version.rb
CHANGED
data/lib/starter.rb
CHANGED
data/template/.rubocop.yml
CHANGED
data/template/Dockerfile
CHANGED
data/template/Gemfile
CHANGED
data/template/config/boot.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: grape-starter
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- LeFnord
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-10-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: gli
|
|
@@ -112,16 +112,21 @@ files:
|
|
|
112
112
|
- lib/starter.rb
|
|
113
113
|
- lib/starter/build.rb
|
|
114
114
|
- lib/starter/builder/activerecord.rb
|
|
115
|
-
- lib/starter/builder/
|
|
116
|
-
- lib/starter/builder/
|
|
115
|
+
- lib/starter/builder/endpoints.rb
|
|
116
|
+
- lib/starter/builder/files.rb
|
|
117
117
|
- lib/starter/builder/sequel.rb
|
|
118
118
|
- lib/starter/config.rb
|
|
119
119
|
- lib/starter/file_ops.rb
|
|
120
|
+
- lib/starter/import.rb
|
|
121
|
+
- lib/starter/importer/namespace.rb
|
|
122
|
+
- lib/starter/importer/nested_params.rb
|
|
123
|
+
- lib/starter/importer/parameter.rb
|
|
124
|
+
- lib/starter/importer/specification.rb
|
|
125
|
+
- lib/starter/names.rb
|
|
120
126
|
- lib/starter/orms.rb
|
|
121
127
|
- lib/starter/rake/grape_tasks.rb
|
|
122
128
|
- lib/starter/rspec/request_specs.rb
|
|
123
|
-
- lib/starter/
|
|
124
|
-
- lib/starter/templates/files.rb
|
|
129
|
+
- lib/starter/shared/base_file.rb
|
|
125
130
|
- lib/starter/version.rb
|
|
126
131
|
- template/.gitignore
|
|
127
132
|
- template/.rubocop.yml
|
|
@@ -164,14 +169,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
164
169
|
requirements:
|
|
165
170
|
- - ">="
|
|
166
171
|
- !ruby/object:Gem::Version
|
|
167
|
-
version: '
|
|
172
|
+
version: '3.1'
|
|
168
173
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
169
174
|
requirements:
|
|
170
175
|
- - ">="
|
|
171
176
|
- !ruby/object:Gem::Version
|
|
172
177
|
version: '0'
|
|
173
178
|
requirements: []
|
|
174
|
-
rubygems_version: 3.4.
|
|
179
|
+
rubygems_version: 3.4.17
|
|
175
180
|
signing_key:
|
|
176
181
|
specification_version: 4
|
|
177
182
|
summary: Creates a Grape Rack skeleton
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Starter
|
|
4
|
-
module Builder
|
|
5
|
-
class Names
|
|
6
|
-
def initialize(resource)
|
|
7
|
-
@resource = resource
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def klass_name
|
|
11
|
-
for_klass = prepare_klass
|
|
12
|
-
singular? ? for_klass.classify : for_klass.classify.pluralize
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# rubocop:disable Style/StringConcatenation
|
|
16
|
-
def base_file_name
|
|
17
|
-
@resource.tr('/', '-').downcase + '.rb'
|
|
18
|
-
end
|
|
19
|
-
# rubocop:enable Style/StringConcatenation
|
|
20
|
-
|
|
21
|
-
def api_base_file_name
|
|
22
|
-
File.join(Dir.getwd, 'api', 'base.rb')
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def base_spec_name
|
|
26
|
-
base_file_name.gsub(/.rb$/, '_spec.rb')
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# entry in api/base.rb
|
|
30
|
-
def mount_point
|
|
31
|
-
" mount Endpoints::#{klass_name}\n"
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# endpoints file
|
|
35
|
-
def api_file_name
|
|
36
|
-
File.join(Dir.getwd, 'api', 'endpoints', base_file_name)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# entities file
|
|
40
|
-
def entity_file_name
|
|
41
|
-
File.join(Dir.getwd, 'api', 'entities', base_file_name)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# lib file
|
|
45
|
-
def lib_file_name
|
|
46
|
-
File.join(Dir.getwd, 'lib', 'models', base_file_name)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# model entry in lib file
|
|
50
|
-
def lib_klass_name
|
|
51
|
-
return klass_name unless @orm
|
|
52
|
-
|
|
53
|
-
case Starter::Config.read[:orm]
|
|
54
|
-
when 'sequel'
|
|
55
|
-
extend(Starter::Builder::Sequel)
|
|
56
|
-
"#{klass_name} < #{model_klass}"
|
|
57
|
-
when 'activerecord', 'ar'
|
|
58
|
-
extend(Starter::Builder::ActiveRecord)
|
|
59
|
-
"#{klass_name} < #{model_klass}"
|
|
60
|
-
else
|
|
61
|
-
klass_name
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# resource spec
|
|
66
|
-
def api_spec_name
|
|
67
|
-
File.join(Dir.getwd, 'spec', 'requests', base_spec_name)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# lib spec
|
|
71
|
-
def lib_spec_name
|
|
72
|
-
File.join(Dir.getwd, 'spec', 'lib', 'models', base_spec_name)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def singular?
|
|
76
|
-
@resource.singularize.inspect == @resource.inspect
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
private
|
|
80
|
-
|
|
81
|
-
def prepare_klass
|
|
82
|
-
@resource.tr('-', '/')
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|