grape-starter 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rubocop.yml +36 -0
- data/.rubocop_todo.yml +12 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +27 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +70 -0
- data/Rakefile +14 -0
- data/bin/grape-starter +119 -0
- data/grape-starter.gemspec +36 -0
- data/lib/starter.rb +9 -0
- data/lib/starter/builder.rb +90 -0
- data/lib/starter/builder/names.rb +56 -0
- data/lib/starter/builder/template_endpoints.rb +97 -0
- data/lib/starter/builder/template_files.rb +73 -0
- data/lib/starter/rake/grape_tasks.rb +71 -0
- data/lib/starter/rspec/request_specs.rb +109 -0
- data/lib/starter/version.rb +4 -0
- data/template/.rubocop.yml +15 -0
- data/template/.rubocop_todo.yml +28 -0
- data/template/Gemfile +23 -0
- data/template/LICENSE +21 -0
- data/template/README.md +70 -0
- data/template/Rakefile +25 -0
- data/template/api/base.rb +18 -0
- data/template/api/endpoints/root.rb +20 -0
- data/template/api/entities/api_error.rb +17 -0
- data/template/api/entities/route.rb +22 -0
- data/template/config.ru +12 -0
- data/template/config/application.rb +22 -0
- data/template/config/boot.rb +3 -0
- data/template/config/environment.rb +4 -0
- data/template/lib/api.rb +6 -0
- data/template/lib/api/version.rb +4 -0
- data/template/script/console +8 -0
- data/template/script/server +14 -0
- data/template/script/setup +6 -0
- data/template/script/stop +8 -0
- data/template/script/test +17 -0
- data/template/script/update +6 -0
- data/template/spec/lib/api/version_spec.rb +8 -0
- data/template/spec/requests/documentation_spec.rb +12 -0
- data/template/spec/requests/root_spec.rb +25 -0
- data/template/spec/spec_helper.rb +25 -0
- metadata +216 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 52f430416f92875210e64914e6fe61c29d4c3e56
|
4
|
+
data.tar.gz: 77f33daa8ca7ef7f49e4415acaf2261edc888969
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 94908b48037df0376311ddb26b61e408e99b9fd65e017fbb484a121cdaacea7fc65fe12fc7eae1930ba5239becefddf5555ecca2d02599ec9b05cafe570ae48a
|
7
|
+
data.tar.gz: f089a230198355841150ae7353973e0fc8180c50e2e742f98ed63363c193b48ac199f46694238e2a516ebd0ce970028e876bcae079f97962820c500962919b90
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
Exclude:
|
5
|
+
- '**/bin/**/*'
|
6
|
+
- '**/tmp/**/*'
|
7
|
+
- '**/script/**/*'
|
8
|
+
- grape-starter.gemspec
|
9
|
+
UseCache: true
|
10
|
+
TargetRubyVersion: 2.3
|
11
|
+
|
12
|
+
Metrics/BlockLength:
|
13
|
+
Exclude:
|
14
|
+
- 'spec/**/*'
|
15
|
+
|
16
|
+
Metrics/LineLength:
|
17
|
+
Max: 120
|
18
|
+
|
19
|
+
Style/AccessorMethodName:
|
20
|
+
Exclude:
|
21
|
+
- 'lib/starter/builder/template_files.rb'
|
22
|
+
- 'lib/starter/builder/template_endpoints.rb'
|
23
|
+
|
24
|
+
Style/AsciiComments:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
Style/IndentationWidth:
|
28
|
+
Exclude:
|
29
|
+
- 'lib/starter/builder/template_files.rb'
|
30
|
+
- 'lib/starter/builder/template_endpoints.rb'
|
31
|
+
|
32
|
+
Style/Documentation:
|
33
|
+
Exclude:
|
34
|
+
- 'template/**/*'
|
35
|
+
- 'lib/**/*'
|
36
|
+
- 'spec/**/*'
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2016-10-18 20:40:59 +0200 using RuboCop version 0.44.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: CountComments.
|
11
|
+
Metrics/MethodLength:
|
12
|
+
Max: 13
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
### 0.1.8
|
2
|
+
|
3
|
+
- adds request specs shared examples
|
4
|
+
|
5
|
+
### 0.1.7
|
6
|
+
|
7
|
+
- corrects path param for specific endpoints
|
8
|
+
|
9
|
+
### 0.1.6
|
10
|
+
|
11
|
+
- corrects adding of endpoints, if no http verb was given
|
12
|
+
|
13
|
+
### 0.1.5
|
14
|
+
|
15
|
+
- adds flag for entity creating
|
16
|
+
|
17
|
+
### 0.1.4
|
18
|
+
|
19
|
+
- version bump v0.1.4
|
20
|
+
- moves back dependencies to gemspec
|
21
|
+
- adds rubygems badge
|
22
|
+
- cleans up dependencies …
|
23
|
+
- updates readme
|
24
|
+
- version bump v0.1.2
|
25
|
+
- adds `force` option to add
|
26
|
+
- version bump v0.1.1
|
27
|
+
- adds specifying http verbs
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Peter Scholz
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
[![Codeship Status for LeFnord/grape-starter](https://app.codeship.com/projects/91e08e60-9600-0134-5571-4a8607aa1ae3/status?branch=master)](https://app.codeship.com/projects/186901)
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/grape-starter.svg)](https://badge.fury.io/rb/grape-starter)
|
3
|
+
[![Inline docs](http://inch-ci.org/github/LeFnord/grape-starter.svg?branch=master)](http://inch-ci.org/github/LeFnord/grape-starter)
|
4
|
+
|
5
|
+
# Grape Starter
|
6
|
+
|
7
|
+
Is a tool to help you to build up a skeleton for a [Grape](http://github.com/ruby-grape/grape) API mounted on [Rack](https://github.com/rack/rack) ready to run.
|
8
|
+
[grape-swagger](http://github.com/ruby-grape/grape-swagger) would be used to generate a [OAPI](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md) compatible documentation.
|
9
|
+
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
#### Install it
|
14
|
+
```
|
15
|
+
$ gem install grape-starter
|
16
|
+
```
|
17
|
+
|
18
|
+
#### Create a new project
|
19
|
+
```
|
20
|
+
$ grape-starter new awesome_api
|
21
|
+
```
|
22
|
+
|
23
|
+
This command creates a folder named `awesome_api` containing the skeleton. With following structure:
|
24
|
+
|
25
|
+
```
|
26
|
+
├── <Standards>
|
27
|
+
├── api
|
28
|
+
│ ├── base.rb # the main API class, all other endpoints would be mounted in it
|
29
|
+
│ ├── endpoints # contains the endpoint file for a resource
|
30
|
+
│ │ └── root.rb # root is always available, it exposes all routes/endpoints, disable by comment out in base.rb
|
31
|
+
│ └── entities # contains the entity representation of the reource, if wanted
|
32
|
+
│ └── route.rb
|
33
|
+
├── config # base configuration
|
34
|
+
│ └── …
|
35
|
+
├── config.ru # Rack it up
|
36
|
+
├── lib # contains the additional lib file for a resource
|
37
|
+
│ ├── api
|
38
|
+
│ │ └── version.rb
|
39
|
+
│ └── api.rb
|
40
|
+
├── script # setup / server / test etc.
|
41
|
+
│ └── …
|
42
|
+
└── spec # RSpec
|
43
|
+
└── …
|
44
|
+
```
|
45
|
+
|
46
|
+
To run it, go into awesome_api folder, start the server
|
47
|
+
```
|
48
|
+
$ cd awesome_api
|
49
|
+
$ ./script/server
|
50
|
+
```
|
51
|
+
the API is now accessible under: [http://localhost:9292/api/v1/root](http://localhost:9292/api/v1/root)
|
52
|
+
|
53
|
+
More could be found in [README](template/README.md).
|
54
|
+
|
55
|
+
#### Add resources
|
56
|
+
```
|
57
|
+
$ grape-starter add foo
|
58
|
+
```
|
59
|
+
to add CRUD endpoints for resource foo. For more options, see command help.
|
60
|
+
|
61
|
+
This adds endpoint and lib file and belonging specs, and a mount entry in base.rb.
|
62
|
+
|
63
|
+
## Contributing
|
64
|
+
|
65
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/LeFnord/grape-starter.
|
66
|
+
|
67
|
+
|
68
|
+
## License
|
69
|
+
|
70
|
+
The gem is available as open source under the terms of the [MIT License](LICENSE).
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
require 'rake'
|
5
|
+
|
6
|
+
require 'rspec/core'
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
|
9
|
+
RSpec::Core::RakeTask.new(:spec)
|
10
|
+
|
11
|
+
require 'rubocop/rake_task'
|
12
|
+
RuboCop::RakeTask.new(:rubocop)
|
13
|
+
|
14
|
+
task default: [:rubocop, :spec]
|
data/bin/grape-starter
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
|
5
|
+
|
6
|
+
require 'pry'
|
7
|
+
require 'gli'
|
8
|
+
require 'starter'
|
9
|
+
|
10
|
+
include GLI::App
|
11
|
+
|
12
|
+
program_desc 'Create initial grape api skeleton'
|
13
|
+
|
14
|
+
version Starter::VERSION
|
15
|
+
|
16
|
+
subcommand_option_handling :normal
|
17
|
+
arguments :strict
|
18
|
+
|
19
|
+
desc 'overwrites existend stuff'
|
20
|
+
switch [:f, :force], negatable: false
|
21
|
+
|
22
|
+
desc 'Create initial grape api skeleton'
|
23
|
+
arg_name 'project name'
|
24
|
+
|
25
|
+
command :new do |c|
|
26
|
+
|
27
|
+
c.action do |global_options, _, args|
|
28
|
+
dir = args.empty? ? nil : File.join(Dir.getwd, args.first)
|
29
|
+
|
30
|
+
case
|
31
|
+
when args.empty? || dir.nil?
|
32
|
+
exit_now! 'no name given: starter new project'
|
33
|
+
when Dir.exist?(dir) && !global_options[:force]
|
34
|
+
exit_now! 'project exist: -f to overwrite'
|
35
|
+
end
|
36
|
+
|
37
|
+
$stdout.puts "created: #{args.first}"
|
38
|
+
starter_gem = Gem::Specification.find_by_name('grape-starter').gem_dir
|
39
|
+
|
40
|
+
src = File.join(starter_gem, 'template', '.')
|
41
|
+
FileUtils.copy_entry src, dir
|
42
|
+
|
43
|
+
FileUtils.cd(dir) do
|
44
|
+
# TODO:
|
45
|
+
$stdout.puts `bundle install`
|
46
|
+
$stdout.puts `bundle exec rubocop -a`
|
47
|
+
$stdout.puts `git init`
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'Adds a new resource - run from inside the project'
|
53
|
+
long_desc "run this command from inside the project
|
54
|
+
hereby the the given resource name
|
55
|
+
can be given in form of
|
56
|
+
'foo(s)', 'foo_bar(s)''"
|
57
|
+
arg_name 'resource [post* get* put* patch* delete*]'
|
58
|
+
command :add do |c|
|
59
|
+
c.desc 'adds entity file'
|
60
|
+
c.switch [:e, :entity], negatable: false
|
61
|
+
|
62
|
+
c.action do |global_options, options, args|
|
63
|
+
exit_now! 'no resource given' if args.empty?
|
64
|
+
|
65
|
+
resource = args.shift
|
66
|
+
set = args
|
67
|
+
|
68
|
+
begin
|
69
|
+
builder_options = global_options.merge(set: set).merge(options)
|
70
|
+
Starter::Builder.call!(resource, builder_options)
|
71
|
+
created_files = Starter::Builder.save
|
72
|
+
|
73
|
+
`bundle exec rubocop -a #{created_files.join(' ')}`
|
74
|
+
$stdout.puts "added resource: #{resource}"
|
75
|
+
rescue => e
|
76
|
+
exit_now! e
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
desc 'Removes a resource - run from inside the project'
|
82
|
+
arg_name 'resource'
|
83
|
+
command :remove do |c|
|
84
|
+
# c.desc 'adds entity file'
|
85
|
+
# c.switch [:e, :entity], negatable: false
|
86
|
+
|
87
|
+
c.action do |global_options, options, args|
|
88
|
+
exit_now! 'no resource given' if args.empty?
|
89
|
+
resource = args.first
|
90
|
+
|
91
|
+
Starter::Builder.remove!(resource)
|
92
|
+
|
93
|
+
$stdout.puts "removed resource: #{resource}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
pre do |_global, _command, _options, _args|
|
99
|
+
# Pre logic here
|
100
|
+
# Return true to proceed; false to abort and not call the
|
101
|
+
# chosen command
|
102
|
+
# Use skips_pre before a command to skip this block
|
103
|
+
# on that command only
|
104
|
+
true
|
105
|
+
end
|
106
|
+
|
107
|
+
post do |global, command, options, args|
|
108
|
+
# Post logic here
|
109
|
+
# Use skips_post before a command to skip this
|
110
|
+
# block on that command only
|
111
|
+
end
|
112
|
+
|
113
|
+
on_error do |_exception|
|
114
|
+
# Error logic here
|
115
|
+
# return false to skip default error handling
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
119
|
+
exit run(ARGV)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'starter/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'grape-starter'
|
9
|
+
spec.version = Starter::VERSION
|
10
|
+
spec.authors = ['LeFnord']
|
11
|
+
spec.email = ['pscholz.le@gmail.com']
|
12
|
+
|
13
|
+
spec.summary = 'Create a Grape Rack skeleton'
|
14
|
+
spec.description = 'CLI to create a API skeleton based on Grape and Rack'
|
15
|
+
spec.homepage = 'https://github.com/LeFnord/grape-starter'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
+
f.match(%r{^(test|spec|features)/})
|
20
|
+
end
|
21
|
+
spec.bindir = 'bin'
|
22
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.add_dependency 'gli', '~> 2.14'
|
26
|
+
spec.add_dependency 'activesupport', '~> 5.0'
|
27
|
+
spec.add_dependency 'rubocop', '~> 0.40'
|
28
|
+
|
29
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
30
|
+
spec.add_development_dependency 'grape', '~> 0.18'
|
31
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
32
|
+
spec.add_development_dependency 'rack-test'
|
33
|
+
spec.add_development_dependency 'pry'
|
34
|
+
spec.add_development_dependency 'awesome_print'
|
35
|
+
|
36
|
+
end
|
data/lib/starter.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'active_support/core_ext/string'
|
3
|
+
|
4
|
+
module Starter
|
5
|
+
require 'starter/builder/names'
|
6
|
+
require 'starter/builder/template_files'
|
7
|
+
require 'starter/builder/template_endpoints'
|
8
|
+
|
9
|
+
class Builder
|
10
|
+
extend Starter::Names
|
11
|
+
extend Template::Files
|
12
|
+
extend Template::Endpoints
|
13
|
+
|
14
|
+
class << self
|
15
|
+
attr_reader :resource, :set, :force, :entity
|
16
|
+
|
17
|
+
def call!(resource, options = {})
|
18
|
+
@resource = resource
|
19
|
+
@set = options[:set]
|
20
|
+
@force = options[:force]
|
21
|
+
@entity = options[:entity]
|
22
|
+
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def remove!(resource)
|
27
|
+
@resource = resource
|
28
|
+
|
29
|
+
files_to_remove = file_list.map { |x| send("#{x}_name") }
|
30
|
+
FileUtils.rm files_to_remove
|
31
|
+
end
|
32
|
+
|
33
|
+
def save
|
34
|
+
file_list.each do |new_file|
|
35
|
+
save_file(new_file)
|
36
|
+
end
|
37
|
+
|
38
|
+
add_moint_point
|
39
|
+
|
40
|
+
file_list.map { |x| send("#{x}_name") }
|
41
|
+
end
|
42
|
+
|
43
|
+
def endpoints
|
44
|
+
content(endpoint_set).join("\n\n")
|
45
|
+
end
|
46
|
+
|
47
|
+
def endpoint_specs
|
48
|
+
content(endpoint_set.map { |x| "#{x}_spec" }).join("\n")
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def file_list
|
54
|
+
standards = %w(api_file lib_file api_spec lib_spec)
|
55
|
+
|
56
|
+
entity ? standards + ['entity_file'] : standards
|
57
|
+
end
|
58
|
+
|
59
|
+
def save_file(new_file)
|
60
|
+
new_file_name = "#{new_file}_name"
|
61
|
+
should_raise?(send(new_file_name))
|
62
|
+
|
63
|
+
File.open(send(new_file_name), 'w+') { |file| file.write(send(new_file.strip_heredoc)) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def should_raise?(file)
|
67
|
+
raise StandardError, '… resource exists' if File.exist?(file) && !force
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_moint_point
|
71
|
+
file = File.read(api_base_file_name)
|
72
|
+
occurence = file.scan(/(\s+mount.*?\n)/).last.first
|
73
|
+
replacement = occurence + " mount Endpoints::#{klass_name}\n"
|
74
|
+
file.sub!(occurence, replacement)
|
75
|
+
File.open(api_base_file_name, 'w') { |f| f.write(file) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def endpoint_set
|
79
|
+
crud_set = singular? ? singular_one : crud
|
80
|
+
return crud_set if set.blank?
|
81
|
+
|
82
|
+
crud_set.each_with_object([]) { |x, memo| set.map { |y| memo << x if x.to_s.start_with?(y) } }
|
83
|
+
end
|
84
|
+
|
85
|
+
def content(set)
|
86
|
+
set.map { |x| send(x) }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|