railties 7.1.3.4 → 7.2.0

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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +177 -742
  3. data/lib/minitest/rails_plugin.rb +5 -2
  4. data/lib/rails/all.rb +1 -3
  5. data/lib/rails/api/task.rb +6 -4
  6. data/lib/rails/application/bootstrap.rb +5 -6
  7. data/lib/rails/application/configuration.rb +73 -38
  8. data/lib/rails/application/dummy_config.rb +2 -2
  9. data/lib/rails/application/finisher.rb +7 -0
  10. data/lib/rails/application.rb +15 -86
  11. data/lib/rails/backtrace_cleaner.rb +18 -3
  12. data/lib/rails/cli.rb +0 -1
  13. data/lib/rails/command.rb +1 -1
  14. data/lib/rails/commands/app/update_command.rb +93 -0
  15. data/lib/rails/commands/boot/boot_command.rb +14 -0
  16. data/lib/rails/commands/console/console_command.rb +2 -21
  17. data/lib/rails/commands/console/irb_console.rb +137 -0
  18. data/lib/rails/commands/credentials/credentials_command.rb +2 -2
  19. data/lib/rails/commands/dbconsole/dbconsole_command.rb +21 -30
  20. data/lib/rails/commands/devcontainer/devcontainer_command.rb +39 -0
  21. data/lib/rails/commands/rake/rake_command.rb +1 -1
  22. data/lib/rails/commands/runner/runner_command.rb +14 -3
  23. data/lib/rails/commands/server/server_command.rb +5 -3
  24. data/lib/rails/commands/test/test_command.rb +2 -0
  25. data/lib/rails/configuration.rb +10 -1
  26. data/lib/rails/console/app.rb +5 -32
  27. data/lib/rails/console/helpers.rb +5 -16
  28. data/lib/rails/console/methods.rb +23 -0
  29. data/lib/rails/engine.rb +5 -5
  30. data/lib/rails/gem_version.rb +3 -3
  31. data/lib/rails/generators/app_base.rb +70 -49
  32. data/lib/rails/generators/base.rb +5 -1
  33. data/lib/rails/generators/database.rb +227 -69
  34. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
  35. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
  36. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
  37. data/lib/rails/generators/generated_attribute.rb +26 -1
  38. data/lib/rails/generators/migration.rb +3 -3
  39. data/lib/rails/generators/rails/app/app_generator.rb +53 -24
  40. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +22 -15
  41. data/lib/rails/generators/rails/app/templates/Gemfile.tt +16 -16
  42. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
  43. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +8 -1
  44. data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
  45. data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
  46. data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
  47. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
  48. data/lib/rails/generators/rails/app/templates/bin/setup.tt +6 -2
  49. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +1 -1
  50. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
  51. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +7 -0
  52. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +8 -1
  53. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +3 -3
  54. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +14 -7
  55. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +5 -0
  56. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +8 -5
  57. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
  58. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +70 -0
  59. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +24 -26
  60. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +4 -0
  61. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +5 -0
  62. data/lib/rails/generators/rails/app/templates/dockerignore.tt +13 -0
  63. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +138 -0
  64. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
  65. data/lib/rails/generators/rails/app/templates/gitignore.tt +3 -3
  66. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +66 -0
  67. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  68. data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
  69. data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
  70. data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
  71. data/lib/rails/generators/rails/controller/controller_generator.rb +1 -1
  72. data/lib/rails/generators/rails/db/system/change/change_generator.rb +131 -20
  73. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +166 -0
  74. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
  75. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
  76. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
  77. data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
  78. data/lib/rails/generators/rails/plugin/plugin_generator.rb +38 -7
  79. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
  80. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +5 -1
  81. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
  82. data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
  83. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
  84. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
  85. data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
  86. data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
  87. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
  88. data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
  89. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +15 -1
  90. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
  91. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  92. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
  93. data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
  94. data/lib/rails/generators/testing/assertions.rb +20 -0
  95. data/lib/rails/generators/testing/behavior.rb +7 -6
  96. data/lib/rails/generators.rb +1 -1
  97. data/lib/rails/health_controller.rb +1 -1
  98. data/lib/rails/info.rb +2 -2
  99. data/lib/rails/mailers_controller.rb +14 -1
  100. data/lib/rails/paths.rb +2 -2
  101. data/lib/rails/pwa_controller.rb +15 -0
  102. data/lib/rails/rack/logger.rb +15 -7
  103. data/lib/rails/railtie/configurable.rb +2 -2
  104. data/lib/rails/railtie.rb +2 -3
  105. data/lib/rails/tasks/framework.rake +0 -26
  106. data/lib/rails/tasks/tmp.rake +1 -1
  107. data/lib/rails/templates/layouts/application.html.erb +1 -1
  108. data/lib/rails/templates/rails/mailers/email.html.erb +12 -8
  109. data/lib/rails/templates/rails/welcome/index.html.erb +4 -2
  110. data/lib/rails/test_help.rb +2 -4
  111. data/lib/rails/test_unit/reporter.rb +8 -2
  112. data/lib/rails/test_unit/runner.rb +26 -2
  113. data/lib/rails/test_unit/test_parser.rb +45 -0
  114. data/lib/rails.rb +7 -4
  115. metadata +42 -32
  116. data/lib/rails/app_updater.rb +0 -40
  117. data/lib/rails/commands/secrets/USAGE +0 -61
  118. data/lib/rails/commands/secrets/secrets_command.rb +0 -47
  119. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
  120. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +0 -54
  121. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
  122. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
  123. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
  124. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
  125. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_1.rb.tt +0 -284
  126. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
  127. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
  128. data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
  129. data/lib/rails/ruby_version_check.rb +0 -17
  130. 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,3 @@
1
+ # Make sure RUBY_VERSION matches the Ruby version in .ruby-version
2
+ ARG RUBY_VERSION=<%= gem_ruby_version %>
3
+ FROM ghcr.io/rails/devcontainer/images/ruby:$RUBY_VERSION
@@ -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
- remove_file "db/seeds.rb"
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(force = false)
171
- bin_file = engine? ? "bin/rails.tt" : "bin/test.tt"
172
- template bin_file, force: force do |content|
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 = "\ngem '#{name}', path: '#{relative_path}'"
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, true)
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]
@@ -5,6 +5,8 @@
5
5
  <%%= csrf_meta_tags %>
6
6
  <%%= csp_meta_tag %>
7
7
 
8
+ <%%= yield :head %>
9
+
8
10
  <%%= stylesheet_link_tag "<%= namespaced_name %>/application", media: "all" %>
9
11
  </head>
10
12
  <body>
@@ -0,0 +1,7 @@
1
+ require "rubygems"
2
+ require "bundler/setup"
3
+
4
+ # explicit rubocop config increases performance slightly while avoiding config confusion.
5
+ ARGV.unshift("--config", File.expand_path("../.rubocop.yml", __dir__))
6
+
7
+ load Gem.bin_path("rubocop", "rubocop")
@@ -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
+
@@ -0,0 +1,12 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ open-pull-requests-limit: 10
8
+ - package-ecosystem: github-actions
9
+ directory: "/"
10
+ schedule:
11
+ interval: daily
12
+ open-pull-requests-limit: 10
@@ -0,0 +1,8 @@
1
+ # Omakase Ruby styling for Rails
2
+ inherit_gem: { rubocop-rails-omakase: rubocop.yml }
3
+
4
+ # Overwrite or add rules to create your own house style
5
+ #
6
+ # # Use `[a, [b, c]]` not `[ a, [ b, c ] ]`
7
+ # Layout/SpaceInsideArrayLiteralBrackets:
8
+ # Enabled: false
@@ -1,5 +1,5 @@
1
1
  require "test_helper"
2
2
 
3
3
  class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
4
- driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
4
+ driven_by :selenium, using: :headless_chrome, screen_size: [ 1400, 1400 ]
5
5
  end
@@ -2,15 +2,17 @@ require "test_helper"
2
2
 
3
3
  <% module_namespacing do -%>
4
4
  class <%= class_name %>MailerTest < ActionMailer::TestCase
5
- <% actions.each do |action| -%>
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.each do |action| -%>
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.map { |k, v| "#{k}: #{v}" }.join(", ")
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}: { #{attributes_string} }" %> }, as: :json
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}: { #{attributes_string} }" %> }, as: :json
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}: { #{attributes_string} }" %> }
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}: { #{attributes_string} }" %> }
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 -%>