railties 7.0.8 → 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 (221) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +188 -268
  3. data/MIT-LICENSE +1 -1
  4. data/RDOC_MAIN.md +99 -0
  5. data/README.rdoc +4 -4
  6. data/lib/minitest/rails_plugin.rb +67 -1
  7. data/lib/rails/all.rb +1 -3
  8. data/lib/rails/api/task.rb +39 -6
  9. data/lib/rails/application/bootstrap.rb +28 -10
  10. data/lib/rails/application/configuration.rb +228 -72
  11. data/lib/rails/application/default_middleware_stack.rb +8 -2
  12. data/lib/rails/application/dummy_config.rb +19 -0
  13. data/lib/rails/application/finisher.rb +50 -33
  14. data/lib/rails/application.rb +110 -76
  15. data/lib/rails/backtrace_cleaner.rb +19 -4
  16. data/lib/rails/cli.rb +5 -3
  17. data/lib/rails/command/actions.rb +10 -12
  18. data/lib/rails/command/base.rb +55 -53
  19. data/lib/rails/command/environment_argument.rb +32 -16
  20. data/lib/rails/command/helpers/editor.rb +17 -12
  21. data/lib/rails/command.rb +84 -33
  22. data/lib/rails/commands/about/about_command.rb +14 -0
  23. data/lib/rails/commands/app/update_command.rb +93 -0
  24. data/lib/rails/commands/application/application_command.rb +2 -0
  25. data/lib/rails/commands/boot/boot_command.rb +14 -0
  26. data/lib/rails/commands/console/console_command.rb +11 -30
  27. data/lib/rails/commands/console/irb_console.rb +137 -0
  28. data/lib/rails/commands/credentials/USAGE +53 -55
  29. data/lib/rails/commands/credentials/credentials_command/diffing.rb +5 -3
  30. data/lib/rails/commands/credentials/credentials_command.rb +64 -70
  31. data/lib/rails/commands/db/system/change/change_command.rb +2 -1
  32. data/lib/rails/commands/dbconsole/dbconsole_command.rb +32 -131
  33. data/lib/rails/commands/destroy/destroy_command.rb +3 -2
  34. data/lib/rails/commands/dev/dev_command.rb +1 -6
  35. data/lib/rails/commands/devcontainer/devcontainer_command.rb +39 -0
  36. data/lib/rails/commands/encrypted/USAGE +15 -20
  37. data/lib/rails/commands/encrypted/encrypted_command.rb +46 -35
  38. data/lib/rails/commands/gem_help/USAGE +16 -0
  39. data/lib/rails/commands/gem_help/gem_help_command.rb +13 -0
  40. data/lib/rails/commands/generate/generate_command.rb +2 -2
  41. data/lib/rails/commands/help/USAGE +13 -13
  42. data/lib/rails/commands/help/help_command.rb +21 -2
  43. data/lib/rails/commands/initializers/initializers_command.rb +1 -4
  44. data/lib/rails/commands/middleware/middleware_command.rb +17 -0
  45. data/lib/rails/commands/new/new_command.rb +2 -0
  46. data/lib/rails/commands/notes/notes_command.rb +2 -1
  47. data/lib/rails/commands/plugin/plugin_command.rb +2 -0
  48. data/lib/rails/commands/rake/rake_command.rb +25 -22
  49. data/lib/rails/commands/restart/restart_command.rb +14 -0
  50. data/lib/rails/commands/routes/routes_command.rb +13 -1
  51. data/lib/rails/commands/runner/USAGE +14 -12
  52. data/lib/rails/commands/runner/runner_command.rb +42 -19
  53. data/lib/rails/commands/secret/secret_command.rb +13 -0
  54. data/lib/rails/commands/server/server_command.rb +37 -34
  55. data/lib/rails/commands/test/USAGE +14 -0
  56. data/lib/rails/commands/test/test_command.rb +58 -14
  57. data/lib/rails/commands/unused_routes/unused_routes_command.rb +75 -0
  58. data/lib/rails/commands/version/version_command.rb +1 -0
  59. data/lib/rails/configuration.rb +15 -6
  60. data/lib/rails/console/app.rb +5 -35
  61. data/lib/rails/console/helpers.rb +5 -16
  62. data/lib/rails/console/methods.rb +23 -0
  63. data/lib/rails/deprecator.rb +7 -0
  64. data/lib/rails/engine/configuration.rb +50 -6
  65. data/lib/rails/engine.rb +51 -23
  66. data/lib/rails/gem_version.rb +3 -3
  67. data/lib/rails/generators/actions.rb +6 -15
  68. data/lib/rails/generators/active_model.rb +28 -14
  69. data/lib/rails/generators/app_base.rb +382 -88
  70. data/lib/rails/generators/app_name.rb +3 -14
  71. data/lib/rails/generators/base.rb +21 -9
  72. data/lib/rails/generators/database.rb +231 -35
  73. data/lib/rails/generators/erb/mailer/templates/layout.html.erb.tt +1 -1
  74. data/lib/rails/generators/erb/scaffold/templates/edit.html.erb.tt +2 -0
  75. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +2 -0
  76. data/lib/rails/generators/erb/scaffold/templates/new.html.erb.tt +2 -0
  77. data/lib/rails/generators/generated_attribute.rb +38 -1
  78. data/lib/rails/generators/migration.rb +4 -5
  79. data/lib/rails/generators/model_helpers.rb +2 -1
  80. data/lib/rails/generators/rails/app/USAGE +22 -6
  81. data/lib/rails/generators/rails/app/app_generator.rb +132 -82
  82. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +110 -0
  83. data/lib/rails/generators/rails/app/templates/Gemfile.tt +19 -21
  84. data/lib/rails/generators/rails/app/templates/app/controllers/application_controller.rb.tt +4 -0
  85. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +8 -1
  86. data/lib/rails/generators/rails/app/templates/app/views/layouts/mailer.html.erb.tt +1 -1
  87. data/lib/rails/generators/rails/app/templates/app/views/pwa/manifest.json.erb.tt +22 -0
  88. data/lib/rails/generators/rails/app/templates/app/views/pwa/service-worker.js +26 -0
  89. data/lib/rails/generators/rails/app/templates/bin/brakeman.tt +6 -0
  90. data/lib/rails/generators/rails/app/templates/bin/rubocop.tt +7 -0
  91. data/lib/rails/generators/rails/app/templates/bin/setup.tt +15 -2
  92. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +6 -17
  93. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +3 -3
  94. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +11 -6
  95. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +10 -3
  96. data/lib/rails/generators/rails/app/templates/config/databases/{jdbcmysql.yml.tt → trilogy.yml.tt} +12 -7
  97. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +25 -8
  98. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +37 -28
  99. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +20 -13
  100. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +2 -0
  101. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +2 -2
  102. data/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt +1 -1
  103. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +4 -4
  104. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +70 -0
  105. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +11 -9
  106. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +11 -13
  107. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +24 -34
  108. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +9 -1
  109. data/lib/rails/generators/rails/app/templates/db/seeds.rb.tt +6 -4
  110. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +15 -0
  111. data/lib/rails/generators/rails/app/templates/dockerignore.tt +56 -0
  112. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +138 -0
  113. data/lib/rails/generators/rails/app/templates/github/dependabot.yml +12 -0
  114. data/lib/rails/generators/rails/app/templates/gitignore.tt +7 -11
  115. data/lib/rails/generators/rails/app/templates/node-version.tt +1 -0
  116. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +66 -0
  117. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  118. data/lib/rails/generators/rails/app/templates/public/icon.svg +3 -0
  119. data/lib/rails/generators/rails/app/templates/rubocop.yml.tt +8 -0
  120. data/lib/rails/generators/rails/app/templates/test/application_system_test_case.rb.tt +1 -1
  121. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +10 -8
  122. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +9 -7
  123. data/lib/rails/generators/rails/application_record/application_record_generator.rb +4 -0
  124. data/lib/rails/generators/rails/benchmark/benchmark_generator.rb +2 -1
  125. data/lib/rails/generators/rails/controller/USAGE +12 -4
  126. data/lib/rails/generators/rails/controller/controller_generator.rb +6 -1
  127. data/lib/rails/generators/rails/controller/templates/controller.rb.tt +1 -1
  128. data/lib/rails/generators/rails/credentials/credentials_generator.rb +29 -24
  129. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +8 -0
  130. data/lib/rails/generators/rails/db/system/change/change_generator.rb +146 -5
  131. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +166 -0
  132. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/Dockerfile.tt +3 -0
  133. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/compose.yaml.tt +47 -0
  134. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +37 -0
  135. data/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb +1 -2
  136. data/lib/rails/generators/rails/migration/USAGE +21 -11
  137. data/lib/rails/generators/rails/migration/migration_generator.rb +4 -0
  138. data/lib/rails/generators/rails/model/model_generator.rb +4 -0
  139. data/lib/rails/generators/rails/plugin/USAGE +17 -6
  140. data/lib/rails/generators/rails/plugin/plugin_generator.rb +43 -22
  141. data/lib/rails/generators/rails/plugin/templates/%name%.gemspec.tt +2 -2
  142. data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +7 -3
  143. data/lib/rails/generators/rails/plugin/templates/MIT-LICENSE.tt +1 -1
  144. data/lib/rails/generators/rails/plugin/templates/app/views/layouts/%namespaced_name%/application.html.erb.tt +2 -0
  145. data/lib/rails/generators/rails/plugin/templates/bin/rails.tt +1 -17
  146. data/lib/rails/generators/rails/plugin/templates/bin/rubocop.tt +7 -0
  147. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +103 -0
  148. data/lib/rails/generators/rails/plugin/templates/github/dependabot.yml +12 -0
  149. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +0 -2
  150. data/lib/rails/generators/rails/plugin/templates/rubocop.yml.tt +8 -0
  151. data/lib/rails/generators/rails/plugin/templates/test/application_system_test_case.rb.tt +1 -1
  152. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +4 -4
  153. data/lib/rails/generators/rails/resource/resource_generator.rb +6 -0
  154. data/lib/rails/generators/rails/scaffold/scaffold_generator.rb +2 -1
  155. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +1 -1
  156. data/lib/rails/generators/test_case.rb +2 -2
  157. data/lib/rails/generators/test_unit/mailer/templates/functional_test.rb.tt +6 -4
  158. data/lib/rails/generators/test_unit/mailer/templates/preview.rb.tt +3 -2
  159. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +16 -2
  160. data/lib/rails/generators/test_unit/scaffold/templates/api_functional_test.rb.tt +2 -2
  161. data/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb.tt +2 -2
  162. data/lib/rails/generators/test_unit/scaffold/templates/system_test.rb.tt +2 -0
  163. data/lib/rails/generators/test_unit/system/templates/application_system_test_case.rb.tt +1 -1
  164. data/lib/rails/generators/testing/assertions.rb +20 -0
  165. data/lib/rails/generators/testing/{behaviour.rb → behavior.rb} +8 -4
  166. data/lib/rails/generators.rb +7 -15
  167. data/lib/rails/health_controller.rb +55 -0
  168. data/lib/rails/info.rb +3 -3
  169. data/lib/rails/info_controller.rb +31 -11
  170. data/lib/rails/mailers_controller.rb +29 -6
  171. data/lib/rails/paths.rb +15 -12
  172. data/lib/rails/pwa_controller.rb +15 -0
  173. data/lib/rails/rack/logger.rb +27 -16
  174. data/lib/rails/rackup/server.rb +15 -0
  175. data/lib/rails/railtie/configurable.rb +2 -2
  176. data/lib/rails/railtie/configuration.rb +14 -1
  177. data/lib/rails/railtie.rb +20 -21
  178. data/lib/rails/source_annotation_extractor.rb +67 -18
  179. data/lib/rails/tasks/engine.rake +8 -8
  180. data/lib/rails/tasks/framework.rake +2 -34
  181. data/lib/rails/tasks/log.rake +1 -1
  182. data/lib/rails/tasks/misc.rake +3 -14
  183. data/lib/rails/tasks/statistics.rake +5 -4
  184. data/lib/rails/tasks/tmp.rake +6 -6
  185. data/lib/rails/tasks/zeitwerk.rake +15 -35
  186. data/lib/rails/tasks.rb +0 -2
  187. data/lib/rails/templates/layouts/application.html.erb +1 -1
  188. data/lib/rails/templates/rails/mailers/email.html.erb +44 -8
  189. data/lib/rails/templates/rails/mailers/index.html.erb +14 -7
  190. data/lib/rails/templates/rails/mailers/mailer.html.erb +11 -5
  191. data/lib/rails/templates/rails/welcome/index.html.erb +5 -2
  192. data/lib/rails/test_help.rb +11 -18
  193. data/lib/rails/test_unit/line_filtering.rb +1 -1
  194. data/lib/rails/test_unit/reporter.rb +14 -4
  195. data/lib/rails/test_unit/runner.rb +62 -20
  196. data/lib/rails/test_unit/test_parser.rb +133 -0
  197. data/lib/rails/test_unit/testing.rake +13 -33
  198. data/lib/rails/testing/maintain_test_schema.rb +16 -0
  199. data/lib/rails/version.rb +1 -1
  200. data/lib/rails/zeitwerk_checker.rb +15 -0
  201. data/lib/rails.rb +20 -17
  202. metadata +89 -42
  203. data/RDOC_MAIN.rdoc +0 -97
  204. data/lib/rails/app_updater.rb +0 -40
  205. data/lib/rails/application/dummy_erb_compiler.rb +0 -18
  206. data/lib/rails/commands/secrets/USAGE +0 -66
  207. data/lib/rails/commands/secrets/secrets_command.rb +0 -65
  208. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +0 -68
  209. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +0 -70
  210. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +0 -24
  211. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +0 -62
  212. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +0 -53
  213. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +0 -143
  214. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon-precomposed.png +0 -0
  215. data/lib/rails/generators/rails/app/templates/public/apple-touch-icon.png +0 -0
  216. data/lib/rails/generators/rails/app/templates/public/favicon.ico +0 -0
  217. data/lib/rails/generators/rails/model/USAGE +0 -113
  218. data/lib/rails/ruby_version_check.rb +0 -15
  219. data/lib/rails/secrets.rb +0 -110
  220. data/lib/rails/tasks/middleware.rake +0 -9
  221. data/lib/rails/tasks/restart.rake +0 -9
@@ -7,26 +7,15 @@ module Rails
7
7
 
8
8
  private
9
9
  def app_name
10
- @app_name ||= original_app_name.tr("\\", "").tr("-. ", "_")
10
+ @app_name ||= original_app_name.parameterize(preserve_case: true).underscore
11
11
  end
12
12
 
13
13
  def original_app_name
14
- @original_app_name ||= defined_app_const_base? ? defined_app_name : File.basename(destination_root)
14
+ @original_app_name ||= (options[:name] || File.basename(destination_root))
15
15
  end
16
16
 
17
- def defined_app_name
18
- defined_app_const_base.underscore
19
- end
20
-
21
- def defined_app_const_base
22
- Rails.respond_to?(:application) && defined?(Rails::Application) &&
23
- Rails.application.is_a?(Rails::Application) && Rails.application.class.name.chomp("::Application")
24
- end
25
-
26
- alias :defined_app_const_base? :defined_app_const_base
27
-
28
17
  def app_const_base
29
- @app_const_base ||= defined_app_const_base || app_name.gsub(/\W/, "_").squeeze("_").camelize
18
+ @app_const_base ||= app_name.gsub(/\W/, "_").squeeze("_").camelize
30
19
  end
31
20
  alias :camelized :app_const_base
32
21
 
@@ -79,15 +79,15 @@ module Rails
79
79
  #
80
80
  # For example, if the user invoke the controller generator as:
81
81
  #
82
- # bin/rails generate controller Account --test-framework=test_unit
82
+ # $ bin/rails generate controller Account --test-framework=test_unit
83
83
  #
84
84
  # The controller generator will then try to invoke the following generators:
85
85
  #
86
86
  # "rails:test_unit", "test_unit:controller", "test_unit"
87
87
  #
88
88
  # Notice that "rails:generators:test_unit" could be loaded as well, what
89
- # Rails looks for is the first and last parts of the namespace. This is what
90
- # allows any test framework to hook into Rails as long as it provides any
89
+ # \Rails looks for is the first and last parts of the namespace. This is what
90
+ # allows any test framework to hook into \Rails as long as it provides any
91
91
  # of the hooks above.
92
92
  #
93
93
  # ==== Options
@@ -134,11 +134,11 @@ module Rails
134
134
  # All hooks come with switches for user interface. If you do not want
135
135
  # to use any test framework, you can do:
136
136
  #
137
- # bin/rails generate controller Account --skip-test-framework
137
+ # $ bin/rails generate controller Account --skip-test-framework
138
138
  #
139
139
  # Or similarly:
140
140
  #
141
- # bin/rails generate controller Account --no-test-framework
141
+ # $ bin/rails generate controller Account --no-test-framework
142
142
  #
143
143
  # ==== Boolean hooks
144
144
  #
@@ -150,7 +150,7 @@ module Rails
150
150
  #
151
151
  # Then, if you want webrat to be invoked, just supply:
152
152
  #
153
- # bin/rails generate controller Account --webrat
153
+ # $ bin/rails generate controller Account --webrat
154
154
  #
155
155
  # The hooks lookup is similar as above:
156
156
  #
@@ -189,6 +189,13 @@ module Rails
189
189
  class_option(name, defaults.merge!(options))
190
190
  end
191
191
 
192
+ klass = self
193
+
194
+ singleton_class.define_method("#{name}_generator") do
195
+ value = class_options[name].default
196
+ Rails::Generators.find_by_namespace(klass.generator_name, value)
197
+ end
198
+
192
199
  hooks[name] = [ in_base, as_hook ]
193
200
  invoke_from_option(name, options, &block)
194
201
  end
@@ -201,6 +208,7 @@ module Rails
201
208
  remove_invocation(*names)
202
209
 
203
210
  names.each do |name|
211
+ singleton_class.undef_method("#{name}_generator")
204
212
  hooks.delete(name)
205
213
  end
206
214
  end
@@ -214,7 +222,7 @@ module Rails
214
222
  end
215
223
 
216
224
  # Returns the default source root for a given generator. This is used internally
217
- # by rails to set its generators source root. If you want to customize your source
225
+ # by Rails to set its generators source root. If you want to customize your source
218
226
  # root, you should use source_root.
219
227
  def self.default_source_root
220
228
  return unless base_name && generator_name
@@ -317,9 +325,9 @@ module Rails
317
325
  @namespaced_path ||= namespace_dirs.join("/")
318
326
  end
319
327
 
320
- # Use Rails default banner.
328
+ # Use \Rails default banner.
321
329
  def self.banner # :doc:
322
- "rails generate #{namespace.delete_prefix("rails:")} #{arguments.map(&:usage).join(' ')} [options]".gsub(/\s+/, " ")
330
+ "bin/rails generate #{namespace.delete_prefix("rails:")} #{arguments.map(&:usage).join(' ')} [options]".gsub(/\s+/, " ")
323
331
  end
324
332
 
325
333
  # Sets the base_name taking into account the current class namespace.
@@ -415,6 +423,10 @@ module Rails
415
423
  path = File.expand_path(File.join(base_name, generator_name), base_root)
416
424
  path if File.exist?(path)
417
425
  end
426
+
427
+ def gem_ruby_version
428
+ Gem::Version.new(Gem::VERSION) >= Gem::Version.new("3.3.13") ? Gem.ruby_version : RUBY_VERSION
429
+ end
418
430
  end
419
431
  end
420
432
  end
@@ -2,45 +2,76 @@
2
2
 
3
3
  module Rails
4
4
  module Generators
5
- module Database # :nodoc:
6
- JDBC_DATABASES = %w( jdbcmysql jdbcsqlite3 jdbcpostgresql jdbc )
7
- DATABASES = %w( mysql postgresql sqlite3 oracle sqlserver ) + JDBC_DATABASES
8
-
9
- def initialize(*)
10
- super
11
- convert_database_option_for_jruby
12
- end
13
-
14
- def gem_for_database(database = options[:database])
15
- case database
16
- when "mysql" then ["mysql2", ["~> 0.5"]]
17
- when "postgresql" then ["pg", ["~> 1.1"]]
18
- when "sqlite3" then ["sqlite3", ["~> 1.4"]]
19
- when "oracle" then ["activerecord-oracle_enhanced-adapter", nil]
20
- when "sqlserver" then ["activerecord-sqlserver-adapter", nil]
21
- when "jdbcmysql" then ["activerecord-jdbcmysql-adapter", nil]
22
- when "jdbcsqlite3" then ["activerecord-jdbcsqlite3-adapter", nil]
23
- when "jdbcpostgresql" then ["activerecord-jdbcpostgresql-adapter", nil]
24
- when "jdbc" then ["activerecord-jdbc-adapter", nil]
25
- else [database, nil]
26
- end
27
- end
28
-
29
- def convert_database_option_for_jruby
30
- if defined?(JRUBY_VERSION)
31
- opt = options.dup
32
- case opt[:database]
33
- when "postgresql" then opt[:database] = "jdbcpostgresql"
34
- when "mysql" then opt[:database] = "jdbcmysql"
35
- when "sqlite3" then opt[:database] = "jdbcsqlite3"
5
+ class Database
6
+ DATABASES = %w( mysql trilogy postgresql sqlite3 )
7
+
8
+ class << self
9
+ def build(database_name)
10
+ case database_name
11
+ when "mysql" then MySQL.new
12
+ when "postgresql" then PostgreSQL.new
13
+ when "trilogy" then MariaDB.new
14
+ when "sqlite3" then SQLite3.new
15
+ else Null.new
36
16
  end
37
- self.options = opt.freeze
38
17
  end
18
+
19
+ def all
20
+ @all ||= [
21
+ MySQL.new,
22
+ PostgreSQL.new,
23
+ MariaDB.new,
24
+ SQLite3.new,
25
+ ]
26
+ end
27
+ end
28
+
29
+ def name
30
+ raise NotImplementedError
31
+ end
32
+
33
+ def service
34
+ raise NotImplementedError
35
+ end
36
+
37
+ def port
38
+ raise NotImplementedError
39
+ end
40
+
41
+ def feature_name
42
+ raise NotImplementedError
43
+ end
44
+
45
+ def gem
46
+ raise NotImplementedError
47
+ end
48
+
49
+ def base_package
50
+ raise NotImplementedError
51
+ end
52
+
53
+ def build_package
54
+ raise NotImplementedError
55
+ end
56
+
57
+ def socket; end
58
+ def host; end
59
+
60
+ def feature
61
+ return unless feature_name
62
+
63
+ { feature_name => {} }
64
+ end
65
+
66
+ def volume
67
+ return unless service
68
+
69
+ "#{name}-data"
39
70
  end
40
71
 
41
- private
42
- def mysql_socket
43
- @mysql_socket ||= [
72
+ module MySqlSocket
73
+ def socket
74
+ @socket ||= [
44
75
  "/tmp/mysql.sock", # default
45
76
  "/var/run/mysqld/mysqld.sock", # debian/gentoo
46
77
  "/var/tmp/mysql.sock", # freebsd
@@ -52,6 +83,171 @@ module Rails
52
83
  "/opt/lampp/var/mysql/mysql.sock" # xampp for linux
53
84
  ].find { |f| File.exist?(f) } unless Gem.win_platform?
54
85
  end
86
+
87
+ def host
88
+ "localhost"
89
+ end
90
+ end
91
+
92
+ class MySQL < Database
93
+ include MySqlSocket
94
+
95
+ def name
96
+ "mysql"
97
+ end
98
+
99
+ def service
100
+ {
101
+ "image" => "mysql/mysql-server:8.0",
102
+ "restart" => "unless-stopped",
103
+ "environment" => {
104
+ "MYSQL_ALLOW_EMPTY_PASSWORD" => "true",
105
+ "MYSQL_ROOT_HOST" => "%"
106
+ },
107
+ "volumes" => ["mysql-data:/var/lib/mysql"],
108
+ "networks" => ["default"],
109
+ }
110
+ end
111
+
112
+ def port
113
+ 3306
114
+ end
115
+
116
+ def gem
117
+ ["mysql2", ["~> 0.5"]]
118
+ end
119
+
120
+ def base_package
121
+ "default-mysql-client"
122
+ end
123
+
124
+ def build_package
125
+ "default-libmysqlclient-dev"
126
+ end
127
+
128
+ def feature_name
129
+ "ghcr.io/rails/devcontainer/features/mysql-client"
130
+ end
131
+ end
132
+
133
+ class PostgreSQL < Database
134
+ def name
135
+ "postgres"
136
+ end
137
+
138
+ def service
139
+ {
140
+ "image" => "postgres:16.1",
141
+ "restart" => "unless-stopped",
142
+ "networks" => ["default"],
143
+ "volumes" => ["postgres-data:/var/lib/postgresql/data"],
144
+ "environment" => {
145
+ "POSTGRES_USER" => "postgres",
146
+ "POSTGRES_PASSWORD" => "postgres"
147
+ }
148
+ }
149
+ end
150
+
151
+ def port
152
+ 5432
153
+ end
154
+
155
+ def gem
156
+ ["pg", ["~> 1.1"]]
157
+ end
158
+
159
+ def base_package
160
+ "postgresql-client"
161
+ end
162
+
163
+ def build_package
164
+ "libpq-dev"
165
+ end
166
+
167
+ def feature_name
168
+ "ghcr.io/rails/devcontainer/features/postgres-client"
169
+ end
170
+ end
171
+
172
+ class MariaDB < Database
173
+ include MySqlSocket
174
+
175
+ def name
176
+ "mariadb"
177
+ end
178
+
179
+ def service
180
+ {
181
+ "image" => "mariadb:10.5",
182
+ "restart" => "unless-stopped",
183
+ "networks" => ["default"],
184
+ "volumes" => ["mariadb-data:/var/lib/mysql"],
185
+ "environment" => {
186
+ "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" => "true",
187
+ },
188
+ }
189
+ end
190
+
191
+ def port
192
+ 3306
193
+ end
194
+
195
+ def gem
196
+ ["trilogy", ["~> 2.7"]]
197
+ end
198
+
199
+ def base_package
200
+ nil
201
+ end
202
+
203
+ def build_package
204
+ nil
205
+ end
206
+
207
+ def feature_name
208
+ nil
209
+ end
210
+ end
211
+
212
+ class SQLite3 < Database
213
+ def name
214
+ "sqlite3"
215
+ end
216
+
217
+ def service
218
+ nil
219
+ end
220
+
221
+ def port
222
+ nil
223
+ end
224
+
225
+ def gem
226
+ ["sqlite3", [">= 1.4"]]
227
+ end
228
+
229
+ def base_package
230
+ "libsqlite3-0"
231
+ end
232
+
233
+ def build_package
234
+ nil
235
+ end
236
+
237
+ def feature_name
238
+ "ghcr.io/rails/devcontainer/features/sqlite3"
239
+ end
240
+ end
241
+
242
+ class Null < Database
243
+ def name; end
244
+ def service; end
245
+ def port; end
246
+ def volume; end
247
+ def base_package; end
248
+ def build_package; end
249
+ def feature_name; end
250
+ end
55
251
  end
56
252
  end
57
253
  end
@@ -1,7 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
5
  <style>
6
6
  /* Email styles need to be inline */
7
7
  </style>
@@ -1,3 +1,5 @@
1
+ <%% content_for :title, "Editing <%= human_name.downcase %>" %>
2
+
1
3
  <h1>Editing <%= human_name.downcase %></h1>
2
4
 
3
5
  <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
@@ -1,5 +1,7 @@
1
1
  <p style="color: green"><%%= notice %></p>
2
2
 
3
+ <%% content_for :title, "<%= human_name.pluralize %>" %>
4
+
3
5
  <h1><%= human_name.pluralize %></h1>
4
6
 
5
7
  <div id="<%= plural_table_name %>">
@@ -1,3 +1,5 @@
1
+ <%% content_for :title, "New <%= human_name.downcase %>" %>
2
+
1
3
  <h1>New <%= human_name.downcase %></h1>
2
4
 
3
5
  <%%= render "form", <%= singular_table_name %>: @<%= singular_table_name %> %>
@@ -43,6 +43,10 @@ module Rails
43
43
  type, attr_options = *parse_type_and_options(type)
44
44
  type = type.to_sym if type
45
45
 
46
+ if dangerous_name?(name)
47
+ raise Error, "Could not generate field '#{name}', as it is already defined by Active Record."
48
+ end
49
+
46
50
  if type && !valid_type?(type)
47
51
  raise Error, "Could not generate field '#{name}' with unknown type '#{type}'."
48
52
  end
@@ -60,9 +64,15 @@ module Rails
60
64
  new(name, type, index_type, attr_options)
61
65
  end
62
66
 
67
+ def dangerous_name?(name)
68
+ defined?(ActiveRecord::Base) &&
69
+ ActiveRecord::Base.dangerous_attribute_method?(name)
70
+ end
71
+
63
72
  def valid_type?(type)
64
73
  DEFAULT_TYPES.include?(type.to_s) ||
65
- ActiveRecord::Base.connection.valid_type?(type)
74
+ !defined?(ActiveRecord::Base) ||
75
+ ActiveRecord::Base.lease_connection.valid_type?(type)
66
76
  end
67
77
 
68
78
  def valid_index_type?(index_type)
@@ -78,6 +88,8 @@ module Rails
78
88
  # when declaring options curly brackets should be used
79
89
  def parse_type_and_options(type)
80
90
  case type
91
+ when /(text|binary)\{([a-z]+)\}/
92
+ return $1, size: $2.to_sym
81
93
  when /(string|text|binary|integer)\{(\d+)\}/
82
94
  return $1, limit: $2.to_i
83
95
  when /decimal\{(\d+)[,.-](\d+)\}/
@@ -227,6 +239,31 @@ module Rails
227
239
  end
228
240
  end
229
241
  end
242
+
243
+ def to_s
244
+ if has_uniq_index?
245
+ "#{name}:#{type}#{print_attribute_options}:uniq"
246
+ elsif has_index?
247
+ "#{name}:#{type}#{print_attribute_options}:index"
248
+ else
249
+ "#{name}:#{type}#{print_attribute_options}"
250
+ end
251
+ end
252
+
253
+ private
254
+ def print_attribute_options
255
+ if attr_options.empty?
256
+ ""
257
+ elsif attr_options[:size]
258
+ "{#{attr_options[:size]}}"
259
+ elsif attr_options[:limit]
260
+ "{#{attr_options[:limit]}}"
261
+ elsif attr_options[:precision] && attr_options[:scale]
262
+ "{#{attr_options[:precision]},#{attr_options[:scale]}}"
263
+ else
264
+ "{#{attr_options.keys.join(",")}}"
265
+ end
266
+ end
230
267
  end
231
268
  end
232
269
  end
@@ -7,7 +7,7 @@ module Rails
7
7
  module Generators
8
8
  # Holds common methods for migrations. It assumes that migrations have the
9
9
  # [0-9]*_name format and can be used by other frameworks (like Sequel)
10
- # just by implementing the next migration version method.
10
+ # just by implementing the +next_migration_number+ method.
11
11
  module Migration
12
12
  extend ActiveSupport::Concern
13
13
  attr_reader :migration_number, :migration_file_name, :migration_class_name
@@ -46,10 +46,10 @@ module Rails
46
46
  end
47
47
 
48
48
  # Creates a migration template at the given destination. The difference
49
- # to the default template method is that the migration version is appended
49
+ # to the default template method is that the migration number is prepended
50
50
  # to the destination file name.
51
51
  #
52
- # The migration version, migration file name, migration class name are
52
+ # The migration number, migration file name, migration class name are
53
53
  # available as instance variables in the template to be rendered.
54
54
  #
55
55
  # migration_template "migration.rb", "db/migrate/add_foo_to_bar.rb"
@@ -57,13 +57,12 @@ module Rails
57
57
  source = File.expand_path(find_in_source_paths(source.to_s))
58
58
 
59
59
  set_migration_assigns!(destination)
60
- context = instance_eval("binding")
61
60
 
62
61
  dir, base = File.split(destination)
63
62
  numbered_destination = File.join(dir, ["%migration_number%", base].join("_"))
64
63
 
65
64
  file = create_migration numbered_destination, nil, config do
66
- ERB.new(::File.binread(source), trim_mode: "-", eoutvar: "@output_buffer").result(context)
65
+ ERB.new(::File.binread(source), trim_mode: "-", eoutvar: "@output_buffer").result(binding)
67
66
  end
68
67
  Rails::Generators.add_generated_file(file)
69
68
  end
@@ -19,7 +19,8 @@ module Rails
19
19
  mattr_accessor :skip_warn
20
20
 
21
21
  def self.included(base) # :nodoc:
22
- base.class_option :force_plural, type: :boolean, default: false, desc: "Forces the use of the given model name"
22
+ base.class_option :force_plural, type: :boolean, default: false,
23
+ desc: "Do not singularize the model name, even if it appears plural"
23
24
  end
24
25
 
25
26
  def initialize(args, *_options)
@@ -1,15 +1,31 @@
1
1
  Description:
2
- The 'rails new' command creates a new Rails application with a default
2
+ The `rails new` command creates a new Rails application with a default
3
3
  directory structure and configuration at the path you specify.
4
4
 
5
5
  You can specify extra command-line arguments to be used every time
6
- 'rails new' runs in the .railsrc configuration file in your home directory,
6
+ `rails new` runs in the .railsrc configuration file in your home directory,
7
7
  or in $XDG_CONFIG_HOME/rails/railsrc if XDG_CONFIG_HOME is set.
8
8
 
9
9
  Note that the arguments specified in the .railsrc file don't affect the
10
- defaults values shown above in this help message.
10
+ default values shown above in this help message.
11
11
 
12
- Example:
13
- rails new ~/Code/Ruby/weblog
12
+ You can specify which version to use when creating a new rails application
13
+ using `rails _<version>_ new`.
14
14
 
15
- This generates a skeletal Rails installation in ~/Code/Ruby/weblog.
15
+ Examples:
16
+ `rails new ~/Code/Ruby/weblog`
17
+
18
+ This generates a new Rails app in ~/Code/Ruby/weblog.
19
+
20
+ `rails _<version>_ new weblog`
21
+
22
+ This generates a new Rails app with the provided version in ./weblog.
23
+
24
+ `rails new weblog --api`
25
+
26
+ This generates a new Rails app in API mode in ./weblog.
27
+
28
+ `rails new weblog --skip-action-mailer`
29
+
30
+ This generates a new Rails app without Action Mailer in ./weblog.
31
+ Any part of Rails can be skipped during app generation.