grape-starter 1.5.2 → 1.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/bin/grape-starter +4 -4
- data/grape-starter.gemspec +1 -0
- data/lib/starter/{builder.rb → build.rb} +15 -15
- data/lib/starter/builder/base_file.rb +41 -39
- data/lib/starter/builder/names.rb +61 -59
- data/lib/starter/builder/templates/activerecord.rb +83 -81
- data/lib/starter/builder/templates/endpoints.rb +87 -85
- data/lib/starter/builder/templates/files.rb +54 -52
- data/lib/starter/builder/templates/sequel.rb +78 -76
- data/lib/starter/{builder/file_foo.rb → file_ops.rb} +1 -1
- data/lib/starter/{builder/orms.rb → orms.rb} +9 -9
- data/lib/starter/rake/grape_tasks.rb +0 -2
- data/lib/starter/rspec/request_specs.rb +2 -2
- data/lib/starter/version.rb +1 -1
- data/lib/starter.rb +7 -3
- data/template/Dockerfile +1 -1
- data/template/Gemfile +1 -1
- data/template/config/puma.rb +10 -0
- data/template/script/server +1 -13
- metadata +20 -6
- data/template/script/stop +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70eb1ef044b58a9637cb920fcc9129a12ca25392d5d160de75a6ee3ea9483052
|
4
|
+
data.tar.gz: c700ad85e12e2406b11a647d8584d3070d7e6e9c10742fba0909a8182264dff5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c46ea6564c067d4174c29d705482068b991589503928bb5de57f0cfb5b0034485d48a8f3dc7f4b52621110727d6b78f7d86544682ea2d9ebf36054ba00029da8
|
7
|
+
data.tar.gz: ba9e7eb94b6e5412baba003037927310686dae982b439fffb5241d800101c405999c4246ad22c44b175ba3d676c52af632c8f24eb6241cfacab42995e36297d0
|
data/bin/grape-starter
CHANGED
@@ -38,7 +38,7 @@ command :new do |c|
|
|
38
38
|
starter_gem = Gem::Specification.find_by_name('grape-starter').gem_dir
|
39
39
|
src = File.join(starter_gem, 'template', '.')
|
40
40
|
|
41
|
-
Starter::
|
41
|
+
Starter::Build.new!(args.first, src, dest, options)
|
42
42
|
$stdout.puts "created: #{args.first}"
|
43
43
|
|
44
44
|
# after creating tasks
|
@@ -71,7 +71,7 @@ command :add do |c|
|
|
71
71
|
|
72
72
|
begin
|
73
73
|
builder_options = global_options.merge(set: set).merge(options)
|
74
|
-
created_files = Starter::
|
74
|
+
created_files = Starter::Build.add!(resource, builder_options)
|
75
75
|
|
76
76
|
`bundle exec rubocop -a #{created_files.join(' ')}`
|
77
77
|
$stdout.puts "added resource: #{resource}"
|
@@ -87,11 +87,11 @@ command :rm do |c|
|
|
87
87
|
c.desc 'removes also entity file'
|
88
88
|
c.switch [:e, :entity], negatable: false
|
89
89
|
|
90
|
-
c.action do |
|
90
|
+
c.action do |_global_options, options, args|
|
91
91
|
exit_now! 'no resource given' if args.empty?
|
92
92
|
resource = args.first
|
93
93
|
|
94
|
-
Starter::
|
94
|
+
Starter::Build.remove!(resource, options)
|
95
95
|
|
96
96
|
$stdout.puts "removed resource: #{resource}"
|
97
97
|
end
|
data/grape-starter.gemspec
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Starter
|
4
|
-
require 'starter/builder/orms'
|
5
|
-
require 'starter/builder/names'
|
6
|
-
require 'starter/builder/base_file'
|
7
|
-
require 'starter/builder/file_foo'
|
8
|
-
require 'starter/builder/templates/files'
|
9
|
-
require 'starter/builder/templates/endpoints'
|
10
|
-
|
11
|
-
class
|
12
|
-
extend Names
|
13
|
-
extend BaseFile
|
14
|
-
extend Templates::Files
|
15
|
-
extend Templates::Endpoints
|
4
|
+
# require 'starter/builder/orms'
|
5
|
+
# require 'starter/builder/names'
|
6
|
+
# require 'starter/builder/base_file'
|
7
|
+
# require 'starter/builder/file_foo'
|
8
|
+
# require 'starter/builder/templates/files'
|
9
|
+
# require 'starter/builder/templates/endpoints'
|
10
|
+
|
11
|
+
class Build
|
12
|
+
extend Builder::Names
|
13
|
+
extend Builder::BaseFile
|
14
|
+
extend Builder::Templates::Files
|
15
|
+
extend Builder::Templates::Endpoints
|
16
16
|
|
17
17
|
class << self
|
18
18
|
attr_reader :prefix, :resource, :set, :force, :entity, :destination, :orm
|
@@ -120,7 +120,7 @@ module Starter
|
|
120
120
|
# creates a new file in lib folder as namespace, includind the version
|
121
121
|
def add_namespace_with_version
|
122
122
|
new_lib = File.join(destination, 'lib', base_file_name)
|
123
|
-
|
123
|
+
FileOps.write_file(new_lib, base_namespace_file.strip_heredoc)
|
124
124
|
end
|
125
125
|
|
126
126
|
#
|
@@ -128,7 +128,7 @@ module Starter
|
|
128
128
|
def replace_static(file, replacement)
|
129
129
|
file_path = File.join(destination, file)
|
130
130
|
|
131
|
-
|
131
|
+
FileOps.call!(file_path) { |content| content.gsub!('{{{grape-starter}}}', replacement.to_s) }
|
132
132
|
end
|
133
133
|
|
134
134
|
# #add! a new resource releated helper methods
|
@@ -159,7 +159,7 @@ module Starter
|
|
159
159
|
def save_file(new_file)
|
160
160
|
new_file_name = send("#{new_file}_name")
|
161
161
|
should_raise?(new_file_name)
|
162
|
-
|
162
|
+
FileOps.write_file(new_file_name, send(new_file.strip_heredoc))
|
163
163
|
end
|
164
164
|
|
165
165
|
#
|
@@ -1,45 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Starter
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
file
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
4
|
+
module Builder
|
5
|
+
module BaseFile
|
6
|
+
# add it in api base
|
7
|
+
def add_mount_point
|
8
|
+
FileOps.call!(api_base_file_name) { |content| add_to_base(content) }
|
9
|
+
end
|
10
|
+
|
11
|
+
# adding mount point to base class
|
12
|
+
def add_to_base(file)
|
13
|
+
occurence = file.scan(/(\s+mount\s.*?\n)/).last.first
|
14
|
+
replacement = occurence + mount_point
|
15
|
+
file.sub!(occurence, replacement)
|
16
|
+
end
|
17
|
+
|
18
|
+
# removes in api base
|
19
|
+
def remove_mount_point
|
20
|
+
FileOps.call!(api_base_file_name) { |content| remove_from_base(content) }
|
21
|
+
end
|
22
|
+
|
23
|
+
# removes mount point from base class
|
24
|
+
def remove_from_base(file)
|
25
|
+
file.sub!(mount_point, '')
|
26
|
+
end
|
27
|
+
|
28
|
+
# parses out the prefix from base api file
|
29
|
+
def base_prefix
|
30
|
+
Starter::Config.read[:prefix]
|
31
|
+
end
|
32
|
+
|
33
|
+
# parses out the version from base api file
|
34
|
+
def base_version
|
35
|
+
base_file
|
36
|
+
|
37
|
+
base_file.scan(/version\s+(.+),/).first.first.delete!("'")
|
38
|
+
end
|
39
|
+
|
40
|
+
# get api base file as string
|
41
|
+
def base_file
|
42
|
+
file = File.join(Dir.getwd, 'api', 'base.rb')
|
43
|
+
FileOps.read_file(file)
|
44
|
+
end
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
@@ -1,80 +1,82 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Starter
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
module Builder
|
5
|
+
module Names
|
6
|
+
def klass_name
|
7
|
+
for_klass = prepare_klass
|
8
|
+
singular? ? for_klass.classify : for_klass.classify.pluralize
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
def lib_klass_name
|
12
|
+
return klass_name unless @orm
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
14
|
+
case Starter::Config.read[:orm]
|
15
|
+
when 'sequel'
|
16
|
+
require 'starter/builder/templates/sequel'
|
17
|
+
extend(Starter::Builder::Templates::Sequel)
|
18
|
+
"#{klass_name} < #{model_klass}"
|
19
|
+
when 'activerecord', 'ar'
|
20
|
+
require 'starter/builder/templates/activerecord'
|
21
|
+
extend(Starter::Builder::Templates::ActiveRecord)
|
22
|
+
"#{klass_name} < #{model_klass}"
|
23
|
+
else
|
24
|
+
klass_name
|
25
|
+
end
|
24
26
|
end
|
25
|
-
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
# rubocop:disable Style/StringConcatenation
|
29
|
+
def base_file_name
|
30
|
+
@resource.tr('/', '-').downcase + '.rb'
|
31
|
+
end
|
32
|
+
# rubocop:enable Style/StringConcatenation
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
def base_spec_name
|
35
|
+
base_file_name.gsub(/.rb$/, '_spec.rb')
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
def mount_point
|
39
|
+
" mount Endpoints::#{klass_name}\n"
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
def api_base_file_name
|
43
|
+
File.join(Dir.getwd, 'api', 'base.rb')
|
44
|
+
end
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
# resource file
|
47
|
+
def api_file_name
|
48
|
+
File.join(Dir.getwd, 'api', 'endpoints', base_file_name)
|
49
|
+
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
# resource file
|
52
|
+
def entity_file_name
|
53
|
+
File.join(Dir.getwd, 'api', 'entities', base_file_name)
|
54
|
+
end
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
# lib file
|
57
|
+
def lib_file_name
|
58
|
+
File.join(Dir.getwd, 'lib', 'models', base_file_name)
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
# resource spec
|
62
|
+
def api_spec_name
|
63
|
+
File.join(Dir.getwd, 'spec', 'requests', base_spec_name)
|
64
|
+
end
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
# lib spec
|
67
|
+
def lib_spec_name
|
68
|
+
File.join(Dir.getwd, 'spec', 'lib', 'models', base_spec_name)
|
69
|
+
end
|
69
70
|
|
70
|
-
|
71
|
+
private
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
|
73
|
+
def prepare_klass
|
74
|
+
@resource.tr('-', '/')
|
75
|
+
end
|
75
76
|
|
76
|
-
|
77
|
-
|
77
|
+
def singular?
|
78
|
+
@resource.singularize.inspect == @resource.inspect
|
79
|
+
end
|
78
80
|
end
|
79
81
|
end
|
80
82
|
end
|
@@ -3,102 +3,104 @@
|
|
3
3
|
require 'active_record'
|
4
4
|
|
5
5
|
module Starter
|
6
|
-
module
|
7
|
-
module
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
module Builder
|
7
|
+
module Templates
|
8
|
+
module ActiveRecord
|
9
|
+
def model_klass
|
10
|
+
'ActiveRecord::Base'
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
13
|
+
def initializer
|
14
|
+
<<-FILE.strip_heredoc
|
15
|
+
# frozen_string_literal: true
|
16
|
+
|
17
|
+
require 'yaml'
|
18
|
+
require 'erb'
|
19
|
+
require 'active_record'
|
20
|
+
|
21
|
+
config_content = File.read(File.join('config', 'database.yml'))
|
22
|
+
|
23
|
+
db_conf = YAML.safe_load(ERB.new(config_content).result)
|
24
|
+
env = ENV['RACK_ENV'] || 'development'
|
25
|
+
|
26
|
+
ActiveRecord::Base.establish_connection db_conf[env]
|
27
|
+
logger = if %w[development test].include? env
|
28
|
+
log_dir = File.join(Dir.getwd, 'log')
|
29
|
+
log_file = File.join(log_dir, 'db.log')
|
30
|
+
FileUtils.mkdir(log_dir) unless Dir.exist?(log_dir)
|
31
|
+
Logger.new(File.open(log_file, 'a'))
|
32
|
+
else
|
33
|
+
Logger.new($stdout)
|
34
|
+
end
|
35
|
+
|
36
|
+
ActiveRecord::Base.logger = logger
|
37
|
+
|
38
|
+
# Middleware
|
39
|
+
module ActiveRecord
|
40
|
+
module Rack
|
41
|
+
# ActiveRecord >= 5 removes the Pool management
|
42
|
+
class ConnectionManagement
|
43
|
+
def initialize(app)
|
44
|
+
@app = app
|
45
|
+
end
|
46
|
+
|
47
|
+
def call(env)
|
48
|
+
response = @app.call(env)
|
49
|
+
response[2] = ::Rack::BodyProxy.new(response[2]) do
|
50
|
+
ActiveRecord::Base.clear_active_connections!
|
51
|
+
end
|
45
52
|
|
46
|
-
|
47
|
-
|
48
|
-
response[2] = ::Rack::BodyProxy.new(response[2]) do
|
53
|
+
return response
|
54
|
+
rescue StandardError
|
49
55
|
ActiveRecord::Base.clear_active_connections!
|
56
|
+
raise
|
50
57
|
end
|
51
|
-
|
52
|
-
return response
|
53
|
-
rescue StandardError
|
54
|
-
ActiveRecord::Base.clear_active_connections!
|
55
|
-
raise
|
56
58
|
end
|
57
59
|
end
|
58
60
|
end
|
61
|
+
FILE
|
59
62
|
end
|
60
|
-
FILE
|
61
|
-
end
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
64
|
+
def rakefile
|
65
|
+
<<-FILE.strip_heredoc
|
66
|
+
# ActiveRecord migration tasks
|
67
|
+
require 'active_record'
|
68
|
+
include ActiveRecord::Tasks
|
69
|
+
config_dir = File.expand_path('../config', __FILE__)
|
70
|
+
config_content = File.join(config_dir, 'database.yml')
|
71
|
+
DatabaseTasks.env = ENV['RACK_ENV'] || 'development'
|
72
|
+
DatabaseTasks.database_configuration = YAML.load_file(config_content)
|
73
|
+
DatabaseTasks.db_dir = 'db'
|
74
|
+
DatabaseTasks.migrations_paths = File.join('db', 'migrate')
|
75
|
+
|
76
|
+
ActiveRecord::Base.configurations = DatabaseTasks.database_configuration
|
77
|
+
ActiveRecord::Base.establish_connection DatabaseTasks.env.to_sym
|
78
|
+
|
79
|
+
load 'active_record/railties/databases.rake'
|
80
|
+
FILE
|
81
|
+
end
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
83
|
+
def gemfile
|
84
|
+
<<-FILE.strip_heredoc
|
85
|
+
# DB stuff
|
86
|
+
gem 'activerecord', '>= 6'
|
87
|
+
gem 'pg'
|
88
|
+
FILE
|
89
|
+
end
|
89
90
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
91
|
+
def migration(klass_name, resource)
|
92
|
+
version = "#{::ActiveRecord::VERSION::MAJOR}.#{::ActiveRecord::VERSION::MINOR}"
|
93
|
+
<<-FILE.strip_heredoc
|
94
|
+
class Create#{klass_name} < ActiveRecord::Migration[#{version}]
|
95
|
+
def change
|
96
|
+
create_table :#{resource} do |t|
|
96
97
|
|
97
|
-
|
98
|
+
t.timestamps
|
99
|
+
end
|
98
100
|
end
|
99
101
|
end
|
102
|
+
FILE
|
100
103
|
end
|
101
|
-
FILE
|
102
104
|
end
|
103
105
|
end
|
104
106
|
end
|
@@ -1,117 +1,119 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Starter
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
def singular_one
|
19
|
-
%i[
|
20
|
-
post
|
21
|
-
get_one
|
22
|
-
put_one
|
23
|
-
patch_one
|
24
|
-
delete_one
|
25
|
-
]
|
26
|
-
end
|
27
|
-
|
28
|
-
# available API/HTTP methods
|
29
|
-
# POST
|
30
|
-
def post
|
31
|
-
"
|
32
|
-
desc 'create #{resource.singularize}' do
|
33
|
-
tags %w[#{resource.singularize}]
|
4
|
+
module Builder
|
5
|
+
module Templates
|
6
|
+
# defining the endpoints -> http methods of a resource
|
7
|
+
module Endpoints
|
8
|
+
def crud
|
9
|
+
%i[
|
10
|
+
post
|
11
|
+
get_all
|
12
|
+
get_specific
|
13
|
+
put_specific
|
14
|
+
patch_specific
|
15
|
+
delete_specific
|
16
|
+
]
|
34
17
|
end
|
35
|
-
params do
|
36
|
-
# TODO: specify the parameters
|
37
|
-
end
|
38
|
-
post do
|
39
|
-
# your code goes here
|
40
|
-
end"
|
41
|
-
end
|
42
18
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
19
|
+
def singular_one
|
20
|
+
%i[
|
21
|
+
post
|
22
|
+
get_one
|
23
|
+
put_one
|
24
|
+
patch_one
|
25
|
+
delete_one
|
26
|
+
]
|
49
27
|
end
|
50
|
-
get do
|
51
|
-
# your code goes here
|
52
|
-
end"
|
53
|
-
end
|
54
28
|
|
55
|
-
|
56
|
-
|
57
|
-
|
29
|
+
# available API/HTTP methods
|
30
|
+
# POST
|
31
|
+
def post
|
58
32
|
"
|
59
|
-
desc '
|
33
|
+
desc 'create #{resource.singularize}' do
|
60
34
|
tags %w[#{resource.singularize}]
|
61
35
|
end
|
62
|
-
|
36
|
+
params do
|
37
|
+
# TODO: specify the parameters
|
38
|
+
end
|
39
|
+
post do
|
63
40
|
# your code goes here
|
64
41
|
end"
|
65
42
|
end
|
66
|
-
end
|
67
43
|
|
68
|
-
|
69
|
-
|
44
|
+
# GET
|
45
|
+
def get_all
|
70
46
|
"
|
71
|
-
desc '
|
47
|
+
desc 'get all of #{resource.pluralize}' do
|
48
|
+
is_array true
|
72
49
|
tags %w[#{resource.singularize}]
|
73
50
|
end
|
74
|
-
|
75
|
-
requires :id
|
76
|
-
end
|
77
|
-
#{verb} ':id' do
|
51
|
+
get do
|
78
52
|
# your code goes here
|
79
53
|
end"
|
80
54
|
end
|
81
|
-
end
|
82
|
-
# rubocop:enable Style/CombinableLoops
|
83
55
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
56
|
+
# rubocop:disable Style/CombinableLoops
|
57
|
+
%w[get put patch delete].each do |verb|
|
58
|
+
define_method(:"#{verb}_one") do
|
59
|
+
"
|
60
|
+
desc '#{verb} #{resource.singularize}' do
|
61
|
+
tags %w[#{resource.singularize}]
|
62
|
+
end
|
63
|
+
#{verb} do
|
64
|
+
# your code goes here
|
65
|
+
end"
|
66
|
+
end
|
67
|
+
end
|
89
68
|
|
90
|
-
|
91
|
-
|
92
|
-
|
69
|
+
%w[get put patch delete].each do |verb|
|
70
|
+
define_method(:"#{verb}_specific") do
|
71
|
+
"
|
72
|
+
desc '#{verb} specific #{resource.singularize}' do
|
73
|
+
tags %w[#{resource.singularize}]
|
74
|
+
end
|
75
|
+
params do
|
76
|
+
requires :id
|
77
|
+
end
|
78
|
+
#{verb} ':id' do
|
79
|
+
# your code goes here
|
80
|
+
end"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
# rubocop:enable Style/CombinableLoops
|
93
84
|
|
94
|
-
|
95
|
-
|
96
|
-
|
85
|
+
# request specs shared examples
|
86
|
+
#
|
87
|
+
def post_spec
|
88
|
+
"it_behaves_like 'POST', params: {}"
|
97
89
|
end
|
98
|
-
end
|
99
90
|
|
100
|
-
|
101
|
-
|
102
|
-
"it_behaves_like '#{verb.upcase} one', params: {}"
|
91
|
+
def get_all_spec
|
92
|
+
"it_behaves_like 'GET all'"
|
103
93
|
end
|
104
|
-
end
|
105
94
|
|
106
|
-
|
107
|
-
|
108
|
-
|
95
|
+
%w[get delete].each do |verb|
|
96
|
+
define_method(:"#{verb}_one_spec") do
|
97
|
+
"it_behaves_like '#{verb.upcase} one'"
|
98
|
+
end
|
109
99
|
end
|
110
|
-
end
|
111
100
|
|
112
|
-
|
113
|
-
|
114
|
-
|
101
|
+
%w[put patch].each do |verb|
|
102
|
+
define_method(:"#{verb}_one_spec") do
|
103
|
+
"it_behaves_like '#{verb.upcase} one', params: {}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
%w[get delete].each do |verb|
|
108
|
+
define_method(:"#{verb}_specific_spec") do
|
109
|
+
"it_behaves_like '#{verb.upcase} specific', key: 1"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
%w[put patch].each do |verb|
|
114
|
+
define_method(:"#{verb}_specific_spec") do
|
115
|
+
"it_behaves_like '#{verb.upcase} specific', key: 1, params: {}"
|
116
|
+
end
|
115
117
|
end
|
116
118
|
end
|
117
119
|
end
|
@@ -1,83 +1,85 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Starter
|
4
|
-
module
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
module Builder
|
5
|
+
module Templates
|
6
|
+
module Files
|
7
|
+
# API template for resource
|
8
|
+
def api_file
|
9
|
+
<<-FILE.strip_heredoc
|
10
|
+
# frozen_string_literal: true
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
module Api
|
13
|
+
module Endpoints
|
14
|
+
class #{klass_name} < Grape::API
|
15
|
+
namespace :#{resource.downcase} do
|
16
|
+
#{endpoints}
|
17
|
+
end
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
21
|
+
FILE
|
19
22
|
end
|
20
|
-
FILE
|
21
|
-
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def entity_file
|
25
|
+
<<-FILE.strip_heredoc
|
26
|
+
# frozen_string_literal: true
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
module Api
|
29
|
+
module Entities
|
30
|
+
class #{klass_name} < Grape::Entity
|
31
|
+
end
|
30
32
|
end
|
31
33
|
end
|
34
|
+
FILE
|
32
35
|
end
|
33
|
-
FILE
|
34
|
-
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
# LIB template for resource
|
38
|
+
def base_namespace_file
|
39
|
+
<<-FILE.strip_heredoc
|
40
|
+
# frozen_string_literal: true
|
40
41
|
|
41
|
-
|
42
|
-
|
42
|
+
module #{klass_name}
|
43
|
+
VERSION = '0.1.0'
|
44
|
+
end
|
45
|
+
FILE
|
43
46
|
end
|
44
|
-
FILE
|
45
|
-
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
def lib_file
|
49
|
+
<<-FILE.strip_heredoc
|
50
|
+
# frozen_string_literal: true
|
50
51
|
|
51
|
-
|
52
|
-
|
52
|
+
module Models
|
53
|
+
class #{lib_klass_name}
|
54
|
+
end
|
53
55
|
end
|
56
|
+
FILE
|
54
57
|
end
|
55
|
-
FILE
|
56
|
-
end
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
59
|
+
def api_spec
|
60
|
+
prefix = base_prefix ? "/#{base_prefix}" : ''
|
61
|
+
<<-FILE.strip_heredoc
|
62
|
+
# frozen_string_literal: true
|
62
63
|
|
63
|
-
|
64
|
+
require 'spec_helper'
|
64
65
|
|
65
|
-
|
66
|
-
|
66
|
+
RSpec.describe '#{prefix}/#{base_version}/#{resource.downcase}' do
|
67
|
+
#{endpoint_specs}
|
68
|
+
end
|
69
|
+
FILE
|
67
70
|
end
|
68
|
-
FILE
|
69
|
-
end
|
70
71
|
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
def lib_spec
|
73
|
+
<<-FILE.strip_heredoc
|
74
|
+
# frozen_string_literal: true
|
74
75
|
|
75
|
-
|
76
|
+
require 'spec_helper'
|
76
77
|
|
77
|
-
|
78
|
-
|
78
|
+
RSpec.describe Models::#{klass_name} do
|
79
|
+
pending 'write specs'
|
80
|
+
end
|
81
|
+
FILE
|
79
82
|
end
|
80
|
-
FILE
|
81
83
|
end
|
82
84
|
end
|
83
85
|
end
|
@@ -1,105 +1,107 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Starter
|
4
|
-
module
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
module Builder
|
5
|
+
module Templates
|
6
|
+
module Sequel
|
7
|
+
def model_klass
|
8
|
+
'Sequel::Model'
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def initializer
|
12
|
+
<<-FILE.strip_heredoc
|
13
|
+
# frozen_string_literal: true
|
13
14
|
|
14
|
-
|
15
|
+
require 'yaml'
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
# load Sequel Configuration
|
18
|
+
settings = YAML.load_file('config/database.yml')
|
19
|
+
DB = Sequel.connect(settings[ENV['RACK_ENV']])
|
19
20
|
|
20
|
-
|
21
|
+
env = ENV['RACK_ENV'] || 'development'
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
logger = if %w[development test].include? env
|
24
|
+
log_dir = File.join(Dir.getwd, 'log')
|
25
|
+
log_file = File.join(log_dir, 'db.log')
|
26
|
+
FileUtils.mkdir(log_dir) unless Dir.exist?(log_dir)
|
27
|
+
Logger.new(File.open(log_file, 'a'))
|
28
|
+
else
|
29
|
+
Logger.new($stdout)
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
+
DB.loggers << logger
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
# FIXME: maybe remove it later …
|
35
|
+
# see: https://groups.google.com/forum/#!topic/sequel-talk/QIIv5qoltjs
|
36
|
+
Sequel::Model.require_valid_table = false
|
37
|
+
Sequel::Model.plugin :force_encoding, 'UTF-8'
|
38
|
+
FILE
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
def rakefile
|
42
|
+
<<-FILE.strip_heredoc
|
43
|
+
# Sequel migration tasks
|
44
|
+
namespace :db do
|
45
|
+
Sequel.extension(:migration)
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
desc "Prints current schema version"
|
48
|
+
task version: :connect do
|
49
|
+
version = DB.tables.include?(:schema_info) ? DB[:schema_info].first[:version] : 0
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
$stdout.print 'Schema Version: '
|
52
|
+
$stdout.puts version
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
desc 'Run all migrations in db/migrations'
|
56
|
+
task migrate: :connect do
|
57
|
+
Sequel::Migrator.apply(DB, 'db/migrations')
|
58
|
+
Rake::Task['db:version'].execute
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
|
61
|
+
desc "Perform rollback to specified target or full rollback as default"
|
62
|
+
task :rollback, [:target] => :connect do |t, args|
|
63
|
+
args.with_defaults(:target => 0)
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
65
|
+
Sequel::Migrator.run(DB, 'db/migrations', :target => args[:target].to_i)
|
66
|
+
Rake::Task['db:version'].execute
|
67
|
+
end
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
69
|
+
desc "Perform migration reset (full rollback and migration)"
|
70
|
+
task reset: :connect do
|
71
|
+
Sequel::Migrator.run(DB, 'db/migrations', target: 0)
|
72
|
+
Sequel::Migrator.run(DB, 'db/migrations')
|
73
|
+
Rake::Task['db:version'].execute
|
74
|
+
end
|
74
75
|
|
75
|
-
|
76
|
-
|
76
|
+
task connect: :environment do
|
77
|
+
require './config/initializers/database'
|
78
|
+
end
|
77
79
|
end
|
80
|
+
FILE
|
78
81
|
end
|
79
|
-
FILE
|
80
|
-
end
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
83
|
+
def gemfile
|
84
|
+
<<-FILE.strip_heredoc
|
85
|
+
# DB stack
|
86
|
+
gem 'sequel'
|
87
|
+
gem 'pg'
|
88
|
+
FILE
|
89
|
+
end
|
89
90
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
91
|
+
def migration(_klass_name, resource)
|
92
|
+
<<-FILE.strip_heredoc
|
93
|
+
Sequel.migration do
|
94
|
+
change do
|
95
|
+
create_table :#{resource} do
|
96
|
+
primary_key :id
|
96
97
|
|
97
|
-
|
98
|
-
|
98
|
+
DateTime :created_at
|
99
|
+
DateTime :updated_at
|
100
|
+
end
|
99
101
|
end
|
100
102
|
end
|
103
|
+
FILE
|
101
104
|
end
|
102
|
-
FILE
|
103
105
|
end
|
104
106
|
end
|
105
107
|
end
|
@@ -61,7 +61,7 @@ module Starter
|
|
61
61
|
|
62
62
|
file_name = "#{Time.now.strftime('%Y%m%d%H%m%S')}_create_#{klass_name.downcase}.rb"
|
63
63
|
migration_dest = File.join(Dir.pwd, 'db', 'migrate', file_name)
|
64
|
-
|
64
|
+
FileOps.write_file(migration_dest, migration(klass_name, resource))
|
65
65
|
end
|
66
66
|
|
67
67
|
def load_orm(orm: ::Starter::Config.read[:orm])
|
@@ -70,10 +70,10 @@ module Starter
|
|
70
70
|
case @orm
|
71
71
|
when 'sequel'
|
72
72
|
require 'starter/builder/templates/sequel'
|
73
|
-
extend(
|
73
|
+
extend(Starter::Builder::Templates::Sequel)
|
74
74
|
when 'activerecord', 'ar'
|
75
75
|
require 'starter/builder/templates/activerecord'
|
76
|
-
extend(
|
76
|
+
extend(Starter::Builder::Templates::ActiveRecord)
|
77
77
|
else
|
78
78
|
@orm = nil
|
79
79
|
end
|
@@ -87,26 +87,26 @@ module Starter
|
|
87
87
|
|
88
88
|
def build_initializer(dest)
|
89
89
|
FileUtils.mkdir_p(dest)
|
90
|
-
|
90
|
+
FileOps.write_file(File.join(dest, 'database.rb'), initializer)
|
91
91
|
end
|
92
92
|
|
93
93
|
def build_config(dest)
|
94
|
-
|
94
|
+
FileOps.write_file(File.join(dest, 'database.yml'), config)
|
95
95
|
end
|
96
96
|
|
97
97
|
def build_standalone_migrations(dest)
|
98
|
-
|
98
|
+
FileOps.write_file(dest, standalone_migrations)
|
99
99
|
end
|
100
100
|
|
101
101
|
# adds a middleware to config.ru
|
102
102
|
def add_middleware(dest, middleware)
|
103
103
|
replacement = "use #{middleware}\n\n\\1"
|
104
|
-
|
104
|
+
FileOps.call!(File.join(dest, 'config.ru')) { |content| content.sub!(/^(run.+)$/, replacement) }
|
105
105
|
end
|
106
106
|
|
107
107
|
def append_to_file(file_name, content)
|
108
|
-
original =
|
109
|
-
|
108
|
+
original = FileOps.read_file(file_name)
|
109
|
+
FileOps.write_file(file_name, "#{original}\n\n#{content}")
|
110
110
|
end
|
111
111
|
|
112
112
|
def prepare_for_migrations(dest)
|
@@ -45,7 +45,7 @@ RSpec.shared_examples 'DELETE one' do
|
|
45
45
|
let(:route) { route_from_description }
|
46
46
|
|
47
47
|
subject { delete route }
|
48
|
-
specify { expect(subject.status).to eql
|
48
|
+
specify { expect(subject.status).to eql 204 }
|
49
49
|
end
|
50
50
|
|
51
51
|
# plural forms
|
@@ -75,5 +75,5 @@ RSpec.shared_examples 'DELETE specific' do |key: nil|
|
|
75
75
|
let(:specific_route) { "#{route_from_description}/#{key}" }
|
76
76
|
|
77
77
|
subject { delete specific_route }
|
78
|
-
specify { expect(subject.status).to eql
|
78
|
+
specify { expect(subject.status).to eql 204 }
|
79
79
|
end
|
data/lib/starter/version.rb
CHANGED
data/lib/starter.rb
CHANGED
@@ -5,9 +5,13 @@ require 'awesome_print'
|
|
5
5
|
require 'active_support'
|
6
6
|
require 'active_support/core_ext/string'
|
7
7
|
|
8
|
-
require 'starter/version'
|
9
|
-
require 'starter/builder'
|
10
|
-
require 'starter/config'
|
8
|
+
# require 'starter/version'
|
9
|
+
# require 'starter/builder'
|
10
|
+
# require 'starter/config'
|
11
|
+
|
12
|
+
require 'zeitwerk'
|
13
|
+
loader = Zeitwerk::Loader.for_gem
|
14
|
+
loader.setup
|
11
15
|
|
12
16
|
module Starter
|
13
17
|
autoload :Rake, 'starter/rake/grape_tasks'
|
data/template/Dockerfile
CHANGED
data/template/Gemfile
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
workers ENV.fetch('WEB_CONCURRENCY', 0)
|
4
|
+
min_threads_count = ENV.fetch('MIN_THREADS', 1)
|
5
|
+
max_threads_count = ENV.fetch('MAX_THREADS', 8)
|
6
|
+
threads min_threads_count, max_threads_count
|
7
|
+
|
8
|
+
port ENV.fetch('PORT', 9292)
|
9
|
+
|
10
|
+
environment ENV.fetch('RACK_ENV', 'development')
|
data/template/script/server
CHANGED
@@ -7,16 +7,4 @@ cd "$(dirname "$0")/.."
|
|
7
7
|
test -z "$RACK_ENV" &&
|
8
8
|
RACK_ENV='development'
|
9
9
|
|
10
|
-
|
11
|
-
PORT=$1
|
12
|
-
else
|
13
|
-
PORT=9292
|
14
|
-
fi
|
15
|
-
|
16
|
-
export PORT=$PORT
|
17
|
-
|
18
|
-
if [ "$RACK_ENV" = 'production' ]; then
|
19
|
-
bundle exec thin start -p $PORT -e $RACK_ENV --tag {{{grape-starter}}} -d --threaded
|
20
|
-
else
|
21
|
-
bundle exec thin start -p $PORT -e $RACK_ENV --tag {{{grape-starter}}} -D
|
22
|
-
fi
|
10
|
+
bundle exec puma --tag API-Baz
|
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: 1.
|
4
|
+
version: 1.6.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-02-
|
11
|
+
date: 2023-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gli
|
@@ -72,6 +72,20 @@ dependencies:
|
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '1.9'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: zeitwerk
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
type: :runtime
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
75
89
|
description: CLI to create a API skeleton based on Grape and Rack
|
76
90
|
email:
|
77
91
|
- pscholz.le@gmail.com
|
@@ -96,16 +110,16 @@ files:
|
|
96
110
|
- doc/re-doc.png
|
97
111
|
- grape-starter.gemspec
|
98
112
|
- lib/starter.rb
|
99
|
-
- lib/starter/
|
113
|
+
- lib/starter/build.rb
|
100
114
|
- lib/starter/builder/base_file.rb
|
101
|
-
- lib/starter/builder/file_foo.rb
|
102
115
|
- lib/starter/builder/names.rb
|
103
|
-
- lib/starter/builder/orms.rb
|
104
116
|
- lib/starter/builder/templates/activerecord.rb
|
105
117
|
- lib/starter/builder/templates/endpoints.rb
|
106
118
|
- lib/starter/builder/templates/files.rb
|
107
119
|
- lib/starter/builder/templates/sequel.rb
|
108
120
|
- lib/starter/config.rb
|
121
|
+
- lib/starter/file_ops.rb
|
122
|
+
- lib/starter/orms.rb
|
109
123
|
- lib/starter/rake/grape_tasks.rb
|
110
124
|
- lib/starter/rspec/request_specs.rb
|
111
125
|
- lib/starter/version.rb
|
@@ -125,13 +139,13 @@ files:
|
|
125
139
|
- template/config/boot.rb
|
126
140
|
- template/config/environment.rb
|
127
141
|
- template/config/initializers/.keep
|
142
|
+
- template/config/puma.rb
|
128
143
|
- template/lib/models.rb
|
129
144
|
- template/lib/models/version.rb
|
130
145
|
- template/public/.keep
|
131
146
|
- template/script/console
|
132
147
|
- template/script/server
|
133
148
|
- template/script/setup
|
134
|
-
- template/script/stop
|
135
149
|
- template/script/test
|
136
150
|
- template/script/update
|
137
151
|
- template/spec/lib/models/.keep
|