railties 7.1.3.4 → 7.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +177 -742
- data/lib/minitest/rails_plugin.rb +5 -2
- data/lib/rails/all.rb +1 -3
- data/lib/rails/api/task.rb +6 -4
- data/lib/rails/application/bootstrap.rb +5 -6
- data/lib/rails/application/configuration.rb +73 -38
- data/lib/rails/application/dummy_config.rb +2 -2
- data/lib/rails/application/finisher.rb +7 -0
- data/lib/rails/application.rb +15 -86
- data/lib/rails/backtrace_cleaner.rb +18 -3
- data/lib/rails/cli.rb +0 -1
- data/lib/rails/command.rb +1 -1
- data/lib/rails/commands/app/update_command.rb +93 -0
- data/lib/rails/commands/boot/boot_command.rb +14 -0
- data/lib/rails/commands/console/console_command.rb +2 -21
- data/lib/rails/commands/console/irb_console.rb +137 -0
- data/lib/rails/commands/credentials/credentials_command.rb +2 -2
- data/lib/rails/commands/dbconsole/dbconsole_command.rb +21 -30
- data/lib/rails/commands/devcontainer/devcontainer_command.rb +39 -0
- data/lib/rails/commands/rake/rake_command.rb +1 -1
- data/lib/rails/commands/runner/runner_command.rb +14 -3
- data/lib/rails/commands/server/server_command.rb +5 -3
- data/lib/rails/commands/test/test_command.rb +2 -0
- data/lib/rails/configuration.rb +10 -1
- data/lib/rails/console/app.rb +5 -32
- data/lib/rails/console/helpers.rb +5 -16
- data/lib/rails/console/methods.rb +23 -0
- data/lib/rails/engine.rb +5 -5
- data/lib/rails/gem_version.rb +3 -3
- data/lib/rails/generators/app_base.rb +70 -49
- data/lib/rails/generators/base.rb +5 -1
- data/lib/rails/generators/database.rb +227 -69
- data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
- data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
- data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
- data/lib/rails/generators/generated_attribute.rb +26 -1
- data/lib/rails/generators/migration.rb +3 -3
- data/lib/rails/generators/rails/app/app_generator.rb +53 -24
- data/lib/rails/generators/rails/app/templates/Dockerfile.tt +22 -15
- data/lib/rails/generators/rails/app/templates/Gemfile.tt +16 -16
- data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
- data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +8 -1
- data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
- data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
- data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
- data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
- data/lib/rails/generators/rails/app/templates/bin/setup.tt +6 -2
- data/lib/rails/generators/rails/app/templates/config/application.rb.tt +1 -1
- data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
- data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +7 -0
- data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +8 -1
- data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +3 -3
- data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +14 -7
- data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +5 -0
- data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +8 -5
- data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +70 -0
- data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +24 -26
- data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +4 -0
- data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +5 -0
- data/lib/rails/generators/rails/app/templates/dockerignore.tt +13 -0
- data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +138 -0
- data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
- data/lib/rails/generators/rails/app/templates/gitignore.tt +3 -3
- data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +66 -0
- data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
- data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
- data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
- data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
- data/lib/rails/generators/rails/controller/controller_generator.rb +1 -1
- data/lib/rails/generators/rails/db/system/change/change_generator.rb +131 -20
- data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +166 -0
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
- data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
- data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
- data/lib/rails/generators/rails/plugin/plugin_generator.rb +38 -7
- data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
- data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +5 -1
- data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
- data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
- data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
- data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
- data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
- data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
- data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
- data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
- data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +15 -1
- data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
- data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
- data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
- data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
- data/lib/rails/generators/testing/assertions.rb +20 -0
- data/lib/rails/generators/testing/behavior.rb +7 -6
- data/lib/rails/generators.rb +1 -1
- data/lib/rails/health_controller.rb +1 -1
- data/lib/rails/info.rb +2 -2
- data/lib/rails/mailers_controller.rb +14 -1
- data/lib/rails/paths.rb +2 -2
- data/lib/rails/pwa_controller.rb +15 -0
- data/lib/rails/rack/logger.rb +15 -7
- data/lib/rails/railtie/configurable.rb +2 -2
- data/lib/rails/railtie.rb +2 -3
- data/lib/rails/tasks/framework.rake +0 -26
- data/lib/rails/tasks/tmp.rake +1 -1
- data/lib/rails/templates/layouts/application.html.erb +1 -1
- data/lib/rails/templates/rails/mailers/email.html.erb +12 -8
- data/lib/rails/templates/rails/welcome/index.html.erb +4 -2
- data/lib/rails/test_help.rb +2 -4
- data/lib/rails/test_unit/reporter.rb +8 -2
- data/lib/rails/test_unit/runner.rb +26 -2
- data/lib/rails/test_unit/test_parser.rb +45 -0
- data/lib/rails.rb +7 -4
- metadata +42 -32
- data/lib/rails/app_updater.rb +0 -40
- data/lib/rails/commands/secrets/USAGE +0 -61
- data/lib/rails/commands/secrets/secrets_command.rb +0 -47
- data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +0 -54
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
- data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
- data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_1.rb.tt +0 -284
- data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
- data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
- data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
- data/lib/rails/ruby_version_check.rb +0 -17
- data/lib/rails/secrets.rb +0 -110
@@ -0,0 +1,166 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
|
5
|
+
module Rails
|
6
|
+
module Generators
|
7
|
+
class DevcontainerGenerator < Base # :nodoc:
|
8
|
+
class_option :app_name, type: :string, default: "rails_app",
|
9
|
+
desc: "Name of the app"
|
10
|
+
|
11
|
+
class_option :database, enum: Database::DATABASES, type: :string, default: "sqlite3",
|
12
|
+
desc: "Include configuration for selected database"
|
13
|
+
|
14
|
+
class_option :redis, type: :boolean, default: true,
|
15
|
+
desc: "Include configuration for Redis"
|
16
|
+
|
17
|
+
class_option :system_test, type: :boolean, default: true,
|
18
|
+
desc: "Include configuration for System Tests"
|
19
|
+
|
20
|
+
class_option :active_storage, type: :boolean, default: true,
|
21
|
+
desc: "Include configuration for Active Storage"
|
22
|
+
|
23
|
+
class_option :node, type: :boolean, default: false,
|
24
|
+
desc: "Include configuration for Node"
|
25
|
+
|
26
|
+
class_option :dev, type: :boolean, default: false,
|
27
|
+
desc: "For applications pointing to a local Rails checkout"
|
28
|
+
|
29
|
+
source_paths << File.expand_path(File.join(base_name, "app", "templates"), base_root)
|
30
|
+
|
31
|
+
def create_devcontainer
|
32
|
+
empty_directory ".devcontainer"
|
33
|
+
|
34
|
+
template "devcontainer/devcontainer.json", ".devcontainer/devcontainer.json"
|
35
|
+
template "devcontainer/Dockerfile", ".devcontainer/Dockerfile"
|
36
|
+
template "devcontainer/compose.yaml", ".devcontainer/compose.yaml"
|
37
|
+
end
|
38
|
+
|
39
|
+
def update_application_system_test_case
|
40
|
+
return unless options[:system_test]
|
41
|
+
return unless File.exist?("test/application_system_test_case.rb")
|
42
|
+
|
43
|
+
gsub_file("test/application_system_test_case.rb", /^\s*driven_by\b.*/, system_test_configuration)
|
44
|
+
end
|
45
|
+
|
46
|
+
def update_database_yml
|
47
|
+
# Only postgresql has devcontainer specific configuration, so only update database.yml if we are using postgres
|
48
|
+
return unless options[:database] == "postgresql"
|
49
|
+
|
50
|
+
template("config/databases/#{options[:database]}.yml", "config/database.yml")
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def devcontainer?
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
def app_name
|
59
|
+
options[:app_name]
|
60
|
+
end
|
61
|
+
|
62
|
+
def dependencies
|
63
|
+
return @dependencies if @dependencies
|
64
|
+
|
65
|
+
@dependencies = []
|
66
|
+
|
67
|
+
@dependencies << "selenium" if options[:system_test]
|
68
|
+
@dependencies << "redis" if options[:redis]
|
69
|
+
@dependencies << database.name if database.service
|
70
|
+
@dependencies
|
71
|
+
end
|
72
|
+
|
73
|
+
def container_env
|
74
|
+
return @container_env if @container_env
|
75
|
+
|
76
|
+
@container_env = {}
|
77
|
+
|
78
|
+
@container_env["CAPYBARA_SERVER_PORT"] = "45678" if options[:system_test]
|
79
|
+
@container_env["SELENIUM_HOST"] = "selenium" if options[:system_test]
|
80
|
+
@container_env["REDIS_URL"] = "redis://redis:6379/1" if options[:redis]
|
81
|
+
@container_env["DB_HOST"] = database.name if database.service
|
82
|
+
|
83
|
+
@container_env
|
84
|
+
end
|
85
|
+
|
86
|
+
def volumes
|
87
|
+
return @volumes if @volumes
|
88
|
+
|
89
|
+
@volumes = []
|
90
|
+
|
91
|
+
@volumes << "redis-data" if options[:redis]
|
92
|
+
@volumes << database.volume if database.volume
|
93
|
+
|
94
|
+
@volumes
|
95
|
+
end
|
96
|
+
|
97
|
+
def features
|
98
|
+
return @features if @features
|
99
|
+
|
100
|
+
@features = {
|
101
|
+
"ghcr.io/devcontainers/features/github-cli:1" => {}
|
102
|
+
}
|
103
|
+
|
104
|
+
@features["ghcr.io/rails/devcontainer/features/activestorage"] = {} if options[:active_storage]
|
105
|
+
@features["ghcr.io/devcontainers/features/node:1"] = {} if options[:node]
|
106
|
+
|
107
|
+
@features.merge!(database.feature) if database.feature
|
108
|
+
|
109
|
+
@features
|
110
|
+
end
|
111
|
+
|
112
|
+
def mounts
|
113
|
+
return @mounts if @mounts
|
114
|
+
|
115
|
+
@mounts = []
|
116
|
+
|
117
|
+
@mounts << local_rails_mount if options[:dev]
|
118
|
+
|
119
|
+
@mounts
|
120
|
+
end
|
121
|
+
|
122
|
+
def forward_ports
|
123
|
+
return @forward_ports if @forward_ports
|
124
|
+
|
125
|
+
@forward_ports = [3000]
|
126
|
+
@forward_ports << database.port if database.port
|
127
|
+
@forward_ports << 6379 if options[:redis]
|
128
|
+
|
129
|
+
@forward_ports
|
130
|
+
end
|
131
|
+
|
132
|
+
def database
|
133
|
+
@database ||= Database.build(options[:database])
|
134
|
+
end
|
135
|
+
|
136
|
+
def devcontainer_db_service_yaml(**options)
|
137
|
+
return unless service = database.service
|
138
|
+
|
139
|
+
{ database.name => service }.to_yaml(**options)[4..-1]
|
140
|
+
end
|
141
|
+
|
142
|
+
def local_rails_mount
|
143
|
+
{
|
144
|
+
type: "bind",
|
145
|
+
source: Rails::Generators::RAILS_DEV_PATH,
|
146
|
+
target: Rails::Generators::RAILS_DEV_PATH
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
def system_test_configuration
|
151
|
+
optimize_indentation(<<-'RUBY', 2)
|
152
|
+
if ENV["CAPYBARA_SERVER_PORT"]
|
153
|
+
served_by host: "rails-app", port: ENV["CAPYBARA_SERVER_PORT"]
|
154
|
+
|
155
|
+
driven_by :selenium, using: :headless_chrome, screen_size: [ 1400, 1400 ], options: {
|
156
|
+
browser: :remote,
|
157
|
+
url: "http://#{ENV["SELENIUM_HOST"]}:4444"
|
158
|
+
}
|
159
|
+
else
|
160
|
+
driven_by :selenium, using: :headless_chrome, screen_size: [ 1400, 1400 ]
|
161
|
+
end
|
162
|
+
RUBY
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
name: "<%= options[:app_name] %>"
|
2
|
+
|
3
|
+
services:
|
4
|
+
rails-app:
|
5
|
+
build:
|
6
|
+
context: ..
|
7
|
+
dockerfile: .devcontainer/Dockerfile
|
8
|
+
|
9
|
+
volumes:
|
10
|
+
- ../..:/workspaces:cached
|
11
|
+
|
12
|
+
# Overrides default command so things don't shut down after the process ends.
|
13
|
+
command: sleep infinity
|
14
|
+
|
15
|
+
# Uncomment the next line to use a non-root user for all processes.
|
16
|
+
# user: vscode
|
17
|
+
|
18
|
+
# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
|
19
|
+
# (Adding the "ports" property to this file will not forward from a Codespace.)
|
20
|
+
<%- if !dependencies.empty? -%>
|
21
|
+
depends_on:
|
22
|
+
<%- dependencies.each do |dependency| -%>
|
23
|
+
- <%= dependency %>
|
24
|
+
<%- end -%>
|
25
|
+
<%- end -%>
|
26
|
+
<%- if options[:system_test] -%>
|
27
|
+
|
28
|
+
selenium:
|
29
|
+
image: selenium/standalone-chromium
|
30
|
+
restart: unless-stopped
|
31
|
+
<%- end -%>
|
32
|
+
|
33
|
+
<%- if options[:redis] -%>
|
34
|
+
redis:
|
35
|
+
image: redis:7.2
|
36
|
+
restart: unless-stopped
|
37
|
+
volumes:
|
38
|
+
- redis-data:/data
|
39
|
+
|
40
|
+
<%- end -%>
|
41
|
+
<%= devcontainer_db_service_yaml(indentation: 4) %>
|
42
|
+
<%- if !volumes.empty? -%>
|
43
|
+
volumes:
|
44
|
+
<%- volumes.each do |volume| -%>
|
45
|
+
<%= volume %>:
|
46
|
+
<%- end -%>
|
47
|
+
<%- end -%>
|
@@ -0,0 +1,37 @@
|
|
1
|
+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
2
|
+
// README at: https://github.com/devcontainers/templates/tree/main/src/ruby
|
3
|
+
{
|
4
|
+
"name": "<%= options[:app_name] %>",
|
5
|
+
"dockerComposeFile": "compose.yaml",
|
6
|
+
"service": "rails-app",
|
7
|
+
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
8
|
+
|
9
|
+
// Features to add to the dev container. More info: https://containers.dev/features.
|
10
|
+
"features": {
|
11
|
+
<%= features.map { |key, value| "\"#{key}\": #{value.as_json}" }.join(",\n ") %>
|
12
|
+
},
|
13
|
+
|
14
|
+
<%- if !container_env.empty? -%>
|
15
|
+
"containerEnv": {
|
16
|
+
<%= container_env.map { |key, value| "\"#{key}\": \"#{value}\"" }.join(",\n ") %>
|
17
|
+
},
|
18
|
+
<%- end -%>
|
19
|
+
|
20
|
+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
21
|
+
"forwardPorts": <%= forward_ports.as_json %>,
|
22
|
+
|
23
|
+
// Configure tool-specific properties.
|
24
|
+
// "customizations": {},
|
25
|
+
|
26
|
+
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
27
|
+
// "remoteUser": "root",
|
28
|
+
|
29
|
+
<%- if !mounts.empty? -%>
|
30
|
+
"mounts": [
|
31
|
+
<%= mounts.map { |mount| "{\n " + mount.map { |key, value| "\"#{key}\": \"#{value}\"" }.join(",\n ") + "\n }" }.join(",\n ") %>
|
32
|
+
],
|
33
|
+
<%- end -%>
|
34
|
+
|
35
|
+
// Use 'postCreateCommand' to run commands after the container is created.
|
36
|
+
"postCreateCommand": "bin/setup"
|
37
|
+
}
|
@@ -5,6 +5,10 @@ module Rails
|
|
5
5
|
class MigrationGenerator < NamedBase # :nodoc:
|
6
6
|
argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]"
|
7
7
|
hook_for :orm, required: true, desc: "ORM to be invoked"
|
8
|
+
|
9
|
+
def self.exit_on_failure? # :nodoc:
|
10
|
+
true
|
11
|
+
end
|
8
12
|
end
|
9
13
|
end
|
10
14
|
end
|
@@ -66,6 +66,16 @@ module Rails
|
|
66
66
|
template "gitignore", ".gitignore"
|
67
67
|
end
|
68
68
|
|
69
|
+
def cifiles
|
70
|
+
empty_directory ".github/workflows"
|
71
|
+
template "github/ci.yml", ".github/workflows/ci.yml"
|
72
|
+
template "github/dependabot.yml", ".github/dependabot.yml"
|
73
|
+
end
|
74
|
+
|
75
|
+
def rubocop
|
76
|
+
template "rubocop.yml", ".rubocop.yml"
|
77
|
+
end
|
78
|
+
|
69
79
|
def version_control
|
70
80
|
if !options[:skip_git] && !options[:pretend]
|
71
81
|
run git_init_command, capture: options[:quiet], abort_on_failure: false
|
@@ -112,9 +122,12 @@ module Rails
|
|
112
122
|
def generate_test_dummy(force = false)
|
113
123
|
opts = options.transform_keys(&:to_sym).except(*DUMMY_IGNORE_OPTIONS)
|
114
124
|
opts[:force] = force
|
125
|
+
opts[:skip_brakeman] = true
|
115
126
|
opts[:skip_bundle] = true
|
127
|
+
opts[:skip_ci] = true
|
116
128
|
opts[:skip_git] = true
|
117
129
|
opts[:skip_hotwire] = true
|
130
|
+
opts[:skip_rubocop] = true
|
118
131
|
opts[:dummy_app] = true
|
119
132
|
|
120
133
|
invoke Rails::Generators::AppGenerator,
|
@@ -144,7 +157,7 @@ module Rails
|
|
144
157
|
def test_dummy_clean
|
145
158
|
inside dummy_path do
|
146
159
|
remove_file ".ruby-version"
|
147
|
-
|
160
|
+
remove_dir "db"
|
148
161
|
remove_file "Gemfile"
|
149
162
|
remove_file "lib/tasks"
|
150
163
|
remove_file "public/robots.txt"
|
@@ -167,12 +180,12 @@ module Rails
|
|
167
180
|
end
|
168
181
|
end
|
169
182
|
|
170
|
-
def bin
|
171
|
-
|
172
|
-
|
183
|
+
def bin
|
184
|
+
exclude_pattern = Regexp.union([(engine? ? /test\.tt/ : /rails\.tt/), (/rubocop/ if skip_rubocop?)].compact)
|
185
|
+
directory "bin", { exclude_pattern: exclude_pattern } do |content|
|
173
186
|
"#{shebang}\n" + content
|
174
187
|
end
|
175
|
-
chmod "bin", 0755, verbose: false
|
188
|
+
chmod "bin", 0755 & ~File.umask, verbose: false
|
176
189
|
end
|
177
190
|
|
178
191
|
def gemfile_entry
|
@@ -180,7 +193,7 @@ module Rails
|
|
180
193
|
|
181
194
|
gemfile_in_app_path = File.join(rails_app_path, "Gemfile")
|
182
195
|
if File.exist? gemfile_in_app_path
|
183
|
-
entry =
|
196
|
+
entry = %{\ngem "#{name}", path: "#{relative_path}"}
|
184
197
|
append_file gemfile_in_app_path, entry
|
185
198
|
end
|
186
199
|
end
|
@@ -243,6 +256,16 @@ module Rails
|
|
243
256
|
build(:app)
|
244
257
|
end
|
245
258
|
|
259
|
+
def create_rubocop_file
|
260
|
+
return if skip_rubocop?
|
261
|
+
build(:rubocop)
|
262
|
+
end
|
263
|
+
|
264
|
+
def create_cifiles
|
265
|
+
return if skip_ci?
|
266
|
+
build(:cifiles)
|
267
|
+
end
|
268
|
+
|
246
269
|
def create_config_files
|
247
270
|
build(:config)
|
248
271
|
end
|
@@ -341,7 +364,7 @@ module Rails
|
|
341
364
|
build(:test_dummy_sprocket_assets) unless skip_sprockets?
|
342
365
|
build(:test_dummy_clean)
|
343
366
|
# ensure that bin/rails has proper dummy_path
|
344
|
-
build(:bin
|
367
|
+
build(:bin)
|
345
368
|
end
|
346
369
|
end
|
347
370
|
|
@@ -465,6 +488,14 @@ module Rails
|
|
465
488
|
return unless inside_application?
|
466
489
|
app_path.delete_prefix("#{rails_app_path}/")
|
467
490
|
end
|
491
|
+
|
492
|
+
def test_command
|
493
|
+
if engine? && !options[:skip_active_record] && with_dummy_app?
|
494
|
+
"db:test:prepare test"
|
495
|
+
else
|
496
|
+
"test"
|
497
|
+
end
|
498
|
+
end
|
468
499
|
end
|
469
500
|
end
|
470
501
|
end
|
@@ -3,8 +3,8 @@ require_relative "lib/<%= namespaced_name %>/version"
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = <%= name.inspect %>
|
5
5
|
spec.version = <%= camelized_modules %>::VERSION
|
6
|
-
spec.authors = [<%= author.inspect %>]
|
7
|
-
spec.email = [<%= email.inspect %>]
|
6
|
+
spec.authors = [ <%= author.inspect %> ]
|
7
|
+
spec.email = [ <%= email.inspect %> ]
|
8
8
|
spec.homepage = "TODO"
|
9
9
|
spec.summary = "TODO: Summary of <%= camelized_modules %>."
|
10
10
|
spec.description = "TODO: Description of <%= camelized_modules %>."
|
@@ -1,5 +1,4 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
|
-
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
3
2
|
<% unless options[:skip_gemspec] -%>
|
4
3
|
|
5
4
|
# Specify your gem's dependencies in <%= name %>.gemspec.
|
@@ -8,6 +7,11 @@ gemspec
|
|
8
7
|
<% gemfile_entries.each do |gemfile_entry| %>
|
9
8
|
<%= gemfile_entry %>
|
10
9
|
<% end -%>
|
10
|
+
<%- unless options.skip_rubocop? -%>
|
11
|
+
|
12
|
+
# Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/]
|
13
|
+
gem "rubocop-rails-omakase", require: false
|
14
|
+
<%- end -%>
|
11
15
|
<% if RUBY_ENGINE == "ruby" -%>
|
12
16
|
|
13
17
|
# Start debugger with binding.b [https://github.com/ruby/debug]
|
@@ -0,0 +1,103 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
push:
|
6
|
+
branches: [ main ]
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
<%- unless skip_rubocop? -%>
|
10
|
+
lint:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
steps:
|
13
|
+
- name: Checkout code
|
14
|
+
uses: actions/checkout@v4
|
15
|
+
|
16
|
+
- name: Set up Ruby
|
17
|
+
uses: ruby/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
ruby-version: <%= ENV["RBENV_VERSION"] || ENV["rvm_ruby_string"] || "#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}" %>
|
20
|
+
bundler-cache: true
|
21
|
+
|
22
|
+
- name: Lint code for consistent style
|
23
|
+
run: bin/rubocop -f github
|
24
|
+
|
25
|
+
<% end -%>
|
26
|
+
<% unless options[:skip_test] -%>
|
27
|
+
test:
|
28
|
+
runs-on: ubuntu-latest
|
29
|
+
|
30
|
+
<%- if options[:database] == "sqlite3" -%>
|
31
|
+
# services:
|
32
|
+
# redis:
|
33
|
+
# image: redis
|
34
|
+
# ports:
|
35
|
+
# - 6379:6379
|
36
|
+
# options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
|
37
|
+
<%- else -%>
|
38
|
+
services:
|
39
|
+
<%- if options[:database] == "mysql" || options[:database] == "trilogy" -%>
|
40
|
+
mysql:
|
41
|
+
image: mysql
|
42
|
+
env:
|
43
|
+
MYSQL_ALLOW_EMPTY_PASSWORD: true
|
44
|
+
ports:
|
45
|
+
- 3306:3306
|
46
|
+
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
|
47
|
+
<%- elsif options[:database] == "postgresql" -%>
|
48
|
+
postgres:
|
49
|
+
image: postgres
|
50
|
+
env:
|
51
|
+
POSTGRES_USER: postgres
|
52
|
+
POSTGRES_PASSWORD: postgres
|
53
|
+
ports:
|
54
|
+
- 5432:5432
|
55
|
+
options: --health-cmd="pg_isready" --health-interval=10s --health-timeout=5s --health-retries=3
|
56
|
+
<%- end -%>
|
57
|
+
|
58
|
+
# redis:
|
59
|
+
# image: redis
|
60
|
+
# ports:
|
61
|
+
# - 6379:6379
|
62
|
+
# options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
|
63
|
+
|
64
|
+
<%- end -%>
|
65
|
+
steps:
|
66
|
+
- name: Install packages
|
67
|
+
run: sudo apt-get update && sudo apt-get install --no-install-recommends -y google-chrome-stable <%= dockerfile_base_packages.join(" ") %>
|
68
|
+
|
69
|
+
- name: Checkout code
|
70
|
+
uses: actions/checkout@v4
|
71
|
+
|
72
|
+
- name: Set up Ruby
|
73
|
+
uses: ruby/setup-ruby@v1
|
74
|
+
with:
|
75
|
+
ruby-version: <%= ENV["RBENV_VERSION"] || ENV["rvm_ruby_string"] || "#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}" %>
|
76
|
+
bundler-cache: true
|
77
|
+
<%- if using_bun? -%>
|
78
|
+
|
79
|
+
- uses: oven-sh/setup-bun@v1
|
80
|
+
with:
|
81
|
+
bun-version: <%= dockerfile_bun_version %>
|
82
|
+
<%- end -%>
|
83
|
+
|
84
|
+
- name: Run tests
|
85
|
+
env:
|
86
|
+
RAILS_ENV: test
|
87
|
+
<%- if options[:database] == "mysql" || options[:database] == "trilogy" -%>
|
88
|
+
DATABASE_URL: mysql2://127.0.0.1:3306
|
89
|
+
<%- elsif options[:database] == "postgresql" -%>
|
90
|
+
DATABASE_URL: postgres://postgres:postgres@localhost:5432
|
91
|
+
<%- end -%>
|
92
|
+
# REDIS_URL: redis://localhost:6379/0
|
93
|
+
run: bin/rails <%= test_command %>
|
94
|
+
|
95
|
+
- name: Keep screenshots from failed system tests
|
96
|
+
uses: actions/upload-artifact@v4
|
97
|
+
if: failure()
|
98
|
+
with:
|
99
|
+
name: screenshots
|
100
|
+
path: ${{ github.workspace }}/tmp/screenshots
|
101
|
+
if-no-files-found: ignore
|
102
|
+
<% end -%>
|
103
|
+
|
@@ -2,15 +2,17 @@ require "test_helper"
|
|
2
2
|
|
3
3
|
<% module_namespacing do -%>
|
4
4
|
class <%= class_name %>MailerTest < ActionMailer::TestCase
|
5
|
-
<% actions.
|
5
|
+
<% actions.each_with_index do |action, index| -%>
|
6
|
+
<% if index != 0 -%>
|
7
|
+
|
8
|
+
<% end -%>
|
6
9
|
test "<%= action %>" do
|
7
10
|
mail = <%= class_name %>Mailer.<%= action %>
|
8
11
|
assert_equal <%= action.to_s.humanize.inspect %>, mail.subject
|
9
|
-
assert_equal ["to@example.org"], mail.to
|
10
|
-
assert_equal ["from@example.com"], mail.from
|
12
|
+
assert_equal [ "to@example.org" ], mail.to
|
13
|
+
assert_equal [ "from@example.com" ], mail.from
|
11
14
|
assert_match "Hi", mail.body.encoded
|
12
15
|
end
|
13
|
-
|
14
16
|
<% end -%>
|
15
17
|
<% if actions.blank? -%>
|
16
18
|
# test "the truth" do
|
@@ -1,13 +1,14 @@
|
|
1
1
|
<% module_namespacing do -%>
|
2
2
|
# Preview all emails at http://localhost:3000/rails/mailers/<%= file_path %>_mailer
|
3
3
|
class <%= class_name %>MailerPreview < ActionMailer::Preview
|
4
|
-
<% actions.
|
4
|
+
<% actions.each_with_index do |action, index| -%>
|
5
|
+
<% if index != 0 -%>
|
5
6
|
|
7
|
+
<% end -%>
|
6
8
|
# Preview this email at http://localhost:3000/rails/mailers/<%= file_path %>_mailer/<%= action %>
|
7
9
|
def <%= action %>
|
8
10
|
<%= class_name %>Mailer.<%= action %>
|
9
11
|
end
|
10
12
|
<% end -%>
|
11
|
-
|
12
13
|
end
|
13
14
|
<% end -%>
|
@@ -39,7 +39,11 @@ module TestUnit # :nodoc:
|
|
39
39
|
|
40
40
|
private
|
41
41
|
def attributes_string
|
42
|
-
attributes_hash.
|
42
|
+
if attributes_hash.empty?
|
43
|
+
"{}"
|
44
|
+
else
|
45
|
+
"{ #{attributes_hash.map { |k, v| "#{k}: #{v}" }.join(", ")} }"
|
46
|
+
end
|
43
47
|
end
|
44
48
|
|
45
49
|
def attributes_hash
|
@@ -63,6 +67,16 @@ module TestUnit # :nodoc:
|
|
63
67
|
attribute = attributes.find { |attr| attr.name == name }
|
64
68
|
attribute&.virtual?
|
65
69
|
end
|
70
|
+
|
71
|
+
def datetime?(name)
|
72
|
+
attribute = attributes.find { |attr| attr.name == name }
|
73
|
+
attribute&.type == :datetime
|
74
|
+
end
|
75
|
+
|
76
|
+
def time?(name)
|
77
|
+
attribute = attributes.find { |attr| attr.name == name }
|
78
|
+
attribute&.type == :time
|
79
|
+
end
|
66
80
|
end
|
67
81
|
end
|
68
82
|
end
|
@@ -17,7 +17,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
|
|
17
17
|
|
18
18
|
test "should create <%= singular_table_name %>" do
|
19
19
|
assert_difference("<%= class_name %>.count") do
|
20
|
-
post <%= index_helper %>_url, params: { <%= "#{singular_table_name}:
|
20
|
+
post <%= index_helper %>_url, params: { <%= "#{singular_table_name}: #{attributes_string}" %> }, as: :json
|
21
21
|
end
|
22
22
|
|
23
23
|
assert_response :created
|
@@ -29,7 +29,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
|
|
29
29
|
end
|
30
30
|
|
31
31
|
test "should update <%= singular_table_name %>" do
|
32
|
-
patch <%= show_helper %>, params: { <%= "#{singular_table_name}:
|
32
|
+
patch <%= show_helper %>, params: { <%= "#{singular_table_name}: #{attributes_string}" %> }, as: :json
|
33
33
|
assert_response :success
|
34
34
|
end
|
35
35
|
|
@@ -22,7 +22,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
|
|
22
22
|
|
23
23
|
test "should create <%= singular_table_name %>" do
|
24
24
|
assert_difference("<%= class_name %>.count") do
|
25
|
-
post <%= index_helper(type: :url) %>, params: { <%= "#{singular_table_name}:
|
25
|
+
post <%= index_helper(type: :url) %>, params: { <%= "#{singular_table_name}: #{attributes_string}" %> }
|
26
26
|
end
|
27
27
|
|
28
28
|
assert_redirected_to <%= show_helper("#{class_name}.last") %>
|
@@ -39,7 +39,7 @@ class <%= controller_class_name %>ControllerTest < ActionDispatch::IntegrationTe
|
|
39
39
|
end
|
40
40
|
|
41
41
|
test "should update <%= singular_table_name %>" do
|
42
|
-
patch <%= show_helper %>, params: { <%= "#{singular_table_name}:
|
42
|
+
patch <%= show_helper %>, params: { <%= "#{singular_table_name}: #{attributes_string}" %> }
|
43
43
|
assert_redirected_to <%= show_helper %>
|
44
44
|
end
|
45
45
|
|
@@ -35,6 +35,8 @@ class <%= class_name.pluralize %>Test < ApplicationSystemTestCase
|
|
35
35
|
<%- attributes_hash.each do |attr, value| -%>
|
36
36
|
<%- if boolean?(attr) -%>
|
37
37
|
check "<%= attr.humanize %>" if <%= value %>
|
38
|
+
<%- elsif datetime?(attr) || time?(attr) -%>
|
39
|
+
fill_in "<%= attr.humanize %>", with: <%= value %>.to_s
|
38
40
|
<%- else -%>
|
39
41
|
fill_in "<%= attr.humanize %>", with: <%= value %>
|
40
42
|
<%- end -%>
|