service_template 0.5.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.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rubocop.yml +23 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG.md +64 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +24 -0
  8. data/README.md +217 -0
  9. data/Rakefile +9 -0
  10. data/bin/service_template +5 -0
  11. data/lib/service_template.rb +55 -0
  12. data/lib/service_template/active_record_extensions/notifications_subscriber.rb +17 -0
  13. data/lib/service_template/active_record_extensions/seeder.rb +14 -0
  14. data/lib/service_template/active_record_extensions/stats.rb +37 -0
  15. data/lib/service_template/authentication.rb +8 -0
  16. data/lib/service_template/cli.rb +111 -0
  17. data/lib/service_template/deploy.rb +98 -0
  18. data/lib/service_template/gem_dependency.rb +37 -0
  19. data/lib/service_template/generators.rb +3 -0
  20. data/lib/service_template/generators/api_generator.rb +30 -0
  21. data/lib/service_template/generators/readme_generator.rb +47 -0
  22. data/lib/service_template/generators/scaffold_generator.rb +29 -0
  23. data/lib/service_template/generators/templates/api/app/apis/%name_tableize%_api.rb.tt +40 -0
  24. data/lib/service_template/generators/templates/api/app/models/%name_underscore%.rb.tt +2 -0
  25. data/lib/service_template/generators/templates/api/app/representers/%name_underscore%_representer.rb.tt +4 -0
  26. data/lib/service_template/generators/templates/api/spec/apis/%name_tableize%_api_spec.rb.tt +16 -0
  27. data/lib/service_template/generators/templates/api/spec/models/%name_underscore%_spec.rb.tt +9 -0
  28. data/lib/service_template/generators/templates/readme/README.md.tt +55 -0
  29. data/lib/service_template/generators/templates/readme/spec/docs/readme_spec.rb +7 -0
  30. data/lib/service_template/generators/templates/scaffold/.env.development.tt +9 -0
  31. data/lib/service_template/generators/templates/scaffold/.env.test.tt +10 -0
  32. data/lib/service_template/generators/templates/scaffold/.gitignore.tt +13 -0
  33. data/lib/service_template/generators/templates/scaffold/.rubocop.yml +24 -0
  34. data/lib/service_template/generators/templates/scaffold/.ruby-version.tt +1 -0
  35. data/lib/service_template/generators/templates/scaffold/Gemfile.tt +29 -0
  36. data/lib/service_template/generators/templates/scaffold/README.md +3 -0
  37. data/lib/service_template/generators/templates/scaffold/Rakefile +21 -0
  38. data/lib/service_template/generators/templates/scaffold/app.rb +19 -0
  39. data/lib/service_template/generators/templates/scaffold/app/apis/application_api.rb +9 -0
  40. data/lib/service_template/generators/templates/scaffold/app/apis/hello_api.rb.tt +10 -0
  41. data/lib/service_template/generators/templates/scaffold/config.ru.tt +21 -0
  42. data/lib/service_template/generators/templates/scaffold/config/database.yml.tt +19 -0
  43. data/lib/service_template/generators/templates/scaffold/config/initializers/active_record.rb +5 -0
  44. data/lib/service_template/generators/templates/scaffold/db/schema.rb +11 -0
  45. data/lib/service_template/generators/templates/scaffold/lib/.keep +0 -0
  46. data/lib/service_template/generators/templates/scaffold/log/.keep +0 -0
  47. data/lib/service_template/generators/templates/scaffold/spec/apis/hello_api_spec.rb.tt +17 -0
  48. data/lib/service_template/generators/templates/scaffold/spec/factories/.gitkeep +0 -0
  49. data/lib/service_template/generators/templates/scaffold/spec/spec_helper.rb +47 -0
  50. data/lib/service_template/grape_extenders.rb +30 -0
  51. data/lib/service_template/grape_extensions/error_formatter.rb +18 -0
  52. data/lib/service_template/grape_extensions/grape_helpers.rb +27 -0
  53. data/lib/service_template/identity.rb +45 -0
  54. data/lib/service_template/json_error.rb +24 -0
  55. data/lib/service_template/logger/log_transaction.rb +17 -0
  56. data/lib/service_template/logger/logger.rb +42 -0
  57. data/lib/service_template/logger/parseable.rb +37 -0
  58. data/lib/service_template/middleware/app_monitor.rb +17 -0
  59. data/lib/service_template/middleware/authentication.rb +32 -0
  60. data/lib/service_template/middleware/database_stats.rb +15 -0
  61. data/lib/service_template/middleware/logger.rb +67 -0
  62. data/lib/service_template/middleware/request_stats.rb +42 -0
  63. data/lib/service_template/output_formatters/entity.rb +15 -0
  64. data/lib/service_template/output_formatters/include_nil.rb +16 -0
  65. data/lib/service_template/output_formatters/json_api_representer.rb +9 -0
  66. data/lib/service_template/param_sanitizer.rb +30 -0
  67. data/lib/service_template/rspec_extensions/response_helpers.rb +46 -0
  68. data/lib/service_template/setup.rb +36 -0
  69. data/lib/service_template/sortable_api.rb +17 -0
  70. data/lib/service_template/stats.rb +43 -0
  71. data/lib/service_template/stats_d_timer.rb +26 -0
  72. data/lib/service_template/version.rb +45 -0
  73. data/lib/tasks/deploy.rake +11 -0
  74. data/lib/tasks/routes.rake +11 -0
  75. data/service_template.gemspec +42 -0
  76. data/spec/active_record_extensions/filter_by_hash_spec.rb +23 -0
  77. data/spec/active_record_extensions/seeder_spec.rb +13 -0
  78. data/spec/authentication_spec.rb +17 -0
  79. data/spec/deprecations/application_api_spec.rb +19 -0
  80. data/spec/deprecations/entity_spec.rb +9 -0
  81. data/spec/deprecations/filter_by_hash_spec.rb +9 -0
  82. data/spec/deprecations/napa_setup_spec.rb +52 -0
  83. data/spec/generators/api_generator_spec.rb +63 -0
  84. data/spec/generators/migration_generator_spec.rb +105 -0
  85. data/spec/generators/readme_generator_spec.rb +35 -0
  86. data/spec/generators/scaffold_generator_spec.rb +90 -0
  87. data/spec/grape_extenders_spec.rb +50 -0
  88. data/spec/grape_extensions/error_formatter_spec.rb +29 -0
  89. data/spec/grape_extensions/include_nil_spec.rb +23 -0
  90. data/spec/identity_spec.rb +50 -0
  91. data/spec/json_error_spec.rb +33 -0
  92. data/spec/logger/log_transaction_spec.rb +34 -0
  93. data/spec/logger/logger_spec.rb +14 -0
  94. data/spec/logger/parseable_spec.rb +16 -0
  95. data/spec/middleware/authentication_spec.rb +54 -0
  96. data/spec/middleware/database_stats_spec.rb +64 -0
  97. data/spec/middleware/request_stats_spec.rb +21 -0
  98. data/spec/sortable_api_spec.rb +56 -0
  99. data/spec/spec_helper.rb +45 -0
  100. data/spec/stats_d_timer_spec.rb +23 -0
  101. data/spec/stats_spec.rb +66 -0
  102. data/spec/version_spec.rb +40 -0
  103. data/tasks/spec.rake +9 -0
  104. data/tasks/version.rake +51 -0
  105. metadata +456 -0
@@ -0,0 +1,2 @@
1
+ class <%= name.classify %> < ActiveRecord::Base
2
+ end
@@ -0,0 +1,4 @@
1
+ class <%= name.classify %>Representer < ServiceTemplate::Representer
2
+ property :id, type: String
3
+
4
+ end
@@ -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,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe <%= name.classify %> do
4
+
5
+ it 'needs tests to be written!' do
6
+ pending('write tests for <%= name.classify %>!')
7
+ end
8
+
9
+ 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,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'README' do
4
+ it 'has been filled out' do
5
+ pending 'Please fill out the sections that have a :bow:'
6
+ end
7
+ end
@@ -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,13 @@
1
+ .DS_Store
2
+ .env
3
+ .vagrant
4
+ .rspec
5
+ .env
6
+ !.env.test
7
+ !log/.keep
8
+ log/*
9
+ tmp/*
10
+ coverage
11
+ !.keep
12
+ .ruby-gemset
13
+ .ruby-version
@@ -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,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,3 @@
1
+ # Welcome to ServiceTemplate
2
+
3
+ TODO: Add an awesome README that explains how all this stuff works!
@@ -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,9 @@
1
+ class ApplicationApi < Grape::API
2
+ format :json
3
+ extend ServiceTemplate::GrapeExtenders
4
+
5
+ mount HelloApi => '/'
6
+
7
+ add_swagger_documentation
8
+ end
9
+
@@ -0,0 +1,10 @@
1
+ class HelloApi < Grape::API
2
+
3
+ resource :hello do
4
+ desc 'Return a Hello World message'
5
+ get do
6
+ { message: 'Hello Wonderful World, from <%= app_name.classify %>!' }
7
+ end
8
+ end
9
+
10
+ end
@@ -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.
@@ -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
@@ -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