gris 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.rspec +3 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +67 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +203 -0
- data/Guardfile +82 -0
- data/MIT-LICENSE +20 -0
- data/README.md +7 -0
- data/Rakefile +11 -0
- data/bin/gris +5 -0
- data/gris.gemspec +40 -0
- data/lib/gris.rb +37 -0
- data/lib/gris/cli.rb +71 -0
- data/lib/gris/deprecations.rb +9 -0
- data/lib/gris/deprecations/gris_setup.rb +14 -0
- data/lib/gris/generators.rb +3 -0
- data/lib/gris/generators/api_generator.rb +31 -0
- data/lib/gris/generators/migration_generator.rb +228 -0
- data/lib/gris/generators/scaffold_generator.rb +21 -0
- data/lib/gris/generators/templates/api/app/apis/%name_tableize%_endpoint.rb.tt +65 -0
- data/lib/gris/generators/templates/api/app/models/%name_underscore%.rb.tt +2 -0
- data/lib/gris/generators/templates/api/app/presenters/%name_tableize%_presenter.rb.tt +5 -0
- data/lib/gris/generators/templates/api/app/presenters/%name_underscore%_presenter.rb.tt +10 -0
- data/lib/gris/generators/templates/api/spec/apis/%name_tableize%_endpoint_spec.rb.tt +70 -0
- data/lib/gris/generators/templates/api/spec/fabricators/%name_tableize%_fabricator.rb.tt +2 -0
- data/lib/gris/generators/templates/api/spec/models/%name_underscore%_spec.rb.tt +7 -0
- data/lib/gris/generators/templates/create_table_migration/%migration_filename%.rb.tt +19 -0
- data/lib/gris/generators/templates/migration/%migration_filename%.rb.tt +39 -0
- data/lib/gris/generators/templates/scaffold/.Procfile.tt +1 -0
- data/lib/gris/generators/templates/scaffold/.env.test.tt +11 -0
- data/lib/gris/generators/templates/scaffold/.env.tt +10 -0
- data/lib/gris/generators/templates/scaffold/.gitignore.tt +11 -0
- data/lib/gris/generators/templates/scaffold/.rspec.tt +3 -0
- data/lib/gris/generators/templates/scaffold/.rubocop.yml +18 -0
- data/lib/gris/generators/templates/scaffold/.ruby-gemset.tt +1 -0
- data/lib/gris/generators/templates/scaffold/.ruby-version.tt +1 -0
- data/lib/gris/generators/templates/scaffold/Gemfile.tt +33 -0
- data/lib/gris/generators/templates/scaffold/README.md.tt +3 -0
- data/lib/gris/generators/templates/scaffold/Rakefile +9 -0
- data/lib/gris/generators/templates/scaffold/app.rb +57 -0
- data/lib/gris/generators/templates/scaffold/app/apis/application_endpoint.rb +9 -0
- data/lib/gris/generators/templates/scaffold/app/presenters/root_presenter.rb +20 -0
- data/lib/gris/generators/templates/scaffold/config.ru.tt +6 -0
- data/lib/gris/generators/templates/scaffold/config/database.yml.tt +19 -0
- data/lib/gris/generators/templates/scaffold/config/initializers/active_record.rb +4 -0
- data/lib/gris/generators/templates/scaffold/db/schema.rb +11 -0
- data/lib/gris/generators/templates/scaffold/public/errors/404.html +11 -0
- data/lib/gris/generators/templates/scaffold/public/errors/500.html +11 -0
- data/lib/gris/generators/templates/scaffold/spec/apis/cors_spec.rb +31 -0
- data/lib/gris/generators/templates/scaffold/spec/spec_helper.rb +26 -0
- data/lib/gris/generators/templates/scaffold/spec/support/app_helper.rb +3 -0
- data/lib/gris/grape_extensions/crud_helpers.rb +26 -0
- data/lib/gris/identity.rb +50 -0
- data/lib/gris/middleware/app_monitor.rb +17 -0
- data/lib/gris/output_formatters/paginated_presenter.rb +41 -0
- data/lib/gris/output_formatters/presenter.rb +15 -0
- data/lib/gris/rspec_extensions/response_helpers.rb +57 -0
- data/lib/gris/setup.rb +17 -0
- data/lib/gris/version.rb +38 -0
- data/lib/tasks/db.rake +81 -0
- data/lib/tasks/routes.rake +11 -0
- data/spec/generators/api_generator_spec.rb +76 -0
- data/spec/generators/migration_generator_spec.rb +96 -0
- data/spec/generators/scaffold_generator_spec.rb +119 -0
- data/spec/grape_extensions/crud_helpers_spec.rb +5 -0
- data/spec/identity_spec.rb +86 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/spec_generators_helper.rb +11 -0
- data/spec/version_spec.rb +40 -0
- metadata +426 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
class <%= name.classify.pluralize %>Endpoint < Grape::API
|
2
|
+
namespace :<%= name.underscore.tableize %> do
|
3
|
+
desc 'Get a list of <%= name.underscore.tableize %>'
|
4
|
+
params do
|
5
|
+
optional :ids, type: Array, desc: 'Array of <%= name.underscore %> ids'
|
6
|
+
optional :page, type: Integer, default: 1, desc: 'Current page.'
|
7
|
+
optional :size, type: Integer, default: 10, desc: 'Number of <%= name.underscore.tableize %> to return per page.'
|
8
|
+
end
|
9
|
+
get do
|
10
|
+
<%= name.underscore.tableize %> = params[:ids] ? <%= name.classify %>.where(id: params[:ids]) : <%= name.classify %>.all
|
11
|
+
present Kaminari.paginate_array(<%= name.underscore.tableize %>).page(params[:page]).per(params[:size]), with: <%= name.classify.pluralize %>Presenter
|
12
|
+
end
|
13
|
+
|
14
|
+
desc 'Create a new <%= name.underscore %>.'
|
15
|
+
params do
|
16
|
+
requires :<%= name.underscore %>, type: Hash do
|
17
|
+
# Use this requires block to whitelist params which
|
18
|
+
# may be updated via mass assignment at this endpoint.
|
19
|
+
#
|
20
|
+
# requires :name, type: String, default: false
|
21
|
+
# optional :category, type: String, default: false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
post do
|
25
|
+
create <%= name.classify %>, with: <%= name.classify %>Presenter, from: permitted_params[:<%= name.underscore %>]
|
26
|
+
end
|
27
|
+
|
28
|
+
desc 'Get an existing <%= name.underscore %>.'
|
29
|
+
params do
|
30
|
+
requires :id, desc: 'ID of the <%= name.underscore %>'
|
31
|
+
end
|
32
|
+
route_param :id do
|
33
|
+
desc 'Get an <%= name.underscore %>'
|
34
|
+
get do
|
35
|
+
<%= name.underscore %> = <%= name.classify %>.find params[:id]
|
36
|
+
present <%= name.underscore %>, with: <%= name.classify %>Presenter
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'Update an existing <%= name.underscore %>.'
|
41
|
+
params do
|
42
|
+
requires :id, type: String, desc: '<%= name.classify %> id.'
|
43
|
+
requires :<%= name.underscore %>, type: Hash do
|
44
|
+
# Use this requires block to whitelist params which
|
45
|
+
# may be updated via mass assignment at this endpoint.
|
46
|
+
#
|
47
|
+
# requires :name, type: String, default: false
|
48
|
+
# optional :category, type: String, default: false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
patch ':id' do
|
52
|
+
<%= name.underscore %> = <%= name.classify %>.find params[:id]
|
53
|
+
update <%= name.underscore %>, with: <%= name.classify %>Presenter, from: permitted_params[:<%= name.underscore %>]
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'Delete an existing <%= name.underscore %>.'
|
57
|
+
params do
|
58
|
+
requires :id, type: String, desc: '<%= name.classify %> id.'
|
59
|
+
end
|
60
|
+
delete ':id' do
|
61
|
+
<%= name.underscore %> = <%= name.classify %>.find params[:id]
|
62
|
+
delete <%= name.underscore %>, with: <%= name.classify %>Presenter
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module <%= name.classify %>Presenter
|
2
|
+
include Gris::Presenter
|
3
|
+
|
4
|
+
property :id, writeable: false, type: String, desc: '<%= name.classify %> unique ID.'
|
5
|
+
|
6
|
+
link :self do |opts|
|
7
|
+
request = Grape::Request.new(opts[:env])
|
8
|
+
"#{request.base_url}/<%= name.tableize %>/#{id}"
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe <%= name.classify.pluralize %>Endpoint do
|
4
|
+
include Rack::Test::Methods
|
5
|
+
include_context 'with a running app'
|
6
|
+
|
7
|
+
context '<%= name.tableize %>' do
|
8
|
+
before(:each) do
|
9
|
+
20.times do
|
10
|
+
Fabricate(:<%= name.underscore %>)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns 10 <%= name.tableize %> by default' do
|
15
|
+
get '/<%= name.tableize %>'
|
16
|
+
expect(response_code).to eq 200
|
17
|
+
expect_embedded_results_count_of 10, <%= name.classify %>
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns 2 <%= name.tableize %>' do
|
21
|
+
get '/<%= name.tableize %>?size=2'
|
22
|
+
expect(response_code).to eq 200
|
23
|
+
expect_embedded_results_count_of 2, <%= name.classify %>
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'returns pagination' do
|
27
|
+
get '/<%= name.tableize %>?size=2&page=2'
|
28
|
+
expect(response_code).to eq 200
|
29
|
+
expect(link_to_next[:href]).to eq 'http://example.org/<%= name.tableize %>?page=3&size=2'
|
30
|
+
expect(link_to_previous[:href]).to eq 'http://example.org/<%= name.tableize %>?page=1&size=2'
|
31
|
+
expect(link_to_self[:href]).to eq 'http://example.org/<%= name.tableize %>?page=2&size=2'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns all unique ids' do
|
35
|
+
get '/<%= name.tableize %>'
|
36
|
+
expect(response_code).to eq 200
|
37
|
+
expect(embedded_results(<%= name.classify %>).map { |s| s[:id] }.uniq.count).to eq 10
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context '<%= name.underscore %>' do
|
42
|
+
let(:<%= name.underscore %>1) { Fabricate(:<%= name.underscore %>) }
|
43
|
+
|
44
|
+
it 'creates a <%= name.underscore %>' do
|
45
|
+
post '/<%= name.tableize %>', <%= name.underscore %>: { replace: 'REPLACE ME' }
|
46
|
+
expect(response_code).to eq 201
|
47
|
+
expect(result[:id]).to_not be_blank
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns a <%= name.underscore %>' do
|
51
|
+
get "/<%= name.tableize %>/#{<%= name.underscore %>1.id}"
|
52
|
+
expect(response_code).to eq 200
|
53
|
+
expect(result[:id]).to eq <%= name.underscore %>1.id
|
54
|
+
expect(link_to_self[:href]).to eq "http://example.org/<%= name.tableize %>/#{<%= name.underscore %>1.id}"
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'updates a <%= name.underscore %>' do
|
58
|
+
patch "/<%= name.tableize %>/#{<%= name.underscore %>1.id}", <%= name.underscore %>: { replace: 'REPLACE ME' }
|
59
|
+
expect(response_code).to eq 200
|
60
|
+
expect(result[:id]).to eq <%= name.underscore %>1.id
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'deletes a <%= name.underscore %>' do
|
64
|
+
expect_any_instance_of(<%= name.classify %>).to receive(:destroy)
|
65
|
+
delete "/<%= name.tableize %>/#{<%= name.underscore %>1.id}"
|
66
|
+
expect(response_code).to eq 200
|
67
|
+
expect(result[:id]).to eq <%= name.underscore %>1.id
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class <%= migration_name.camelize %> < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
|
+
<% attributes.each do |attribute| -%>
|
5
|
+
<% if attribute.password_digest? -%>
|
6
|
+
t.string :password_digest<%= attribute.inject_options %>
|
7
|
+
<% else -%>
|
8
|
+
t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
|
9
|
+
<% end -%>
|
10
|
+
<% end -%>
|
11
|
+
<% if options[:timestamps] %>
|
12
|
+
t.timestamps
|
13
|
+
<% end -%>
|
14
|
+
end
|
15
|
+
<% attributes_with_index.each do |attribute| -%>
|
16
|
+
add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
17
|
+
<% end -%>
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class <%= migration_name.camelize %> < ActiveRecord::Migration
|
2
|
+
<%- if migration_action == 'add' -%>
|
3
|
+
def change
|
4
|
+
<% attributes.each do |attribute| -%>
|
5
|
+
<%- if attribute.reference? -%>
|
6
|
+
add_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %>
|
7
|
+
<%- else -%>
|
8
|
+
add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %>
|
9
|
+
<%- if attribute.has_index? -%>
|
10
|
+
add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
11
|
+
<%- end -%>
|
12
|
+
<%- end -%>
|
13
|
+
<%- end -%>
|
14
|
+
end
|
15
|
+
<%- elsif migration_action == 'join' -%>
|
16
|
+
def change
|
17
|
+
create_join_table :<%= join_tables.first %>, :<%= join_tables.second %> do |t|
|
18
|
+
<%- attributes.each do |attribute| -%>
|
19
|
+
<%= '# ' unless attribute.has_index? -%>t.index <%= attribute.index_name %><%= attribute.inject_index_options %>
|
20
|
+
<%- end -%>
|
21
|
+
end
|
22
|
+
end
|
23
|
+
<%- else -%>
|
24
|
+
def change
|
25
|
+
<% attributes.each do |attribute| -%>
|
26
|
+
<%- if migration_action -%>
|
27
|
+
<%- if attribute.reference? -%>
|
28
|
+
remove_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %>
|
29
|
+
<%- else -%>
|
30
|
+
<%- if attribute.has_index? -%>
|
31
|
+
remove_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
32
|
+
<%- end -%>
|
33
|
+
remove_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %>
|
34
|
+
<%- end -%>
|
35
|
+
<%- end -%>
|
36
|
+
<%- end -%>
|
37
|
+
end
|
38
|
+
<%- end -%>
|
39
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
web: bundle exec puma -p $PORT -e $RACK_ENV -t 0:5
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Uncomment when using Gris::Middleware::Authentication
|
2
|
+
# HEADER_PASSWORD=''
|
3
|
+
|
4
|
+
SERVICE_NAME=<%= app_name %>
|
5
|
+
RACK_ENV=test
|
6
|
+
|
7
|
+
DATABASE_USER=''
|
8
|
+
DATABASE_PASSWORD=''
|
9
|
+
DATABASE_HOST=localhost
|
10
|
+
DATABASE_NAME=<%= app_name.underscore %>_test
|
11
|
+
BASE_URL=http://127.0.0.1:9393
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Uncomment when using Gris::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
|
10
|
+
BASE_URL=http://127.0.0.1:9292
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= app_name %>
|
@@ -0,0 +1 @@
|
|
1
|
+
2.1.5
|
@@ -0,0 +1,33 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
ruby '2.1.5'
|
3
|
+
|
4
|
+
gem 'rack-cors'
|
5
|
+
gem 'pg'
|
6
|
+
gem 'activerecord', '~> 4.2.0', require: 'active_record'
|
7
|
+
gem 'json'
|
8
|
+
|
9
|
+
gem 'gris'
|
10
|
+
|
11
|
+
gem 'roar'
|
12
|
+
gem 'grape-roar', '~> 0.3.0'
|
13
|
+
gem 'grape-swagger'
|
14
|
+
gem 'kaminari', '~> 0.16.2', require: 'kaminari/grape'
|
15
|
+
gem 'puma'
|
16
|
+
|
17
|
+
group :development, :test do
|
18
|
+
gem 'pry'
|
19
|
+
end
|
20
|
+
|
21
|
+
group :development do
|
22
|
+
gem 'rubocop', require: false
|
23
|
+
gem 'shotgun', require: false
|
24
|
+
end
|
25
|
+
|
26
|
+
group :test do
|
27
|
+
gem 'fabrication'
|
28
|
+
gem 'rspec'
|
29
|
+
gem 'rack-test'
|
30
|
+
gem 'simplecov'
|
31
|
+
gem 'webmock'
|
32
|
+
gem 'database_cleaner'
|
33
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# load bundler
|
2
|
+
require 'bundler/setup'
|
3
|
+
Bundler.setup(:default)
|
4
|
+
|
5
|
+
require 'gris/setup'
|
6
|
+
Bundler.require(:default, Gris.env.to_sym)
|
7
|
+
require 'gris'
|
8
|
+
|
9
|
+
# load environment
|
10
|
+
Gris.load_environment
|
11
|
+
|
12
|
+
# autoload initalizers
|
13
|
+
Dir['./config/initializers/**/*.rb'].map { |file| require file }
|
14
|
+
|
15
|
+
# load middleware configs
|
16
|
+
Dir['./config/middleware/**/*.rb'].map { |file| require file }
|
17
|
+
|
18
|
+
# autoload app
|
19
|
+
relative_load_paths = %w(app/apis app/presenters app/models app/workers lib)
|
20
|
+
ActiveSupport::Dependencies.autoload_paths += relative_load_paths
|
21
|
+
|
22
|
+
module Application
|
23
|
+
class Service
|
24
|
+
def initialize
|
25
|
+
@filenames = ['', '.html', 'index.html', '/index.html']
|
26
|
+
@rack_static = ::Rack::Static.new(
|
27
|
+
-> { [404, {}, []] },
|
28
|
+
root: File.expand_path('../public', __FILE__),
|
29
|
+
urls: ['/']
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.instance
|
34
|
+
@instance ||= Rack::Builder.new do
|
35
|
+
use Rack::Cors do
|
36
|
+
allow do
|
37
|
+
origins '*'
|
38
|
+
resource '*', headers: :any, methods: :get
|
39
|
+
end
|
40
|
+
end
|
41
|
+
run Application::Service.new
|
42
|
+
end.to_app
|
43
|
+
end
|
44
|
+
|
45
|
+
def call(env)
|
46
|
+
response = ApplicationEndpoint.call(env)
|
47
|
+
# Render error pages or return API response
|
48
|
+
case response[0]
|
49
|
+
when 404, 500
|
50
|
+
content = @rack_static.call(env.merge('PATH_INFO' => "/errors/#{response[0]}.html"))
|
51
|
+
[response[0], content[1], content[2]]
|
52
|
+
else
|
53
|
+
response
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RootPresenter
|
2
|
+
include Roar::JSON::HAL
|
3
|
+
include Roar::Hypermedia
|
4
|
+
include Grape::Roar::Representer
|
5
|
+
|
6
|
+
link :self do |opts|
|
7
|
+
"#{base_url(opts)}"
|
8
|
+
end
|
9
|
+
|
10
|
+
link :health do |opts|
|
11
|
+
{ href: "#{base_url(opts)}/health" }
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def base_url(opts)
|
17
|
+
request = Grape::Request.new(opts[:env])
|
18
|
+
request.base_url
|
19
|
+
end
|
20
|
+
end
|