railties 7.2.1 → 8.0.0.beta1

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +111 -287
  3. data/lib/minitest/rails_plugin.rb +1 -1
  4. data/lib/rails/application/configuration.rb +15 -2
  5. data/lib/rails/application/default_middleware_stack.rb +4 -0
  6. data/lib/rails/application/finisher.rb +2 -2
  7. data/lib/rails/application/routes_reloader.rb +11 -1
  8. data/lib/rails/application.rb +5 -0
  9. data/lib/rails/code_statistics.rb +128 -86
  10. data/lib/rails/code_statistics_calculator.rb +78 -76
  11. data/lib/rails/command/helpers/editor.rb +1 -1
  12. data/lib/rails/commands/app/update_command.rb +1 -9
  13. data/lib/rails/commands/credentials/USAGE +4 -4
  14. data/lib/rails/commands/credentials/credentials_command.rb +5 -1
  15. data/lib/rails/commands/dev/dev_command.rb +1 -1
  16. data/lib/rails/commands/devcontainer/devcontainer_command.rb +1 -1
  17. data/lib/rails/commands/stats/stats_command.rb +19 -0
  18. data/lib/rails/dev_caching.rb +2 -2
  19. data/lib/rails/engine/configuration.rb +3 -1
  20. data/lib/rails/engine/lazy_route_set.rb +109 -0
  21. data/lib/rails/engine.rb +10 -5
  22. data/lib/rails/gem_version.rb +4 -4
  23. data/lib/rails/generators/app_base.rb +46 -24
  24. data/lib/rails/generators/database.rb +101 -67
  25. data/lib/rails/generators/erb/authentication/authentication_generator.rb +15 -0
  26. data/lib/rails/generators/erb/authentication/templates/views/passwords/edit.html.erb +9 -0
  27. data/lib/rails/generators/erb/authentication/templates/views/passwords/new.html.erb +8 -0
  28. data/lib/rails/generators/erb/authentication/templates/views/sessions/new.html.erb +11 -0
  29. data/lib/rails/generators/generated_attribute.rb +16 -11
  30. data/lib/rails/generators/rails/app/app_generator.rb +19 -32
  31. data/lib/rails/generators/rails/app/templates/Dockerfile.tt +12 -3
  32. data/lib/rails/generators/rails/app/templates/Gemfile.tt +23 -8
  33. data/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css.tt +6 -11
  34. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +10 -3
  35. data/lib/rails/generators/rails/app/templates/bin/dev.tt +1 -0
  36. data/lib/rails/generators/rails/app/templates/bin/setup.tt +5 -7
  37. data/lib/rails/generators/rails/app/templates/bin/thrust.tt +4 -0
  38. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +23 -0
  39. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +23 -0
  40. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +40 -0
  41. data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +23 -0
  42. data/lib/rails/generators/rails/app/templates/config/deploy.yml.tt +124 -0
  43. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +12 -23
  44. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +34 -51
  45. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +5 -19
  46. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +0 -7
  47. data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +1 -1
  48. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_8_0.rb.tt +25 -0
  49. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +11 -2
  50. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +3 -3
  51. data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +4 -3
  52. data/lib/rails/generators/rails/app/templates/dockerignore.tt +1 -2
  53. data/lib/rails/generators/rails/app/templates/github/ci.yml.tt +1 -1
  54. data/lib/rails/generators/rails/app/templates/gitignore.tt +1 -2
  55. data/lib/rails/generators/rails/app/templates/kamal-secrets.tt +17 -0
  56. data/lib/rails/generators/rails/app/templates/public/400.html +114 -0
  57. data/lib/rails/generators/rails/app/templates/public/404.html +113 -66
  58. data/lib/rails/generators/rails/app/templates/public/406-unsupported-browser.html +113 -65
  59. data/lib/rails/generators/rails/app/templates/public/422.html +113 -66
  60. data/lib/rails/generators/rails/app/templates/public/500.html +113 -65
  61. data/lib/rails/generators/rails/app/templates/public/icon.png +0 -0
  62. data/lib/rails/generators/rails/app/templates/public/icon.svg +2 -2
  63. data/lib/rails/generators/rails/authentication/USAGE +6 -0
  64. data/lib/rails/generators/rails/authentication/authentication_generator.rb +54 -0
  65. data/lib/rails/generators/rails/authentication/templates/controllers/concerns/authentication.rb +55 -0
  66. data/lib/rails/generators/rails/authentication/templates/controllers/passwords_controller.rb +33 -0
  67. data/lib/rails/generators/rails/authentication/templates/controllers/sessions_controller.rb +21 -0
  68. data/lib/rails/generators/rails/authentication/templates/mailers/passwords_mailer.rb +6 -0
  69. data/lib/rails/generators/rails/authentication/templates/models/current.rb +4 -0
  70. data/lib/rails/generators/rails/authentication/templates/models/session.rb +3 -0
  71. data/lib/rails/generators/rails/authentication/templates/models/user.rb +6 -0
  72. data/lib/rails/generators/rails/authentication/templates/test/mailers/previews/passwords_mailer_preview.rb +7 -0
  73. data/lib/rails/generators/rails/authentication/templates/views/passwords_mailer/reset.html.erb +4 -0
  74. data/lib/rails/generators/rails/authentication/templates/views/passwords_mailer/reset.text.erb +2 -0
  75. data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +4 -0
  76. data/lib/rails/generators/rails/db/system/change/change_generator.rb +1 -1
  77. data/lib/rails/generators/rails/devcontainer/devcontainer_generator.rb +5 -3
  78. data/lib/rails/generators/rails/devcontainer/templates/devcontainer/devcontainer.json.tt +1 -1
  79. data/lib/rails/generators/rails/plugin/plugin_generator.rb +11 -11
  80. data/lib/rails/generators/rails/plugin/templates/github/ci.yml.tt +1 -1
  81. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +2 -2
  82. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +2 -2
  83. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +3 -3
  84. data/lib/rails/generators/rails/script/USAGE +18 -0
  85. data/lib/rails/generators/rails/script/script_generator.rb +18 -0
  86. data/lib/rails/generators/rails/script/templates/script.rb.tt +3 -0
  87. data/lib/rails/generators.rb +7 -2
  88. data/lib/rails/info_controller.rb +10 -2
  89. data/lib/rails/rack/silence_request.rb +33 -0
  90. data/lib/rails/rack.rb +1 -0
  91. data/lib/rails/railtie.rb +13 -13
  92. data/lib/rails/source_annotation_extractor.rb +31 -14
  93. data/lib/rails/tasks/statistics.rake +13 -28
  94. data/lib/rails/templates/rails/info/notes.html.erb +65 -0
  95. metadata +45 -25
  96. data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -2
  97. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/channel.rb.tt +0 -4
  98. data/lib/rails/generators/rails/app/templates/app/channels/application_cable/connection.rb.tt +0 -4
  99. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_2.rb.tt +0 -70
  100. data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +0 -13
  101. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +0 -13
  102. data/lib/rails/generators/rails/plugin/templates/rails/dummy_manifest.js.tt +0 -10
  103. data/lib/rails/generators/rails/plugin/templates/rails/engine_manifest.js.tt +0 -6
  104. data/lib/rails/generators/rails/plugin/templates/rails/javascripts.js.tt +0 -17
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :markup: markdown
4
+
5
+ require "action_dispatch/routing/route_set"
6
+
7
+ module Rails
8
+ class Engine
9
+ class LazyRouteSet < ActionDispatch::Routing::RouteSet # :nodoc:
10
+ class NamedRouteCollection < ActionDispatch::Routing::RouteSet::NamedRouteCollection
11
+ def route_defined?(name)
12
+ Rails.application&.reload_routes_unless_loaded
13
+ super
14
+ end
15
+ end
16
+
17
+ module ProxyUrlHelpers
18
+ def url_for(options)
19
+ Rails.application&.reload_routes_unless_loaded
20
+ super
21
+ end
22
+
23
+ def full_url_for(options)
24
+ Rails.application&.reload_routes_unless_loaded
25
+ super
26
+ end
27
+
28
+ def route_for(name, *args)
29
+ Rails.application&.reload_routes_unless_loaded
30
+ super
31
+ end
32
+
33
+ def optimize_routes_generation?
34
+ Rails.application&.reload_routes_unless_loaded
35
+ super
36
+ end
37
+
38
+ def polymorphic_url(record_or_hash_or_array, options = {})
39
+ Rails.application&.reload_routes_unless_loaded
40
+ super
41
+ end
42
+
43
+ def polymorphic_path(record_or_hash_or_array, options = {})
44
+ Rails.application&.reload_routes_unless_loaded
45
+ super
46
+ end
47
+ end
48
+
49
+ def initialize(config = DEFAULT_CONFIG)
50
+ super
51
+ self.named_routes = NamedRouteCollection.new
52
+ named_routes.url_helpers_module.prepend(method_missing_module)
53
+ named_routes.path_helpers_module.prepend(method_missing_module)
54
+ end
55
+
56
+ def generate_extras(options, recall = {})
57
+ Rails.application&.reload_routes_unless_loaded
58
+
59
+ super(options, recall)
60
+ end
61
+
62
+ def generate_url_helpers(supports_path)
63
+ super.tap { |mod| mod.singleton_class.prepend(ProxyUrlHelpers) }
64
+ end
65
+
66
+ def call(req)
67
+ Rails.application&.reload_routes_unless_loaded
68
+ super
69
+ end
70
+
71
+ def draw(&block)
72
+ Rails.application&.reload_routes_unless_loaded
73
+ super
74
+ end
75
+
76
+ def recognize_path(path, environment = {})
77
+ Rails.application&.reload_routes_unless_loaded
78
+ super
79
+ end
80
+
81
+ def routes
82
+ Rails.application&.reload_routes_unless_loaded
83
+ super
84
+ end
85
+
86
+ private
87
+ def method_missing_module
88
+ @method_missing_module ||= Module.new do
89
+ private
90
+ def method_missing(method_name, *args, &block)
91
+ if Rails.application&.reload_routes_unless_loaded
92
+ public_send(method_name, *args, &block)
93
+ else
94
+ super(method_name, *args, &block)
95
+ end
96
+ end
97
+
98
+ def respond_to_missing?(method_name, *args)
99
+ if Rails.application&.reload_routes_unless_loaded
100
+ respond_to?(method_name, *args)
101
+ else
102
+ super(method_name, *args)
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
data/lib/rails/engine.rb CHANGED
@@ -6,7 +6,6 @@ require "active_support/callbacks"
6
6
  require "active_support/core_ext/module/delegation"
7
7
  require "active_support/core_ext/object/try"
8
8
  require "pathname"
9
- require "thread"
10
9
 
11
10
  module Rails
12
11
  # +Rails::Engine+ allows you to wrap a specific \Rails application or subset of
@@ -349,6 +348,7 @@ module Rails
349
348
  # config.railties_order = [Blog::Engine, :main_app, :all]
350
349
  class Engine < Railtie
351
350
  autoload :Configuration, "rails/engine/configuration"
351
+ autoload :LazyRouteSet, "rails/engine/lazy_route_set"
352
352
 
353
353
  class << self
354
354
  attr_accessor :called_from, :isolated
@@ -385,7 +385,8 @@ module Rails
385
385
  def isolate_namespace(mod)
386
386
  engine_name(generate_railtie_name(mod.name))
387
387
 
388
- routes.default_scope = { module: ActiveSupport::Inflector.underscore(mod.name) }
388
+ config.default_scope = { module: ActiveSupport::Inflector.underscore(mod.name) }
389
+
389
390
  self.isolated = true
390
391
 
391
392
  unless mod.respond_to?(:railtie_namespace)
@@ -543,7 +544,7 @@ module Rails
543
544
  # Defines the routes for this engine. If a block is given to
544
545
  # routes, it is appended to the engine.
545
546
  def routes(&block)
546
- @routes ||= ActionDispatch::Routing::RouteSet.new_with_config(config)
547
+ @routes ||= config.route_set_class.new_with_config(config)
547
548
  @routes.append(&block) if block_given?
548
549
  @routes
549
550
  end
@@ -588,6 +589,10 @@ module Rails
588
589
  config.eager_load_paths.freeze
589
590
  end
590
591
 
592
+ initializer :make_routes_lazy, before: :bootstrap_hook do |app|
593
+ config.route_set_class = LazyRouteSet if Rails.env.local?
594
+ end
595
+
591
596
  initializer :add_routing_paths do |app|
592
597
  routing_paths = paths["config/routes.rb"].existent
593
598
  external_paths = self.paths["config/routes"].paths
@@ -643,9 +648,9 @@ module Rails
643
648
  end
644
649
  end
645
650
 
646
- initializer :wrap_executor_around_load_seed do |app|
651
+ initializer :wrap_reloader_around_load_seed do |app|
647
652
  self.class.set_callback(:load_seed, :around) do |engine, seeds_block|
648
- app.executor.wrap(&seeds_block)
653
+ app.reloader.wrap(&seeds_block)
649
654
  end
650
655
  end
651
656
 
@@ -7,10 +7,10 @@ module Rails
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 7
11
- MINOR = 2
12
- TINY = 1
13
- PRE = nil
10
+ MAJOR = 8
11
+ MINOR = 0
12
+ TINY = 0
13
+ PRE = "beta1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -19,7 +19,6 @@ module Rails
19
19
 
20
20
  JAVASCRIPT_OPTIONS = %w( importmap bun webpack esbuild rollup )
21
21
  CSS_OPTIONS = %w( tailwind bootstrap bulma postcss sass )
22
- ASSET_PIPELINE_OPTIONS = %w( none sprockets propshaft )
23
22
 
24
23
  attr_accessor :rails_template
25
24
  add_shebang_option!
@@ -74,10 +73,6 @@ module Rails
74
73
 
75
74
  class_option :skip_asset_pipeline, type: :boolean, aliases: "-A", default: nil
76
75
 
77
- class_option :asset_pipeline, type: :string, aliases: "-a", default: "sprockets",
78
- enum: ASSET_PIPELINE_OPTIONS,
79
- desc: "Choose your asset pipeline"
80
-
81
76
  class_option :skip_javascript, type: :boolean, aliases: ["-J", "--skip-js"], default: (true if name == "plugin"),
82
77
  desc: "Skip JavaScript files"
83
78
 
@@ -99,6 +94,9 @@ module Rails
99
94
  class_option :skip_dev_gems, type: :boolean, default: nil,
100
95
  desc: "Skip development gems (e.g., web-console)"
101
96
 
97
+ class_option :skip_thruster, type: :boolean, default: nil,
98
+ desc: "Skip Thruster setup"
99
+
102
100
  class_option :skip_rubocop, type: :boolean, default: nil,
103
101
  desc: "Skip RuboCop setup"
104
102
 
@@ -108,10 +106,16 @@ module Rails
108
106
  class_option :skip_ci, type: :boolean, default: nil,
109
107
  desc: "Skip GitHub CI files"
110
108
 
109
+ class_option :skip_kamal, type: :boolean, default: nil,
110
+ desc: "Skip Kamal setup"
111
+
112
+ class_option :skip_solid, type: :boolean, default: nil,
113
+ desc: "Skip Solid Cache & Queue setup"
114
+
111
115
  class_option :dev, type: :boolean, default: nil,
112
116
  desc: "Set up the #{name} with Gemfile pointing to your Rails checkout"
113
117
 
114
- class_option :devcontainer, type: :boolean, default: false,
118
+ class_option :devcontainer, type: :boolean, default: nil,
115
119
  desc: "Generate devcontainer files"
116
120
 
117
121
  class_option :edge, type: :boolean, default: nil,
@@ -197,7 +201,7 @@ module Rails
197
201
 
198
202
  OPTION_IMPLICATIONS = { # :nodoc:
199
203
  skip_active_job: [:skip_action_mailer, :skip_active_storage],
200
- skip_active_record: [:skip_active_storage],
204
+ skip_active_record: [:skip_active_storage, :skip_solid],
201
205
  skip_active_storage: [:skip_action_mailbox, :skip_action_text],
202
206
  skip_javascript: [:skip_hotwire],
203
207
  }
@@ -287,12 +291,7 @@ module Rails
287
291
  end
288
292
 
289
293
  def asset_pipeline_gemfile_entry
290
- return if skip_asset_pipeline?
291
-
292
- if options[:asset_pipeline] == "sprockets"
293
- GemfileEntry.floats "sprockets-rails",
294
- "The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]"
295
- elsif options[:asset_pipeline] == "propshaft"
294
+ unless skip_asset_pipeline?
296
295
  GemfileEntry.floats "propshaft", "The modern asset pipeline for Rails [https://github.com/rails/propshaft]"
297
296
  end
298
297
  end
@@ -386,12 +385,8 @@ module Rails
386
385
  options[:skip_asset_pipeline]
387
386
  end
388
387
 
389
- def skip_sprockets?
390
- skip_asset_pipeline? || options[:asset_pipeline] != "sprockets"
391
- end
392
-
393
- def skip_propshaft?
394
- skip_asset_pipeline? || options[:asset_pipeline] != "propshaft"
388
+ def skip_thruster?
389
+ options[:skip_thruster]
395
390
  end
396
391
 
397
392
  def skip_rubocop?
@@ -414,6 +409,14 @@ module Rails
414
409
  options[:devcontainer]
415
410
  end
416
411
 
412
+ def skip_kamal?
413
+ options[:skip_kamal]
414
+ end
415
+
416
+ def skip_solid?
417
+ options[:skip_solid]
418
+ end
419
+
417
420
  class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out)
418
421
  def initialize(name, version, comment, options = {}, commented_out = false)
419
422
  super
@@ -572,7 +575,7 @@ module Rails
572
575
  end
573
576
 
574
577
  def dockerfile_base_packages
575
- # Add curl to work with the default healthcheck strategy in Kamal
578
+ # Add curl to work with the default health check strategy in Kamal
576
579
  packages = ["curl"]
577
580
 
578
581
  # ActiveRecord databases
@@ -620,10 +623,10 @@ module Rails
620
623
  end
621
624
 
622
625
  def cable_gemfile_entry
623
- return if options[:skip_action_cable]
624
-
625
- comment = "Use Redis adapter to run Action Cable in production"
626
- GemfileEntry.new("redis", ">= 4.0.1", comment, {}, true)
626
+ if !options[:skip_action_cable] && options[:skip_solid]
627
+ comment = "Use Redis adapter to run Action Cable in production"
628
+ GemfileEntry.new("redis", ">= 4.0.1", comment, {}, true)
629
+ end
627
630
  end
628
631
 
629
632
  def bundle_command(command, env = {})
@@ -721,6 +724,25 @@ module Rails
721
724
  end
722
725
  end
723
726
 
727
+ def run_kamal
728
+ return if options[:skip_kamal] || !bundle_install?
729
+
730
+ bundle_command "binstubs kamal"
731
+ bundle_command "exec kamal init"
732
+
733
+ template "kamal-secrets.tt", ".kamal/secrets", force: true
734
+ template "config/deploy.yml", force: true
735
+ end
736
+
737
+ def run_solid
738
+ return if skip_solid? || !bundle_install?
739
+
740
+ commands = "solid_cache:install solid_queue:install"
741
+ commands += " solid_cable:install" unless skip_action_cable?
742
+
743
+ rails_command commands
744
+ end
745
+
724
746
  def add_bundler_platforms
725
747
  if bundle_install?
726
748
  # The vast majority of Rails apps will be deployed on `x86_64-linux`.
@@ -3,25 +3,91 @@
3
3
  module Rails
4
4
  module Generators
5
5
  class Database
6
- DATABASES = %w( mysql trilogy postgresql sqlite3 )
6
+ DATABASES = %w( mysql trilogy postgresql sqlite3 mariadb-mysql mariadb-trilogy )
7
+
8
+ module MySQL
9
+ def name
10
+ "mysql"
11
+ end
12
+
13
+ def port
14
+ 3306
15
+ end
16
+
17
+ def service
18
+ {
19
+ "image" => "mysql/mysql-server:8.0",
20
+ "restart" => "unless-stopped",
21
+ "environment" => {
22
+ "MYSQL_ALLOW_EMPTY_PASSWORD" => "true",
23
+ "MYSQL_ROOT_HOST" => "%"
24
+ },
25
+ "volumes" => ["mysql-data:/var/lib/mysql"],
26
+ "networks" => ["default"],
27
+ }
28
+ end
29
+
30
+ def socket
31
+ @socket ||= [
32
+ "/tmp/mysql.sock", # default
33
+ "/var/run/mysqld/mysqld.sock", # debian/gentoo
34
+ "/var/tmp/mysql.sock", # freebsd
35
+ "/var/lib/mysql/mysql.sock", # fedora
36
+ "/opt/local/lib/mysql/mysql.sock", # fedora
37
+ "/opt/local/var/run/mysqld/mysqld.sock", # mac + darwinports + mysql
38
+ "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4
39
+ "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5
40
+ "/opt/lampp/var/mysql/mysql.sock" # xampp for linux
41
+ ].find { |f| File.exist?(f) } unless Gem.win_platform?
42
+ end
43
+
44
+ def host
45
+ "127.0.0.1"
46
+ end
47
+ end
48
+
49
+ module MariaDB
50
+ def name
51
+ "mariadb"
52
+ end
53
+
54
+ def port
55
+ 3306
56
+ end
57
+
58
+ def service
59
+ {
60
+ "image" => "mariadb:10.5",
61
+ "restart" => "unless-stopped",
62
+ "networks" => ["default"],
63
+ "volumes" => ["mariadb-data:/var/lib/mysql"],
64
+ "environment" => {
65
+ "MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" => "true",
66
+ },
67
+ }
68
+ end
69
+ end
7
70
 
8
71
  class << self
9
72
  def build(database_name)
10
73
  case database_name
11
- when "mysql" then MySQL.new
74
+ when "mysql" then MySQL2.new
12
75
  when "postgresql" then PostgreSQL.new
13
- when "trilogy" then MariaDB.new
76
+ when "trilogy" then Trilogy.new
14
77
  when "sqlite3" then SQLite3.new
78
+ when "mariadb-mysql" then MariaDBMySQL2.new
79
+ when "mariadb-trilogy" then MariaDBTrilogy.new
15
80
  else Null.new
16
81
  end
17
82
  end
18
83
 
19
84
  def all
20
85
  @all ||= [
21
- MySQL.new,
86
+ MySQL2.new,
22
87
  PostgreSQL.new,
23
- MariaDB.new,
24
88
  SQLite3.new,
89
+ MariaDBMySQL2.new,
90
+ MariaDBTrilogy.new
25
91
  ]
26
92
  end
27
93
  end
@@ -30,6 +96,10 @@ module Rails
30
96
  raise NotImplementedError
31
97
  end
32
98
 
99
+ def template
100
+ raise NotImplementedError
101
+ end
102
+
33
103
  def service
34
104
  raise NotImplementedError
35
105
  end
@@ -69,48 +139,11 @@ module Rails
69
139
  "#{name}-data"
70
140
  end
71
141
 
72
- module MySqlSocket
73
- def socket
74
- @socket ||= [
75
- "/tmp/mysql.sock", # default
76
- "/var/run/mysqld/mysqld.sock", # debian/gentoo
77
- "/var/tmp/mysql.sock", # freebsd
78
- "/var/lib/mysql/mysql.sock", # fedora
79
- "/opt/local/lib/mysql/mysql.sock", # fedora
80
- "/opt/local/var/run/mysqld/mysqld.sock", # mac + darwinports + mysql
81
- "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4
82
- "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5
83
- "/opt/lampp/var/mysql/mysql.sock" # xampp for linux
84
- ].find { |f| File.exist?(f) } unless Gem.win_platform?
85
- end
86
-
87
- def host
88
- "localhost"
89
- end
90
- end
91
-
92
- class MySQL < Database
93
- include MySqlSocket
142
+ class MySQL2 < Database
143
+ include MySQL
94
144
 
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
145
+ def template
146
+ "config/databases/mysql.yml"
114
147
  end
115
148
 
116
149
  def gem
@@ -135,6 +168,10 @@ module Rails
135
168
  "postgres"
136
169
  end
137
170
 
171
+ def template
172
+ "config/databases/postgresql.yml"
173
+ end
174
+
138
175
  def service
139
176
  {
140
177
  "image" => "postgres:16.1",
@@ -169,27 +206,11 @@ module Rails
169
206
  end
170
207
  end
171
208
 
172
- class MariaDB < Database
173
- include MySqlSocket
209
+ class Trilogy < Database
210
+ include MySQL
174
211
 
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
212
+ def template
213
+ "config/databases/trilogy.yml"
193
214
  end
194
215
 
195
216
  def gem
@@ -214,6 +235,10 @@ module Rails
214
235
  "sqlite3"
215
236
  end
216
237
 
238
+ def template
239
+ "config/databases/sqlite3.yml"
240
+ end
241
+
217
242
  def service
218
243
  nil
219
244
  end
@@ -223,7 +248,7 @@ module Rails
223
248
  end
224
249
 
225
250
  def gem
226
- ["sqlite3", [">= 1.4"]]
251
+ ["sqlite3", [">= 2.1"]]
227
252
  end
228
253
 
229
254
  def base_package
@@ -239,8 +264,17 @@ module Rails
239
264
  end
240
265
  end
241
266
 
267
+ class MariaDBMySQL2 < MySQL2
268
+ include MariaDB
269
+ end
270
+
271
+ class MariaDBTrilogy < Trilogy
272
+ include MariaDB
273
+ end
274
+
242
275
  class Null < Database
243
276
  def name; end
277
+ def template; end
244
278
  def service; end
245
279
  def port; end
246
280
  def volume; end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/erb"
4
+
5
+ module Erb # :nodoc:
6
+ module Generators # :nodoc:
7
+ class AuthenticationGenerator < Rails::Generators::Base # :nodoc:
8
+ def create_files
9
+ template "views/passwords/new.html.erb", File.join("app/views/passwords/new.html.erb")
10
+ template "views/passwords/edit.html.erb", File.join("app/views/passwords/edit.html.erb")
11
+ template "views/sessions/new.html.erb", File.join("app/views/sessions/new.html.erb")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ <h1>Update your password</h2>
2
+
3
+ <%%= tag.div(flash[:alert], style: "color:red") if flash[:alert] %>
4
+
5
+ <%%= form_with url: password_path(params[:token]), method: :put do |form| %>
6
+ <%%= form.password_field :password, required: true, autocomplete: "new-password", placeholder: "Enter new password", maxlength: 72 %><br>
7
+ <%%= form.password_field :password_confirmation, required: true, autocomplete: "new-password", placeholder: "Repeat new password", maxlength: 72 %><br>
8
+ <%%= form.submit "Save" %>
9
+ <%% end %>
@@ -0,0 +1,8 @@
1
+ <h1>Forgot your password?</h1>
2
+
3
+ <%%= tag.div(flash[:alert], style: "color:red") if flash[:alert] %>
4
+
5
+ <%%= form_with url: passwords_path do |form| %>
6
+ <%%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address] %><br>
7
+ <%%= form.submit "Email reset instructions" %>
8
+ <%% end %>
@@ -0,0 +1,11 @@
1
+ <%%= tag.div(flash[:alert], style: "color:red") if flash[:alert] %>
2
+ <%%= tag.div(flash[:notice], style: "color:green") if flash[:notice] %>
3
+
4
+ <%%= form_with url: session_path do |form| %>
5
+ <%%= form.email_field :email_address, required: true, autofocus: true, autocomplete: "username", placeholder: "Enter your email address", value: params[:email_address] %><br>
6
+ <%%= form.password_field :password, required: true, autocomplete: "current-password", placeholder: "Enter your password", maxlength: 72 %><br>
7
+ <%%= form.submit "Sign in" %>
8
+ <%% end %>
9
+ <br>
10
+
11
+ <%%= link_to "Forgot password?", new_password_path %>
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/time"
4
+ require "active_support/core_ext/string/starts_ends_with"
4
5
 
5
6
  module Rails
6
7
  module Generators
@@ -89,20 +90,24 @@ module Rails
89
90
  def parse_type_and_options(type)
90
91
  case type
91
92
  when /(text|binary)\{([a-z]+)\}/
92
- return $1, size: $2.to_sym
93
+ parsed_type, parsed_options = $1, { size: $2.to_sym }
93
94
  when /(string|text|binary|integer)\{(\d+)\}/
94
- return $1, limit: $2.to_i
95
+ parsed_type, parsed_options = $1, { limit: $2.to_i }
95
96
  when /decimal\{(\d+)[,.-](\d+)\}/
96
- return :decimal, precision: $1.to_i, scale: $2.to_i
97
+ parsed_type, parsed_options = :decimal, { precision: $1.to_i, scale: $2.to_i }
97
98
  when /(references|belongs_to)\{(.+)\}/
98
- type = $1
99
+ parsed_type = $1
99
100
  provided_options = $2.split(/[,.-]/)
100
- options = Hash[provided_options.map { |opt| [opt.to_sym, true] }]
101
-
102
- return type, options
101
+ parsed_options = Hash[provided_options.map { |opt| [opt.to_sym, true] }]
103
102
  else
104
- return type, {}
103
+ parsed_type, parsed_options = type&.remove("!"), {}
104
+ end
105
+
106
+ if type&.ends_with?("!")
107
+ parsed_options[:null] = false
105
108
  end
109
+
110
+ return parsed_type, parsed_options
106
111
  end
107
112
  end
108
113
 
@@ -121,9 +126,9 @@ module Rails
121
126
  when :time then :time_field
122
127
  when :datetime, :timestamp then :datetime_field
123
128
  when :date then :date_field
124
- when :text then :text_area
125
- when :rich_text then :rich_text_area
126
- when :boolean then :check_box
129
+ when :text then :textarea
130
+ when :rich_text then :rich_textarea
131
+ when :boolean then :checkbox
127
132
  when :attachment, :attachments then :file_field
128
133
  else
129
134
  :text_field