# frozen_string_literal: true require "rails/generators" require_relative "generator_messages" require_relative "generator_helper" module ReactOnRails module Generators class BaseGenerator < Rails::Generators::Base include GeneratorHelper Rails::Generators.hide_namespace(namespace) source_root(File.expand_path("templates", __dir__)) # --redux class_option :redux, type: :boolean, default: false, desc: "Install Redux gems and Redux version of Hello World Example", aliases: "-R" def add_hello_world_route route "get 'hello_world', to: 'hello_world#index'" end def create_react_directories dirs = %w[components] dirs.each { |name| empty_directory("app/javascript/bundles/HelloWorld/#{name}") } end def copy_base_files base_path = "base/base/" base_files = %w[app/controllers/hello_world_controller.rb app/views/layouts/hello_world.html.erb config/initializers/react_on_rails.rb Procfile.dev Procfile.dev-static] base_files.each { |file| copy_file("#{base_path}#{file}", file) } end def copy_js_bundle_files base_path = "base/base/" base_files = %w[app/javascript/packs/server-bundle.js app/javascript/bundles/HelloWorld/components/HelloWorldServer.js app/javascript/bundles/HelloWorld/components/HelloWorld.module.css] base_files.each { |file| copy_file("#{base_path}#{file}", file) } end def copy_webpack_config puts "Adding Webpack config" base_path = "base/base" base_files = %w[babel.config.js config/webpack/clientWebpackConfig.js config/webpack/commonWebpackConfig.js config/webpack/test.js config/webpack/development.js config/webpack/production.js config/webpack/serverWebpackConfig.js config/webpack/webpack.config.js config/webpack/webpackConfig.js] config = { message: "// The source code including full typescript support is available at:" } base_files.each do |file| template("#{base_path}/#{file}.tt", file, config) end end def copy_shakapacker_config puts "Adding Shakapacker v7 config file" base_path = "base/base/" base_files = %w[config/shakapacker.yml] base_files.each { |file| copy_file("#{base_path}#{file}", file) } end def add_base_gems_to_gemfile run "bundle" end def add_yarn_dependencies major_minor_patch_only = /\A\d+\.\d+\.\d+\z/.freeze if ReactOnRails::VERSION.match?(major_minor_patch_only) run "yarn add react-on-rails@#{ReactOnRails::VERSION} --exact" else # otherwise add latest puts "Adding the lastest react-on-rails NPM module. Double check this is correct in package.json" run "yarn add react-on-rails --exact" end puts "Adding React dependencies" run "yarn add react react-dom @babel/preset-react prop-types babel-plugin-transform-react-remove-prop-types \ babel-plugin-macros" puts "Adding CSS handlers" run "yarn add css-loader css-minimizer-webpack-plugin mini-css-extract-plugin style-loader" puts "Adding dev dependencies" run "yarn add -D @pmmmwh/react-refresh-webpack-plugin react-refresh" end def append_to_spec_rails_helper rails_helper = File.join(destination_root, "spec/rails_helper.rb") if File.exist?(rails_helper) add_configure_rspec_to_compile_assets(rails_helper) else spec_helper = File.join(destination_root, "spec/spec_helper.rb") if File.exist?(spec_helper) add_configure_rspec_to_compile_assets(spec_helper) else # rubocop:disable Layout/EmptyLinesAroundArguments GeneratorMessages.add_info( <<-MSG.strip_heredoc We did not find a spec/rails_helper.rb or spec/spec_helper.rb to add the React on Rails Test helper, which ensures that if we are running js tests, then we are using latest webpack assets. You can later add this to your rspec config: # This will use the defaults of :js and :server_rendering meta tags ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config) MSG ) # rubocop:enable Layout/EmptyLinesAroundArguments end end end CONFIGURE_RSPEC_TO_COMPILE_ASSETS = <<-STR.strip_heredoc RSpec.configure do |config| # Ensure that if we are running js tests, we are using latest webpack assets # This will use the defaults of :js and :server_rendering meta tags ReactOnRails::TestHelper.configure_rspec_to_compile_assets(config) STR private # From https://github.com/rails/rails/blob/4c940b2dbfb457f67c6250b720f63501d74a45fd/railties/lib/rails/generators/rails/app/app_generator.rb def app_name @app_name ||= (defined_app_const_base? ? defined_app_name : File.basename(destination_root)) .tr("\\", "").tr(". ", "_") end def defined_app_name defined_app_const_base.underscore end def defined_app_const_base Rails.respond_to?(:application) && defined?(Rails::Application) && Rails.application.is_a?(Rails::Application) && Rails.application.class.name.sub(/::Application$/, "") end alias defined_app_const_base? defined_app_const_base def app_const_base @app_const_base ||= defined_app_const_base || app_name.gsub(/\W/, "_").squeeze("_").camelize end def app_const @app_const ||= "#{app_const_base}::Application" end def add_configure_rspec_to_compile_assets(helper_file) search_str = "RSpec.configure do |config|" gsub_file(helper_file, search_str, CONFIGURE_RSPEC_TO_COMPILE_ASSETS) end end end end