railties 5.2.3 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +306 -126
  3. data/MIT-LICENSE +1 -1
  4. data/RDOC_MAIN.rdoc +38 -31
  5. data/README.rdoc +2 -2
  6. data/lib/minitest/rails_plugin.rb +7 -11
  7. data/lib/rails.rb +5 -0
  8. data/lib/rails/all.rb +4 -0
  9. data/lib/rails/api/generator.rb +2 -1
  10. data/lib/rails/api/task.rb +16 -0
  11. data/lib/rails/app_loader.rb +2 -2
  12. data/lib/rails/app_updater.rb +3 -1
  13. data/lib/rails/application.rb +71 -29
  14. data/lib/rails/application/bootstrap.rb +2 -10
  15. data/lib/rails/application/configuration.rb +113 -13
  16. data/lib/rails/application/default_middleware_stack.rb +3 -0
  17. data/lib/rails/application/dummy_erb_compiler.rb +18 -0
  18. data/lib/rails/application/finisher.rb +54 -0
  19. data/lib/rails/autoloaders.rb +48 -0
  20. data/lib/rails/backtrace_cleaner.rb +5 -17
  21. data/lib/rails/code_statistics.rb +3 -3
  22. data/lib/rails/command.rb +11 -10
  23. data/lib/rails/command/base.rb +12 -4
  24. data/lib/rails/command/behavior.rb +7 -48
  25. data/lib/rails/command/environment_argument.rb +8 -15
  26. data/lib/rails/command/spellchecker.rb +58 -0
  27. data/lib/rails/commands/console/console_command.rb +6 -0
  28. data/lib/rails/commands/credentials/USAGE +19 -1
  29. data/lib/rails/commands/credentials/credentials_command.rb +52 -19
  30. data/lib/rails/commands/db/system/change/change_command.rb +20 -0
  31. data/lib/rails/commands/dbconsole/dbconsole_command.rb +20 -8
  32. data/lib/rails/commands/dev/dev_command.rb +19 -0
  33. data/lib/rails/commands/encrypted/USAGE +1 -1
  34. data/lib/rails/commands/encrypted/encrypted_command.rb +2 -2
  35. data/lib/rails/commands/help/help_command.rb +1 -1
  36. data/lib/rails/commands/initializers/initializers_command.rb +23 -0
  37. data/lib/rails/commands/new/new_command.rb +2 -2
  38. data/lib/rails/commands/notes/notes_command.rb +39 -0
  39. data/lib/rails/commands/plugin/plugin_command.rb +1 -1
  40. data/lib/rails/commands/routes/routes_command.rb +37 -0
  41. data/lib/rails/commands/runner/runner_command.rb +13 -9
  42. data/lib/rails/commands/secrets/USAGE +3 -3
  43. data/lib/rails/commands/secrets/secrets_command.rb +3 -3
  44. data/lib/rails/commands/server/server_command.rb +113 -50
  45. data/lib/rails/configuration.rb +1 -7
  46. data/lib/rails/engine.rb +32 -18
  47. data/lib/rails/engine/configuration.rb +5 -2
  48. data/lib/rails/gem_version.rb +3 -3
  49. data/lib/rails/generators.rb +11 -10
  50. data/lib/rails/generators/actions.rb +52 -39
  51. data/lib/rails/generators/app_base.rb +59 -97
  52. data/lib/rails/generators/app_name.rb +50 -0
  53. data/lib/rails/generators/database.rb +58 -0
  54. data/lib/rails/generators/erb/mailer/mailer_generator.rb +1 -1
  55. data/lib/rails/generators/erb/scaffold/templates/_form.html.erb.tt +6 -3
  56. data/lib/rails/generators/erb/scaffold/templates/index.html.erb.tt +1 -1
  57. data/lib/rails/generators/erb/scaffold/templates/show.html.erb.tt +9 -1
  58. data/lib/rails/generators/generated_attribute.rb +53 -27
  59. data/lib/rails/generators/migration.rb +1 -2
  60. data/lib/rails/generators/model_helpers.rb +8 -1
  61. data/lib/rails/generators/named_base.rb +1 -5
  62. data/lib/rails/generators/rails/app/app_generator.rb +37 -71
  63. data/lib/rails/generators/rails/app/templates/Gemfile.tt +7 -10
  64. data/lib/rails/generators/rails/app/templates/app/assets/config/manifest.js.tt +0 -3
  65. data/lib/rails/generators/rails/app/templates/app/{assets/javascripts/cable.js.tt → javascript/channels/consumer.js} +2 -9
  66. data/lib/rails/generators/rails/app/templates/app/javascript/channels/index.js +5 -0
  67. data/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt +23 -0
  68. data/lib/rails/generators/rails/app/templates/app/jobs/application_job.rb.tt +5 -0
  69. data/lib/rails/generators/rails/app/templates/app/views/layouts/application.html.erb.tt +4 -4
  70. data/lib/rails/generators/rails/app/templates/bin/setup.tt +7 -7
  71. data/lib/rails/generators/rails/app/templates/config/application.rb.tt +2 -0
  72. data/lib/rails/generators/rails/app/templates/config/cable.yml.tt +1 -1
  73. data/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml.tt +2 -2
  74. data/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml.tt +2 -2
  75. data/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +2 -2
  76. data/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +3 -3
  77. data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +3 -3
  78. data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +1 -1
  79. data/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +4 -4
  80. data/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +2 -2
  81. data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +6 -6
  82. data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +1 -1
  83. data/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +2 -2
  84. data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +5 -2
  85. data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +28 -12
  86. data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +13 -7
  87. data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +1 -1
  88. data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +7 -0
  89. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt +45 -0
  90. data/lib/rails/generators/rails/app/templates/config/locales/en.yml +1 -1
  91. data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +7 -3
  92. data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +1 -1
  93. data/lib/rails/generators/rails/app/templates/config/spring.rb.tt +6 -6
  94. data/lib/rails/generators/rails/app/templates/gitignore.tt +2 -7
  95. data/lib/rails/generators/rails/app/templates/package.json.tt +7 -1
  96. data/lib/rails/generators/rails/app/templates/public/robots.txt +1 -1
  97. data/lib/rails/generators/rails/app/templates/ruby-version.tt +1 -1
  98. data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +11 -0
  99. data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +7 -0
  100. data/lib/rails/generators/rails/assets/USAGE +1 -4
  101. data/lib/rails/generators/rails/assets/assets_generator.rb +0 -1
  102. data/lib/rails/generators/rails/controller/controller_generator.rb +11 -1
  103. data/lib/rails/generators/rails/credentials/credentials_generator.rb +7 -8
  104. data/lib/rails/generators/rails/db/system/change/change_generator.rb +65 -0
  105. data/lib/rails/generators/rails/encrypted_file/encrypted_file_generator.rb +4 -5
  106. data/lib/rails/generators/rails/helper/helper_generator.rb +5 -0
  107. data/lib/rails/generators/rails/plugin/plugin_generator.rb +9 -33
  108. data/lib/rails/generators/rails/plugin/templates/app/controllers/%namespaced_name%/application_controller.rb.tt +1 -1
  109. data/lib/rails/generators/rails/plugin/templates/app/helpers/%namespaced_name%/application_helper.rb.tt +1 -1
  110. data/lib/rails/generators/rails/plugin/templates/app/jobs/%namespaced_name%/application_job.rb.tt +1 -1
  111. data/lib/rails/generators/rails/plugin/templates/app/mailers/%namespaced_name%/application_mailer.rb.tt +1 -1
  112. data/lib/rails/generators/rails/plugin/templates/app/models/%namespaced_name%/application_record.rb.tt +1 -1
  113. data/lib/rails/generators/rails/plugin/templates/gitignore.tt +1 -1
  114. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/engine.rb.tt +1 -1
  115. data/lib/rails/generators/rails/plugin/templates/lib/%namespaced_name%/railtie.rb.tt +1 -1
  116. data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +1 -2
  117. data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +14 -0
  118. data/lib/rails/generators/rails/scaffold_controller/templates/api_controller.rb.tt +1 -1
  119. data/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.tt +1 -1
  120. data/lib/rails/generators/resource_helpers.rb +1 -6
  121. data/lib/rails/generators/test_unit/integration/integration_generator.rb +6 -0
  122. data/lib/rails/generators/test_unit/job/job_generator.rb +5 -0
  123. data/lib/rails/generators/test_unit/mailer/mailer_generator.rb +1 -1
  124. data/lib/rails/generators/test_unit/model/templates/fixtures.yml.tt +2 -2
  125. data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +8 -3
  126. data/lib/rails/generators/test_unit/system/system_generator.rb +5 -0
  127. data/lib/rails/generators/testing/behaviour.rb +3 -0
  128. data/lib/rails/info.rb +2 -2
  129. data/lib/rails/info_controller.rb +1 -1
  130. data/lib/rails/mailers_controller.rb +7 -4
  131. data/lib/rails/paths.rb +19 -9
  132. data/lib/rails/railtie.rb +1 -1
  133. data/lib/rails/ruby_version_check.rb +3 -3
  134. data/lib/rails/secrets.rb +0 -1
  135. data/lib/rails/source_annotation_extractor.rb +138 -117
  136. data/lib/rails/tasks.rb +1 -0
  137. data/lib/rails/tasks/annotations.rake +9 -9
  138. data/lib/rails/tasks/dev.rake +5 -4
  139. data/lib/rails/tasks/framework.rake +5 -1
  140. data/lib/rails/tasks/initializers.rake +5 -4
  141. data/lib/rails/tasks/log.rake +0 -1
  142. data/lib/rails/tasks/routes.rake +4 -26
  143. data/lib/rails/tasks/statistics.rake +4 -0
  144. data/lib/rails/tasks/yarn.rake +1 -1
  145. data/lib/rails/tasks/zeitwerk.rake +66 -0
  146. data/lib/rails/templates/rails/welcome/index.html.erb +2 -2
  147. data/lib/rails/test_help.rb +11 -9
  148. data/lib/rails/test_unit/reporter.rb +1 -1
  149. data/lib/rails/test_unit/runner.rb +5 -5
  150. data/lib/rails/test_unit/testing.rake +1 -1
  151. metadata +31 -22
  152. data/lib/rails/generators/js/assets/assets_generator.rb +0 -15
  153. data/lib/rails/generators/js/assets/templates/javascript.js +0 -2
  154. data/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +0 -22
  155. data/lib/rails/generators/rails/app/templates/bin/bundle.tt +0 -2
  156. data/lib/rails/generators/rails/app/templates/bin/update.tt +0 -34
  157. data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_5_2.rb.tt +0 -38
  158. data/lib/rails/generators/rails/assets/templates/javascript.js +0 -2
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module Generators
5
+ module AppName # :nodoc:
6
+ RESERVED_NAMES = %w(application destroy plugin runner test)
7
+
8
+ private
9
+ def app_name
10
+ @app_name ||= original_app_name.tr('\\', "").tr("-. ", "_")
11
+ end
12
+
13
+ def original_app_name
14
+ @original_app_name ||= defined_app_const_base? ? defined_app_name : File.basename(destination_root)
15
+ end
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
+ def app_const_base
29
+ @app_const_base ||= defined_app_const_base || app_name.gsub(/\W/, "_").squeeze("_").camelize
30
+ end
31
+ alias :camelized :app_const_base
32
+
33
+ def app_const
34
+ @app_const ||= "#{app_const_base}::Application"
35
+ end
36
+
37
+ def valid_const?
38
+ if /^\d/.match?(app_const)
39
+ raise Error, "Invalid application name #{original_app_name}. Please give a name which does not start with numbers."
40
+ elsif RESERVED_NAMES.include?(original_app_name)
41
+ raise Error, "Invalid application name #{original_app_name}. Please give a " \
42
+ "name which does not match one of the reserved rails " \
43
+ "words: #{RESERVED_NAMES.join(", ")}"
44
+ elsif Object.const_defined?(app_const_base)
45
+ raise Error, "Invalid application name #{original_app_name}, constant #{app_const_base} is already in use. Please choose another application name."
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module Generators
5
+ module Database # :nodoc:
6
+ JDBC_DATABASES = %w( jdbcmysql jdbcsqlite3 jdbcpostgresql jdbc )
7
+ DATABASES = %w( mysql postgresql sqlite3 oracle frontbase ibm_db 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.4.4"]]
17
+ when "postgresql" then ["pg", [">= 0.18", "< 2.0"]]
18
+ when "sqlite3" then ["sqlite3", ["~> 1.4"]]
19
+ when "oracle" then ["activerecord-oracle_enhanced-adapter", nil]
20
+ when "frontbase" then ["ruby-frontbase", nil]
21
+ when "sqlserver" then ["activerecord-sqlserver-adapter", nil]
22
+ when "jdbcmysql" then ["activerecord-jdbcmysql-adapter", nil]
23
+ when "jdbcsqlite3" then ["activerecord-jdbcsqlite3-adapter", nil]
24
+ when "jdbcpostgresql" then ["activerecord-jdbcpostgresql-adapter", nil]
25
+ when "jdbc" then ["activerecord-jdbc-adapter", nil]
26
+ else [database, nil]
27
+ end
28
+ end
29
+
30
+ def convert_database_option_for_jruby
31
+ if defined?(JRUBY_VERSION)
32
+ opt = options.dup
33
+ case opt[:database]
34
+ when "postgresql" then opt[:database] = "jdbcpostgresql"
35
+ when "mysql" then opt[:database] = "jdbcmysql"
36
+ when "sqlite3" then opt[:database] = "jdbcsqlite3"
37
+ end
38
+ self.options = opt.freeze
39
+ end
40
+ end
41
+
42
+ private
43
+ def mysql_socket
44
+ @mysql_socket ||= [
45
+ "/tmp/mysql.sock", # default
46
+ "/var/run/mysqld/mysqld.sock", # debian/gentoo
47
+ "/var/tmp/mysql.sock", # freebsd
48
+ "/var/lib/mysql/mysql.sock", # fedora
49
+ "/opt/local/lib/mysql/mysql.sock", # fedora
50
+ "/opt/local/var/run/mysqld/mysqld.sock", # mac + darwinports + mysql
51
+ "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4
52
+ "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5
53
+ "/opt/lampp/var/mysql/mysql.sock" # xampp for linux
54
+ ].find { |f| File.exist?(f) } unless Gem.win_platform?
55
+ end
56
+ end
57
+ end
58
+ end
@@ -35,7 +35,7 @@ module Erb # :nodoc:
35
35
  end
36
36
 
37
37
  def file_name
38
- @_file_name ||= super.gsub(/_mailer/i, "")
38
+ @_file_name ||= super.sub(/_mailer\z/i, "")
39
39
  end
40
40
  end
41
41
  end
@@ -4,9 +4,9 @@
4
4
  <h2><%%= pluralize(<%= singular_table_name %>.errors.count, "error") %> prohibited this <%= singular_table_name %> from being saved:</h2>
5
5
 
6
6
  <ul>
7
- <%% <%= singular_table_name %>.errors.full_messages.each do |message| %>
8
- <li><%%= message %></li>
9
- <%% end %>
7
+ <%% <%= singular_table_name %>.errors.full_messages.each do |message| %>
8
+ <li><%%= message %></li>
9
+ <%% end %>
10
10
  </ul>
11
11
  </div>
12
12
  <%% end %>
@@ -21,6 +21,9 @@
21
21
  <div class="field">
22
22
  <%%= form.label :password_confirmation %>
23
23
  <%%= form.password_field :password_confirmation %>
24
+ <% elsif attribute.attachments? -%>
25
+ <%%= form.label :<%= attribute.column_name %> %>
26
+ <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %>, multiple: true %>
24
27
  <% else -%>
25
28
  <%%= form.label :<%= attribute.column_name %> %>
26
29
  <%%= form.<%= attribute.field_type %> :<%= attribute.column_name %> %>
@@ -16,7 +16,7 @@
16
16
  <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
17
17
  <tr>
18
18
  <% attributes.reject(&:password_digest?).each do |attribute| -%>
19
- <td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td>
19
+ <td><%%= <%= singular_table_name %>.<%= attribute.column_name %> %></td>
20
20
  <% end -%>
21
21
  <td><%%= link_to 'Show', <%= model_resource_name %> %></td>
22
22
  <td><%%= link_to 'Edit', edit_<%= singular_route_name %>_path(<%= singular_table_name %>) %></td>
@@ -3,7 +3,15 @@
3
3
  <% attributes.reject(&:password_digest?).each do |attribute| -%>
4
4
  <p>
5
5
  <strong><%= attribute.human_name %>:</strong>
6
- <%%= @<%= singular_table_name %>.<%= attribute.name %> %>
6
+ <% if attribute.attachment? -%>
7
+ <%%= link_to @<%= singular_table_name %>.<%= attribute.column_name %>.filename, @<%= singular_table_name %>.<%= attribute.column_name %> if @<%= singular_table_name %>.<%= attribute.column_name %>.attached? %>
8
+ <% elsif attribute.attachments? -%>
9
+ <%% @<%= singular_table_name %>.<%= attribute.column_name %>.each do |<%= attribute.singular_name %>| %>
10
+ <div><%%= link_to <%= attribute.singular_name %>.filename, <%= attribute.singular_name %> %></div>
11
+ <%% end %>
12
+ <% else -%>
13
+ <%%= @<%= singular_table_name %>.<%= attribute.column_name %> %>
14
+ <% end -%>
7
15
  </p>
8
16
 
9
17
  <% end -%>
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/time"
4
+ require "active_support/deprecation"
4
5
 
5
6
  module Rails
6
7
  module Generators
@@ -39,23 +40,29 @@ module Rails
39
40
 
40
41
  private
41
42
 
42
- # parse possible attribute options like :limit for string/text/binary/integer, :precision/:scale for decimals or :polymorphic for references/belongs_to
43
- # when declaring options curly brackets should be used
44
- def parse_type_and_options(type)
45
- case type
46
- when /(string|text|binary|integer)\{(\d+)\}/
47
- return $1, limit: $2.to_i
48
- when /decimal\{(\d+)[,.-](\d+)\}/
49
- return :decimal, precision: $1.to_i, scale: $2.to_i
50
- when /(references|belongs_to)\{(.+)\}/
51
- type = $1
52
- provided_options = $2.split(/[,.-]/)
53
- options = Hash[provided_options.map { |opt| [opt.to_sym, true] }]
54
- return type, options
55
- else
56
- return type, {}
43
+ # parse possible attribute options like :limit for string/text/binary/integer, :precision/:scale for decimals or :polymorphic for references/belongs_to
44
+ # when declaring options curly brackets should be used
45
+ def parse_type_and_options(type)
46
+ case type
47
+ when /(string|text|binary|integer)\{(\d+)\}/
48
+ return $1, limit: $2.to_i
49
+ when /decimal\{(\d+)[,.-](\d+)\}/
50
+ return :decimal, precision: $1.to_i, scale: $2.to_i
51
+ when /(references|belongs_to)\{(.+)\}/
52
+ type = $1
53
+ provided_options = $2.split(/[,.-]/)
54
+ options = Hash[provided_options.map { |opt| [opt.to_sym, true] }]
55
+
56
+ if options[:required]
57
+ ActiveSupport::Deprecation.warn("Passing {required} option has no effect on the model generator. It will be removed in Rails 6.1.\n")
58
+ options.delete(:required)
59
+ end
60
+
61
+ return type, options
62
+ else
63
+ return type, {}
64
+ end
57
65
  end
58
- end
59
66
  end
60
67
 
61
68
  def initialize(name, type = nil, index_type = false, attr_options = {})
@@ -68,13 +75,15 @@ module Rails
68
75
 
69
76
  def field_type
70
77
  @field_type ||= case type
71
- when :integer then :number_field
72
- when :float, :decimal then :text_field
73
- when :time then :time_select
74
- when :datetime, :timestamp then :datetime_select
75
- when :date then :date_select
76
- when :text then :text_area
77
- when :boolean then :check_box
78
+ when :integer then :number_field
79
+ when :float, :decimal then :text_field
80
+ when :time then :time_select
81
+ when :datetime, :timestamp then :datetime_select
82
+ when :date then :date_select
83
+ when :text then :text_area
84
+ when :rich_text then :rich_text_area
85
+ when :boolean then :check_box
86
+ when :attachment, :attachments then :file_field
78
87
  else
79
88
  :text_field
80
89
  end
@@ -90,7 +99,9 @@ module Rails
90
99
  when :string then name == "type" ? "" : "MyString"
91
100
  when :text then "MyText"
92
101
  when :boolean then false
93
- when :references, :belongs_to then nil
102
+ when :references, :belongs_to,
103
+ :attachment, :attachments,
104
+ :rich_text then nil
94
105
  else
95
106
  ""
96
107
  end
@@ -133,7 +144,7 @@ module Rails
133
144
  end
134
145
 
135
146
  def required?
136
- attr_options[:required]
147
+ reference? && Rails.application.config.active_record.belongs_to_required_by_default
137
148
  end
138
149
 
139
150
  def has_index?
@@ -152,8 +163,24 @@ module Rails
152
163
  type == :token
153
164
  end
154
165
 
166
+ def rich_text?
167
+ type == :rich_text
168
+ end
169
+
170
+ def attachment?
171
+ type == :attachment
172
+ end
173
+
174
+ def attachments?
175
+ type == :attachments
176
+ end
177
+
178
+ def virtual?
179
+ rich_text? || attachment? || attachments?
180
+ end
181
+
155
182
  def inject_options
156
- "".dup.tap { |s| options_for_migration.each { |k, v| s << ", #{k}: #{v.inspect}" } }
183
+ (+"").tap { |s| options_for_migration.each { |k, v| s << ", #{k}: #{v.inspect}" } }
157
184
  end
158
185
 
159
186
  def inject_index_options
@@ -163,7 +190,6 @@ module Rails
163
190
  def options_for_migration
164
191
  @attr_options.dup.tap do |options|
165
192
  if required?
166
- options.delete(:required)
167
193
  options[:null] = false
168
194
  end
169
195
 
@@ -63,8 +63,7 @@ module Rails
63
63
  numbered_destination = File.join(dir, ["%migration_number%", base].join("_"))
64
64
 
65
65
  create_migration numbered_destination, nil, config do
66
- match = ERB.version.match(/\Aerb\.rb \[(?<version>[^ ]+) /)
67
- if match && match[:version] >= "2.2.0" # Ruby 2.6+
66
+ if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
68
67
  ERB.new(::File.binread(source), trim_mode: "-", eoutvar: "@output_buffer").result(context)
69
68
  else
70
69
  ERB.new(::File.binread(source), nil, "-", "@output_buffer").result(context)
@@ -7,6 +7,10 @@ module Rails
7
7
  module ModelHelpers # :nodoc:
8
8
  PLURAL_MODEL_NAME_WARN_MESSAGE = "[WARNING] The model name '%s' was recognized as a plural, using the singular '%s' instead. " \
9
9
  "Override with --force-plural or setup custom inflection rules for this noun before running the generator."
10
+ IRREGULAR_MODEL_NAME_WARN_MESSAGE = <<~WARNING
11
+ [WARNING] Rails cannot recover singular form from its plural form '%s'.
12
+ Please setup custom inflection rules for this noun before running the generator in config/initializers/inflections.rb.
13
+ WARNING
10
14
  mattr_accessor :skip_warn
11
15
 
12
16
  def self.included(base) #:nodoc:
@@ -19,11 +23,14 @@ module Rails
19
23
  singular = name.singularize
20
24
  unless ModelHelpers.skip_warn
21
25
  say PLURAL_MODEL_NAME_WARN_MESSAGE % [name, singular]
22
- ModelHelpers.skip_warn = true
23
26
  end
24
27
  name.replace singular
25
28
  assign_names!(name)
26
29
  end
30
+ if name.singularize != name.pluralize.singularize && ! ModelHelpers.skip_warn
31
+ say IRREGULAR_MODEL_NAME_WARN_MESSAGE % [name.pluralize]
32
+ end
33
+ ModelHelpers.skip_warn = true
27
34
  end
28
35
  end
29
36
  end
@@ -31,12 +31,8 @@ module Rails
31
31
  end
32
32
  end
33
33
 
34
- # TODO Change this to private once we've dropped Ruby 2.2 support.
35
- # Workaround for Ruby 2.2 "private attribute?" warning.
36
- protected
37
- attr_reader :file_name
38
-
39
34
  private
35
+ attr_reader :file_name
40
36
 
41
37
  # FIXME: We are avoiding to use alias because a bug on thor that make
42
38
  # this method public and add it to the task list.
@@ -21,7 +21,6 @@ module Rails
21
21
  RUBY
22
22
  end
23
23
 
24
- # TODO: Remove once this is fully in place
25
24
  def method_missing(meth, *args, &block)
26
25
  @generator.send(meth, *args, &block)
27
26
  end
@@ -81,7 +80,6 @@ module Rails
81
80
  directory "app"
82
81
 
83
82
  keep_file "app/assets/images"
84
- empty_directory_with_keep_file "app/assets/javascripts/channels" unless options[:skip_action_cable]
85
83
 
86
84
  keep_file "app/controllers/concerns"
87
85
  keep_file "app/models/concerns"
@@ -95,11 +93,9 @@ module Rails
95
93
  end
96
94
 
97
95
  def bin_when_updating
98
- bin_yarn_exist = File.exist?("bin/yarn")
99
-
100
96
  bin
101
97
 
102
- if options[:api] && !bin_yarn_exist
98
+ if options[:skip_javascript]
103
99
  remove_file "bin/yarn"
104
100
  end
105
101
  end
@@ -159,10 +155,6 @@ module Rails
159
155
  remove_file "config/initializers/cookies_serializer.rb"
160
156
  end
161
157
 
162
- unless assets_config_exist
163
- remove_file "config/initializers/assets.rb"
164
- end
165
-
166
158
  unless csp_config_exist
167
159
  remove_file "config/initializers/content_security_policy.rb"
168
160
  end
@@ -221,6 +213,7 @@ module Rails
221
213
  empty_directory_with_keep_file "test/helpers"
222
214
  empty_directory_with_keep_file "test/integration"
223
215
 
216
+ template "test/channels/application_cable/connection_test.rb"
224
217
  template "test/test_helper.rb"
225
218
  end
226
219
 
@@ -249,14 +242,13 @@ module Rails
249
242
  # We need to store the RAILS_DEV_PATH in a constant, otherwise the path
250
243
  # can change in Ruby 1.8.7 when we FileUtils.cd.
251
244
  RAILS_DEV_PATH = File.expand_path("../../../../../..", __dir__)
252
- RESERVED_NAMES = %w[application destroy plugin runner test]
253
245
 
254
246
  class AppGenerator < AppBase # :nodoc:
255
247
  WEBPACKS = %w( react vue angular elm stimulus )
256
248
 
257
249
  add_shared_options_for "application"
258
250
 
259
- # Add bin/rails options
251
+ # Add rails command options
260
252
  class_option :version, type: :boolean, aliases: "-v", group: :rails,
261
253
  desc: "Show Rails version number and quit"
262
254
 
@@ -266,21 +258,26 @@ module Rails
266
258
  class_option :skip_bundle, type: :boolean, aliases: "-B", default: false,
267
259
  desc: "Don't run bundle install"
268
260
 
269
- class_option :webpack, type: :string, default: nil,
270
- desc: "Preconfigure for app-like JavaScript with Webpack (options: #{WEBPACKS.join('/')})"
261
+ class_option :webpack, type: :string, aliases: "--webpacker", default: nil,
262
+ desc: "Preconfigure Webpack with a particular framework (options: #{WEBPACKS.join(", ")})"
263
+
264
+ class_option :skip_webpack_install, type: :boolean, default: false,
265
+ desc: "Don't run Webpack install"
271
266
 
272
267
  def initialize(*args)
273
268
  super
274
269
 
275
270
  if !options[:skip_active_record] && !DATABASES.include?(options[:database])
276
- raise Error, "Invalid value for --database option. Supported for preconfiguration are: #{DATABASES.join(", ")}."
271
+ raise Error, "Invalid value for --database option. Supported preconfigurations are: #{DATABASES.join(", ")}."
277
272
  end
278
273
 
279
274
  # Force sprockets and yarn to be skipped when generating API only apps.
280
275
  # Can't modify options hash as it's frozen by default.
281
276
  if options[:api]
282
- self.options = options.merge(skip_sprockets: true, skip_javascript: true, skip_yarn: true).freeze
277
+ self.options = options.merge(skip_sprockets: true, skip_javascript: true).freeze
283
278
  end
279
+
280
+ @after_bundle_callbacks = []
284
281
  end
285
282
 
286
283
  public_task :set_default_accessors!
@@ -294,7 +291,7 @@ module Rails
294
291
  build(:gitignore) unless options[:skip_git]
295
292
  build(:gemfile) unless options[:skip_gemfile]
296
293
  build(:version_control)
297
- build(:package_json) unless options[:skip_yarn]
294
+ build(:package_json) unless options[:skip_javascript]
298
295
  end
299
296
 
300
297
  def create_app_files
@@ -310,6 +307,13 @@ module Rails
310
307
  end
311
308
  remove_task :update_bin_files
312
309
 
310
+ def update_active_storage
311
+ unless skip_active_storage?
312
+ rails_command "active_storage:update"
313
+ end
314
+ end
315
+ remove_task :update_active_storage
316
+
313
317
  def create_config_files
314
318
  build(:config)
315
319
  end
@@ -328,7 +332,7 @@ module Rails
328
332
  end
329
333
 
330
334
  def display_upgrade_guide_info
331
- say "\nAfter this, check Rails upgrade guide at http://guides.rubyonrails.org/upgrading_ruby_on_rails.html for more details about upgrading your app."
335
+ say "\nAfter this, check Rails upgrade guide at https://guides.rubyonrails.org/upgrading_ruby_on_rails.html for more details about upgrading your app."
332
336
  end
333
337
  remove_task :display_upgrade_guide_info
334
338
 
@@ -416,7 +420,7 @@ module Rails
416
420
 
417
421
  def delete_js_folder_skipping_javascript
418
422
  if options[:skip_javascript]
419
- remove_dir "app/assets/javascripts"
423
+ remove_dir "app/javascript"
420
424
  end
421
425
  end
422
426
 
@@ -443,8 +447,9 @@ module Rails
443
447
 
444
448
  def delete_action_cable_files_skipping_action_cable
445
449
  if options[:skip_action_cable]
446
- remove_file "app/assets/javascripts/cable.js"
450
+ remove_dir "app/javascript/channels"
447
451
  remove_dir "app/channels"
452
+ remove_dir "test/channels"
448
453
  end
449
454
  end
450
455
 
@@ -463,12 +468,12 @@ module Rails
463
468
 
464
469
  def delete_new_framework_defaults
465
470
  unless options[:update]
466
- remove_file "config/initializers/new_framework_defaults_5_2.rb"
471
+ remove_file "config/initializers/new_framework_defaults_6_0.rb"
467
472
  end
468
473
  end
469
474
 
470
- def delete_bin_yarn_if_skip_yarn_option
471
- remove_file "bin/yarn" if options[:skip_yarn]
475
+ def delete_bin_yarn
476
+ remove_file "bin/yarn" if options[:skip_javascript]
472
477
  end
473
478
 
474
479
  def finish_template
@@ -476,7 +481,8 @@ module Rails
476
481
  end
477
482
 
478
483
  public_task :apply_rails_template, :run_bundle
479
- public_task :run_webpack, :generate_spring_binstubs
484
+ public_task :generate_bundler_binstub, :generate_spring_binstubs
485
+ public_task :run_webpack
480
486
 
481
487
  def run_after_bundle_callbacks
482
488
  @after_bundle_callbacks.each(&:call)
@@ -493,54 +499,14 @@ module Rails
493
499
  create_file(*args, &block)
494
500
  end
495
501
 
496
- def app_name
497
- @app_name ||= (defined_app_const_base? ? defined_app_name : File.basename(destination_root)).tr('\\', "").tr(". ", "_")
498
- end
499
-
500
- def defined_app_name
501
- defined_app_const_base.underscore
502
- end
503
-
504
- def defined_app_const_base
505
- Rails.respond_to?(:application) && defined?(Rails::Application) &&
506
- Rails.application.is_a?(Rails::Application) && Rails.application.class.name.sub(/::Application$/, "")
507
- end
508
-
509
- alias :defined_app_const_base? :defined_app_const_base
510
-
511
- def app_const_base
512
- @app_const_base ||= defined_app_const_base || app_name.gsub(/\W/, "_").squeeze("_").camelize
513
- end
514
- alias :camelized :app_const_base
515
-
516
- def app_const
517
- @app_const ||= "#{app_const_base}::Application"
518
- end
519
-
520
- def valid_const?
521
- if app_const =~ /^\d/
522
- raise Error, "Invalid application name #{app_name}. Please give a name which does not start with numbers."
523
- elsif RESERVED_NAMES.include?(app_name)
524
- raise Error, "Invalid application name #{app_name}. Please give a " \
525
- "name which does not match one of the reserved rails " \
526
- "words: #{RESERVED_NAMES.join(", ")}"
527
- elsif Object.const_defined?(app_const_base)
528
- raise Error, "Invalid application name #{app_name}, constant #{app_const_base} is already in use. Please choose another application name."
529
- end
530
- end
531
-
532
- def mysql_socket
533
- @mysql_socket ||= [
534
- "/tmp/mysql.sock", # default
535
- "/var/run/mysqld/mysqld.sock", # debian/gentoo
536
- "/var/tmp/mysql.sock", # freebsd
537
- "/var/lib/mysql/mysql.sock", # fedora
538
- "/opt/local/lib/mysql/mysql.sock", # fedora
539
- "/opt/local/var/run/mysqld/mysqld.sock", # mac + darwinports + mysql
540
- "/opt/local/var/run/mysql4/mysqld.sock", # mac + darwinports + mysql4
541
- "/opt/local/var/run/mysql5/mysqld.sock", # mac + darwinports + mysql5
542
- "/opt/lampp/var/mysql/mysql.sock" # xampp for linux
543
- ].find { |f| File.exist?(f) } unless Gem.win_platform?
502
+ # Registers a callback to be executed after bundle and spring binstubs
503
+ # have run.
504
+ #
505
+ # after_bundle do
506
+ # git add: '.'
507
+ # end
508
+ def after_bundle(&block) # :doc:
509
+ @after_bundle_callbacks << block
544
510
  end
545
511
 
546
512
  def get_builder_class