# frozen_string_literal: true require 'rails/generators' require 'rails/generators/rails/app/app_generator' module Underlay class AppGenerator < Rails::Generators::AppGenerator hide! class_option :application_mode, type: :boolean, default: false, desc: 'Application mode is enabled' class_option :database, type: :string, aliases: '-d', default: 'postgresql', desc: "Configure for selected database (options: #{DATABASES.join('/')})" class_option :github, type: :string, default: nil, desc: 'Create Github repository and add remote origin pointed to repo' class_option :help, type: :boolean, aliases: '-h', group: :underlay, desc: 'Show this help message and quit' class_option :heroku, type: :boolean, aliases: '-H', default: false, desc: 'Create staging and production Heroku apps' class_option :heroku_flags, type: :string, default: '', desc: 'Set extra Heroku flags' class_option :path, type: :string, default: nil, desc: 'Path to the gem' class_option :skip_system_test, type: :boolean, default: true, desc: 'Skip system test files' class_option :skip_test, type: :boolean, default: true, desc: 'Skip Test Unit' class_option :skip_turbolinks, type: :boolean, default: true, desc: 'Skip turbolinks gem' class_option :version, type: :boolean, aliases: '-v', group: :underlay, desc: 'Show Underlay version number and quit' def initialize(*args) super if api_mode? self.options = options.merge( api: true, skip_sprockets: true, skip_javascript: true ).freeze end end def finish_template invoke :underlay_customization super end def underlay_customization invoke :customize_gemfile invoke :setup_development_environment invoke :setup_test_environment invoke :setup_production_environment invoke :setup_secret_token invoke :create_underlay_views invoke :configure_app invoke :copy_miscellaneous_files invoke :customize_error_pages invoke :remove_app_comment_lines invoke :remove_config_comment_lines invoke :remove_routes_comment_lines invoke :setup_figaro invoke :setup_database invoke :create_local_heroku_setup invoke :create_heroku_apps invoke :create_github_repo invoke :setup_google_tag_manager invoke :setup_bundler_audit invoke :setup_spring invoke :generate_default invoke :setup_default_directories invoke :clean_up invoke :outro end def customize_gemfile build :replace_gemfile, options[:path] build :set_ruby_to_version_being_used bundle_command 'install' build_for_non_api :configure_simple_form end def setup_database say 'Setting up database' if options[:database] == 'postgresql' build :use_postgres_config_template end build :create_database end def setup_development_environment say 'Setting up the development environment' build_for_non_api :raise_on_missing_assets_in_test build :raise_on_delivery_errors build :set_test_delivery_method build :add_bullet_gem_configuration build :raise_on_unpermitted_parameters build :provide_setup_script build :provide_rake_script build :provide_update_script build :provide_dev_prime_task build :configure_generators build :configure_i18n_for_missing_translations build_for_non_api :configure_quiet_assets end def setup_test_environment say 'Setting up the test environment' build :set_up_factory_bot_for_rspec build :generate_factories_file build :generate_rspec build :configure_rspec build :enable_database_cleaner build :provide_shoulda_matchers_config build :configure_spec_support_features build :configure_ci build :configure_rubocop build_for_non_api :configure_linters build :configure_i18n_for_test_environment build :configure_action_mailer_in_specs build_for_non_api :configure_capybara end def setup_production_environment say 'Setting up the production environment' build :configure_smtp build :configure_rack_timeout build :enable_rack_canonical_host build :enable_rack_deflater build_for_non_api :setup_asset_host end def setup_secret_token say 'Moving secret token out of version control' build :setup_secret_token end def create_underlay_views say 'Creating underlay views' build :create_partials_directory build_for_non_api :create_shared_flashes build_for_non_api :create_shared_javascripts build_for_non_api :create_shared_css_overrides build_for_non_api :create_application_layout end def configure_app say 'Configuring app' build :configure_action_mailer build :configure_active_job build :configure_time_formats build :setup_default_rake_task build :replace_default_puma_configuration build :set_up_forego build :setup_rack_mini_profiler end def create_local_heroku_setup say 'Creating local Heroku setup' build :create_review_apps_setup_script build :create_deploy_script build :create_heroku_application_manifest_file end def create_heroku_apps if options[:heroku] say 'Creating Heroku apps' build :create_heroku_apps, options[:heroku_flags] build :set_heroku_remotes build :set_heroku_rails_secrets build :set_heroku_application_host build :set_heroku_backup_schedule build :create_heroku_pipeline build :configure_automatic_deployment end end def create_github_repo if !options[:skip_git] && options[:github] say 'Creating Github repo' build :create_github_repo, options[:github] end end def setup_google_tag_manager say 'Setting up Google Tage Manager' unless options[:api] build_for_non_api :setup_google_tag_manager end def setup_figaro build :copy_figaro_files end def setup_default_directories build :setup_default_directories end def setup_bundler_audit say 'Setting up bundler-audit' build :setup_bundler_audit end def clean_up say 'Code cleaning' build :rubocop_autocorrect build :manual_code_correct build_for_api :non_api_files_removal end def setup_spring say 'Springifying binstubs' build :setup_spring end def copy_miscellaneous_files say 'Copying miscellaneous support files' build :copy_miscellaneous_files end def customize_error_pages say 'Customizing the 500/404/422 pages' unless options[:api] build_for_non_api :customize_error_pages end def remove_app_comment_lines build :remove_app_comment_lines end def remove_config_comment_lines build :remove_config_comment_lines end def remove_routes_comment_lines build :remove_routes_comment_lines end def generate_default run('spring stop') generate('underlay:initialize_active_job') generate('underlay:enforce_ssl') generate('underlay:static') generate('underlay:stylesheet_base') end def outro say 'You just laid the underlay. Time to add some value!' end def self.banner "underlay #{arguments.map(&:usage).join(' ')} [options]" end protected # rubocop:disable AccessorMethodName def get_builder_class Underlay::AppBuilder end # rubocop:enable AccessorMethodName def using_active_record? !options[:skip_active_record] end def build_for_non_api(args) return if api_mode? build args end def build_for_api(args) return unless api_mode? build args end def api_mode? options[:application_mode].blank? end end end