lib/rails/generators/app_base.rb in railties-7.1.5 vs lib/rails/generators/app_base.rb in railties-7.2.0.beta1

- old
+ new

@@ -10,16 +10,19 @@ require "active_support/core_ext/array/extract_options" module Rails module Generators class AppBase < Base # :nodoc: - include Database include AppName - NODE_LTS_VERSION = "18.15.0" + NODE_LTS_VERSION = "20.11.1" BUN_VERSION = "1.0.1" + JAVASCRIPT_OPTIONS = %w( importmap bun webpack esbuild rollup ) + CSS_OPTIONS = %w( tailwind bootstrap bulma postcss sass ) + ASSET_PIPELINE_OPTIONS = %w( none sprockets propshaft ) + attr_accessor :rails_template add_shebang_option! argument :app_path, type: :string @@ -33,11 +36,12 @@ class_option :template, type: :string, aliases: "-m", desc: "Path to some #{name} template (can be a filesystem path or URL)" class_option :database, type: :string, aliases: "-d", default: "sqlite3", - desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})" + enum: Database::DATABASES, + desc: "Preconfigure for selected database" class_option :skip_git, type: :boolean, aliases: "-G", default: nil, desc: "Skip git init, .gitignore and .gitattributes" class_option :skip_docker, type: :boolean, default: nil, @@ -69,11 +73,12 @@ desc: "Skip Action Cable files" class_option :skip_asset_pipeline, type: :boolean, aliases: "-A", default: nil class_option :asset_pipeline, type: :string, aliases: "-a", default: "sprockets", - desc: "Choose your asset pipeline [options: sprockets (default), propshaft]" + enum: ASSET_PIPELINE_OPTIONS, + desc: "Choose your asset pipeline" class_option :skip_javascript, type: :boolean, aliases: ["-J", "--skip-js"], default: (true if name == "plugin"), desc: "Skip JavaScript files" class_option :skip_hotwire, type: :boolean, default: nil, @@ -92,13 +97,25 @@ desc: "Skip bootsnap gem" class_option :skip_dev_gems, type: :boolean, default: nil, desc: "Skip development gems (e.g., web-console)" + class_option :skip_rubocop, type: :boolean, default: nil, + desc: "Skip RuboCop setup" + + class_option :skip_brakeman, type: :boolean, default: nil, + desc: "Skip brakeman setup" + + class_option :skip_ci, type: :boolean, default: nil, + desc: "Skip GitHub CI files" + class_option :dev, type: :boolean, default: nil, desc: "Set up the #{name} with Gemfile pointing to your Rails checkout" + class_option :devcontainer, type: :boolean, default: false, + desc: "Generate devcontainer files" + class_option :edge, type: :boolean, default: nil, desc: "Set up the #{name} with a Gemfile pointing to the #{edge_branch} branch on the Rails repository" class_option :main, type: :boolean, default: nil, aliases: "--master", desc: "Set up the #{name} with Gemfile pointing to Rails repository main branch" @@ -258,11 +275,11 @@ end def database_gemfile_entry # :doc: return if options[:skip_active_record] - gem_name, gem_version = gem_for_database + gem_name, gem_version = database.gem GemfileEntry.version gem_name, gem_version, "Use #{options[:database]} as the database for Active Record" end def web_server_gemfile_entry # :doc: @@ -343,10 +360,14 @@ def skip_active_storage? # :doc: options[:skip_active_storage] end + def skip_storage? # :doc: + skip_active_storage? && !sqlite3? + end + def skip_action_cable? # :doc: options[:skip_action_cable] end def skip_action_mailer? # :doc: @@ -371,11 +392,30 @@ def skip_propshaft? skip_asset_pipeline? || options[:asset_pipeline] != "propshaft" end + def skip_rubocop? + options[:skip_rubocop] + end + def skip_brakeman? + options[:skip_brakeman] + end + + def skip_ci? + options[:skip_ci] + end + + def skip_devcontainer? + !options[:devcontainer] + end + + def devcontainer? + options[:devcontainer] + end + class GemfileEntry < Struct.new(:name, :version, :comment, :options, :commented_out) def initialize(name, version, comment, options = {}, commented_out = false) super end @@ -408,14 +448,10 @@ *options.map { |key, value| ", #{key}: #{value.inspect}" }, ].compact.join end end - def gem_ruby_version - Gem::Version.new(Gem::VERSION) >= Gem::Version.new("3.3.13") ? Gem.ruby_version : RUBY_VERSION - end - def rails_prerelease? options.dev? || options.edge? || options.main? end def rails_gemfile_entry @@ -533,65 +569,47 @@ end binfixups end - def dockerfile_build_packages - # start with the essentials - packages = %w(build-essential git pkg-config) + def dockerfile_base_packages + # Add curl to work with the default healthcheck strategy in Kamal + packages = ["curl"] - # add database support - packages << build_package_for_database unless skip_active_record? + # ActiveRecord databases + packages << database.base_package unless skip_active_record? # ActiveStorage preview support packages << "libvips" unless skip_active_storage? - packages << "curl" if using_js_runtime? + # jemalloc for memory optimization + packages << "libjemalloc2" + packages.compact.sort + end + + def dockerfile_build_packages + # start with the essentials + packages = %w(build-essential git pkg-config) + + # add database support + packages << database.build_package unless skip_active_record? + packages << "unzip" if using_bun? # node support, including support for building native modules if using_node? packages << "node-gyp" # pkg-config already listed above - # module build process depends on Python, and debian changed - # how python is installed with the bullseye release. Below - # is based on debian release included with the Ruby images on - # Dockerhub. - case Gem.ruby_version.to_s - when /^2\.7/ - bullseye = Gem.ruby_version >= Gem::Version.new("2.7.4") - when /^3\.0/ - bullseye = Gem.ruby_version >= Gem::Version.new("3.0.2") - else - bullseye = true - end - - if bullseye - packages << "python-is-python3" - else - packages << "python" - end + packages << "python-is-python3" end packages.compact.sort end - def dockerfile_deploy_packages - # Add curl to work with the default healthcheck strategy in Kamal - packages = ["curl"] - - # ActiveRecord databases - packages << deploy_package_for_database unless skip_active_record? - - # ActiveStorage preview support - packages << "libvips" unless skip_active_storage? - - packages.compact.sort - end - def css_gemfile_entry + return if options[:api] return unless options[:css] if !using_js_runtime? && options[:css] == "tailwind" GemfileEntry.floats "tailwindcss-rails", "Use Tailwind CSS [https://github.com/rails/tailwindcss-rails]" elsif !using_js_runtime? && options[:css] == "sass" @@ -654,11 +672,10 @@ return unless rails_prerelease? && bundle_install? if !File.exist?(File.expand_path("Gemfile", destination_root)) create_file("Gemfile", <<~GEMFILE) source "https://rubygems.org" - git_source(:github) { |repo| "https://github.com/\#{repo}.git" } #{rails_gemfile_entry} GEMFILE run_bundle @@ -672,11 +689,11 @@ remove_file("Gemfile.lock") end end def run_bundle - bundle_command("install", "BUNDLE_IGNORE_MESSAGES" => "1") if bundle_install? + bundle_command("install --quiet", "BUNDLE_IGNORE_MESSAGES" => "1") if bundle_install? end def run_javascript return if options[:skip_javascript] || !bundle_install? @@ -750,13 +767,17 @@ end def dockerfile_chown_directories directories = %w(log tmp) - directories << "storage" unless skip_active_storage? && !sqlite3? + directories << "storage" unless skip_storage? directories << "db" unless skip_active_record? directories.sort + end + + def database + @database ||= Database.build(options[:database]) end end end end