schienenzeppelin 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/main.yml +17 -0
- data/.github/workflows/outdated.yml +20 -0
- data/.gitignore +282 -0
- data/.rspec_status +3 -0
- data/.rubocop.yml +28 -0
- data/.tool-versions +1 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/GALLERY.md +29 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +184 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +174 -0
- data/Rakefile +12 -0
- data/TODO.md +32 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/exe/sz +25 -0
- data/images/create.png +0 -0
- data/images/error.png +0 -0
- data/images/home.png +0 -0
- data/images/index.png +0 -0
- data/images/login.png +0 -0
- data/images/mobile.png +0 -0
- data/lib/schienenzeppelin.rb +18 -0
- data/lib/schienenzeppelin/app_builder.rb +88 -0
- data/lib/schienenzeppelin/app_generator.rb +95 -0
- data/lib/schienenzeppelin/helper_base.rb +28 -0
- data/lib/schienenzeppelin/helpers/annotate.rb +11 -0
- data/lib/schienenzeppelin/helpers/capistrano.rb +35 -0
- data/lib/schienenzeppelin/helpers/continuous_integration.rb +12 -0
- data/lib/schienenzeppelin/helpers/credentials.rb +49 -0
- data/lib/schienenzeppelin/helpers/devise.rb +45 -0
- data/lib/schienenzeppelin/helpers/errors.rb +67 -0
- data/lib/schienenzeppelin/helpers/factory_bot.rb +13 -0
- data/lib/schienenzeppelin/helpers/generators.rb +26 -0
- data/lib/schienenzeppelin/helpers/high_voltage.rb +11 -0
- data/lib/schienenzeppelin/helpers/home.rb +17 -0
- data/lib/schienenzeppelin/helpers/hotwire.rb +11 -0
- data/lib/schienenzeppelin/helpers/pundit.rb +12 -0
- data/lib/schienenzeppelin/helpers/rspec.rb +13 -0
- data/lib/schienenzeppelin/helpers/rubocop.rb +11 -0
- data/lib/schienenzeppelin/helpers/scaffold.rb +11 -0
- data/lib/schienenzeppelin/helpers/services.rb +11 -0
- data/lib/schienenzeppelin/helpers/sidekiq.rb +13 -0
- data/lib/schienenzeppelin/helpers/stimulus.rb +11 -0
- data/lib/schienenzeppelin/helpers/stimulus_components.rb +29 -0
- data/lib/schienenzeppelin/helpers/tailwind.rb +18 -0
- data/lib/schienenzeppelin/version.rb +7 -0
- data/schienenzeppelin.gemspec +37 -0
- data/schienenzeppelin.jpg +0 -0
- data/script.md +104 -0
- data/templates/.dockerignore.erb +51 -0
- data/templates/.entrypoint.sh.erb +16 -0
- data/templates/.env.development.erb +3 -0
- data/templates/.foreman.erb +1 -0
- data/templates/.github/workflows/build.yml.erb +49 -0
- data/templates/.gitignore.erb +285 -0
- data/templates/.irbrc.erb +12 -0
- data/templates/.rubocop.yml.erb +37 -0
- data/templates/.tool-versions.erb +1 -0
- data/templates/Capfile.erb +24 -0
- data/templates/Dockerfile.erb +45 -0
- data/templates/Gemfile.erb +122 -0
- data/templates/Procfile.dev.erb +6 -0
- data/templates/Procfile.erb +2 -0
- data/templates/README.md.erb +43 -0
- data/templates/app/controllers/authorized_controller.rb.erb +10 -0
- data/templates/app/controllers/errors_controller.rb.erb +24 -0
- data/templates/app/javascript/images/checkmark.svg +1 -0
- data/templates/app/javascript/images/logo.svg +1 -0
- data/templates/app/javascript/stylesheets/components.scss +206 -0
- data/templates/app/policies/application_policy.rb +55 -0
- data/templates/app/services/application_service.rb +14 -0
- data/templates/app/views/devise/confirmations/new.html.erb +24 -0
- data/templates/app/views/devise/passwords/edit.html.erb +34 -0
- data/templates/app/views/devise/passwords/new.html.erb +23 -0
- data/templates/app/views/devise/registrations/edit.html.erb +62 -0
- data/templates/app/views/devise/registrations/new.html.erb +45 -0
- data/templates/app/views/devise/sessions/new.html.erb +33 -0
- data/templates/app/views/devise/shared/_error_messages.html.erb +15 -0
- data/templates/app/views/devise/shared/_form_wrap.html.erb +5 -0
- data/templates/app/views/devise/shared/_links.html.erb +25 -0
- data/templates/app/views/devise/unlocks/new.html.erb +22 -0
- data/templates/app/views/errors/internal_error.html.erb +14 -0
- data/templates/app/views/errors/not_found.html.erb +14 -0
- data/templates/app/views/errors/unacceptable.html.erb +14 -0
- data/templates/app/views/layouts/application.html.erb.tt +30 -0
- data/templates/app/views/pages/home.html.erb.tt +20 -0
- data/templates/app/views/shared/_flashes.html.erb.tt +12 -0
- data/templates/app/views/shared/_footer.html.erb.tt +21 -0
- data/templates/app/views/shared/_navbar.html.erb.tt +40 -0
- data/templates/bin/setup.erb +146 -0
- data/templates/config/credentials.yml.erb +7 -0
- data/templates/config/initializers/high_voltage.rb +6 -0
- data/templates/config/initializers/lograge.rb +5 -0
- data/templates/config/initializers/sidekiq.rb +10 -0
- data/templates/config/postgresql.yml.erb +23 -0
- data/templates/docker-compose.yml.erb +21 -0
- data/templates/lib/capistrano/tasks/seeds.rake +12 -0
- data/templates/lib/capistrano/tasks/sidekiq.rake +36 -0
- data/templates/lib/generators/rails/navigation/USAGE +6 -0
- data/templates/lib/generators/rails/navigation/navigation_generator.rb +15 -0
- data/templates/lib/generators/rails/scaffold_controller_generator.rb +12 -0
- data/templates/lib/tasks/auto_annotate_models.rake +58 -0
- data/templates/lib/templates/erb/scaffold/_form.html.erb +39 -0
- data/templates/lib/templates/erb/scaffold/edit.html.erb +7 -0
- data/templates/lib/templates/erb/scaffold/index.html.erb +34 -0
- data/templates/lib/templates/erb/scaffold/new.html.erb +7 -0
- data/templates/lib/templates/erb/scaffold/show.html.erb +18 -0
- data/templates/public/500.html.erb +26 -0
- data/templates/spec/rails_helper.rb +26 -0
- data/templates/spec/spec_helper.rb +61 -0
- data/templates/spec/support/factory_bot.rb +5 -0
- data/templates/spec/support/shoulda_matchers.rb +8 -0
- metadata +179 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Schienenzeppelin
|
4
|
+
module Helpers
|
5
|
+
class Devise < HelperBase
|
6
|
+
def apply
|
7
|
+
generate('devise:install', capture: true)
|
8
|
+
generate(:devise, 'User', 'name', 'admin:boolean', capture: true)
|
9
|
+
directory('app/views/devise', 'app/views/devise')
|
10
|
+
|
11
|
+
inject_into_file 'config/environments/development.rb', before: /^end/ do
|
12
|
+
<<-RUBY
|
13
|
+
|
14
|
+
# Enable devise mailer
|
15
|
+
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
16
|
+
RUBY
|
17
|
+
end
|
18
|
+
|
19
|
+
gsub_file 'config/initializers/devise.rb', /# config.pepper = .+/, " # config.pepper = 'pepper'"
|
20
|
+
gsub_file 'config/initializers/devise.rb', /# config.secret_key = .+/, " # config.secret_key = 'secret_key'"
|
21
|
+
|
22
|
+
db_changes
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def db_changes
|
28
|
+
in_root do
|
29
|
+
migration = Dir.glob('db/migrate/*').max_by { |f| File.mtime(f) }
|
30
|
+
gsub_file migration, /:admin/, ':admin, default: false'
|
31
|
+
end
|
32
|
+
insert_into_file 'db/seeds.rb' do
|
33
|
+
<<~RUBY
|
34
|
+
# Create an initial admin user for development
|
35
|
+
User.find_or_create_by(email: "admin@admin.com") do |user|
|
36
|
+
user.name = 'Admin'
|
37
|
+
user.password = 'password'
|
38
|
+
user.admin = true
|
39
|
+
end
|
40
|
+
RUBY
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Schienenzeppelin
|
4
|
+
module Helpers
|
5
|
+
class Errors < HelperBase
|
6
|
+
def apply
|
7
|
+
say 'Setting up custom error pages'
|
8
|
+
add_errors
|
9
|
+
setup_public
|
10
|
+
add_routes
|
11
|
+
patch_turbolinks
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def setup_public
|
17
|
+
template('public/500.html.erb', 'public/500.html', force: true)
|
18
|
+
remove_file('public/404.html')
|
19
|
+
remove_file('public/422.html')
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_errors
|
23
|
+
directory('app/views/errors', 'app/views/errors')
|
24
|
+
template('app/controllers/errors_controller.rb.erb', 'app/controllers/errors_controller.rb')
|
25
|
+
inject_into_file 'config/application.rb', before: /^ {2}end\n/ do
|
26
|
+
<<-RUBY
|
27
|
+
# Enable custom error pages
|
28
|
+
config.exceptions_app = routes
|
29
|
+
RUBY
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_routes
|
34
|
+
inject_into_file 'config/routes.rb', before: /^end/ do
|
35
|
+
<<-RUBY
|
36
|
+
get '/404', to: 'errors#not_found'
|
37
|
+
get '/422', to: 'errors#unacceptable'
|
38
|
+
get '/500', to: 'errors#internal_error'
|
39
|
+
RUBY
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def patch_turbolinks
|
44
|
+
inject_into_file 'app/javascript/packs/application.js' do
|
45
|
+
<<~JS
|
46
|
+
// Patching turbolinks to allow custom errors
|
47
|
+
// See https://github.com/turbolinks/turbolinks/issues/179
|
48
|
+
window.Turbolinks.HttpRequest.prototype.requestLoaded = function() {
|
49
|
+
return this.endRequest(function() {
|
50
|
+
var code = this.xhr.status;
|
51
|
+
if (200 <= code && code < 300 ||
|
52
|
+
code === 403 || code === 404 || code === 500) {
|
53
|
+
this.delegate.requestCompletedWithResponse(
|
54
|
+
this.xhr.responseText,
|
55
|
+
this.xhr.getResponseHeader("Turbolinks-Location"));
|
56
|
+
} else {
|
57
|
+
this.failed = true;
|
58
|
+
this.delegate.requestFailedWithStatusCode(code, this.xhr.responseText);
|
59
|
+
}
|
60
|
+
}.bind(this));
|
61
|
+
};
|
62
|
+
JS
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Schienenzeppelin
|
4
|
+
module Helpers
|
5
|
+
class FactoryBot < HelperBase
|
6
|
+
def apply
|
7
|
+
# TODO: Make this work for minitest
|
8
|
+
empty_directory 'spec/factories'
|
9
|
+
template('spec/support/factory_bot.rb')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Schienenzeppelin
|
4
|
+
module Helpers
|
5
|
+
class Generators < HelperBase
|
6
|
+
def apply
|
7
|
+
directory('lib/generators', 'lib/generators')
|
8
|
+
generators = <<-RUBY
|
9
|
+
config.generators do |generate|
|
10
|
+
require_relative '../lib/generators/rails/scaffold_controller_generator'
|
11
|
+
generate.helper false
|
12
|
+
generate.javascripts false
|
13
|
+
generate.request_specs false
|
14
|
+
generate.routing_specs false
|
15
|
+
generate.stylesheets false
|
16
|
+
generate.test_framework :rspec
|
17
|
+
generate.view_specs false
|
18
|
+
generate.jb true
|
19
|
+
generate.factory_bot true
|
20
|
+
end
|
21
|
+
RUBY
|
22
|
+
inject_into_file 'config/application.rb', generators, before: /^ {2}end\n/
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Schienenzeppelin
|
4
|
+
module Helpers
|
5
|
+
class Home < HelperBase
|
6
|
+
def apply
|
7
|
+
say 'Setting up custom landing page'
|
8
|
+
directory 'app/views/layouts', 'app/views/layouts', force: true
|
9
|
+
directory 'app/views/pages', 'app/views/pages'
|
10
|
+
directory 'app/views/shared', 'app/views/shared'
|
11
|
+
# Make sure we can access any images put into the images folder
|
12
|
+
inject_into_file('app/javascript/packs/application.js', "require.context('../images', true)")
|
13
|
+
directory 'app/javascript/images', 'app/javascript/images'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Schienenzeppelin
|
4
|
+
module Helpers
|
5
|
+
class Pundit < HelperBase
|
6
|
+
def apply
|
7
|
+
directory 'app/policies', 'app/policies'
|
8
|
+
template 'app/controllers/authorized_controller.rb.erb', 'app/controllers/authorized_controller.rb'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Schienenzeppelin
|
4
|
+
module Helpers
|
5
|
+
class Rspec < HelperBase
|
6
|
+
def apply
|
7
|
+
create_file('.rspec', '--require spec_helper')
|
8
|
+
template('spec/rails_helper.rb')
|
9
|
+
template('spec/spec_helper.rb')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Schienenzeppelin
|
4
|
+
module Helpers
|
5
|
+
class StimulusComponents < HelperBase
|
6
|
+
def apply
|
7
|
+
run('yarn add tailwindcss-stimulus-components')
|
8
|
+
inject_into_file('app/javascript/packs/application.js') do
|
9
|
+
<<~JS
|
10
|
+
import { Application } from "stimulus"
|
11
|
+
import { definitionsFromContext } from "stimulus/webpack-helpers"
|
12
|
+
|
13
|
+
const application = Application.start();
|
14
|
+
const context = require.context("controllers", true, /.js$/);
|
15
|
+
application.load(definitionsFromContext(context));
|
16
|
+
|
17
|
+
import { Dropdown, Modal, Tabs, Popover, Toggle, Slideover } from "tailwindcss-stimulus-components"
|
18
|
+
application.register('dropdown', Dropdown)
|
19
|
+
application.register('modal', Modal)
|
20
|
+
application.register('tabs', Tabs)
|
21
|
+
application.register('popover', Popover)
|
22
|
+
application.register('toggle', Toggle)
|
23
|
+
application.register('slideover', Slideover)
|
24
|
+
JS
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Schienenzeppelin
|
4
|
+
module Helpers
|
5
|
+
class Tailwind < HelperBase
|
6
|
+
def apply
|
7
|
+
rails_command('tailwindcss:install')
|
8
|
+
template('app/javascript/stylesheets/components.scss')
|
9
|
+
insert_into_file 'app/javascript/stylesheets/application.scss' do
|
10
|
+
<<~CSS
|
11
|
+
|
12
|
+
@import "components";
|
13
|
+
CSS
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require_relative 'lib/schienenzeppelin/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'schienenzeppelin'
|
8
|
+
spec.version = Schienenzeppelin::VERSION
|
9
|
+
spec.authors = ['Hans-Jörg Schnedlitz']
|
10
|
+
spec.email = ['hans.schnedlitz@gmail.com']
|
11
|
+
spec.date = Date.today.strftime('%Y-%m-%d')
|
12
|
+
|
13
|
+
spec.summary = 'The Rails app generator that gets you started quickly'
|
14
|
+
spec.description = <<~HEREDOC
|
15
|
+
Schienenzeppelin is the Ruby on Rails app generator to get you started quickly. Includes TailwindCSS,
|
16
|
+
Devise, Capistrano and much more.
|
17
|
+
HEREDOC
|
18
|
+
spec.license = 'MIT'
|
19
|
+
spec.homepage = 'https://github.com/hschne/schienenzeppelin'
|
20
|
+
|
21
|
+
spec.required_ruby_version = Gem::Requirement.new(">= #{Schienenzeppelin::RUBY_VERSION}")
|
22
|
+
|
23
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
24
|
+
spec.metadata['source_code_uri'] = 'https://github.com/hschne/schienenzeppelin'
|
25
|
+
spec.metadata['changelog_uri'] = 'https://github.com/hschne/schienenzeppelin/CHANGELOG.md'
|
26
|
+
|
27
|
+
# Specify which files should be added to the gem when it is released.
|
28
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
29
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
30
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
31
|
+
end
|
32
|
+
spec.bindir = 'exe'
|
33
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
34
|
+
spec.require_paths = ['lib']
|
35
|
+
|
36
|
+
spec.add_dependency 'rails', Schienenzeppelin::RAILS_VERSION
|
37
|
+
end
|
Binary file
|
data/script.md
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
|
2
|
+
# Script
|
3
|
+
|
4
|
+
## Prep
|
5
|
+
|
6
|
+
- SSH agent eval
|
7
|
+
- Empty GH repo
|
8
|
+
- Reset local docker
|
9
|
+
- Droplet reset database (but make sure DB exists!)
|
10
|
+
- Make sure spring boot is not on
|
11
|
+
|
12
|
+
## Steps
|
13
|
+
|
14
|
+
When you start a new application with Rails, I usually spend ours adding things to make it production ready. From database configuration, to little
|
15
|
+
development tweaks, to thing like authentication and styling. Wouldn't it be nice if generating a new application gave you
|
16
|
+
all these things out of the box?
|
17
|
+
|
18
|
+
Schienenzeppelin was made to create a production ready app that you can deploy within minutes. And that's exactly what I'll show here.
|
19
|
+
|
20
|
+
After you've installed the gem, just run it to create a new application.
|
21
|
+
|
22
|
+
```bash
|
23
|
+
sz tweeter
|
24
|
+
```
|
25
|
+
|
26
|
+
This generates a new application, like rails new, but with some tweaks. The focus here is to get a nice looking, functional
|
27
|
+
application to production as quick as possible.
|
28
|
+
|
29
|
+
That includes
|
30
|
+
- Basic styling - using Tailwind
|
31
|
+
- Authentication using Devise
|
32
|
+
- A production ready database and credential setup
|
33
|
+
- And capistrano deployment out of the box
|
34
|
+
|
35
|
+
There are tons of little details and utilities included, I'll leave a link in the description for you to check out.
|
36
|
+
|
37
|
+
Now that that's done, let's have a look at what we got.
|
38
|
+
```bash
|
39
|
+
cd tweeter
|
40
|
+
```
|
41
|
+
|
42
|
+
Now the first nice thing is that although we depend on things like postgres and redis for example for Sidekiq, there's no need to install
|
43
|
+
any of that if you have docker and docker compose. Foreman start to start everything
|
44
|
+
```ruby
|
45
|
+
foreman start
|
46
|
+
```
|
47
|
+
We still have to do the usual first time setup
|
48
|
+
```
|
49
|
+
rails db:setup
|
50
|
+
rails db:migrate
|
51
|
+
```
|
52
|
+
Out of the box we get a responsive homepage, and devise integration, with custom views to boot. A seedfile is provided
|
53
|
+
to generate an admin user
|
54
|
+
```
|
55
|
+
rails db:seed
|
56
|
+
```
|
57
|
+
So we can login, and edit our profile if we want.
|
58
|
+
|
59
|
+
Let's add a new model and see how that looks.
|
60
|
+
```bash
|
61
|
+
rails g scaffold tweet
|
62
|
+
rails db:migrate
|
63
|
+
```
|
64
|
+
We can see that that generates a new link, and the scaffold is styled too.
|
65
|
+
|
66
|
+
That's dandy and all, let's deploy that thing. We have to edit some files for that.
|
67
|
+
```
|
68
|
+
vim config/deploy.rb
|
69
|
+
set :repo_url, "git@github.com:hschne/tweeter.git"
|
70
|
+
```
|
71
|
+
|
72
|
+
This assumes you already have set up a server. I'll also leave a link how to set one up.
|
73
|
+
```
|
74
|
+
vim config/production.rb
|
75
|
+
server "207.154.218.89", user: "deploy", roles: %w{app db web}
|
76
|
+
```
|
77
|
+
|
78
|
+
Before we can deploy, let's push our changes:
|
79
|
+
```
|
80
|
+
git add . && git commit -m "Initial commit"
|
81
|
+
git remote add origin git@github.com:hschne/tweeter.git
|
82
|
+
git branch -M main
|
83
|
+
git push -f -u origin main
|
84
|
+
```
|
85
|
+
|
86
|
+
And deploy
|
87
|
+
```
|
88
|
+
cap production deploy
|
89
|
+
```
|
90
|
+
|
91
|
+
Get secret key
|
92
|
+
|
93
|
+
```
|
94
|
+
cat config/credentials/production.key | xclip -sel clipboard
|
95
|
+
```
|
96
|
+
|
97
|
+
BREAK
|
98
|
+
|
99
|
+
Once that is finished, we can check out the deployed version.
|
100
|
+
|
101
|
+
And that is how you deploy a nice looking production ready app using Schienenzeppelin.
|
102
|
+
|
103
|
+
Let me know what you think, and have fun!
|
104
|
+
|