grape-starter 1.5.1 → 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/.github/workflows/pipeline.yml +4 -4
- data/.rubocop.yml +4 -1
- 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/Rakefile +2 -2
- data/template/config/boot.rb +1 -1
- data/template/config/puma.rb +10 -0
- data/template/script/server +1 -13
- metadata +21 -8
- data/.travis.yml +0 -24
- data/template/script/stop +0 -8
@@ -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
data/template/Rakefile
CHANGED
@@ -21,8 +21,8 @@ task default: %i[spec rubocop]
|
|
21
21
|
|
22
22
|
# grape-swagger tasks
|
23
23
|
require 'grape-swagger/rake/oapi_tasks'
|
24
|
-
GrapeSwagger::Rake::OapiTasks.new(
|
24
|
+
GrapeSwagger::Rake::OapiTasks.new(Api::Base)
|
25
25
|
|
26
26
|
# starter tasks
|
27
27
|
require 'starter/rake/grape_tasks'
|
28
|
-
Starter::Rake::GrapeTasks.new(
|
28
|
+
Starter::Rake::GrapeTasks.new(Api::Base)
|