schienenzeppelin 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 (117) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/main.yml +17 -0
  3. data/.github/workflows/outdated.yml +20 -0
  4. data/.gitignore +282 -0
  5. data/.rspec_status +3 -0
  6. data/.rubocop.yml +28 -0
  7. data/.tool-versions +1 -0
  8. data/CODE_OF_CONDUCT.md +84 -0
  9. data/GALLERY.md +29 -0
  10. data/Gemfile +13 -0
  11. data/Gemfile.lock +184 -0
  12. data/LICENSE +21 -0
  13. data/LICENSE.txt +21 -0
  14. data/README.md +174 -0
  15. data/Rakefile +12 -0
  16. data/TODO.md +32 -0
  17. data/bin/console +15 -0
  18. data/bin/setup +8 -0
  19. data/exe/sz +25 -0
  20. data/images/create.png +0 -0
  21. data/images/error.png +0 -0
  22. data/images/home.png +0 -0
  23. data/images/index.png +0 -0
  24. data/images/login.png +0 -0
  25. data/images/mobile.png +0 -0
  26. data/lib/schienenzeppelin.rb +18 -0
  27. data/lib/schienenzeppelin/app_builder.rb +88 -0
  28. data/lib/schienenzeppelin/app_generator.rb +95 -0
  29. data/lib/schienenzeppelin/helper_base.rb +28 -0
  30. data/lib/schienenzeppelin/helpers/annotate.rb +11 -0
  31. data/lib/schienenzeppelin/helpers/capistrano.rb +35 -0
  32. data/lib/schienenzeppelin/helpers/continuous_integration.rb +12 -0
  33. data/lib/schienenzeppelin/helpers/credentials.rb +49 -0
  34. data/lib/schienenzeppelin/helpers/devise.rb +45 -0
  35. data/lib/schienenzeppelin/helpers/errors.rb +67 -0
  36. data/lib/schienenzeppelin/helpers/factory_bot.rb +13 -0
  37. data/lib/schienenzeppelin/helpers/generators.rb +26 -0
  38. data/lib/schienenzeppelin/helpers/high_voltage.rb +11 -0
  39. data/lib/schienenzeppelin/helpers/home.rb +17 -0
  40. data/lib/schienenzeppelin/helpers/hotwire.rb +11 -0
  41. data/lib/schienenzeppelin/helpers/pundit.rb +12 -0
  42. data/lib/schienenzeppelin/helpers/rspec.rb +13 -0
  43. data/lib/schienenzeppelin/helpers/rubocop.rb +11 -0
  44. data/lib/schienenzeppelin/helpers/scaffold.rb +11 -0
  45. data/lib/schienenzeppelin/helpers/services.rb +11 -0
  46. data/lib/schienenzeppelin/helpers/sidekiq.rb +13 -0
  47. data/lib/schienenzeppelin/helpers/stimulus.rb +11 -0
  48. data/lib/schienenzeppelin/helpers/stimulus_components.rb +29 -0
  49. data/lib/schienenzeppelin/helpers/tailwind.rb +18 -0
  50. data/lib/schienenzeppelin/version.rb +7 -0
  51. data/schienenzeppelin.gemspec +37 -0
  52. data/schienenzeppelin.jpg +0 -0
  53. data/script.md +104 -0
  54. data/templates/.dockerignore.erb +51 -0
  55. data/templates/.entrypoint.sh.erb +16 -0
  56. data/templates/.env.development.erb +3 -0
  57. data/templates/.foreman.erb +1 -0
  58. data/templates/.github/workflows/build.yml.erb +49 -0
  59. data/templates/.gitignore.erb +285 -0
  60. data/templates/.irbrc.erb +12 -0
  61. data/templates/.rubocop.yml.erb +37 -0
  62. data/templates/.tool-versions.erb +1 -0
  63. data/templates/Capfile.erb +24 -0
  64. data/templates/Dockerfile.erb +45 -0
  65. data/templates/Gemfile.erb +122 -0
  66. data/templates/Procfile.dev.erb +6 -0
  67. data/templates/Procfile.erb +2 -0
  68. data/templates/README.md.erb +43 -0
  69. data/templates/app/controllers/authorized_controller.rb.erb +10 -0
  70. data/templates/app/controllers/errors_controller.rb.erb +24 -0
  71. data/templates/app/javascript/images/checkmark.svg +1 -0
  72. data/templates/app/javascript/images/logo.svg +1 -0
  73. data/templates/app/javascript/stylesheets/components.scss +206 -0
  74. data/templates/app/policies/application_policy.rb +55 -0
  75. data/templates/app/services/application_service.rb +14 -0
  76. data/templates/app/views/devise/confirmations/new.html.erb +24 -0
  77. data/templates/app/views/devise/passwords/edit.html.erb +34 -0
  78. data/templates/app/views/devise/passwords/new.html.erb +23 -0
  79. data/templates/app/views/devise/registrations/edit.html.erb +62 -0
  80. data/templates/app/views/devise/registrations/new.html.erb +45 -0
  81. data/templates/app/views/devise/sessions/new.html.erb +33 -0
  82. data/templates/app/views/devise/shared/_error_messages.html.erb +15 -0
  83. data/templates/app/views/devise/shared/_form_wrap.html.erb +5 -0
  84. data/templates/app/views/devise/shared/_links.html.erb +25 -0
  85. data/templates/app/views/devise/unlocks/new.html.erb +22 -0
  86. data/templates/app/views/errors/internal_error.html.erb +14 -0
  87. data/templates/app/views/errors/not_found.html.erb +14 -0
  88. data/templates/app/views/errors/unacceptable.html.erb +14 -0
  89. data/templates/app/views/layouts/application.html.erb.tt +30 -0
  90. data/templates/app/views/pages/home.html.erb.tt +20 -0
  91. data/templates/app/views/shared/_flashes.html.erb.tt +12 -0
  92. data/templates/app/views/shared/_footer.html.erb.tt +21 -0
  93. data/templates/app/views/shared/_navbar.html.erb.tt +40 -0
  94. data/templates/bin/setup.erb +146 -0
  95. data/templates/config/credentials.yml.erb +7 -0
  96. data/templates/config/initializers/high_voltage.rb +6 -0
  97. data/templates/config/initializers/lograge.rb +5 -0
  98. data/templates/config/initializers/sidekiq.rb +10 -0
  99. data/templates/config/postgresql.yml.erb +23 -0
  100. data/templates/docker-compose.yml.erb +21 -0
  101. data/templates/lib/capistrano/tasks/seeds.rake +12 -0
  102. data/templates/lib/capistrano/tasks/sidekiq.rake +36 -0
  103. data/templates/lib/generators/rails/navigation/USAGE +6 -0
  104. data/templates/lib/generators/rails/navigation/navigation_generator.rb +15 -0
  105. data/templates/lib/generators/rails/scaffold_controller_generator.rb +12 -0
  106. data/templates/lib/tasks/auto_annotate_models.rake +58 -0
  107. data/templates/lib/templates/erb/scaffold/_form.html.erb +39 -0
  108. data/templates/lib/templates/erb/scaffold/edit.html.erb +7 -0
  109. data/templates/lib/templates/erb/scaffold/index.html.erb +34 -0
  110. data/templates/lib/templates/erb/scaffold/new.html.erb +7 -0
  111. data/templates/lib/templates/erb/scaffold/show.html.erb +18 -0
  112. data/templates/public/500.html.erb +26 -0
  113. data/templates/spec/rails_helper.rb +26 -0
  114. data/templates/spec/spec_helper.rb +61 -0
  115. data/templates/spec/support/factory_bot.rb +5 -0
  116. data/templates/spec/support/shoulda_matchers.rb +8 -0
  117. metadata +179 -0
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
data/TODO.md ADDED
@@ -0,0 +1,32 @@
1
+
2
+ # TODO
3
+
4
+ ## Phase 2
5
+ - Schienenzeppelin Repo CI (notify gem releases, tests)
6
+ - Loads of testing
7
+ - Hide generators and scaffolds in sz gem, don't copy as templates. See JB, use railtie
8
+
9
+ ## Phase 3
10
+ - Make everything skippable, manage dependencies between items
11
+ - Take advantage of saved config (as rails new does)
12
+ - Licensing?
13
+ - Homepage & Newsletter
14
+ - Goodies for Business:
15
+ - Admin pages
16
+ - Social Logins
17
+ - Cloud Storage ?
18
+ - Payments
19
+ - Monitoring (Skylight, ...)
20
+ - Email Providers (Mailgun, ...)
21
+ - Reporting (Bugsnag, ...)
22
+ - Dockerfile
23
+ - https://dev.to/citronak/modern-rails-flash-messages-part-1-viewcomponent-stimulus-tailwind-css-3alm
24
+ - Configuration wizard via command line
25
+ - Alternative configurations:
26
+ - Differernt DB
27
+ - Different BG Jobs
28
+ - Different Deployment
29
+
30
+ - Additional Gems:
31
+ - Pagy
32
+ - Ansible repo setup if deploy is Capistrano
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'schienenzeppelin'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/sz ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'pathname'
5
+
6
+ source_path = File.expand_path("#{Pathname.new(__FILE__).dirname}/../lib")
7
+ $LOAD_PATH << source_path
8
+
9
+ require 'schienenzeppelin'
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 %w[-v --version].include? ARGV[0]
17
+ puts Schienenzeppelin::VERSION
18
+ exit 0
19
+ end
20
+
21
+ templates_root = File.expand_path(File.join('..', 'templates'), File.dirname(__FILE__))
22
+ Schienenzeppelin::AppGenerator.source_root templates_root
23
+ Schienenzeppelin::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root << templates_root
24
+
25
+ Schienenzeppelin::AppGenerator.start
data/images/create.png ADDED
Binary file
data/images/error.png ADDED
Binary file
data/images/home.png ADDED
Binary file
data/images/index.png ADDED
Binary file
data/images/login.png ADDED
Binary file
data/images/mobile.png ADDED
Binary file
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/command/base'
4
+ require 'rails/generators/app_base'
5
+ require 'rails/generators'
6
+ require 'rails/generators/app_name'
7
+ require 'rails/generators/rails/app/app_generator'
8
+ require 'bundler'
9
+
10
+ require_relative 'schienenzeppelin/version'
11
+ require_relative 'schienenzeppelin/helper_base'
12
+ Dir[File.join(__dir__, 'schienenzeppelin', 'helpers', '*.rb')].sort.each { |file| require file }
13
+ require_relative 'schienenzeppelin/app_generator'
14
+ require_relative 'schienenzeppelin/app_builder'
15
+
16
+ module Schienenzeppelin
17
+ class Error < StandardError; end
18
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ class AppBuilder < Rails::AppBuilder
5
+ def bin
6
+ super
7
+ template 'bin/setup.erb', 'bin/setup', force: true
8
+ end
9
+
10
+ def credentials
11
+ super
12
+ # This sets up credentials using a custom template for both development and production use
13
+ Schienenzeppelin::Helpers::Credentials.apply
14
+ end
15
+
16
+ def readme
17
+ template 'README.md.erb', 'README.md'
18
+ end
19
+
20
+ def ruby_version
21
+ template '.tool-versions.erb', '.tool-versions'
22
+ end
23
+
24
+ def gemfile
25
+ template 'Gemfile.erb', 'Gemfile'
26
+ end
27
+
28
+ def gitignore
29
+ template '.gitignore.erb', '.gitignore'
30
+ end
31
+
32
+ def irbrc
33
+ template '.irbrc.erb', '.irbrc'
34
+ end
35
+
36
+ def docker
37
+ template 'Dockerfile.erb', 'Dockerfile'
38
+ template '.dockerignore.erb', '.dockerignore'
39
+ template 'docker-compose.yml.erb', 'docker-compose.yml'
40
+ end
41
+
42
+ def dotenv
43
+ template '.env.development.erb', '.env.development'
44
+ end
45
+
46
+ def foreman
47
+ template '.foreman.erb', '.foreman'
48
+ template 'Procfile.erb', 'Procfile'
49
+ template 'Procfile.dev.erb', 'Procfile.dev'
50
+ end
51
+
52
+ def database_yml
53
+ if options[:database] == 'postgresql'
54
+ template 'config/postgresql.yml.erb', 'config/database.yml'
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ def lograge
61
+ template 'config/initializers/lograge.rb'
62
+ end
63
+
64
+ def sidekiq
65
+ Schienenzeppelin::Helpers::Sidekiq.apply
66
+ end
67
+
68
+ def pundit
69
+ Schienenzeppelin::Helpers::Pundit.apply
70
+ end
71
+
72
+ def rspec
73
+ Schienenzeppelin::Helpers::Rspec.apply
74
+ end
75
+
76
+ def shoulda
77
+ template 'spec/support/shoulda_matchers.rb'
78
+ end
79
+
80
+ def high_voltage
81
+ Schienenzeppelin::Helpers::HighVoltage.apply
82
+ end
83
+
84
+ def factory_bot
85
+ Schienenzeppelin::Helpers::FactoryBot.apply
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ class AppGenerator < Rails::Generators::AppGenerator
5
+ class_option :database,
6
+ type: :string,
7
+ aliases: '-d',
8
+ default: 'postgresql',
9
+ desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})"
10
+
11
+ class_option :skip_active_job,
12
+ type: :boolean, default: true,
13
+ desc: 'Skip Active Job'
14
+
15
+ class_option :skip_jbuilder,
16
+ type: :boolean,
17
+ default: true,
18
+ desc: 'Skip jbuilder gem'
19
+
20
+ class_option :skip_test,
21
+ type: :boolean,
22
+ aliases: '-T', default: true,
23
+ desc: 'Skip test files'
24
+
25
+ class_option :skip_sidekiq,
26
+ type: :boolean, default: false,
27
+ desc: 'Skip sidekiq'
28
+
29
+ class_option :skip_rspec,
30
+ type: :boolean,
31
+ aliases: '-T', default: false,
32
+ desc: 'Skip rspec'
33
+
34
+ def create_config_files
35
+ super
36
+ Schienenzeppelin::Helpers::Generators.apply
37
+ end
38
+
39
+ def create_root_files
40
+ super
41
+
42
+ build(:irbrc)
43
+ build(:foreman)
44
+ build(:dotenv)
45
+ build(:docker)
46
+ build(:docker_compose)
47
+ # TODO: Make optional
48
+ # Schienenzeppelin::Helpers::Rubocop.apply
49
+ end
50
+
51
+ def create_test_files
52
+ build(:test) unless options[:skip_test]
53
+ build(:rspec) unless options[:skip_rspec]
54
+ build(:factory_bot) unless options[:skip_factory_bot]
55
+ build(:shoulda) unless options[:skip_shoulda]
56
+ end
57
+
58
+ def finish_template
59
+ super
60
+ # These require the presence of config/controllers, so they must be done after everything else
61
+ Schienenzeppelin::Helpers::Annotate.apply
62
+ build(:lograge)
63
+ build(:high_voltage)
64
+ build(:pundit)
65
+ Schienenzeppelin::Helpers::Services.apply unless options[:skip_services]
66
+ build(:sidekiq)
67
+ end
68
+
69
+ def after_install
70
+ Schienenzeppelin::Helpers::Devise.apply
71
+ Schienenzeppelin::Helpers::Stimulus.apply
72
+ # TODO: Re-enable with Rails 6.2
73
+ # Schienenzeppelin::Helpers::Hotwire.apply
74
+ Schienenzeppelin::Helpers::Tailwind.apply
75
+ Schienenzeppelin::Helpers::StimulusComponents.apply
76
+
77
+ Schienenzeppelin::Helpers::Home.apply
78
+ Schienenzeppelin::Helpers::Errors.apply
79
+ Schienenzeppelin::Helpers::Scaffold.apply
80
+
81
+ Schienenzeppelin::Helpers::ContinuousIntegration.apply
82
+ Schienenzeppelin::Helpers::Capistrano.apply
83
+ end
84
+
85
+ def self.banner
86
+ "sz new #{arguments.map(&:usage).join(' ')} [options]"
87
+ end
88
+
89
+ protected
90
+
91
+ def get_builder_class
92
+ Schienenzeppelin::AppBuilder
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ class HelperBase < Rails::Generators::Base
5
+ include Thor::Actions
6
+ include Rails::Generators::Actions
7
+ include Rails::Generators::AppName
8
+
9
+ def self.apply(options = {})
10
+ new(options).apply
11
+ end
12
+
13
+ def initialize(options, *)
14
+ super
15
+ @options = options
16
+ end
17
+
18
+ private_class_method :new
19
+
20
+ def apply
21
+ raise NotImplementedError
22
+ end
23
+
24
+ def self.default_source_root
25
+ File.expand_path(File.join('..', '..', 'templates'), __dir__)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ module Helpers
5
+ class Annotate < HelperBase
6
+ def apply
7
+ template('lib/tasks/auto_annotate_models.rake', force: true)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ module Helpers
5
+ class Capistrano < HelperBase
6
+ def apply
7
+ say 'Installing and configuring Capistrano'
8
+ run('bundle exec cap install', capture: true)
9
+ directory('lib/capistrano', 'lib/capistrano')
10
+
11
+ configure_deploy
12
+
13
+ template('Capfile.erb', 'Capfile', force: true)
14
+ end
15
+
16
+ private
17
+
18
+ def configure_deploy
19
+ gsub_file('config/deploy.rb', /set :application, .+/, "set :application, '#{app_name}'")
20
+ uncomment_lines('config/deploy.rb', /set :deploy_to/)
21
+ gsub_file('config/deploy.rb', /set :deploy_to, .+"/, 'set :deploy_to, "/home/deploy/#{fetch :application}"') # rubocop:disable Lint/InterpolationCheck
22
+
23
+ uncomment_lines('config/deploy.rb', /set :keep_releases/)
24
+ uncomment_lines('config/deploy.rb', /append :linked_dirs/)
25
+ uncomment_lines('config/deploy.rb', /ask :branch/)
26
+ gsub_file('config/deploy.rb', /ask :branch/, 'set :branch')
27
+ append_to_file('config/deploy.rb') do
28
+ <<~RUBY
29
+ set :passenger_restart_with_sudo, true
30
+ RUBY
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ module Helpers
5
+ class ContinuousIntegration < HelperBase
6
+ def apply
7
+ say 'Setting up GitHub CI'
8
+ template('.github/workflows/build.yml.erb', '.github/workflows/build.yml')
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Schienenzeppelin
4
+ module Helpers
5
+ class Credentials < HelperBase
6
+ def apply
7
+ key_path = Pathname.new('config/credentials/production.key')
8
+ create_credential_files(key_path, 'config/credentials/production.yml.enc')
9
+ end
10
+
11
+ private
12
+
13
+ def create_credential_files(key_path, file_path)
14
+ key = ActiveSupport::EncryptedFile.generate_key
15
+ encryption_key_file_generator.add_key_file_silently(key_path, key)
16
+ require 'active_support/encrypted_file'
17
+ ActiveSupport::EncryptedFile.new(
18
+ content_path: file_path,
19
+ key_path: key_path,
20
+ env_key: 'RAILS_MASTER_KEY',
21
+ raise_if_missing_key: true
22
+ ).write(credentials_template)
23
+ end
24
+
25
+ def encryption_key_file_generator
26
+ require 'rails/generators/rails/encrypted_file/encrypted_file_generator'
27
+ Rails::Generators::EncryptionKeyFileGenerator.new
28
+ end
29
+
30
+ def credentials_template
31
+ context = instance_eval('binding', __FILE__, __LINE__)
32
+ source = File.expand_path(find_in_source_paths('config/credentials.yml.erb'))
33
+ match = ERB.version.match(/(\d+\.\d+\.\d+)/)
34
+ capturable_erb = capturable_erb(match, source)
35
+ capturable_erb.tap do |erb|
36
+ erb.filename = source
37
+ end.result(context)
38
+ end
39
+
40
+ def capturable_erb(match, source)
41
+ if match && match[1] >= '2.2.0' # Ruby 2.6+
42
+ CapturableERB.new(::File.binread(source), trim_mode: '-', eoutvar: '@output_buffer')
43
+ else
44
+ CapturableERB.new(::File.binread(source), nil, '-', '@output_buffer')
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end