rsg 0.0.1

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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +13 -0
  3. data/.gitignore +11 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +14 -0
  6. data/Gemfile +13 -0
  7. data/Gemfile.lock +190 -0
  8. data/LICENSE +201 -0
  9. data/README.md +192 -0
  10. data/Rakefile +10 -0
  11. data/bin/console +12 -0
  12. data/bin/setup +8 -0
  13. data/exe/rsg +22 -0
  14. data/lib/rsg/generators/actions.rb +108 -0
  15. data/lib/rsg/generators/app/USAGE +14 -0
  16. data/lib/rsg/generators/app/app_builder.rb +42 -0
  17. data/lib/rsg/generators/app/app_generator.rb +80 -0
  18. data/lib/rsg/generators/app/templates/README.md.erb +22 -0
  19. data/lib/rsg/generators/base.rb +27 -0
  20. data/lib/rsg/generators/dotenv/install_generator.rb +24 -0
  21. data/lib/rsg/generators/dotenv/templates/env.development +2 -0
  22. data/lib/rsg/generators/dotenv/templates/env.test +2 -0
  23. data/lib/rsg/generators/gemfile/cleanup_generator.rb +28 -0
  24. data/lib/rsg/generators/install/install_generator.rb +13 -0
  25. data/lib/rsg/generators/logging/common_generator.rb +40 -0
  26. data/lib/rsg/generators/logging/lograge_generator.rb +31 -0
  27. data/lib/rsg/generators/logging/templates/initializer_lograge.rb +9 -0
  28. data/lib/rsg/generators/misc/misc_generator.rb +61 -0
  29. data/lib/rsg/generators/misc/templates/puma.rb +44 -0
  30. data/lib/rsg/generators/options.rb +15 -0
  31. data/lib/rsg/generators/orm/active_record_generator.rb +44 -0
  32. data/lib/rsg/generators/orm/templates/active_record/mysql.yml +59 -0
  33. data/lib/rsg/generators/orm/templates/active_record/postgresql.yml +86 -0
  34. data/lib/rsg/generators/orm/templates/active_record/sqlite3.yml +25 -0
  35. data/lib/rsg/generators/orm/templates/db.rake +7 -0
  36. data/lib/rsg/generators/orm/templates/samples.rb +10 -0
  37. data/lib/rsg/generators/orm/templates/seeds.rb +9 -0
  38. data/lib/rsg/generators/testing/rspec_generator.rb +33 -0
  39. data/lib/rsg/generators/webpacker/install_generator.rb +51 -0
  40. data/lib/rsg/generators/webpacker/templates/application.js +18 -0
  41. data/lib/rsg/generators/webpacker/templates/application.sass +19 -0
  42. data/lib/rsg/generators/webpacker/templates/landing_controller.rb.erb +6 -0
  43. data/lib/rsg/generators/webpacker/templates/landing_show.html.erb +8 -0
  44. data/lib/rsg/version.rb +4 -0
  45. data/lib/rsg.rb +36 -0
  46. data/rsg.gemspec +28 -0
  47. data/templates/README.md +4 -0
  48. data/templates/rsg-default.rb +17 -0
  49. metadata +109 -0
data/exe/rsg ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "pathname"
5
+
6
+ source_path = Pathname.new(__FILE__).dirname.join("../lib").expand_path
7
+ $LOAD_PATH << source_path
8
+
9
+ require "rsg"
10
+
11
+ if ARGV.empty?
12
+ puts "Please provide a path for the new application"
13
+ puts
14
+ puts "See --help for more info"
15
+ exit 0
16
+ elsif ["-v", "--version"].include? ARGV[0]
17
+ puts "RSG: #{RSG::VERSION}"
18
+ puts "Rails: #{Rails::VERSION}"
19
+ exit 0
20
+ end
21
+
22
+ Rsg::AppGenerator.start
@@ -0,0 +1,108 @@
1
+ require "json"
2
+ require "shellwords"
3
+
4
+ module Rsg
5
+ module Generators
6
+ module Actions
7
+ def rsg_install
8
+ append_gem "rsg",
9
+ within_group: %i(development test),
10
+ install: false,
11
+ path: options[:path]
12
+ end
13
+
14
+ def rsg_generate(name, quiet: false)
15
+ cmd = "generate #{name}"
16
+ cmd << " -q" if quiet
17
+
18
+ rails_command cmd
19
+ git_add_commit "RSG Generator executed: #{name}"
20
+ end
21
+
22
+ def rsg_apply_default!
23
+ rsg_apply "rsg-default"
24
+ end
25
+
26
+ def rsg_apply(template)
27
+ apply Rsg.lookup_app_template(template)
28
+ end
29
+
30
+ def api_mode?
31
+ return @api_mode if defined?(@api_mode)
32
+ @api_mode = !!(File.read("config/application.rb") =~ /^[^#]*config\.api_only = true[^\n]*$/)
33
+ end
34
+
35
+ def confirm?(prompt)
36
+ opts = { limited_to: %w(y n) }
37
+ ask(prompt, opts).downcase == 'y'
38
+ end
39
+
40
+ def git_add_commit(commit_msg)
41
+ truncated_msg = commit_msg.strip.gsub("\n", ' ')[0..59].strip
42
+ truncated_msg.gsub!(/.{3}$/, '...') if commit_msg.length > 60
43
+ say_status :run, "git add . && git commit -m \"#{truncated_msg}\""
44
+
45
+ run "git add .", verbose: false, capture: true
46
+ run "git commit -m #{Shellwords.escape(commit_msg)}", verbose: false, capture: true
47
+ end
48
+
49
+ def enable_railtie(name)
50
+ uncomment_lines "config/application.rb", /require ['"]#{name}\/railtie['"]/
51
+ end
52
+
53
+ def append_gem(gem_name, install: true, within_group: [], after: ["bootsnap", "rails"], **gem_line_params)
54
+ within_group = Array(within_group)
55
+ if within_group.any?
56
+ group_part = within_group.map { |g| "[:'\"]#{g}['\"]?" }.join(", ")
57
+ regex = /^ *group #{group_part} do\n(\s*(gem|#)[^\n]+\n)+ *end\n/
58
+ else
59
+ regex = /.+/m
60
+ end
61
+
62
+ gsub_file "Gemfile", regex do |match|
63
+ gem_line = build_gem_line(gem_name, gem_line_params)
64
+ append_gem_line(match, gem_line, after)
65
+ end
66
+
67
+ run("bundle install", capture: true) if install
68
+ end
69
+
70
+ private
71
+
72
+ def append_gem_line(code, gem_line, after)
73
+ code_lines = code.split("\n")
74
+ index = code_lines.length
75
+ indentation = ""
76
+
77
+ # Goes to the line above the `end` line by default
78
+ if code_lines[0] =~ /^([^#]*)group/
79
+ index -= 1
80
+ indentation = "#{$1} "
81
+ end
82
+
83
+ Array(after).each do |candidate|
84
+ idx = code_lines.index { |l| l =~ /^([^#]*)gem ['"]#{candidate}['"].*$/ }
85
+ next unless idx
86
+
87
+ indentation = $1
88
+ index = idx + 1
89
+ break
90
+ end
91
+
92
+ code_lines.insert(index, "#{indentation}#{gem_line}").join("\n") << "\n"
93
+ end
94
+
95
+ def build_gem_line(gem_name, params = {})
96
+ line = "gem '#{gem_name}'"
97
+ if params.key?(:version)
98
+ version_args = Array(params[:version]).map { |v| "'#{v}'" }.join(", ")
99
+ line << ", #{version_args}"
100
+ end
101
+ line << ", require: '#{params[:require]}'" if params.key?(:require)
102
+ line << ", group: #{params[:group]}" if params.key?(:group)
103
+ line << ", path: '#{params[:path]}'" if params[:path].present?
104
+ line
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,14 @@
1
+ Description:
2
+ RSG is a Rails app generator with Doximity's basic defaults configured.
3
+
4
+ For full details on the changes we've made compared to a vanilla Rails app, check
5
+ our GitHub project:
6
+ https://github.com/doximity/rsg
7
+
8
+ Example:
9
+ rsg ~/Code/weblog [options]
10
+
11
+ Is the equivalent of running `rails new ~/Code/weblog [options]` with most Rails
12
+ components disabled by default. This will generate a minimal Rails app in
13
+ ~/Code/weblog configured with our preferred defaults. Some questions might be
14
+ asked along the way to fine tune the generated app.
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rsg
4
+ # The application builder allows you to override elements of the application
5
+ # generator without being forced to reverse the operations of the default
6
+ # generator.
7
+ #
8
+ # This allows you to override entire operations, like the creation of the
9
+ # Gemfile, README, or JavaScript files, without needing to know exactly
10
+ # what those operations do so you can create another template action.
11
+ #
12
+ # For Rails 6.1, you can check out https://github.com/rails/rails/blob/6-1-stable/railties/lib/rails/generators/rails/app/app_generator.rb#L44
13
+ class AppBuilder < ::Rails::AppBuilder
14
+ def master_key
15
+ gsub_file "config/application.rb",
16
+ /^(\s*)(config\.load_defaults[^\n]+)\n$/,
17
+ "\\1\\2\n\n\\1# We don't use Rails encrypted secrets\n"\
18
+ "\\1config.require_master_key = false\n" \
19
+ "\\1config.active_support.use_authenticated_message_encryption = false\n"
20
+ end
21
+
22
+ ###########################################################################
23
+ # Simple template overwrites
24
+ ###########################################################################
25
+
26
+ def readme
27
+ template "README.md.erb", "README.md"
28
+ end
29
+
30
+ ###########################################################################
31
+ # Things to skip since we don't care about them
32
+ ###########################################################################
33
+
34
+ def ruby_version
35
+ # NOOP since we have the ruby version in Gemfile
36
+ end
37
+
38
+ def credentials
39
+ # NOOP since we store env vars / secrets elsewhere
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,80 @@
1
+ # require "rails/generators"
2
+ require "rails/generators/rails/app/app_generator"
3
+
4
+ require_relative "app_builder"
5
+
6
+ module Rsg
7
+ # AppGenerator is the entrypoint for generation of new apps which builds on
8
+ # top of the core `rails new` command
9
+ class AppGenerator < Rails::Generators::AppGenerator
10
+ include Generators::Actions
11
+
12
+ hide!
13
+
14
+ class_option :version, type: :boolean, aliases: "-v", group: :rsg, desc: "Show RSG version number and quit"
15
+ class_option :help, type: :boolean, aliases: "-h", group: :rsg, desc: "Show this help message and quit"
16
+ class_option :path, type: :string, default: nil, desc: "Path to the RSG gem"
17
+ class_option :template, aliases: "-m", type: :string, default: "rsg-default", desc: "Path to some application template (can be a filesystem path or URL)"
18
+
19
+ # --minimal might take care of some of these, but not all, we change all defaults here regardless since
20
+ # --minimal is subject to change with new releases. We also hide them all, and re-add things as necessary
21
+ # based on user input as generators kick in
22
+ class_option :skip_action_cable, type: :boolean, default: true, desc: "Skip Action Cable files", hide: true
23
+ class_option :skip_action_mailbox, type: :boolean, default: true, desc: "Skip Action Mailbox files", hide: true
24
+ class_option :skip_action_mailer, type: :boolean, default: true, desc: "Skip Action Mailer files", hide: true
25
+ class_option :skip_action_text, type: :boolean, default: true, desc: "Skip Action Text files", hide: true
26
+ class_option :skip_active_job, type: :boolean, default: true, desc: "Skip Active Job files", hide: true
27
+ class_option :skip_active_record, type: :boolean, default: true, desc: "Skip Active Record files", hide: true
28
+ class_option :skip_active_storage, type: :boolean, default: true, desc: "Skip Active Storage files", hide: true
29
+ class_option :skip_bundle, type: :boolean, default: true, desc: "Don't run bundle install", hide: true
30
+ class_option :skip_javascript, type: :boolean, default: true, desc: "Skip JavaScript files", hide: true
31
+ class_option :skip_jbuilder, type: :boolean, default: true, desc: "Skip jbuilder gem", hide: true
32
+ class_option :skip_keeps, type: :boolean, default: true, desc: "Skip Puma", hide: true
33
+ class_option :skip_spring, type: :boolean, default: true, desc: "Don't install Spring application preloader", hide: true
34
+ class_option :skip_sprockets, type: :boolean, default: true, desc: "Skip Sprockets files", hide: true
35
+ class_option :skip_system_test, type: :boolean, default: true, desc: "Skip system test files", hide: true
36
+ class_option :skip_test, type: :boolean, default: true, desc: "Skip Test Unit", hide: true
37
+ class_option :skip_turbolinks, type: :boolean, default: true, desc: "Skip turbolinks gem", hide: true
38
+ class_option :skip_webpack_install, type: :boolean, default: true, desc: "Don't run webpack install", hide: true
39
+
40
+ # Hide other flags, but leave their defaults untouched
41
+ class_option :database, type: :string, default: "sqlite3", desc: "Configure for selected database (options: #{DATABASES.join("/")})", hide: true
42
+ class_option :dev, type: :boolean, default: false, desc: "Set up the application with Gemfile pointing to your Rails checkout", hide: true
43
+ class_option :edge, type: :boolean, default: false, desc: "Set up the application with Gemfile pointing to Rails repository", hide: true
44
+ class_option :master, type: :boolean, default: false, desc: "Preconfigure a minimal rails app", hide: true
45
+ class_option :minimal, type: :boolean, default: false, desc: "Preconfigure a minimal rails app", hide: true
46
+ class_option :skip_bootsnap, type: :boolean, default: false, desc: "Skip bootsnap gem", hide: true
47
+ class_option :skip_collision_check, type: :boolean, default: false, desc: "Skip collision check", hide: true
48
+ class_option :skip_gemfile, type: :boolean, default: false, desc: "Don't create a Gemfile", hide: true
49
+ class_option :skip_git, type: :boolean, default: false, desc: "Skip .gitignore file", hide: true
50
+ class_option :skip_listen, type: :boolean, default: false, desc: "Don't generate configuration that depends on the listen gem", hide: true
51
+ class_option :skip_namespace, type: :boolean, default: false, desc: "Skip namespace (affects only isolated engines)", hide: true
52
+ class_option :skip_puma, type: :boolean, default: false, desc: "Skip Puma related files", hide: true
53
+ class_option :webpack, type: :string, desc: "Preconfigure Webpack with a particular framework (options: react, vue, angular, elm, stimulus)", hide: true
54
+
55
+ def self.banner
56
+ "rsg #{arguments.map(&:usage).join(" ")} [options]"
57
+ end
58
+
59
+ def self.source_paths
60
+ @__source_paths ||= [
61
+ Rails::Generators::AppGenerator.source_root,
62
+ Pathname.new(__FILE__).dirname.join("templates").expand_path
63
+ ]
64
+ end
65
+
66
+ def set_default_accessors!
67
+ bundled_template = Rsg.lookup_app_template(options[:template])
68
+ super
69
+ self.rails_template = bundled_template if bundled_template
70
+ end
71
+
72
+ protected
73
+
74
+ # rubocop:disable Naming/AccessorMethodName
75
+ def get_builder_class
76
+ Rsg::AppBuilder
77
+ end
78
+ # rubocop:enable Naming/AccessorMethodName
79
+ end
80
+ end
@@ -0,0 +1,22 @@
1
+ # <%= app_name.humanize %>
2
+
3
+ ```
4
+ TODO: Write a few words about what the app does
5
+ ```
6
+
7
+ ## Generated with RSG v<%= Rsg::VERSION %>
8
+
9
+ This is an application generated with [rsg](https://github.com/doximity/rsg). If you've skipped any of its
10
+ generators (like ActiveRecord's) or if you'd like to know what else is available for you to configure you
11
+ can run `rails generate --help | grep rsg`.
12
+
13
+ ## Getting Started
14
+
15
+ After you have cloned this repo, run this setup script to set up your machine
16
+ with the necessary dependencies to run and test this app:
17
+
18
+ % ./bin/setup
19
+
20
+ Then start the web server with:
21
+
22
+ % ./bin/rails server
@@ -0,0 +1,27 @@
1
+ require "pathname"
2
+ require "rails/generators"
3
+
4
+ module Rsg
5
+ module Generators
6
+ class Base < Rails::Generators::Base
7
+ include Actions
8
+ include Options
9
+
10
+ def self.inherited(base)
11
+ super
12
+
13
+ parts = base.namespace.split(":")
14
+ return unless parts[0] == "rsg"
15
+
16
+ parts = parts[1..-2] + ["templates"]
17
+ templates_path = Pathname.new(__FILE__).dirname.join(*parts).expand_path
18
+
19
+ base.source_paths << templates_path if templates_path.exist?
20
+ end
21
+
22
+ def self.exit_on_failure?
23
+ true
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "../base"
2
+
3
+ module Rsg
4
+ module Dotenv
5
+ class InstallGenerator < Rsg::Generators::Base
6
+ def banner
7
+ say "Configuring dotent-rails in development and test environments"
8
+ end
9
+
10
+ def add_dotenv
11
+ append_gem "dotenv-rails",
12
+ version: "< 3",
13
+ after: "rails",
14
+ group: [:development, :test],
15
+ require: "dotenv/rails-now"
16
+ end
17
+
18
+ def configure_dotenv
19
+ copy_file "env.development", ".env.development"
20
+ copy_file "env.test", ".env.test"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,2 @@
1
+ PORT="3000"
2
+ APP_URL="http://localhost:${PORT}"
@@ -0,0 +1,2 @@
1
+ PORT="3000"
2
+ APP_URL="http://test:${PORT}"
@@ -0,0 +1,28 @@
1
+ require_relative "../base"
2
+
3
+ module Rsg
4
+ module Gemfile
5
+ class CleanupGenerator < Rsg::Generators::Base
6
+ def banner
7
+ say "Cleaning up Gemfile"
8
+ end
9
+
10
+ def remove_comments
11
+ gsub_file "Gemfile", /^ *#\s*[^#\n]+\n/, ""
12
+ end
13
+
14
+ def remove_tzinfo
15
+ # Remove tzinfo-data since we don't have a need for it in dev / prod env
16
+ gsub_file "Gemfile", /\ngem 'tzinfo-data'[^\n]+\n/, ""
17
+ end
18
+
19
+ def remove_extra_whitespace
20
+ gsub_file "Gemfile", /^( *gem[^\n]+)\n\n\n/, "\\1\n\n"
21
+ end
22
+
23
+ def isolate_rails_gem
24
+ gsub_file "Gemfile", /^( *)(gem ["']rails["'][^\n]+)\n(?: *)(gem ['"]puma['"][^\n]+)\n$/, "\\1\\2\n\n\\3"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ require_relative "../base"
2
+
3
+ module Rsg
4
+ module Install
5
+ class InstallGenerator < Rsg::Generators::Base
6
+ class_option :path, type: :string, default: nil, desc: "Path to the RSG gem"
7
+
8
+ def add_rsg
9
+ install_rsg
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ require_relative "../base"
2
+
3
+ module Rsg
4
+ module Logging
5
+ class CommonGenerator < Rsg::Generators::Base
6
+ def banner
7
+ say "Improving basic logging configs"
8
+ end
9
+
10
+ def log_level_env_var
11
+ inject_into_file "config/application.rb", <<-CODE, before: /^ end$/
12
+ \n # Sane default log levels per env, but able to tweak with env var
13
+ # NOTE: Settings on config/environments/*.rb take precedence over this
14
+ config.log_level = ENV.fetch('LOG_LEVEL') { Rails.env.development? ? 'debug' : 'info' }.to_sym
15
+
16
+ # Log to stdout most of the time and allow use of JSON logs in dev by using an env var
17
+ config.x.log_to_stdout = %w[1 true yes].include?(ENV.fetch('RAILS_LOG_TO_STDOUT', '1'))
18
+ CODE
19
+ end
20
+
21
+ def stdout_logging_in_dev
22
+ inject_into_file "config/environments/development.rb", <<-CODE, before: /^end$/
23
+ \n # Configure stdout logging in dev as well
24
+ if config.x.log_to_stdout
25
+ logger = ActiveSupport::Logger.new(STDOUT)
26
+ logger.formatter = config.log_formatter
27
+ config.logger = ActiveSupport::TaggedLogging.new(logger)
28
+ end
29
+ CODE
30
+ end
31
+
32
+ def adjust_prod
33
+ comment_lines "config/environments/production.rb", /^(\s*)(config\.log_level .+)$/
34
+ gsub_file "config/environments/production.rb",
35
+ 'ENV["RAILS_LOG_TO_STDOUT"].present?',
36
+ "config.x.log_to_stdout"
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ require_relative "../base"
2
+
3
+ module Rsg
4
+ module Logging
5
+ class LogrageGenerator < Rsg::Generators::Base
6
+ def self.source_root
7
+ Pathname.new(__FILE__).dirname.join("templates").expand_path
8
+ end
9
+
10
+ def banner
11
+ say "Configuring lograge with JSON logging"
12
+ end
13
+
14
+ def add_lograge
15
+ append_gem "lograge", install: false
16
+ append_gem "logstash-event", after: "lograge"
17
+ end
18
+
19
+ def initializer
20
+ copy_file "initializer_lograge.rb", "config/initializers/logging.rb"
21
+ end
22
+
23
+ def json_logs_env_var
24
+ inject_into_file "config/application.rb", <<-CODE, before: /^ end$/
25
+ \n # Enable JSON logs with lograge
26
+ config.x.json_logs = Rails.env.production? || %w[1 true yes].include?(ENV.fetch('JSON_LOGS', '0'))
27
+ CODE
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,9 @@
1
+ Rails.application.configure do
2
+ return unless config.x.json_logs
3
+
4
+ # See https://github.com/roidrage/lograge for more information on how to configure the gem
5
+ # This only configures logs to be formatted as JSON when lograge is enabled but you can do much more with it,
6
+ # like annotating logs with user IDs
7
+ config.lograge.enabled = true
8
+ config.lograge.formatter = Lograge::Formatters::Logstash.new
9
+ end
@@ -0,0 +1,61 @@
1
+ require_relative "../base"
2
+
3
+ module Rsg
4
+ module Misc
5
+ class MiscGenerator < Generators::Base
6
+ def self.source_root
7
+ Pathname.new(__FILE__).dirname.join("templates").expand_path
8
+ end
9
+
10
+ def banner
11
+ say "Making some extra tweaks"
12
+ end
13
+
14
+ def disable_assets_generators
15
+ return if api_mode?
16
+
17
+ inject_into_file "config/application.rb", <<-CODE, before: /^\s*# Don't generate system test files./
18
+
19
+ # Don't generate CSS files when using scaffolding commands, since we compile assets through webpacker
20
+ config.generators.assets = false
21
+ config.generators.scaffold_stylesheet = false
22
+ config.generators.stylesheets = false
23
+
24
+ # Most of time we can get away with a handful of methods in the default application_helper. Other ones
25
+ # can be introduced as needed
26
+ config.generators.helper = false
27
+ CODE
28
+ end
29
+
30
+ def configure_pry
31
+ append_gem "pry-rails", within_group: :development
32
+ end
33
+
34
+ def remove_assets
35
+ run "rm -rf app/assets"
36
+ end
37
+
38
+ # TODO: Skip puma on app generator, introduce a new Puma::InstallGenerator
39
+ def puma_configs
40
+ copy_file "puma.rb", "config/puma.rb", force: true
41
+ end
42
+
43
+ # TODO: Move to an i18n generator that does this and more
44
+ def configure_environments
45
+ # If by any chance we make use of translations, let them fail and get
46
+ # caught early on the dev process
47
+ uncomment_lines "config/environments/development.rb", /raise_on_missing_translations/
48
+ uncomment_lines "config/environments/test.rb", /raise_on_missing_translations/
49
+ end
50
+
51
+ def healthcheck
52
+ inject_into_file "config/routes.rb", <<-CODE, before: "end"
53
+
54
+ # Defines a static healthcheck for probes. Please note that this won't
55
+ # output any logs in production
56
+ get :healthcheck, to: proc { [200, {}, ['OK']] }
57
+ CODE
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Puma can serve each request in a thread from an internal thread pool.
4
+ # The `threads` method setting takes two numbers: a minimum and maximum.
5
+ # Any libraries that use thread pools should be configured to match
6
+ # the maximum value specified for Puma. Default is set to 5 threads for minimum
7
+ # and maximum; this matches the default thread size of Active Record.
8
+ max_threads_count = ENV.fetch('RAILS_MAX_THREADS', 5)
9
+ min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count }
10
+ threads min_threads_count, max_threads_count
11
+
12
+ # Specifies the `worker_timeout` threshold that Puma will use to wait before
13
+ # terminating a worker in development environments.
14
+ # worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
15
+
16
+ # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
17
+ port ENV.fetch('PORT', 3000)
18
+
19
+ # Specifies the `environment` that Puma will run in.
20
+ # environment ENV.fetch("RAILS_ENV") { "development" }
21
+
22
+ # Specifies the `pidfile` that Puma will use.
23
+ # pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
24
+
25
+ # Specifies the number of `workers` to boot in clustered mode. Workers are
26
+ # forked web server processes. If using threads and workers together the
27
+ # concurrency of the application would be max `threads` * `workers`. Workers do
28
+ # not work on JRuby or Windows (both of which do not support processes).
29
+ #
30
+ # Here we disable workers by default since we tipically run our apps in
31
+ # containers, so we can scale the amount of processes by spinning up new
32
+ # containers to handle the load instead of having multiple processes running in
33
+ # the same container.
34
+ workers ENV.fetch('WEB_CONCURRENCY', 0)
35
+
36
+ # Use the `preload_app!` method when specifying a `workers` number.
37
+ # This directive tells Puma to first boot the application and load code
38
+ # before forking the application. This takes advantage of Copy On Write
39
+ # process behavior so workers use less memory.
40
+ #
41
+ # preload_app!
42
+
43
+ # Allow puma to be restarted by `rails restart` command.
44
+ plugin :tmp_restart
@@ -0,0 +1,15 @@
1
+ module Rsg
2
+ module Generators
3
+ module Options
4
+ def self.included(base)
5
+ configure_basic_options(base)
6
+ end
7
+
8
+ def self.configure_basic_options(base)
9
+ base.instance_eval do
10
+ class_option :quiet, type: :boolean, aliases: "-q", default: false, desc: "Suppress status output"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,44 @@
1
+ require_relative "../base"
2
+
3
+ module Rsg
4
+ module Orm
5
+ class ActiveRecordGenerator < Generators::Base
6
+ include Rails::Generators::Database
7
+
8
+ SUPPORTED_DBS = %w(sqlite3 mysql postgres)
9
+ class_option :database, type: :string, default: nil, desc: "Configure for selected database (options: #{SUPPORTED_DBS.join("/")})"
10
+
11
+ def self.source_root
12
+ Pathname.new(__FILE__).dirname.join("templates").expand_path
13
+ end
14
+
15
+ def banner
16
+ say "Configuring active record"
17
+ end
18
+
19
+ def enable_active_record
20
+ enable_railtie "active_record"
21
+ end
22
+
23
+ def configure_driver
24
+ database = options.fetch(:database) { ask("Which database you'd like to use?", limited_to: SUPPORTED_DBS, default: "sqlite3") }
25
+ template "active_record/#{database}.yml", "config/database.yml"
26
+
27
+ name, version = gem_for_database(database)
28
+ append_gem name, version: version
29
+ end
30
+
31
+ def write_db_sample
32
+ copy_file "db.rake", "lib/tasks/db.rake"
33
+ copy_file "seeds.rb", "db/seeds.rb"
34
+ copy_file "samples.rb", "db/samples.rb"
35
+ end
36
+
37
+ def migrate
38
+ return if no?("Would you like to create the database schema?")
39
+
40
+ rake "db:create db:migrate"
41
+ end
42
+ end
43
+ end
44
+ end