lib/generators/katapult/basics/basics_generator.rb in katapult-0.2.0 vs lib/generators/katapult/basics/basics_generator.rb in katapult-0.3.0
- old
+ new
@@ -1,125 +1,224 @@
# Generates model-independent application basics (see method names).
+require 'katapult/generator_goodies'
+require 'katapult/version' # For writing .ruby-version
+
module Katapult
module Generators
class BasicsGenerator < Rails::Generators::Base
+ include Katapult::GeneratorGoodies
- SKIP_GEMS = %w(sass-rails coffee-rails turbolinks sdoc uglifier)
+ WEBPACK_DIR = 'app/webpack'
+ YARN_PACKAGES = %w[
+ autoprefixer
+ autosize
+ bootstrap-sass
+ jquery
+ jquery-ujs
+ unpoly
+ ]
desc 'Generate basics like test directories and gems'
source_root File.expand_path('../templates', __FILE__)
- class_option :db_user, type: :string, default: 'root',
+ class_option :db_user, type: :string, default: '',
description: 'The user to set in config/database.yml'
class_option :db_password, type: :string, default: '',
description: 'The password to set in config/database.yml'
+ def write_ruby_version
+ template '.ruby-version'
+ end
def add_gitignore
template '.gitignore', force: true
end
- def write_ruby_version
- template '.ruby-version'
+ def add_robots_txt
+ template 'public/robots.txt', force: true
end
- def write_database_ymls
- @db_user = options.db_user
- @db_password = options.db_password
+ # Gems ###################################################################
- template 'config/database.yml', force: true
- template 'config/database.sample.yml'
- end
-
- # Overwrite Gemfile with the template, but transfer all gems that are not
- # skipped (see SKIP_GEMS).
def enhance_gemfile
- gem_lines = File.readlines('Gemfile').select{ |line| line =~ /^gem/ }
- @original_gems = gem_lines.reject do |line|
- line =~ /'(#{ SKIP_GEMS.join '|' })'/
- end
-
+ # Need to transfer the katapult line, because in tests, katapult is
+ # installed with a custom :path option
+ @katapult = File.readlines('Gemfile').find{ |line| line =~ /^gem 'katapult'/ }
template 'Gemfile', force: true
end
def bundle_install
run 'bundle install'
+ # Fix Bundler for parallel_tests
+ run 'bundle config --local disable_exec_load true'
+
# This is relevant for the server, so it may happen after bundling here.
# By having Nokogiri use system libraries, it will get automatic updates
# of the frequently broken libxml (i.e. when the system libxml updates).
run 'bundle config --local build.nokogiri --use-system-libraries'
end
- def remove_turbolinks_js
- gsub_file 'app/assets/javascripts/application.js', "//= require turbolinks\n", ''
- gsub_file 'app/views/layouts/application.html.erb', ", 'data-turbolinks-track' => true", ''
+
+ # Database ###############################################################
+
+ def write_database_ymls
+ @db_user = options.db_user
+ @db_password = options.db_password
+
+ template 'config/database.yml', force: true
+ template 'config/database.sample.yml'
end
- def setup_spring
- # run 'spring binstub --all'
- # # remove_file 'bin/bundle' # Won't play together with parallel_tests
- # template 'config/spring.rb'
- # template 'bin/rake'
- run 'spring stop' # Reload (just in case)
+ def create_databases
+ # Need to unset RAILS_ENV variable for this sub command because
+ # parallel_tests defaults to "test" only if the variable is not set (<->
+ # empty string value). However, because this is run from a Rails
+ # generator, the variable is already set to "development". Cannot set to
+ # "test" either because parallel_tests is only loaded in development.
+ run 'unset RAILS_ENV; bundle exec rake db:drop db:create parallel:drop parallel:create'
end
- def setup_guard
- template 'Guardfile'
- environment 'config.middleware.use Rack::LiveReload', env: :development
+
+ # Configure Rails ########################################################
+
+ def install_application_layout
+ remove_file 'app/views/layouts/application.html.erb'
+ directory 'app/views/layouts'
end
+ # We're using Webpacker
+ def remove_asset_pipeline_traces
+ remove_dir 'app/assets'
+ end
+
+ def disable_migration_errors
+ development = 'config/environments/development.rb'
+ gsub_file development, /(migration_error =) :page_load/, '\1 false'
+ end
+
def setup_staging
- FileUtils.copy 'config/environments/production.rb', 'config/environments/staging.rb'
- secret = `rake secret`.chomp
+ template 'config/environments/staging.rb'
+
# Cheating in the "staging" secret between "test" and "production"
+ secret = run('bundle exec rake secret', capture: true).chomp
insert_into_file 'config/secrets.yml', <<~SECRET, after: "test:\n"
secret_key_base: #{ secret }
staging:
SECRET
end
- def create_databases
- run 'rake db:drop:all db:create:all parallel:create'
+ def configure_test_environment
+ test_env = 'config/environments/test.rb'
+
+ gsub_file test_env,
+ /# Do not eager load code on boot.*config\.eager_load = false/m,
+ 'config.eager_load = true'
+ gsub_file test_env,
+ / # Show full error.*\n config\.consider_all_requests_local\s.*$/,
+ ' config.consider_all_requests_local = false'
+ gsub_file test_env,
+ / # Disable request forgery protection.*\n config\.action_controller\.allow_forgery_protection\s.*$\n/,
+ ''
+ gsub_file test_env, /config\.action_controller\.perform_caching\s.*$/,
+ 'config.action_controller.perform_caching = true'
end
def configure_action_mailer
app_con = 'app/controllers/application_controller.rb'
inject_into_file app_con, <<-CONFIG, before: /end\n\z/
- before_filter :make_action_mailer_use_request_host_and_protocol
+ before_action :make_action_mailer_use_request_host_and_protocol
private
def make_action_mailer_use_request_host_and_protocol
ActionMailer::Base.default_url_options[:protocol] = request.protocol
ActionMailer::Base.default_url_options[:host] = request.host_with_port
end
CONFIG
+
+ gsub_file 'app/mailers/application_mailer.rb',
+ /(^\s+default from:).*$/, '\1 Rails.configuration.system_email'
end
def set_timezone
+ # This results in correct indentation :)
+ application <<-'LOAD_PATHS'
+config.time_zone = 'Berlin'
+ config.active_record.default_timezone = :local
+ config.active_record.time_zone_aware_attributes = false
+ LOAD_PATHS
gsub_file 'config/application.rb',
/# config\.time_zone =.*$/,
"config.time_zone = 'Berlin'"
end
+ def configure_system_email
+ application "config.system_email = 'system@#{app_name}.com'\n"
+ end
+
def disable_asset_debugging # Faster
gsub_file 'config/environments/development.rb',
/config\.assets\.debug =.*$/,
'config.assets.debug = false'
end
+ def install_helpers
+ directory 'app/helpers'
+ end
+
+ def install_errors_controller
+ template 'app/controllers/errors_controller.rb'
+ route 'resources :errors, only: :new'
+ end
+
def install_initializers
directory 'config/initializers'
end
def install_ext
directory 'lib/ext'
end
+
+ # Configure 3rd party ####################################################
+
+ def setup_spring
+ run 'spring binstub --all'
+
+ # Enhance Spring config
+ config = 'config/spring.rb'
+ inject_into_file config, <<-DIR, after: /\A%w\(\n/
+ lib/templates
+ DIR
+ prepend_to_file config, <<-MKDIR
+# Custom generator templates are put into lib/templates
+FileUtils.mkdir_p 'lib/templates'
+
+ MKDIR
+
+ # Parallel-fix binstubs
+ Dir['bin/*'].each do |binstub|
+ if File.read(binstub) =~ /load.*spring/
+ inject_into_file binstub, <<-PARALLEL, after: /\A.*\n/
+running_in_parallel = ENV.has_key?('TEST_ENV_NUMBER') || ARGV.any? { |arg| arg =~ /^parallel:/ }
+
+ PARALLEL
+
+ gsub_file binstub, /^(\s*load .*spring.*)$/, '\1 unless running_in_parallel'
+ end
+ end
+ end
+
+ def setup_guard
+ template 'Guardfile'
+ environment "config.middleware.use Rack::LiveReload\n", env: :development
+ environment "config.assets.digest = false # For Guard::Livereload\n", env: :development
+ end
+
def add_modularity_load_paths
# This results in correct indentation :)
application <<-'LOAD_PATHS'
config.autoload_paths << "#{Rails.root}/app/controllers/shared"
config.autoload_paths << "#{Rails.root}/app/models/shared"
@@ -127,57 +226,93 @@
config.autoload_paths << "#{Rails.root}/app/util/shared"
LOAD_PATHS
end
def install_cucumber
+ run 'spring stop' # Spring constantly causes trouble here
+
generate 'cucumber:install'
directory 'features/support'
template 'config/cucumber.yml', force: true
# Remove cucumber section from database.yml. Don't need this.
gsub_file 'config/database.yml', /^cucumber.*\z/m, ''
+
+ environment <<~ACTIVE_JOB, env: 'test'
+ config.active_job.queue_adapter = :inline
+ ACTIVE_JOB
end
def install_rspec
generate 'rspec:install'
+ directory 'spec'
+
gsub_file '.rspec', "--warnings\n", '' # Don't show Ruby warnings
- uncomment_lines 'spec/rails_helper.rb', /Dir.Rails.root.join.+spec.support/
- template 'spec/support/shoulda_matchers.rb'
- template 'spec/support/factory_girl.rb'
- directory 'spec/factories'
+ template '.rspec_parallel'
+
+ merge_rails_helper_into_spec_helper
+
+ uncomment_lines 'spec/spec_helper.rb', /Dir.Rails.root.join.+spec.support/
+ gsub_file 'spec/spec_helper.rb',
+ /^ config\.use_transactional_fixtures = true/, <<-CONTENT
+ # RSpec's transaction logic needs to be disabled for DatabaseCleaner to work
+ config.use_transactional_fixtures = false
+ CONTENT
end
def install_capistrano
# Create Capfile *before* installing Capistrano to prevent annoying
# Harrow.io ad
template 'Capfile', force: true
run 'cap install'
+ deploy_rb = File.read('config/deploy.rb')
+ @version = deploy_rb[/^lock.*?([\d\.]+)/, 1]
template 'config/deploy.rb', force: true
template 'config/deploy/staging.rb', force: true
template 'config/deploy/production.rb', force: true
directory 'lib/capistrano/tasks'
template 'lib/tasks/pending_migrations.rake'
end
- def install_styles
- remove_file 'app/assets/stylesheets/application.css'
- directory 'app/assets/stylesheets', force: true
- end
+ def setup_webpacker
+ remove_dir 'app/javascript'
+ directory WEBPACK_DIR
+ directory 'config/webpack'
+ gsub_file 'config/webpacker.yml', /^( source_path:).*$/, '\1 ' + WEBPACK_DIR
+ inject_into_file 'config/webpack/environment.js', <<~JQUERY, after: /\A.*\n/ # 1st line
+ const webpack = require('webpack')
- private
+ environment.plugins.set('Provide', new webpack.ProvidePlugin({
+ $: 'jquery',
+ jQuery: 'jquery'
+ })
+ )
+ JQUERY
- def app_name
- File.basename(Dir.pwd)
+ yarn :add, *YARN_PACKAGES
end
- def run(*)
- Bundler.with_clean_env do
- super
- end
+ def configure_autoprefixer
+ template '.browserslistrc'
+ end
+
+ # Bundler prefers installed gems, but we want the newest versions possible
+ def update_gems
+ run 'bundle install'
+ end
+
+ private
+
+ def merge_rails_helper_into_spec_helper
+ spec_helper = File.read 'spec/spec_helper.rb'
+ spec_helper.gsub! /.*^RSpec\.configure.+?$/m, '' # Remove introduction
+ gsub_file 'spec/rails_helper.rb', /end\n\z/, spec_helper
+
+ FileUtils.mv 'spec/rails_helper.rb', 'spec/spec_helper.rb', force: true
end
end
end
end