eivo-rails-api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/Gemfile +5 -0
  4. data/LICENSE +19 -0
  5. data/README.md +36 -0
  6. data/Rakefile +1 -0
  7. data/app/controllers/eivo/application_controller.rb +33 -0
  8. data/app/controllers/eivo/concerns/exception.rb +23 -0
  9. data/app/controllers/eivo/concerns/pagination.rb +34 -0
  10. data/app/controllers/eivo/concerns/rendering.rb +73 -0
  11. data/app/controllers/eivo/concerns/resource.rb +77 -0
  12. data/app/controllers/eivo/concerns/resources.rb +93 -0
  13. data/app/controllers/eivo/status_controller.rb +11 -0
  14. data/bin/eivo +5 -0
  15. data/config/initializers/sentry.rb +8 -0
  16. data/config/routes.rb +7 -0
  17. data/eivo-rails-api.gemspec +32 -0
  18. data/lib/eivo-rails-api/cli.rb +12 -0
  19. data/lib/eivo-rails-api/engine.rb +9 -0
  20. data/lib/eivo-rails-api/environments/development.rb +54 -0
  21. data/lib/eivo-rails-api/environments/production.rb +79 -0
  22. data/lib/eivo-rails-api/environments/staging.rb +11 -0
  23. data/lib/eivo-rails-api/environments/test.rb +44 -0
  24. data/lib/eivo-rails-api.rb +29 -0
  25. data/lib/generators/eivo/USAGE +3 -0
  26. data/lib/generators/eivo/install_generator.rb +101 -0
  27. data/lib/generators/eivo/templates/.env.example +5 -0
  28. data/lib/generators/eivo/templates/.ruby-version +1 -0
  29. data/lib/generators/eivo/templates/Gemfile +40 -0
  30. data/lib/generators/eivo/templates/Procfile +1 -0
  31. data/lib/generators/eivo/templates/app/controllers/application_controller.rb +2 -0
  32. data/lib/generators/eivo/templates/config/application.rb +16 -0
  33. data/lib/generators/eivo/templates/config/database.example.yml +24 -0
  34. data/lib/generators/eivo/templates/config/puma.rb +30 -0
  35. data/lib/generators/eivo/templates/db/migrate/enable_btree_gin_extension.rb +7 -0
  36. data/lib/generators/eivo/templates/db/migrate/enable_pg_stat_statements_extension.rb +7 -0
  37. data/lib/generators/eivo/templates/db/migrate/enable_pgcrypto_extension.rb +7 -0
  38. data/lib/generators/eivo/templates/db/migrate/enable_unaccent_extension.rb +7 -0
  39. metadata +194 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b7ca7376988bf2e7bd7449c8a267b327f228fcb3
4
+ data.tar.gz: f06a2a177096ce3a994a57d9705c98d3b7670e58
5
+ SHA512:
6
+ metadata.gz: 0949512009b53d64a9d76933fe023b223be8a2e1feeea589f720ed64cb2b1aa721253bfd1d1e5a1a5efec2889587c9c7bd4cddd759cc2f53cb1cc6fde984cb3f
7
+ data.tar.gz: 4675524835f20b9d248ddf31d442fb9dcc13b002afb31177605d68c75db50bd381fd856affacc88980d6d0b5826b970d9ddd808ddbd213f5ea8abc4be7de5b5e
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ /.bundle/
3
+ /pkg/
4
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2019 Jonathan VUKOVICH-TRIBOUHARET
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # EIVO Rails API
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'eivo-rails-api'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install eivo-rails-api -N
18
+
19
+ ## Usage
20
+
21
+ If you don't have a Ruby On Rails project:
22
+
23
+ $ rails new ../example/ -d postgresql --skip-yarn --skip-active-storage --skip-action-cable --skip-sprockets --skip-spring --skip-coffee --skip-javascript --skip-turbolinks --skip-test --skip-system-test --skip-bootsnap --skip-action-mailer --api
24
+
25
+ Then:
26
+
27
+ $ rails g eivo:install
28
+
29
+ Add missing credentials:
30
+
31
+ $ rails credentials:edit
32
+
33
+ ```
34
+ sentry:
35
+ dsn: ""
36
+ ```
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ class ApplicationController < ::ActionController::API
5
+
6
+ include EIVO::Concerns::Exception
7
+ include EIVO::Concerns::Rendering
8
+ include EIVO::Concerns::Pagination
9
+
10
+ # doesn't work
11
+ # rescue_from ::ActiveRecord::RecordNotFound, with: :render_not_found
12
+ # rescue_from ::ActionController::ParameterMissing, with: :render_parameter_missing
13
+ # rescue_from ::StandardError, with: :render_internal_server_error
14
+
15
+ def process_action(*args)
16
+ begin
17
+ super
18
+ rescue ::ActiveRecord::RecordNotFound => e
19
+ render_not_found(e)
20
+ rescue ::ActionController::ParameterMissing => e
21
+ render_parameter_missing(e)
22
+ rescue ::StandardError => e
23
+ if Rails.env.development?
24
+ raise e
25
+ else
26
+ ::Raven.capture_exception(exception)
27
+ end
28
+ render_internal_server_error(e)
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ module Concerns
5
+ module Exception
6
+
7
+ extend ::ActiveSupport::Concern
8
+
9
+ included do
10
+ before_action :set_exception_context
11
+ end
12
+
13
+ def set_exception_context
14
+ ::Raven.extra_context(
15
+ params: params.to_unsafe_h,
16
+ url: request.url,
17
+ request_id: request.request_id
18
+ )
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ module Concerns
5
+ module Pagination
6
+ extend ::ActiveSupport::Concern
7
+
8
+ def pagination_options(collection)
9
+ options = {
10
+ is_collection: true,
11
+ meta: {
12
+ total: collection.total_count,
13
+ pages: collection.total_pages
14
+ },
15
+ links: {
16
+ self: url_for(params.to_unsafe_h.merge({ page: collection.current_page })),
17
+ first: url_for(params.to_unsafe_h.merge({ page: 1 })),
18
+ last: url_for(params.to_unsafe_h.merge({ page: collection.total_pages })),
19
+ }
20
+ }
21
+
22
+ if !collection.out_of_range? && !collection.first_page?
23
+ options[:links][:prev] = url_for(params.to_unsafe_h.merge({ page: collection.prev_page }))
24
+ end
25
+ if !collection.out_of_range? && !collection.last_page?
26
+ options[:links][:next] = url_for(params.to_unsafe_h.merge({ page: collection.next_page }))
27
+ end
28
+
29
+ options
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ module Concerns
5
+ module Rendering
6
+
7
+ extend ::ActiveSupport::Concern
8
+
9
+ def render_success(serializer = nil)
10
+ if serializer
11
+ render json: serializer.serialized_json
12
+ else
13
+ data = {
14
+ data: nil
15
+ }
16
+ render json: ::MultiJson.dump(data)
17
+ end
18
+ end
19
+
20
+ def render_unauthorized(exception = nil)
21
+ render_error 'unauthorized', status: :unauthorized
22
+ end
23
+
24
+ def render_forbidden(exception = nil)
25
+ render_error 'forbidden', status: :forbidden
26
+ end
27
+
28
+ def render_not_found(exception = nil)
29
+ render_error 'not_found', status: :not_found
30
+ end
31
+
32
+ def render_internal_server_error(exception)
33
+ render_error 'internal_server_error', status: :internal_server_error
34
+ end
35
+
36
+ def render_parameter_missing(exception)
37
+ render_error 'parameter_missing', source: { parameter: exception.param }
38
+ end
39
+
40
+ def render_model_errors(errors)
41
+ json_errors = errors.details.map do |attribute, errors|
42
+ errors.map do |error|
43
+ {
44
+ code: error[:error],
45
+ source: {
46
+ parameter: attribute
47
+ },
48
+ status: ::Rack::Utils::SYMBOL_TO_STATUS_CODE[:bad_request].to_s
49
+ }
50
+ end
51
+ end
52
+
53
+ render_errors json_errors.flatten
54
+ end
55
+
56
+ def render_error(code, status: :bad_request, source: nil)
57
+ render_errors([{
58
+ code: code,
59
+ source: source,
60
+ status: ::Rack::Utils::SYMBOL_TO_STATUS_CODE[status].to_s
61
+ }.compact], status: status)
62
+ end
63
+
64
+ def render_errors(errors, status: :bad_request)
65
+ data = {
66
+ errors: errors
67
+ }
68
+ render json: ::MultiJson.dump(data), status: status
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ module Concerns
5
+ module Resource
6
+ extend ::ActiveSupport::Concern
7
+
8
+ included do
9
+ before_action :set_default_serializer_options
10
+ end
11
+
12
+ def show
13
+ @object ||= collection
14
+ render_success serializer.new(@object, @serializer_options)
15
+ end
16
+
17
+ def create
18
+ @object ||= collection.new(object_params_create)
19
+ if @object.save
20
+ render_success serializer.new(@object, @serializer_options)
21
+ else
22
+ render_model_errors @object.errors
23
+ end
24
+ end
25
+
26
+ def update
27
+ @object ||= collection
28
+ if @object.update(object_params_update)
29
+ render_success serializer.new(@object, @serializer_options)
30
+ else
31
+ render_model_errors @object.errors
32
+ end
33
+ end
34
+
35
+ def destroy
36
+ @object ||= collection
37
+
38
+ if @object.destroy
39
+ render_success
40
+ else
41
+ render_model_errors @object.errors
42
+ end
43
+ end
44
+
45
+ protected
46
+
47
+ def collection
48
+ raise NotImplementedError
49
+ end
50
+
51
+ def collection_index
52
+ collection
53
+ end
54
+
55
+ def serializer
56
+ raise NotImplementedError
57
+ end
58
+
59
+ def object_params
60
+ raise NotImplementedError
61
+ end
62
+
63
+ def object_params_create
64
+ object_params
65
+ end
66
+
67
+ def object_params_update
68
+ object_params
69
+ end
70
+
71
+ def set_default_serializer_options
72
+ @serializer_options ||= {}
73
+ end
74
+
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ module Concerns
5
+ module Resources
6
+ extend ::ActiveSupport::Concern
7
+
8
+ included do
9
+ before_action :set_default_serializer_options
10
+ end
11
+
12
+ def index
13
+ @objects ||= collection_index
14
+
15
+ unless ::ActiveModel::Type::Boolean.new.cast(params[:pagination]) == false
16
+ limit = 50
17
+ if params[:limit]
18
+ limit = [[params[:limit].to_i, 1].max, 500].min
19
+ end
20
+
21
+ @objects = @objects.page(params[:page]).per(limit)
22
+ @serializer_options.merge!(pagination_options(@objects))
23
+ end
24
+
25
+ render_success serializer.new(@objects, @serializer_options)
26
+ end
27
+
28
+ def show
29
+ @object ||= collection.find(params[:id])
30
+ render_success serializer.new(@object, @serializer_options)
31
+ end
32
+
33
+ def create
34
+ @object ||= collection.new(object_params_create)
35
+ if @object.save
36
+ render_success serializer.new(@object, @serializer_options)
37
+ else
38
+ render_model_errors @object.errors
39
+ end
40
+ end
41
+
42
+ def update
43
+ @object ||= collection.find(params[:id])
44
+ if @object.update(object_params_update)
45
+ render_success serializer.new(@object, @serializer_options)
46
+ else
47
+ render_model_errors @object.errors
48
+ end
49
+ end
50
+
51
+ def destroy
52
+ @object ||= collection.find(params[:id])
53
+
54
+ if @object.destroy
55
+ render_success
56
+ else
57
+ render_model_errors @object.errors
58
+ end
59
+ end
60
+
61
+ protected
62
+
63
+ def collection
64
+ raise NotImplementedError
65
+ end
66
+
67
+ def collection_index
68
+ collection
69
+ end
70
+
71
+ def serializer
72
+ raise NotImplementedError
73
+ end
74
+
75
+ def object_params
76
+ raise NotImplementedError
77
+ end
78
+
79
+ def object_params_create
80
+ object_params
81
+ end
82
+
83
+ def object_params_update
84
+ object_params
85
+ end
86
+
87
+ def set_default_serializer_options
88
+ @serializer_options ||= {}
89
+ end
90
+
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ class StatusController < ApplicationController
5
+
6
+ def index
7
+ render_success
8
+ end
9
+
10
+ end
11
+ end
data/bin/eivo ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'eivo-rails-api/cli'
4
+
5
+ EIVO::CLI.start
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'raven'
4
+
5
+ Raven.configure do |config|
6
+ config.environments = %w[ staging production ]
7
+ config.dsn = Rails.application.credentials.dig(:sentry, :dsn)
8
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ EIVO::Engine.routes.draw do
4
+ scope module: 'eivo' do
5
+ get :status, to: 'status#index'
6
+ end
7
+ end
@@ -0,0 +1,32 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'eivo-rails-api'
5
+ spec.version = '0.0.1'
6
+ spec.authors = ['Jonathan VUKOVICH-TRIBOUHARET']
7
+ spec.email = ['jonathan@eivo.co']
8
+
9
+ spec.summary = 'EIVO Rails API'
10
+ spec.description = 'EIVO Rails API'
11
+ spec.homepage = 'https://www.eivo.co'
12
+ spec.license = 'MIT'
13
+
14
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
15
+ `git ls-files -z`.split("\x0")
16
+ end
17
+ spec.executables << 'eivo'
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_dependency 'thor'
21
+
22
+ spec.add_dependency 'oj'
23
+ spec.add_dependency 'multi_json'
24
+ spec.add_dependency 'fast_jsonapi'
25
+
26
+ spec.add_dependency 'kaminari'
27
+
28
+ spec.add_dependency 'sentry-raven'
29
+
30
+ spec.add_development_dependency 'bundler'
31
+ spec.add_development_dependency 'rake'
32
+ end
@@ -0,0 +1,12 @@
1
+ require 'thor'
2
+
3
+ module EIVO
4
+ class CLI < Thor
5
+
6
+ desc 'install', 'Initialize default files'
7
+ def install(args = nil)
8
+ system("rails g eivo:install #{args}")
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ class Engine < ::Rails::Engine
5
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
6
+ inflect.acronym 'EIVO'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ class Environment
5
+ def self.development
6
+ Rails.application.configure do
7
+ # Settings specified here will take precedence over those in config/application.rb.
8
+
9
+ # In the development environment your application's code is reloaded on
10
+ # every request. This slows down response time but is perfect for development
11
+ # since you don't have to restart the web server when you make code changes.
12
+ config.cache_classes = false
13
+
14
+ # Do not eager load code on boot.
15
+ config.eager_load = false
16
+
17
+ # Show full error reports.
18
+ config.consider_all_requests_local = true
19
+
20
+ # Enable/disable caching. By default caching is disabled.
21
+ # Run rails dev:cache to toggle caching.
22
+ if Rails.root.join('tmp', 'caching-dev.txt').exist?
23
+ config.action_controller.perform_caching = true
24
+
25
+ config.cache_store = :memory_store
26
+ config.public_file_server.headers = {
27
+ 'Cache-Control' => "public, max-age=#{2.days.to_i}"
28
+ }
29
+ else
30
+ config.action_controller.perform_caching = false
31
+
32
+ config.cache_store = :null_store
33
+ end
34
+
35
+ # Print deprecation notices to the Rails logger.
36
+ config.active_support.deprecation = :log
37
+
38
+ # Raise an error on page load if there are pending migrations.
39
+ config.active_record.migration_error = :page_load
40
+
41
+ # Highlight code that triggered database queries in logs.
42
+ config.active_record.verbose_query_logs = true
43
+
44
+
45
+ # Raises error for missing translations
46
+ # config.action_view.raise_on_missing_translations = true
47
+
48
+ # Use an evented file watcher to asynchronously detect changes in source code,
49
+ # routes, locales, etc. This feature depends on the listen gem.
50
+ config.file_watcher = ActiveSupport::EventedFileUpdateChecker
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ class Environment
5
+ def self.production
6
+ Rails.application.configure do
7
+ # Settings specified here will take precedence over those in config/application.rb.
8
+
9
+ # Code is not reloaded between requests.
10
+ config.cache_classes = true
11
+
12
+ # Eager load code on boot. This eager loads most of Rails and
13
+ # your application in memory, allowing both threaded web servers
14
+ # and those relying on copy on write to perform better.
15
+ # Rake tasks automatically ignore this option for performance.
16
+ config.eager_load = true
17
+
18
+ # Full error reports are disabled and caching is turned on.
19
+ config.consider_all_requests_local = false
20
+ config.action_controller.perform_caching = true
21
+
22
+ # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"]
23
+ # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).
24
+ # config.require_master_key = true
25
+
26
+ # Disable serving static files from the `/public` folder by default since
27
+ # Apache or NGINX already handles this.
28
+ config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
29
+
30
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server.
31
+ # config.action_controller.asset_host = 'http://assets.example.com'
32
+
33
+ # Specifies the header that your server uses for sending files.
34
+ # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
35
+ config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
36
+
37
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
38
+ config.force_ssl = true
39
+
40
+ # Use the lowest log level to ensure availability of diagnostic information
41
+ # when problems arise.
42
+ config.log_level = :debug
43
+
44
+ # Prepend all log lines with the following tags.
45
+ config.log_tags = [ :request_id ]
46
+
47
+ # Use a different cache store in production.
48
+ # config.cache_store = :mem_cache_store
49
+
50
+ # Use a real queuing backend for Active Job (and separate queues per environment)
51
+ # config.active_job.queue_adapter = :resque
52
+ # config.active_job.queue_name_prefix = "example_#{Rails.env}"
53
+
54
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
55
+ # the I18n.default_locale when a translation cannot be found).
56
+ config.i18n.fallbacks = true
57
+
58
+ # Send deprecation notices to registered listeners.
59
+ config.active_support.deprecation = :notify
60
+
61
+ # Use default logging formatter so that PID and timestamp are not suppressed.
62
+ config.log_formatter = ::Logger::Formatter.new
63
+
64
+ # Use a different logger for distributed setups.
65
+ # require 'syslog/logger'
66
+ # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
67
+
68
+ if ENV["RAILS_LOG_TO_STDOUT"].present?
69
+ logger = ActiveSupport::Logger.new(STDOUT)
70
+ logger.formatter = config.log_formatter
71
+ config.logger = ActiveSupport::TaggedLogging.new(logger)
72
+ end
73
+
74
+ # Do not dump schema after migrations.
75
+ config.active_record.dump_schema_after_migration = false
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'production'
4
+
5
+ module EIVO
6
+ class Environment
7
+ def self.staging
8
+ production
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EIVO
4
+ class Environment
5
+ def self.test
6
+ Rails.application.configure do
7
+ # Settings specified here will take precedence over those in config/application.rb.
8
+
9
+ # The test environment is used exclusively to run your application's
10
+ # test suite. You never need to work with it otherwise. Remember that
11
+ # your test database is "scratch space" for the test suite and is wiped
12
+ # and recreated between test runs. Don't rely on the data there!
13
+ config.cache_classes = true
14
+
15
+ # Do not eager load code on boot. This avoids loading your whole application
16
+ # just for the purpose of running a single test. If you are using a tool that
17
+ # preloads Rails for running tests, you may have to set it to true.
18
+ config.eager_load = false
19
+
20
+ # Configure public file server for tests with Cache-Control for performance.
21
+ config.public_file_server.enabled = true
22
+ config.public_file_server.headers = {
23
+ 'Cache-Control' => "public, max-age=#{1.hour.to_i}"
24
+ }
25
+
26
+ # Show full error reports and disable caching.
27
+ config.consider_all_requests_local = true
28
+ config.action_controller.perform_caching = false
29
+
30
+ # Raise exceptions instead of rendering exception templates.
31
+ config.action_dispatch.show_exceptions = false
32
+
33
+ # Disable request forgery protection in test environment.
34
+ config.action_controller.allow_forgery_protection = false
35
+
36
+ # Print deprecation notices to the stderr.
37
+ config.active_support.deprecation = :stderr
38
+
39
+ # Raises error for missing translations
40
+ # config.action_view.raise_on_missing_translations = true
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'raven'
4
+
5
+ require 'oj'
6
+ require 'multi_json'
7
+ require 'fast_jsonapi'
8
+
9
+ require 'kaminari'
10
+
11
+ require_relative 'eivo-rails-api/engine'
12
+
13
+ module EIVO
14
+ class << self
15
+ def configure(application)
16
+ application.config.load_defaults 5.2
17
+ application.config.api_only = true
18
+
19
+ application.config.require_master_key = true
20
+
21
+ application.config.generators do |g|
22
+ g.orm :active_record, primary_key_type: :uuid
23
+ end
24
+
25
+ require_relative "eivo-rails-api/environments/#{Rails.env}"
26
+ EIVO::Environment.send(Rails.env)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ Initialize default files
2
+
3
+ rails g eivo:install
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ module EIVO
6
+ class InstallGenerator < Rails::Generators::Base
7
+ include Rails::Generators::Migration
8
+
9
+ source_root File.expand_path('../templates', __FILE__)
10
+
11
+ def self.namespace(name = nil)
12
+ @namespace ||= super.sub('e_i_v_o', 'eivo')
13
+ end
14
+
15
+ # Implement the required interface for Rails::Generators::Migration.
16
+ def self.next_migration_number(dirname)
17
+ next_migration_number = current_migration_number(dirname) + 1
18
+ ActiveRecord::Migration.next_migration_number(next_migration_number)
19
+ end
20
+
21
+ def create_initializer_file
22
+ @application = Rails.application.class.parent_name
23
+
24
+ remove_dir 'config/environments'
25
+
26
+ copy_file 'Gemfile'
27
+ copy_file 'Procfile'
28
+ copy_file '.env.example'
29
+ copy_file '.ruby-version'
30
+
31
+ create_restart_files
32
+
33
+ template 'config/application.rb'
34
+ copy_file 'config/puma.rb'
35
+ template 'config/database.example.yml'
36
+ template 'config/database.example.yml', 'config/database.yml', skip: true
37
+
38
+ copy_file 'app/controllers/application_controller.rb'
39
+
40
+ migration_template 'db/migrate/enable_pgcrypto_extension.rb', 'db/migrate/enable_pgcrypto_extension.rb', skip: true
41
+ migration_template 'db/migrate/enable_pg_stat_statements_extension.rb', 'db/migrate/enable_pg_stat_statements_extension.rb', skip: true
42
+ migration_template 'db/migrate/enable_btree_gin_extension.rb', 'db/migrate/enable_btree_gin_extension.rb', skip: true
43
+ migration_template 'db/migrate/enable_unaccent_extension.rb', 'db/migrate/enable_unaccent_extension.rb', skip: true
44
+
45
+ route "mount EIVO::Engine => '/'"
46
+ end
47
+
48
+ def create_restart_files
49
+ restart_code = <<-'EOF'
50
+ ### EIVO begin ###
51
+
52
+ bundle exec pumactl -F config/puma.rb restart
53
+
54
+ ### EIVO end ###
55
+ EOF
56
+
57
+ stop_code = <<-'EOF'
58
+ ### EIVO begin ###
59
+
60
+ bundle exec pumactl -F config/puma.rb stop
61
+
62
+ ### EIVO end ###
63
+ EOF
64
+
65
+ header_production = <<-'EOF'
66
+ #!/usr/bin/env bash
67
+ export RAILS_ENV="production"
68
+
69
+ EOF
70
+ header_staging = <<-'EOF'
71
+ #!/usr/bin/env bash
72
+ export RAILS_ENV="staging"
73
+
74
+ EOF
75
+
76
+ create_file 'restart_production.sh', header_production, skip: true
77
+ create_file 'stop_production.sh', header_production, skip: true
78
+ create_file 'restart_staging.sh', header_staging, skip: true
79
+ create_file 'stop_staging.sh', header_staging, skip: true
80
+
81
+ # Remove old code if present
82
+ regexp = /\n### EIVO begin ###.*### EIVO end ###/m
83
+ gsub_file 'restart_production.sh', regexp, ''
84
+ gsub_file 'restart_staging.sh', regexp, ''
85
+ gsub_file 'stop_production.sh', regexp, ''
86
+ gsub_file 'stop_staging.sh', regexp, ''
87
+
88
+ # Inject new code
89
+ inject_into_file 'restart_production.sh', restart_code, after: header_production
90
+ inject_into_file 'stop_production.sh', stop_code, after: header_production
91
+ inject_into_file 'restart_staging.sh', restart_code, after: header_staging
92
+ inject_into_file 'stop_staging.sh', stop_code, after: header_staging
93
+
94
+ chmod 'restart_production.sh', 0755
95
+ chmod 'stop_production.sh', 0755
96
+ chmod 'restart_staging.sh', 0755
97
+ chmod 'stop_staging.sh', 0755
98
+ end
99
+
100
+ end
101
+ end
@@ -0,0 +1,5 @@
1
+ WEB_CONCURRENCY="0"
2
+ RAILS_MAX_THREADS="5"
3
+ DB_POOL="5" # RAILS_MAX_THREADS
4
+ DB_STATEMENT_TIMEOUT="10000"
5
+ REDIS_URL="redis://localhost:6379/0"
@@ -0,0 +1 @@
1
+ ruby-2.6.3
@@ -0,0 +1,40 @@
1
+ source 'https://rubygems.org'
2
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
+
4
+ ruby '2.6.3'
5
+
6
+ gem 'rails', '~> 5.2.3'
7
+ gem 'pg', '>= 0.18', '< 2.0'
8
+ gem 'puma', '~> 3.11'
9
+
10
+ group :development, :test do
11
+ gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
12
+ end
13
+
14
+ group :development do
15
+ gem 'listen', '>= 3.0.5', '< 3.2'
16
+ end
17
+
18
+ gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
19
+
20
+ group :development, :test do
21
+ gem 'derailed_benchmarks'
22
+ gem 'factory_bot_rails'
23
+ gem 'faker'
24
+ gem 'rspec-rails'
25
+ gem 'brakeman'
26
+ gem 'rubocop'
27
+ gem 'rubocop-rspec'
28
+ gem 'webmock'
29
+ end
30
+
31
+ gem 'eivo-rails-api'
32
+
33
+ gem 'rack-cors'
34
+ gem 'jwt'
35
+
36
+ gem 'validates_email_format_of'
37
+ gem 'validates_phone_format_of'
38
+ gem 'validates_timeliness'
39
+
40
+ ### EIVO ###
@@ -0,0 +1 @@
1
+ web: bundle exec puma -C config/puma.rb
@@ -0,0 +1,2 @@
1
+ class ApplicationController < EIVO::ApplicationController
2
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'boot'
4
+
5
+ require 'rails'
6
+ require 'active_model/railtie'
7
+ require 'active_record/railtie'
8
+ require 'action_controller/railtie'
9
+
10
+ Bundler.require(*Rails.groups)
11
+
12
+ module <%= @application %>
13
+ class Application < Rails::Application
14
+ EIVO.configure(self)
15
+ end
16
+ end
@@ -0,0 +1,24 @@
1
+ default: &default
2
+ adapter: postgresql
3
+ encoding: unicode
4
+ pool: <%%= ENV.fetch('DB_POOL') { 5 } %>
5
+ host: db
6
+ username: postgres
7
+ variables:
8
+ statement_timeout: <%%= ENV.fetch('DB_STATEMENT_TIMEOUT') { 10000 } %>
9
+
10
+ development:
11
+ <<: *default
12
+ database: <%= @application.parameterize %>_development
13
+
14
+ test:
15
+ <<: *default
16
+ database: <%= @application.parameterize %>_test
17
+
18
+ staging:
19
+ <<: *default
20
+ database: <%= @application.parameterize %>_staging
21
+
22
+ production:
23
+ <<: *default
24
+ database: <%= @application.parameterize %>
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ workers ENV.fetch('WEB_CONCURRENCY') { 0 }
4
+ threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 }
5
+ threads threads_count, threads_count
6
+
7
+ environment ENV.fetch('RAILS_ENV') { "development" }
8
+
9
+ if ['production', 'staging'].include?(ENV['RAILS_ENV'])
10
+ bind 'unix://tmp/sockets/puma.sock'
11
+ pidfile 'tmp/pids/puma.pid'
12
+ state_path 'tmp/pids/puma.state'
13
+ daemonize true
14
+ else
15
+ port ENV.fetch('PORT') { 3000 }
16
+ end
17
+
18
+ before_fork do
19
+ ActiveRecord::Base.connection.disconnect!
20
+ end
21
+
22
+ on_worker_boot do
23
+ ActiveSupport.on_load(:active_record) do
24
+ ActiveRecord::Base.establish_connection
25
+ end
26
+ end
27
+
28
+ preload_app!
29
+
30
+ plugin :tmp_restart
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class EnableBtreeGinExtension < ActiveRecord::Migration[5.2]
4
+ def change
5
+ enable_extension 'btree_gin'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class EnablePgStatStatementsExtension < ActiveRecord::Migration[5.2]
4
+ def change
5
+ enable_extension 'pg_stat_statements'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class EnablePgcryptoExtension < ActiveRecord::Migration[5.2]
4
+ def change
5
+ enable_extension 'pgcrypto'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class EnableUnaccentExtension < ActiveRecord::Migration[5.2]
4
+ def change
5
+ enable_extension 'unaccent'
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,194 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eivo-rails-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jonathan VUKOVICH-TRIBOUHARET
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-06-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: oj
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: multi_json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: fast_jsonapi
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: kaminari
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sentry-raven
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: bundler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: EIVO Rails API
126
+ email:
127
+ - jonathan@eivo.co
128
+ executables:
129
+ - eivo
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - ".gitignore"
134
+ - Gemfile
135
+ - LICENSE
136
+ - README.md
137
+ - Rakefile
138
+ - app/controllers/eivo/application_controller.rb
139
+ - app/controllers/eivo/concerns/exception.rb
140
+ - app/controllers/eivo/concerns/pagination.rb
141
+ - app/controllers/eivo/concerns/rendering.rb
142
+ - app/controllers/eivo/concerns/resource.rb
143
+ - app/controllers/eivo/concerns/resources.rb
144
+ - app/controllers/eivo/status_controller.rb
145
+ - bin/eivo
146
+ - config/initializers/sentry.rb
147
+ - config/routes.rb
148
+ - eivo-rails-api.gemspec
149
+ - lib/eivo-rails-api.rb
150
+ - lib/eivo-rails-api/cli.rb
151
+ - lib/eivo-rails-api/engine.rb
152
+ - lib/eivo-rails-api/environments/development.rb
153
+ - lib/eivo-rails-api/environments/production.rb
154
+ - lib/eivo-rails-api/environments/staging.rb
155
+ - lib/eivo-rails-api/environments/test.rb
156
+ - lib/generators/eivo/USAGE
157
+ - lib/generators/eivo/install_generator.rb
158
+ - lib/generators/eivo/templates/.env.example
159
+ - lib/generators/eivo/templates/.ruby-version
160
+ - lib/generators/eivo/templates/Gemfile
161
+ - lib/generators/eivo/templates/Procfile
162
+ - lib/generators/eivo/templates/app/controllers/application_controller.rb
163
+ - lib/generators/eivo/templates/config/application.rb
164
+ - lib/generators/eivo/templates/config/database.example.yml
165
+ - lib/generators/eivo/templates/config/puma.rb
166
+ - lib/generators/eivo/templates/db/migrate/enable_btree_gin_extension.rb
167
+ - lib/generators/eivo/templates/db/migrate/enable_pg_stat_statements_extension.rb
168
+ - lib/generators/eivo/templates/db/migrate/enable_pgcrypto_extension.rb
169
+ - lib/generators/eivo/templates/db/migrate/enable_unaccent_extension.rb
170
+ homepage: https://www.eivo.co
171
+ licenses:
172
+ - MIT
173
+ metadata: {}
174
+ post_install_message:
175
+ rdoc_options: []
176
+ require_paths:
177
+ - lib
178
+ required_ruby_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ required_rubygems_version: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ requirements: []
189
+ rubyforge_project:
190
+ rubygems_version: 2.4.5
191
+ signing_key:
192
+ specification_version: 4
193
+ summary: EIVO Rails API
194
+ test_files: []