service_template 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rubocop.yml +23 -0
- data/.travis.yml +13 -0
- data/CHANGELOG.md +64 -0
- data/Gemfile +4 -0
- data/LICENSE +24 -0
- data/README.md +217 -0
- data/Rakefile +9 -0
- data/bin/service_template +5 -0
- data/lib/service_template.rb +55 -0
- data/lib/service_template/active_record_extensions/notifications_subscriber.rb +17 -0
- data/lib/service_template/active_record_extensions/seeder.rb +14 -0
- data/lib/service_template/active_record_extensions/stats.rb +37 -0
- data/lib/service_template/authentication.rb +8 -0
- data/lib/service_template/cli.rb +111 -0
- data/lib/service_template/deploy.rb +98 -0
- data/lib/service_template/gem_dependency.rb +37 -0
- data/lib/service_template/generators.rb +3 -0
- data/lib/service_template/generators/api_generator.rb +30 -0
- data/lib/service_template/generators/readme_generator.rb +47 -0
- data/lib/service_template/generators/scaffold_generator.rb +29 -0
- data/lib/service_template/generators/templates/api/app/apis/%name_tableize%_api.rb.tt +40 -0
- data/lib/service_template/generators/templates/api/app/models/%name_underscore%.rb.tt +2 -0
- data/lib/service_template/generators/templates/api/app/representers/%name_underscore%_representer.rb.tt +4 -0
- data/lib/service_template/generators/templates/api/spec/apis/%name_tableize%_api_spec.rb.tt +16 -0
- data/lib/service_template/generators/templates/api/spec/models/%name_underscore%_spec.rb.tt +9 -0
- data/lib/service_template/generators/templates/readme/README.md.tt +55 -0
- data/lib/service_template/generators/templates/readme/spec/docs/readme_spec.rb +7 -0
- data/lib/service_template/generators/templates/scaffold/.env.development.tt +9 -0
- data/lib/service_template/generators/templates/scaffold/.env.test.tt +10 -0
- data/lib/service_template/generators/templates/scaffold/.gitignore.tt +13 -0
- data/lib/service_template/generators/templates/scaffold/.rubocop.yml +24 -0
- data/lib/service_template/generators/templates/scaffold/.ruby-version.tt +1 -0
- data/lib/service_template/generators/templates/scaffold/Gemfile.tt +29 -0
- data/lib/service_template/generators/templates/scaffold/README.md +3 -0
- data/lib/service_template/generators/templates/scaffold/Rakefile +21 -0
- data/lib/service_template/generators/templates/scaffold/app.rb +19 -0
- data/lib/service_template/generators/templates/scaffold/app/apis/application_api.rb +9 -0
- data/lib/service_template/generators/templates/scaffold/app/apis/hello_api.rb.tt +10 -0
- data/lib/service_template/generators/templates/scaffold/config.ru.tt +21 -0
- data/lib/service_template/generators/templates/scaffold/config/database.yml.tt +19 -0
- data/lib/service_template/generators/templates/scaffold/config/initializers/active_record.rb +5 -0
- data/lib/service_template/generators/templates/scaffold/db/schema.rb +11 -0
- data/lib/service_template/generators/templates/scaffold/lib/.keep +0 -0
- data/lib/service_template/generators/templates/scaffold/log/.keep +0 -0
- data/lib/service_template/generators/templates/scaffold/spec/apis/hello_api_spec.rb.tt +17 -0
- data/lib/service_template/generators/templates/scaffold/spec/factories/.gitkeep +0 -0
- data/lib/service_template/generators/templates/scaffold/spec/spec_helper.rb +47 -0
- data/lib/service_template/grape_extenders.rb +30 -0
- data/lib/service_template/grape_extensions/error_formatter.rb +18 -0
- data/lib/service_template/grape_extensions/grape_helpers.rb +27 -0
- data/lib/service_template/identity.rb +45 -0
- data/lib/service_template/json_error.rb +24 -0
- data/lib/service_template/logger/log_transaction.rb +17 -0
- data/lib/service_template/logger/logger.rb +42 -0
- data/lib/service_template/logger/parseable.rb +37 -0
- data/lib/service_template/middleware/app_monitor.rb +17 -0
- data/lib/service_template/middleware/authentication.rb +32 -0
- data/lib/service_template/middleware/database_stats.rb +15 -0
- data/lib/service_template/middleware/logger.rb +67 -0
- data/lib/service_template/middleware/request_stats.rb +42 -0
- data/lib/service_template/output_formatters/entity.rb +15 -0
- data/lib/service_template/output_formatters/include_nil.rb +16 -0
- data/lib/service_template/output_formatters/json_api_representer.rb +9 -0
- data/lib/service_template/param_sanitizer.rb +30 -0
- data/lib/service_template/rspec_extensions/response_helpers.rb +46 -0
- data/lib/service_template/setup.rb +36 -0
- data/lib/service_template/sortable_api.rb +17 -0
- data/lib/service_template/stats.rb +43 -0
- data/lib/service_template/stats_d_timer.rb +26 -0
- data/lib/service_template/version.rb +45 -0
- data/lib/tasks/deploy.rake +11 -0
- data/lib/tasks/routes.rake +11 -0
- data/service_template.gemspec +42 -0
- data/spec/active_record_extensions/filter_by_hash_spec.rb +23 -0
- data/spec/active_record_extensions/seeder_spec.rb +13 -0
- data/spec/authentication_spec.rb +17 -0
- data/spec/deprecations/application_api_spec.rb +19 -0
- data/spec/deprecations/entity_spec.rb +9 -0
- data/spec/deprecations/filter_by_hash_spec.rb +9 -0
- data/spec/deprecations/napa_setup_spec.rb +52 -0
- data/spec/generators/api_generator_spec.rb +63 -0
- data/spec/generators/migration_generator_spec.rb +105 -0
- data/spec/generators/readme_generator_spec.rb +35 -0
- data/spec/generators/scaffold_generator_spec.rb +90 -0
- data/spec/grape_extenders_spec.rb +50 -0
- data/spec/grape_extensions/error_formatter_spec.rb +29 -0
- data/spec/grape_extensions/include_nil_spec.rb +23 -0
- data/spec/identity_spec.rb +50 -0
- data/spec/json_error_spec.rb +33 -0
- data/spec/logger/log_transaction_spec.rb +34 -0
- data/spec/logger/logger_spec.rb +14 -0
- data/spec/logger/parseable_spec.rb +16 -0
- data/spec/middleware/authentication_spec.rb +54 -0
- data/spec/middleware/database_stats_spec.rb +64 -0
- data/spec/middleware/request_stats_spec.rb +21 -0
- data/spec/sortable_api_spec.rb +56 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/stats_d_timer_spec.rb +23 -0
- data/spec/stats_spec.rb +66 -0
- data/spec/version_spec.rb +40 -0
- data/tasks/spec.rake +9 -0
- data/tasks/version.rake +51 -0
- metadata +456 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def app
|
4
|
+
ApplicationApi
|
5
|
+
end
|
6
|
+
|
7
|
+
describe <%= name.classify.pluralize %>Api do
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
describe 'e.g. GET, POST, PUT, etc.' do
|
11
|
+
it 'needs tests to be written!' do
|
12
|
+
pending('write tests for <%= name.classify.pluralize %>Api!')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# <%= service_name %>
|
2
|
+
|
3
|
+
:bow: Please put your auspicious [Travis status button](http://docs.travis-ci.com/user/status-images/) here :bow:
|
4
|
+
|
5
|
+
1. [Overview](#overview)
|
6
|
+
2. [How Does It Work](#how-does-it-work)
|
7
|
+
3. [Endpoints](#endpoints)
|
8
|
+
4. [Development](#development)
|
9
|
+
5. [Extra Links](#extra-links)
|
10
|
+
|
11
|
+
### Overview
|
12
|
+
|
13
|
+
:bow: Tell us about your wonderful service :bow:
|
14
|
+
|
15
|
+
In this section, please answer the questions, "What is this service?" or "What does this service do?"
|
16
|
+
|
17
|
+
### How Does It Work
|
18
|
+
|
19
|
+
Ohhh tell us, how does it function? :bow: :bow:
|
20
|
+
|
21
|
+
Tell us about the __mechanics__ or __logic__ driving the service. Diagrams and pictures are :angel:
|
22
|
+
|
23
|
+
### Endpoints
|
24
|
+
|
25
|
+
How must we interact with your great service? :bow:
|
26
|
+
|
27
|
+
Try typing `rake routes` into your console, and then paste that here.
|
28
|
+
|
29
|
+
If those endpoints need to be explained in more detail, please bless us with your wisdom.
|
30
|
+
|
31
|
+
### Development
|
32
|
+
|
33
|
+
```
|
34
|
+
bundle install
|
35
|
+
|
36
|
+
rake db:reset
|
37
|
+
|
38
|
+
rspec spec
|
39
|
+
|
40
|
+
rackup
|
41
|
+
```
|
42
|
+
|
43
|
+
So wonderful, so informative! :bow:
|
44
|
+
|
45
|
+
What else do we need to know so that a new developer can start contributing __within 30 minutes__?
|
46
|
+
|
47
|
+
### Extra Links
|
48
|
+
|
49
|
+
What a perfectly constructed service! We're so honored :bow:
|
50
|
+
|
51
|
+
If your service makes heavy use of other gems or API's, imbue us with that knowledge in the form of
|
52
|
+
|
53
|
+
- [Link to documentation]()
|
54
|
+
- [etc.]()
|
55
|
+
- [For information on how to create links in Markdown, please click here](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#links)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Uncomment when using ServiceTemplate::Middleware::Authentication
|
2
|
+
# HEADER_PASSWORD=''
|
3
|
+
|
4
|
+
SERVICE_NAME=<%= app_name %>
|
5
|
+
|
6
|
+
DATABASE_USER='<%= @database_user %>'
|
7
|
+
DATABASE_PASSWORD=''
|
8
|
+
DATABASE_HOST=localhost
|
9
|
+
DATABASE_NAME=<%= app_name.underscore %>_development
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Uncomment when using ServiceTemplate::Middleware::Authentication
|
2
|
+
# HEADER_PASSWORD=''
|
3
|
+
|
4
|
+
SERVICE_NAME=<%= app_name %>
|
5
|
+
RACK_ENV=test
|
6
|
+
|
7
|
+
DATABASE_USER='<%= @database_user %>'
|
8
|
+
DATABASE_PASSWORD=''
|
9
|
+
DATABASE_HOST=localhost
|
10
|
+
DATABASE_NAME=<%= app_name.underscore %>_test
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Documentation:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
Encoding:
|
5
|
+
EnforcedStyle: when_needed
|
6
|
+
|
7
|
+
LineLength:
|
8
|
+
Max: 120
|
9
|
+
|
10
|
+
# This cop checks for big numeric literals without _ between groups of digits in them.
|
11
|
+
# ie: 100_000 vs 100000
|
12
|
+
NumericLiterals:
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
# how to bubble up exceptions (raise or fail)
|
16
|
+
SignalException:
|
17
|
+
EnforcedStyle: only_raise
|
18
|
+
|
19
|
+
MethodLength:
|
20
|
+
Max: 30
|
21
|
+
|
22
|
+
AllCops:
|
23
|
+
Exclude:
|
24
|
+
- db/schema.rb
|
@@ -0,0 +1 @@
|
|
1
|
+
2.1.5
|
@@ -0,0 +1,29 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
ruby "2.1.5"
|
3
|
+
|
4
|
+
gem 'rack-cors'
|
5
|
+
gem '<%= @database_gem %>'
|
6
|
+
gem 'activerecord', '~> 4.2.0', :require => 'active_record'
|
7
|
+
gem 'json'
|
8
|
+
gem 'service_template'
|
9
|
+
gem 'roar'
|
10
|
+
gem 'grape-swagger'
|
11
|
+
gem 'grape-activerecord'
|
12
|
+
|
13
|
+
group :development,:test do
|
14
|
+
gem 'pry'
|
15
|
+
end
|
16
|
+
|
17
|
+
group :development do
|
18
|
+
gem 'rubocop', require: false
|
19
|
+
gem 'shotgun', require: false
|
20
|
+
end
|
21
|
+
|
22
|
+
group :test do
|
23
|
+
gem 'factory_girl'
|
24
|
+
gem 'rspec'
|
25
|
+
gem 'rack-test'
|
26
|
+
gem 'simplecov'
|
27
|
+
gem 'webmock'
|
28
|
+
gem 'database_cleaner'
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'service_template/setup'
|
4
|
+
require 'dotenv'
|
5
|
+
require 'grape/activerecord/rake'
|
6
|
+
ServiceTemplate.load_environment
|
7
|
+
|
8
|
+
require './app'
|
9
|
+
require 'json'
|
10
|
+
|
11
|
+
# active record tasks
|
12
|
+
namespace :db do
|
13
|
+
# Some db tasks require your app code to be loaded
|
14
|
+
task :environment do
|
15
|
+
require_relative 'app'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Dir.glob('./lib/tasks/*.rake').each { |r| import r }
|
20
|
+
|
21
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# load bundler
|
2
|
+
require 'bundler/setup'
|
3
|
+
Bundler.setup(:default)
|
4
|
+
require 'service_template/setup'
|
5
|
+
Bundler.require(:default, ServiceTemplate.env.to_sym)
|
6
|
+
require 'service_template'
|
7
|
+
|
8
|
+
# load environment
|
9
|
+
ServiceTemplate.load_environment
|
10
|
+
|
11
|
+
# autoload initalizers
|
12
|
+
Dir['./config/initializers/**/*.rb'].map { |file| require file }
|
13
|
+
|
14
|
+
# load middleware configs
|
15
|
+
Dir['./config/middleware/**/*.rb'].map { |file| require file }
|
16
|
+
|
17
|
+
# autoload app
|
18
|
+
relative_load_paths = %w(app/apis app/representers app/models app/workers lib)
|
19
|
+
ActiveSupport::Dependencies.autoload_paths += relative_load_paths
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require './app'
|
2
|
+
|
3
|
+
# Experimental StatsD Emitter for ActiveRecord
|
4
|
+
# require 'service_template/active_record_extensions/stats.rb'
|
5
|
+
|
6
|
+
# use Rack::Cors do
|
7
|
+
# allow do
|
8
|
+
# origins '*'
|
9
|
+
# resource '*', headers: :any, methods: [:get, :post, :delete, :put, :options]
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# use Honeybadger::Rack::ErrorNotifier
|
14
|
+
# use ServiceTemplate::Middleware::Logger
|
15
|
+
|
16
|
+
use ServiceTemplate::Middleware::AppMonitor
|
17
|
+
# Uncomment to require header passwords for all requests
|
18
|
+
# use ServiceTemplate::Middleware::Authentication
|
19
|
+
use ActiveRecord::ConnectionAdapters::ConnectionManagement
|
20
|
+
|
21
|
+
run ApplicationApi
|
@@ -0,0 +1,19 @@
|
|
1
|
+
defaults: &defaults
|
2
|
+
encoding: <%= @database_encoding %>
|
3
|
+
adapter: <%= @database_adapter %>
|
4
|
+
host: <%%= ENV['DATABASE_HOST'] %>
|
5
|
+
username: <%%= ENV['DATABASE_USER'] %>
|
6
|
+
password: <%%= ENV['DATABASE_PASSWORD'] %>
|
7
|
+
database: <%%= ENV['DATABASE_NAME'] %>
|
8
|
+
|
9
|
+
production:
|
10
|
+
<<: *defaults
|
11
|
+
|
12
|
+
development:
|
13
|
+
<<: *defaults
|
14
|
+
|
15
|
+
test:
|
16
|
+
<<: *defaults
|
17
|
+
|
18
|
+
staging:
|
19
|
+
<<: *defaults
|
@@ -0,0 +1,5 @@
|
|
1
|
+
require 'erb'
|
2
|
+
db = YAML.load(ERB.new(File.read('./config/database.yml')).result)[ServiceTemplate.env]
|
3
|
+
ActiveRecord::Base.establish_connection(db)
|
4
|
+
ActiveRecord::Base.logger = ServiceTemplate::Logger.logger if ServiceTemplate.env.development?
|
5
|
+
ActiveRecord::Base.include_root_in_json = false
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead
|
2
|
+
# of editing this file, please use the migrations feature of Active Record to
|
3
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
4
|
+
#
|
5
|
+
# Note that this schema.rb definition is the authoritative source for your
|
6
|
+
# database schema. If you need to create the application database on another
|
7
|
+
# system, you should be using db:schema:load, not running all the migrations
|
8
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
9
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
10
|
+
#
|
11
|
+
# It's strongly recommended that you check this file into your version control system.
|
File without changes
|
File without changes
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def app
|
4
|
+
ApplicationApi
|
5
|
+
end
|
6
|
+
|
7
|
+
describe HelloApi do
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
describe 'GET /hello' do
|
11
|
+
it 'returns a hello world message' do
|
12
|
+
get '/hello'
|
13
|
+
expect(response_body).to eq({ message: 'Hello Wonderful World, from <%= app_name.classify %>!' }.to_json)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
File without changes
|
@@ -0,0 +1,47 @@
|
|
1
|
+
ENV['RACK_ENV'] = 'test'
|
2
|
+
|
3
|
+
require 'webmock/rspec'
|
4
|
+
require 'rack/test'
|
5
|
+
require 'simplecov'
|
6
|
+
require 'factory_girl'
|
7
|
+
require 'service_template/rspec_extensions/response_helpers'
|
8
|
+
|
9
|
+
FactoryGirl.definition_file_paths = %w(./spec/factories)
|
10
|
+
FactoryGirl.find_definitions
|
11
|
+
SimpleCov.start do
|
12
|
+
add_filter "/spec\/.*/"
|
13
|
+
add_filter "/vendor\/.*/"
|
14
|
+
end
|
15
|
+
|
16
|
+
require './app'
|
17
|
+
require 'database_cleaner'
|
18
|
+
|
19
|
+
SimpleCov.start do
|
20
|
+
add_filter "/spec\/.*/"
|
21
|
+
add_filter "/vendor\/.*/"
|
22
|
+
end
|
23
|
+
|
24
|
+
# fail once the test coverage gets below an accepted amount
|
25
|
+
# SimpleCov.minimum_coverage 90
|
26
|
+
|
27
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
28
|
+
# in spec/support/ and its subdirectories.
|
29
|
+
Dir['./spec/support/**/*.rb'].each { |f| require f }
|
30
|
+
|
31
|
+
RSpec.configure do |config|
|
32
|
+
config.include FactoryGirl::Syntax::Methods
|
33
|
+
config.include ServiceTemplate::RspecExtensions::ResponseHelpers
|
34
|
+
|
35
|
+
config.before(:suite) do
|
36
|
+
DatabaseCleaner.strategy = :transaction
|
37
|
+
DatabaseCleaner.clean_with(:truncation)
|
38
|
+
end
|
39
|
+
|
40
|
+
config.before(:each) do
|
41
|
+
DatabaseCleaner.start
|
42
|
+
end
|
43
|
+
|
44
|
+
config.after(:each) do
|
45
|
+
DatabaseCleaner.clean
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ServiceTemplate
|
2
|
+
module GrapeExtenders
|
3
|
+
def self.extended(modified_class)
|
4
|
+
# when extended, set the exceptions to handle
|
5
|
+
|
6
|
+
# if AR is being used, rescue from common AR errors
|
7
|
+
if defined?(::ActiveRecord)
|
8
|
+
modified_class.rescue_from ::ActiveRecord::RecordNotFound do |e|
|
9
|
+
err = ServiceTemplate::JsonError.new(:record_not_found, 'record not found')
|
10
|
+
ServiceTemplate::Logger.logger.debug ServiceTemplate::Logger.response(404, {}, err)
|
11
|
+
rack_response(err.to_json, 404)
|
12
|
+
end
|
13
|
+
modified_class.rescue_from ::ActiveRecord::RecordInvalid do |e|
|
14
|
+
err = ServiceTemplate::JsonError.new(:unprocessable_entity, e.message, e.record.errors.messages)
|
15
|
+
ServiceTemplate::Logger.logger.debug ServiceTemplate::Logger.response(422, {}, err)
|
16
|
+
rack_response(err.to_json, 422)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# if AASM is being used, rescue from invalid transitions
|
21
|
+
if defined?(::AASM)
|
22
|
+
modified_class.rescue_from ::AASM::InvalidTransition do |e|
|
23
|
+
err = ServiceTemplate::JsonError.new(:unprocessable_entity, e.message)
|
24
|
+
ServiceTemplate::Logger.logger.debug ServiceTemplate::Logger.response(422, {}, err)
|
25
|
+
rack_response(err.to_json, 422)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
if defined?(Grape)
|
2
|
+
module Grape
|
3
|
+
module ErrorFormatter
|
4
|
+
module Json
|
5
|
+
class << self
|
6
|
+
def call(message, backtrace, options = {}, env = nil)
|
7
|
+
result = message.is_a?(ServiceTemplate::JsonError) ? message : ServiceTemplate::JsonError.new(:api_error, message)
|
8
|
+
|
9
|
+
if (options[:rescue_options] || {})[:backtrace] && backtrace && !backtrace.empty?
|
10
|
+
result = result.to_h.merge(backtrace: backtrace)
|
11
|
+
end
|
12
|
+
MultiJson.dump(result)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|