class Suspenders::AppBuilder
Public Instance Methods
accept_defaults()
click to toggle source
# File lib/voyage/app_builder.rb, line 10 def accept_defaults if agree?('Would you like to accept all defaults? [slim, devise w/ first & last name, refills nav & footer] (Y/n)') @@accept_defaults = true else @@accept_defaults = false end end
add_admin_views_for_devise_resource(adding_first_and_last_name)
click to toggle source
# File lib/voyage/app_builder.rb, line 316 def add_admin_views_for_devise_resource(adding_first_and_last_name) config = { adding_first_and_last_name: adding_first_and_last_name } template '../templates/users_index.html.erb', 'app/views/admin/users/index.html.erb', config if @@use_slim inside('lib') do # arbitrary, run in context of newly generated app run "erb2slim '../app/views/users' '../app/views/users'" run "erb2slim -d '../app/views/users'" run "erb2slim '../app/views/admin/users' '../app/views/admin/users'" run "erb2slim -d '../app/views/admin/users'" end end template '../templates/admin_users_controller.rb', 'app/controllers/admin/users_controller.rb' template '../templates/admin_controller.rb', 'app/controllers/admin/admin_controller.rb' end
add_analytics_initializer()
click to toggle source
# File lib/voyage/app_builder.rb, line 294 def add_analytics_initializer template '../templates/analytics_ruby_initializer.rb', 'config/initializers/analytics_ruby.rb' template '../templates/analytics_alias.html.erb.erb', 'app/views/users/analytics_alias.html.erb' end
add_api_foundation()
click to toggle source
# File lib/voyage/app_builder.rb, line 563 def add_api_foundation # Create /app/api/base_api_controller.rb template '../templates/api_base_controller.rb', 'app/controllers/api/base_api_controller.rb', force: true # Create /app/api/v1/users_controller.rb template '../templates/api_users_controller.rb', 'app/controllers/api/v1/users_controller.rb', force: true # Update routes to include namespaced API inject_into_file 'config/routes.rb', before: /^end/ do <<-RUBY.gsub(/^ {6}/, '') # API-specific routes namespace 'api' do namespace 'v1' do resources :users, except: [:new, :edit] end end RUBY end end
add_app_css_file()
click to toggle source
# File lib/voyage/app_builder.rb, line 666 def add_app_css_file create_file "app/assets/stylesheets/#{app_name}.sass" do <<-RUBY.gsub(/^ {8}/, '') .outer-wrapper position: relative min-height: 100% .navigation-wrapper @include outer-container .main padding: 18px @include outer-container padding-bottom: 450px .footer min-height: 420px position: absolute bottom: 0 left: 0 RUBY end end
add_auto_annotate_models_rake_task()
click to toggle source
# File lib/voyage/app_builder.rb, line 769 def add_auto_annotate_models_rake_task template '../templates/auto_annotate_models.rake', 'lib/tasks/auto_annotate_models.rake', force: true end
add_bullet_gem_configuration()
click to toggle source
# File lib/suspenders/app_builder.rb, line 63 def add_bullet_gem_configuration config = <<-RUBY config.after_initialize do Bullet.enable = true Bullet.bullet_logger = true Bullet.rails_logger = true end RUBY inject_into_file( "config/environments/development.rb", config, after: "config.action_mailer.raise_delivery_errors = true\n", ) end
add_canard_roles_to_devise_resource()
click to toggle source
# File lib/voyage/app_builder.rb, line 365 def add_canard_roles_to_devise_resource inject_into_file 'app/models/user.rb', before: /^end/ do <<-RUBY.gsub(/^ {6}/, '') before_create :generate_uuid # Permissions cascade/inherit through the roles listed below. The order of # this list is important, it should progress from least to most privelage ROLES = [:admin].freeze acts_as_user roles: ROLES roles ROLES validates :email, presence: true, format: /\\A[-a-z0-9_+\\.]+\\@([-a-z0-9]+\\.)+[a-z0-9]{2,8}\\z/i, uniqueness: true # NOTE: these password validations won't run if the user has an invite token validates :password, presence: true, length: { within: 8..72 }, confirmation: true, on: :create validates :password_confirmation, presence: true, on: :create def tester? (email =~ /(example.com|headway.io)$/).present? end private def generate_uuid loop do uuid = SecureRandom.uuid self.uuid = uuid break unless User.exists?(uuid: uuid) end end RUBY end end
add_custom_routes_for_devise()
click to toggle source
# File lib/voyage/app_builder.rb, line 417 def add_custom_routes_for_devise find = <<-RUBY.gsub(/^ {6}/, '') devise_for :users resources :users RUBY replace = <<-RUBY.gsub(/^ {6}/, '') devise_for :users, controllers: { registrations: 'devise_customizations/registrations', } resources :users do member do get 'analytics_alias' end end namespace :admin do resources :users do member do get 'impersonate' end collection do get 'stop_impersonating' end end end authenticated :user do # root to: 'dashboard#show', as: :authenticated_root root to: 'high_voltage/pages#show', id: 'welcome', as: :authenticated_root end devise_scope :user do get 'sign-in', to: 'devise/sessions#new' get 'sign-out', to: 'devise/sessions#destroy' end RUBY replace_in_file 'config/routes.rb', find, replace end
add_devise_registrations_controller()
click to toggle source
# File lib/voyage/app_builder.rb, line 288 def add_devise_registrations_controller template '../templates/devise_registrations_controller.rb', 'app/controllers/devise_customizations/registrations_controller.rb' end
add_favicon()
click to toggle source
# File lib/voyage/app_builder.rb, line 773 def add_favicon template '../templates/favicon.ico', 'app/assets/images/favicon.ico', force: true end
add_high_voltage_static_pages()
click to toggle source
# File lib/voyage/app_builder.rb, line 615 def add_high_voltage_static_pages template '../templates/about.html.erb', "app/views/pages/about.html.#{@@use_slim ? 'slim' : 'erb'}" template '../templates/welcome.html.erb', "app/views/pages/welcome.html.erb" inject_into_file 'config/routes.rb', before: /^end/ do <<-RUBY.gsub(/^ {6}/, '') root 'high_voltage/pages#show', id: 'welcome' RUBY end create_file 'config/initializers/high_voltage.rb' do <<-RUBY.gsub(/^ {8}/, '') HighVoltage.configure do |config| config.route_drawer = HighVoltage::RouteDrawers::Root end RUBY end end
add_refills_to_stylesheets()
click to toggle source
# File lib/voyage/app_builder.rb, line 724 def add_refills_to_stylesheets inject_into_file 'app/assets/stylesheets/application.scss', after: '@import "refills/flashes";' do <<-RUBY.gsub(/^ {8}/, '') \n@import "refills/navigation"; @import "refills/footer"; @import "#{app_name}"; RUBY end end
add_rubocop_config()
click to toggle source
# File lib/voyage/app_builder.rb, line 765 def add_rubocop_config template '../templates/rubocop.yml', '.rubocop.yml', force: true end
add_specs()
click to toggle source
# File lib/voyage/app_builder.rb, line 781 def add_specs inject_into_file 'app/jobs/application_job.rb', before: "class ApplicationJob < ActiveJob::Base" do <<-RUBY.gsub(/^ {8}/, '') # :nocov: RUBY end template '../templates/specs/controllers/admin/users_controller_spec.rb', 'spec/controllers/admin/users_controller_spec.rb', force: true template '../templates/specs/controllers/application_controller_spec.rb', 'spec/controllers/application_controller_spec.rb', force: true end
add_to_gitignore()
click to toggle source
# File lib/voyage/app_builder.rb, line 822 def add_to_gitignore inject_into_file '.gitignore', after: '/tmp/*' do <<-RUBY.gsub(/^ {8}/, '') .env .zenflow-log errors.err .ctags .cadre/coverage.vim RUBY end end
add_token_auth()
click to toggle source
# File lib/voyage/app_builder.rb, line 541 def add_token_auth inject_into_file 'app/models/user.rb', after: "class User < ApplicationRecord" do <<-'RUBY'.gsub(/^ {6}/, '') acts_as_token_authenticatable RUBY end generate 'migration add_authentication_token_to_users "authentication_token:string{30}:uniq"' # specs template '../templates/specs/features/user_impersonation_spec.rb', 'spec/features/user_impersonation_spec.rb', force: true template '../templates/specs/features/user_list_spec.rb', 'spec/features/user_list_spec.rb', force: true template '../templates/specs/features/user_signup_spec.rb', 'spec/features/user_signup_spec.rb', force: true template '../templates/specs/requests/user_api_spec.rb', 'spec/requests/user_api_spec.rb', force: true template '../templates/specs/support/api/schemas/user.json', 'spec/support/api/schemas/user.json', force: true template '../templates/config_initializers_ams.rb', 'config/initializers/ams.rb', force: true template '../templates/specs/support/matchers/api_schema_matcher.rb', 'spec/support/matchers/api_schema_matcher.rb', force: true template '../templates/specs/mailers/application_mailer_spec.rb.erb', 'spec/mailers/application_mailer_spec.rb', force: true template '../templates/specs/support/features/session_helpers.rb', 'spec/support/features/session_helpers.rb', force: true template '../templates/specs/support/request_spec_helper.rb', 'spec/support/request_spec_helper.rb', force: true end
agree?(prompt)
click to toggle source
# File lib/voyage/app_builder.rb, line 3 def agree?(prompt) puts prompt response = STDIN.gets.chomp response.empty? || %w(y yes).include?(response.downcase.strip) end
bundle_without_production()
click to toggle source
# File lib/voyage/app_builder.rb, line 25 def bundle_without_production template '../templates/bundle_config', '.bundle/config' end
configure_action_mailer()
click to toggle source
# File lib/suspenders/app_builder.rb, line 312 def configure_action_mailer action_mailer_host "development", %{"localhost:3000"} action_mailer_host "test", %{"www.example.com"} action_mailer_host "production", %{ENV.fetch("APPLICATION_HOST")} end
configure_action_mailer_in_specs()
click to toggle source
# File lib/suspenders/app_builder.rb, line 287 def configure_action_mailer_in_specs copy_file 'action_mailer.rb', 'spec/support/action_mailer.rb' end
configure_active_job()
click to toggle source
# File lib/suspenders/app_builder.rb, line 318 def configure_active_job configure_application_file( "config.active_job.queue_adapter = :delayed_job" ) configure_environment "test", "config.active_job.queue_adapter = :inline" end
configure_automatic_deployment()
click to toggle source
# File lib/suspenders/app_builder.rb, line 382 def configure_automatic_deployment deploy_command = <<-YML.strip_heredoc deployment: staging: branch: master commands: - bin/deploy staging YML append_file "circle.yml", deploy_command end
configure_background_jobs_for_rspec()
click to toggle source
# File lib/suspenders/app_builder.rb, line 283 def configure_background_jobs_for_rspec run 'rails g delayed_job:active_record' end
configure_capybara_webkit()
click to toggle source
# File lib/suspenders/app_builder.rb, line 291 def configure_capybara_webkit copy_file "capybara_webkit.rb", "spec/support/capybara_webkit.rb" end
configure_ci()
click to toggle source
# File lib/suspenders/app_builder.rb, line 270 def configure_ci template "circle.yml.erb", "circle.yml" end
configure_generators()
click to toggle source
# File lib/suspenders/app_builder.rb, line 105 def configure_generators config = <<-RUBY config.generators do |generate| generate.helper false generate.javascripts false generate.request_specs false generate.routing_specs false generate.stylesheets false generate.test_framework :rspec generate.view_specs false end RUBY inject_into_class 'config/application.rb', 'Application', config end
configure_i18n_for_missing_translations()
click to toggle source
# File lib/suspenders/app_builder.rb, line 278 def configure_i18n_for_missing_translations raise_on_missing_translations_in("development") raise_on_missing_translations_in("test") end
configure_i18n_for_test_environment()
click to toggle source
# File lib/suspenders/app_builder.rb, line 274 def configure_i18n_for_test_environment copy_file "i18n.rb", "spec/support/i18n.rb" end
configure_quiet_assets()
click to toggle source
# File lib/suspenders/app_builder.rb, line 88 def configure_quiet_assets config = <<-RUBY config.assets.quiet = true RUBY inject_into_class "config/application.rb", "Application", config end
configure_rack_timeout()
click to toggle source
# File lib/suspenders/app_builder.rb, line 300 def configure_rack_timeout rack_timeout_config = <<-RUBY Rack::Timeout.timeout = (ENV["RACK_TIMEOUT"] || 10).to_i RUBY append_file "config/environments/production.rb", rack_timeout_config end
configure_rspec()
click to toggle source
# File lib/suspenders/app_builder.rb, line 263 def configure_rspec remove_file "spec/rails_helper.rb" remove_file "spec/spec_helper.rb" copy_file "rails_helper.rb", "spec/rails_helper.rb" copy_file "spec_helper.rb", "spec/spec_helper.rb" end
configure_rvm_prepend_bin_to_path()
click to toggle source
# File lib/voyage/app_builder.rb, line 797 def configure_rvm_prepend_bin_to_path run "rm -f $rvm_path/hooks/after_cd_bundler" run "touch $rvm_path/hooks/after_cd_bundler" git_safe_dir = <<-RUBY.gsub(/^ {8}/, '') #!/usr/bin/env bash export PATH=".git/safe/../../bin:$PATH" RUBY run "echo '#{git_safe_dir}' >> $rvm_path/hooks/after_cd_bundler" run 'chmod +x $rvm_path/hooks/after_cd_bundler' run 'mkdir -p .git/safe' end
configure_simple_form()
click to toggle source
# File lib/suspenders/app_builder.rb, line 308 def configure_simple_form bundle_command "exec rails generate simple_form:install" end
configure_smtp()
click to toggle source
# File lib/suspenders/app_builder.rb, line 135 def configure_smtp copy_file 'smtp.rb', 'config/smtp.rb' prepend_file 'config/environments/production.rb', %{require Rails.root.join("config/smtp")\n} config = <<-RUBY config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = SMTP_SETTINGS RUBY inject_into_file 'config/environments/production.rb', config, after: "config.action_mailer.raise_delivery_errors = false" end
configure_spec_support_features()
click to toggle source
# File lib/suspenders/app_builder.rb, line 258 def configure_spec_support_features empty_directory_with_keep_file 'spec/features' empty_directory_with_keep_file 'spec/support/features' end
configure_time_formats()
click to toggle source
# File lib/suspenders/app_builder.rb, line 295 def configure_time_formats remove_file "config/locales/en.yml" template "config_locales_en.yml.erb", "config/locales/en.yml" end
copy_dotfiles()
click to toggle source
# File lib/suspenders/app_builder.rb, line 351 def copy_dotfiles directory("dotfiles", ".") end
copy_env_to_example()
click to toggle source
# File lib/voyage/app_builder.rb, line 818 def copy_env_to_example run 'cp .env .env.example' end
copy_miscellaneous_files()
click to toggle source
# File lib/suspenders/app_builder.rb, line 412 def copy_miscellaneous_files copy_file "browserslist", "browserslist" copy_file "errors.rb", "config/initializers/errors.rb" copy_file "json_encoding.rb", "config/initializers/json_encoding.rb" end
create_application_layout()
click to toggle source
# File lib/suspenders/app_builder.rb, line 218 def create_application_layout template 'suspenders_layout.html.erb.erb', 'app/views/layouts/application.html.erb', force: true end
create_database()
click to toggle source
# File lib/suspenders/app_builder.rb, line 229 def create_database bundle_command 'exec rake db:create db:migrate' end
create_deploy_script()
click to toggle source
# File lib/suspenders/app_builder.rb, line 364 def create_deploy_script copy_file "bin_deploy", "bin/deploy" instructions = <<-MARKDOWN ## Deploying If you have previously run the `./bin/setup` script, you can deploy to staging and production with: % ./bin/deploy staging % ./bin/deploy production MARKDOWN append_file "README.md", instructions run "chmod a+x bin/deploy" end
create_github_repo(repo_name)
click to toggle source
# File lib/suspenders/app_builder.rb, line 394 def create_github_repo(repo_name) run "hub create #{repo_name}" end
create_heroku_apps(flags)
click to toggle source
# File lib/suspenders/app_builder.rb, line 359 def create_heroku_apps(flags) create_staging_heroku_app(flags) create_production_heroku_app(flags) end
create_partials_directory()
click to toggle source
# File lib/suspenders/app_builder.rb, line 198 def create_partials_directory empty_directory 'app/views/application' end
customize_application_controller_for_devise(adding_first_and_last_name, devise_token_auth)
click to toggle source
# File lib/voyage/app_builder.rb, line 163 def customize_application_controller_for_devise(adding_first_and_last_name, devise_token_auth) inject_into_file 'app/controllers/application_controller.rb', before: "class ApplicationController < ActionController::Base" do <<-RUBY.gsub(/^ {8}/, '') # rubocop:disable Metrics/ClassLength, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/LineLength RUBY end inject_into_file 'app/controllers/application_controller.rb', after: " protect_from_forgery with: :exception" do <<-RUBY.gsub(/^ {6}/, '') check_authorization unless: :devise_or_pages_controller? impersonates :user #{'acts_as_token_authentication_handler_for User' if devise_token_auth} before_action :configure_permitted_parameters, if: :devise_controller? before_action :authenticate_user!, unless: -> { is_a?(HighVoltage::PagesController) } before_action :add_layout_name_to_gon before_action :detect_device_type rescue_from CanCan::AccessDenied do |exception| redirect_to root_path, alert: exception.message end # Example Traditional Event: analytics_track(user, 'Created Widget', { widget_name: 'foo' }) # Example Page View: analytics_track(user, 'Page Viewed', { page_name: 'Terms and Conditions', url: '/terms' }) # # NOTE: setup some defaults that we want to track on every event mixpanel_track # NOTE: the identify step happens on every page load to keep intercom.io and mixpanel people up to date def analytics_track(user, event_name, options = {}) return if user.tester? sanitized_options = sanitize_hash_javascript(options) segment_attributes = { user_id: user.uuid, event: event_name, properties: { browser: "\#{browser.name rescue 'unknown'}", browser_id: "\#{browser.id rescue 'unknown'}", browser_version: "\#{browser.version rescue 'unknown'}", platform: "\#{browser.platform rescue 'unknown'}", roles: "\#{user.roles.map(&:to_s).join(',') rescue ''}", rails_env: Rails.env.to_s, }.merge(sanitized_options), } Analytics.track(segment_attributes) end protected def devise_or_pages_controller? devise_controller? == true || is_a?(HighVoltage::PagesController) end def sanitize_hash_javascript(hash) hash.deep_stringify_keys .deep_transform_keys { |k| sanitize_javascript(k) } .transform_values { |v| sanitize_javascript(v) } end def sanitize_javascript(value) value.is_a?(String) ? ActionView::Base.new.escape_javascript(value) : value end def configure_permitted_parameters devise_parameter_sanitizer.permit( :sign_up, keys: [ #{':first_name,' if adding_first_and_last_name} #{':last_name,' if adding_first_and_last_name} :email, :password, :password_confirmation, :remember_me, ], ) devise_parameter_sanitizer.permit( :sign_in, keys: [ :login, :email, :password, :remember_me ], ) devise_parameter_sanitizer.permit( :account_update, keys: [ #{':first_name,' if adding_first_and_last_name} #{':last_name,' if adding_first_and_last_name} :email, :password, :password_confirmation, :current_password, ], ) end def add_layout_name_to_gon gon.layout = case devise_controller? when true 'devise' else 'application' end end def detect_device_type request.variant = case request.user_agent when /iPad/i :tablet when /iPhone/i :phone when /Android/i && /mobile/i :phone when /Android/i :tablet when /Windows Phone/i :phone end end RUBY end end
customize_application_js()
click to toggle source
# File lib/voyage/app_builder.rb, line 583 def customize_application_js template '../templates/application.js', 'app/assets/javascripts/application.js', force: true inject_into_file 'app/views/application/_javascript.html.erb', after: '<%= render "analytics" %>' do <<-RUBY.gsub(/^ {8}/, '') <%= render "analytics_identify" %> RUBY end end
customize_application_mailer()
click to toggle source
# File lib/voyage/app_builder.rb, line 777 def customize_application_mailer template '../templates/application_mailer.rb.erb', 'app/mailers/application_mailer.rb', force: true end
customize_devise_views()
click to toggle source
# File lib/voyage/app_builder.rb, line 143 def customize_devise_views %w(edit new).each do |file| if @@use_slim file_path = "app/views/devise/registrations/#{file}.html.slim" inject_into_file file_path, before: " = f.input :email, required: true, autofocus: true" do <<-'RUBY'.gsub(/^ {8}/, '') = f.input :first_name, required: true, autofocus: true = f.input :last_name, required: true RUBY end else file_path = "app/views/devise/registrations/#{file}.html.erb" inject_into_file file_path, before: " <%= f.input :email, required: true, autofocus: true %>" do <<-'RUBY'.gsub(/^ {8}/, '') <%= f.input :first_name, required: true, autofocus: true %> <%= f.input :last_name, required: true %> RUBY end end end end
customize_error_pages()
click to toggle source
# File lib/suspenders/app_builder.rb, line 418 def customize_error_pages meta_tags =<<-EOS <meta charset="utf-8" /> <meta name="ROBOTS" content="NOODP" /> <meta name="viewport" content="initial-scale=1" /> EOS %w(500 404 422).each do |page| inject_into_file "public/#{page}.html", meta_tags, after: "<head>\n" replace_in_file "public/#{page}.html", /<!--.+-->\n/, '' end end
customize_resource_controller_for_devise(adding_first_and_last_name)
click to toggle source
# File lib/voyage/app_builder.rb, line 299 def customize_resource_controller_for_devise(adding_first_and_last_name) bundle_command 'exec rails generate controller users' run 'rm spec/controllers/users_controller_spec.rb' inject_into_class 'app/controllers/users_controller.rb', 'UsersController' do <<-RUBY.gsub(/^ {6}/, '') # https://github.com/CanCanCommunity/cancancan/wiki/authorizing-controller-actions # load_and_authorize_resource only: [] skip_authorization_check only: [:analytics_alias] def analytics_alias # view file has JS that will identify the anonymous user through segment # after registration via "after devise registration path" end RUBY end end
customize_user_factory(adding_first_and_last_name)
click to toggle source
# File lib/voyage/app_builder.rb, line 460 def customize_user_factory(adding_first_and_last_name) inject_into_file 'spec/factories/users.rb', before: /^ end/ do <<-'RUBY'.gsub(/^ {4}/, '') password 'asdfjkl123' password_confirmation 'asdfjkl123' sequence(:email) { |n| "user_#{n}@example.com" } trait :admin do roles [:admin] email 'admin@example.com' end RUBY end if adding_first_and_last_name inject_into_file 'spec/factories/users.rb', after: /roles \[:admin\]\n/ do <<-'RUBY'.gsub(/^ {4}/, '') first_name 'Admin' last_name 'User' RUBY end end end
customize_user_spec()
click to toggle source
# File lib/voyage/app_builder.rb, line 491 def customize_user_spec find = <<-RUBY.gsub(/^ {6}/, '') pending "add some examples to (or delete) \#{__FILE__}" RUBY replace = <<-RUBY.gsub(/^ {6}/, '') describe 'constants' do context 'roles' do it 'has the admin role' do expect(User::ROLES).to eq([:admin]) end end end describe 'validations' do it { is_expected.to validate_presence_of(:email) } it { is_expected.to validate_presence_of(:password) } it { is_expected.to validate_presence_of(:password_confirmation) } end context '#tester?' do ['example.com', 'headway.io'].each do |domain| it "an email including the \#{domain} domain is a tester" do user = build(:user, email: "asdf@\#{domain}") expect(user.tester?).to eq(true) end end it 'an email including the gmail.com domain is NOT a tester' do user = build(:user, email: 'asdf@gmail.com') expect(user.tester?).to eq(false) end end context 'new user creation' do it 'ensures uniqueness of the uuid' do allow(User).to receive(:exists?).and_return(true, false) expect do create(:user) end.to change { User.count }.by(1) expect(User).to have_received(:exists?).exactly(2).times end end RUBY replace_in_file 'spec/models/user_spec.rb', find, replace end
disallow_wrapping_parameters()
click to toggle source
# File lib/suspenders/app_builder.rb, line 194 def disallow_wrapping_parameters remove_file "config/initializers/wrap_parameters.rb" end
downgrade_neat_1_8_so_refills_media_mixin_works()
click to toggle source
TEMP FIX
https://github.com/thoughtbot/bourbon/issues/993 https://github.com/thoughtbot/refills/issues/400
# File lib/voyage/app_builder.rb, line 638 def downgrade_neat_1_8_so_refills_media_mixin_works replace_in_file 'Gemfile', "gem 'neat', '~> 2.0.0.beta.1'", "gem 'neat', '~> 1.8.0'" run 'gem uninstall -x neat -v2.0.0' run 'bundle' end
enable_database_cleaner()
click to toggle source
# File lib/suspenders/app_builder.rb, line 247 def enable_database_cleaner copy_file 'database_cleaner_rspec.rb', 'spec/support/database_cleaner.rb' end
enable_rack_canonical_host()
click to toggle source
# File lib/suspenders/app_builder.rb, line 151 def enable_rack_canonical_host config = <<-RUBY if ENV.fetch("HEROKU_APP_NAME", "").include?("staging-pr-") ENV["APPLICATION_HOST"] = ENV["HEROKU_APP_NAME"] + ".herokuapp.com" end config.middleware.use Rack::CanonicalHost, ENV.fetch("APPLICATION_HOST") RUBY inject_into_file( "config/environments/production.rb", config, after: "Rails.application.configure do", ) end
enable_rack_deflater()
click to toggle source
# File lib/suspenders/app_builder.rb, line 168 def enable_rack_deflater configure_environment "production", "config.middleware.use Rack::Deflater" end
gemfile()
click to toggle source
# File lib/suspenders/app_builder.rb, line 27 def gemfile template "Gemfile.erb", "Gemfile" end
generate_data_migrations()
click to toggle source
# File lib/voyage/app_builder.rb, line 606 def generate_data_migrations generate 'data_migrations:install' file = Dir['db/migrate/*_create_data_migrations.rb'].first replace_in_file file, 'class CreateDataMigrations < ActiveRecord::Migration', "class CreateDataMigrations < ActiveRecord::Migration[4.2]" empty_directory_with_keep_file 'db/data_migrate' end
generate_factories_file()
click to toggle source
# File lib/suspenders/app_builder.rb, line 127 def generate_factories_file copy_file "factories.rb", "spec/factories.rb" end
generate_refills()
click to toggle source
ADDING REFILLS COMPONENTS
# File lib/voyage/app_builder.rb, line 651 def generate_refills if @@accept_defaults || agree?('Would you like to install default Refill components? (Y/n)') @@add_refills = true bundle_command 'exec rails generate refills:import navigation' bundle_command 'exec rails generate refills:import footer' add_admin_links_to_navigation add_refills_to_stylesheets else @@add_refills = false end end
generate_rspec()
click to toggle source
# File lib/suspenders/app_builder.rb, line 325 def generate_rspec generate 'rspec:install' end
generate_ruby_version_and_gemset()
click to toggle source
# File lib/voyage/app_builder.rb, line 602 def generate_ruby_version_and_gemset create_file '.ruby-gemset', "#{app_name}\n" end
generate_seeder_templates(using_devise:)
click to toggle source
END DEVISE SETUP
# File lib/voyage/app_builder.rb, line 485 def generate_seeder_templates(using_devise:) config = { force: true, using_devise: using_devise } template '../templates/seeder.rb.erb', 'lib/seeder.rb', config template '../templates/seeds.rb.erb', 'db/seeds.rb', config end
generate_test_environment()
click to toggle source
END ADDING REFILLS COMPONENTS
# File lib/voyage/app_builder.rb, line 737 def generate_test_environment template '../templates/controller_helpers.rb', 'spec/support/controller_helpers.rb' template '../templates/simplecov.rb', '.simplecov' end
gitignore()
click to toggle source
# File lib/suspenders/app_builder.rb, line 23 def gitignore copy_file "suspenders_gitignore", ".gitignore" end
init_git()
click to toggle source
# File lib/suspenders/app_builder.rb, line 355 def init_git run 'git init' end
install_devise()
click to toggle source
DEVISE SETUP
# File lib/voyage/app_builder.rb, line 90 def install_devise if @@accept_defaults || agree?('Would you like to install Devise? (Y/n)') @@use_devise = true if @@accept_defaults || agree?('Would you like to install Devise token authentication? (Y/n)') devise_token_auth = true end bundle_command 'exec rails generate devise:install' if @@accept_defaults || agree?("Would you like to add first_name and last_name to the devise model? (Y/n)") adding_first_and_last_name = true bundle_command "exec rails generate resource user first_name:string last_name:string uuid:string" replace_in_file 'spec/factories/users.rb', 'first_name "MyString"', 'first_name { Faker::Name.first_name }' replace_in_file 'spec/factories/users.rb', 'last_name "MyString"', 'last_name { Faker::Name.last_name }' replace_in_file 'spec/factories/users.rb', 'uuid "MyString"', 'uuid { SecureRandom.uuid }' end bundle_command "exec rails generate devise user" bundle_command 'exec rails generate devise:views' if @@use_slim inside('lib') do # arbitrary, run in context of newly generated app run "erb2slim '../app/views/devise' '../app/views/devise'" run "erb2slim -d '../app/views/devise'" end end customize_devise_views if adding_first_and_last_name customize_application_controller_for_devise(adding_first_and_last_name, devise_token_auth) add_devise_registrations_controller customize_resource_controller_for_devise(adding_first_and_last_name) add_admin_views_for_devise_resource(adding_first_and_last_name) add_analytics_initializer authorize_devise_resource_for_index_action add_canard_roles_to_devise_resource update_devise_initializer add_custom_routes_for_devise customize_user_factory(adding_first_and_last_name) generate_seeder_templates(using_devise: true) customize_user_spec add_token_auth else @@use_devise = false generate_seeder_templates(using_devise: false) end end
overwrite_application_layout()
click to toggle source
# File lib/voyage/app_builder.rb, line 865 def overwrite_application_layout template '../templates/voyage_layout.html.erb.erb', 'app/views/layouts/application.html.erb', force: true, add_refills: @@add_refills update_application_layout_for_slim if @@use_slim template '../templates/analytics_identify.html.erb.erb', 'app/views/application/_analytics_identify.html.erb', force: true end
provide_dev_prime_task()
click to toggle source
# File lib/suspenders/app_builder.rb, line 101 def provide_dev_prime_task copy_file 'dev.rake', 'lib/tasks/dev.rake' end
provide_setup_script()
click to toggle source
# File lib/suspenders/app_builder.rb, line 96 def provide_setup_script template "bin_setup", "bin/setup", force: true run "chmod a+x bin/setup" end
provide_shoulda_matchers_config()
click to toggle source
# File lib/suspenders/app_builder.rb, line 251 def provide_shoulda_matchers_config copy_file( "shoulda_matchers_config_rspec.rb", "spec/support/shoulda_matchers.rb" ) end
raise_on_delivery_errors()
click to toggle source
# File lib/suspenders/app_builder.rb, line 42 def raise_on_delivery_errors replace_in_file 'config/environments/development.rb', 'raise_delivery_errors = false', 'raise_delivery_errors = true' end
raise_on_missing_assets_in_test()
click to toggle source
# File lib/suspenders/app_builder.rb, line 38 def raise_on_missing_assets_in_test configure_environment "test", "config.assets.raise_runtime_errors = true" end
raise_on_unpermitted_parameters()
click to toggle source
# File lib/suspenders/app_builder.rb, line 80 def raise_on_unpermitted_parameters config = <<-RUBY config.action_controller.action_on_unpermitted_parameters = :raise RUBY inject_into_class "config/application.rb", "Application", config end
rake_db_setup()
click to toggle source
Do this last
# File lib/voyage/app_builder.rb, line 792 def rake_db_setup rake 'db:migrate' rake 'db:seed' if File.exist?('config/initializers/devise.rb') end
readme()
click to toggle source
# File lib/suspenders/app_builder.rb, line 19 def readme template 'README.md.erb', 'README.md' end
remove_config_comment_lines()
click to toggle source
# File lib/suspenders/app_builder.rb, line 431 def remove_config_comment_lines config_files = [ "application.rb", "environment.rb", "environments/development.rb", "environments/production.rb", "environments/test.rb", ] config_files.each do |config_file| path = File.join(destination_root, "config/#{config_file}") accepted_content = File.readlines(path).reject do |line| line =~ /^.*#.*$/ || line =~ /^$\n/ end File.open(path, "w") do |file| accepted_content.each { |line| file.puts line } end end end
remove_routes_comment_lines()
click to toggle source
# File lib/suspenders/app_builder.rb, line 453 def remove_routes_comment_lines replace_in_file 'config/routes.rb', /Rails\.application\.routes\.draw do.*end/m, "Rails.application.routes.draw do\nend" end
remove_turbolinks()
click to toggle source
# File lib/suspenders/app_builder.rb, line 47 def remove_turbolinks replace_in_file( "app/assets/javascripts/application.js", "//= require turbolinks", "" ) end
replace_default_puma_configuration()
click to toggle source
# File lib/suspenders/app_builder.rb, line 329 def replace_default_puma_configuration copy_file "puma.rb", "config/puma.rb", force: true end
replace_gemfile(path)
click to toggle source
# File lib/suspenders/app_builder.rb, line 233 def replace_gemfile(path) template 'Gemfile.erb', 'Gemfile', force: true do |content| if path content.gsub(%r{gem .suspenders.}) { |s| %{#{s}, path: "#{path}"} } else content end end end
require_files_in_lib()
click to toggle source
# File lib/voyage/app_builder.rb, line 593 def require_files_in_lib create_file 'config/initializers/require_files_in_lib.rb' do <<-RUBY.gsub(/^ {8}/, '') # rubocop:disable Rails/FilePath Dir[File.join(Rails.root, 'lib', '**', '*.rb')].each { |l| require l } # rubocop:enable Rails/FilePath RUBY end end
run_rubocop_auto_correct()
click to toggle source
# File lib/voyage/app_builder.rb, line 814 def run_rubocop_auto_correct run 'rubocop --auto-correct' end
set_ruby_to_version_being_used()
click to toggle source
# File lib/suspenders/app_builder.rb, line 243 def set_ruby_to_version_being_used create_file '.ruby-version', "#{Suspenders::RUBY_VERSION}\n" end
set_test_delivery_method()
click to toggle source
# File lib/suspenders/app_builder.rb, line 55 def set_test_delivery_method inject_into_file( "config/environments/development.rb", "\n config.action_mailer.delivery_method = :file", after: "config.action_mailer.raise_delivery_errors = true", ) end
set_up_factory_girl_for_rspec()
click to toggle source
# File lib/suspenders/app_builder.rb, line 123 def set_up_factory_girl_for_rspec copy_file 'factory_girl_rspec.rb', 'spec/support/factory_girl.rb' end
set_up_forego()
click to toggle source
# File lib/suspenders/app_builder.rb, line 333 def set_up_forego copy_file "Procfile", "Procfile" end
set_up_hound()
click to toggle source
# File lib/suspenders/app_builder.rb, line 131 def set_up_hound copy_file "hound.yml", ".hound.yml" end
setup_asset_host()
click to toggle source
# File lib/suspenders/app_builder.rb, line 172 def setup_asset_host replace_in_file 'config/environments/production.rb', "# config.action_controller.asset_host = 'http://assets.example.com'", 'config.action_controller.asset_host = ENV.fetch("ASSET_HOST", ENV.fetch("APPLICATION_HOST"))' replace_in_file 'config/initializers/assets.rb', "config.assets.version = '1.0'", 'config.assets.version = (ENV["ASSETS_VERSION"] || "1.0")' config = <<-EOD config.public_file_server.headers = { "Cache-Control" => "public, max-age=31557600", } EOD configure_environment("production", config) end
setup_bundler_audit()
click to toggle source
# File lib/suspenders/app_builder.rb, line 403 def setup_bundler_audit copy_file "bundler_audit.rake", "lib/tasks/bundler_audit.rake" append_file "Rakefile", %{\ntask default: "bundle:audit"\n} end
setup_default_directories()
click to toggle source
# File lib/suspenders/app_builder.rb, line 337 def setup_default_directories [ 'app/views/pages', 'spec/lib', 'spec/controllers', 'spec/helpers', 'spec/support/matchers', 'spec/support/mixins', 'spec/support/shared_examples' ].each do |dir| empty_directory_with_keep_file dir end end
setup_default_rake_task()
click to toggle source
# File lib/suspenders/app_builder.rb, line 459 def setup_default_rake_task append_file 'Rakefile' do <<-EOS task(:default).clear task default: [:spec] if defined? RSpec task(:spec).clear RSpec::Core::RakeTask.new(:spec) do |t| t.verbose = false end end EOS end end
setup_rack_mini_profiler()
click to toggle source
# File lib/suspenders/app_builder.rb, line 31 def setup_rack_mini_profiler copy_file( "rack_mini_profiler.rb", "config/initializers/rack_mini_profiler.rb", ) end
setup_secret_token()
click to toggle source
# File lib/suspenders/app_builder.rb, line 190 def setup_secret_token template 'secrets.yml', 'config/secrets.yml', force: true end
setup_segment()
click to toggle source
# File lib/suspenders/app_builder.rb, line 398 def setup_segment copy_file '_analytics.html.erb', 'app/views/application/_analytics.html.erb' end
setup_spring()
click to toggle source
# File lib/suspenders/app_builder.rb, line 408 def setup_spring bundle_command "exec spring binstub --all" end
spin_up_webpacker()
click to toggle source
# File lib/voyage/app_builder.rb, line 834 def spin_up_webpacker rake 'webpacker:install' rake 'webpacker:install:react' end
update_application_css_file()
click to toggle source
# File lib/voyage/app_builder.rb, line 693 def update_application_css_file inject_into_file 'app/assets/stylesheets/application.scss', before: '@import "neat";' do <<-RUBY.gsub(/^ {8}/, '') $visual-grid: true; $visual-grid-color: #9cf !default; $visual-grid-index: front !default; $visual-grid-opacity: 0.1 !default; RUBY end end
update_application_layout_for_slim()
click to toggle source
# File lib/voyage/app_builder.rb, line 40 def update_application_layout_for_slim find = <<-RUBY.gsub(/^ {4}/, '') <%# Configure default and controller-, and view-specific titles in config/locales/en.yml. For more see: https://github.com/calebthompson/title#usage %> RUBY replace = <<-RUBY.gsub(/^ {8}/, '') <% # Configure default and controller-, and view-specific titles in # config/locales/en.yml. For more see: # https://github.com/calebthompson/title#usage %> RUBY replace_in_file 'app/views/layouts/application.html.erb', find, replace inside('lib') do # arbitrary, run in context of newly generated app run "erb2slim '../app/views/layouts' '../app/views/layouts'" run "erb2slim -d '../app/views/layouts'" end # strip trailing space after closing "> in application layout before # trying to find and replace it replace_in_file 'app/views/layouts/application.html.slim', '| "> ', '| ">' find = <<-RUBY.gsub(/^ {6}/, '') | <body class=" = devise_controller? ? 'devise' : 'application' = body_class | "> RUBY replace = <<-RUBY.gsub(/^ {6}/, '') body class="\#{devise_controller? ? 'devise' : 'application'} \#{body_class}" RUBY replace_in_file 'app/views/layouts/application.html.slim', find, replace end
update_application_rb_for_slim()
click to toggle source
# File lib/voyage/app_builder.rb, line 80 def update_application_rb_for_slim inject_into_file "config/application.rb", after: " g.fixture_replacement :factory_girl, dir: 'spec/factories'\n" do <<-'RUBY'.gsub(/^ {2}/, '') g.template_engine :slim RUBY end end
update_devise_initializer()
click to toggle source
# File lib/voyage/app_builder.rb, line 408 def update_devise_initializer replace_in_file 'config/initializers/devise.rb', 'config.sign_out_via = :delete', 'config.sign_out_via = :get' replace_in_file 'config/initializers/devise.rb', "config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'", "config.mailer_sender = 'user@example.com'" end
update_flashes_css_file()
click to toggle source
# File lib/voyage/app_builder.rb, line 689 def update_flashes_css_file replace_in_file 'app/assets/stylesheets/refills/_flashes.scss', "margin-bottom: $base-spacing / 2;", "// margin-bottom: $base-spacing / 2;" end
update_gemset_in_gemfile()
click to toggle source
# File lib/voyage/app_builder.rb, line 18 def update_gemset_in_gemfile replace_in_file 'Gemfile', '#ruby-gemset', "#ruby-gemset=#{app_name}" # Remove commented out lines from template gsub_file('Gemfile', /^\s{2}\n/, '') end
update_test_environment()
click to toggle source
# File lib/voyage/app_builder.rb, line 742 def update_test_environment inject_into_file 'spec/support/factory_girl.rb', before: /^end/ do <<-RUBY.gsub(/^ {6}/, '') # Spring doesn't reload factory_girl config.before(:all) do FactoryGirl.reload end RUBY end template "../templates/rails_helper.rb.erb", "spec/rails_helper.rb", force: true %w(test development).each do |environment| inject_into_file "config/environments/#{environment}.rb", after: /^end/ do <<-RUBY.gsub(/^ {10}/, '') # NOTE: console can use create(:factory_name), or build(:factory_name) without # needing to use FactoryGirl.create(:factory_name). include FactoryGirl::Syntax::Methods RUBY end end end
use_postgres_config_template()
click to toggle source
# File lib/suspenders/app_builder.rb, line 224 def use_postgres_config_template template 'postgresql_database.yml.erb', 'config/database.yml', force: true end
use_slim()
click to toggle source
# File lib/voyage/app_builder.rb, line 29 def use_slim if @@accept_defaults || agree?('Would you like to use slim? (Y/n)') @@use_slim = true run 'gem install html2slim' update_application_rb_for_slim else @@use_slim = false gsub_file('Gemfile', /^gem 'slim-rails'\n/, '') end end
Private Instance Methods
heroku_adapter()
click to toggle source
# File lib/suspenders/app_builder.rb, line 483 def heroku_adapter @heroku_adapter ||= Adapters::Heroku.new(self) end
raise_on_missing_translations_in(environment)
click to toggle source
# File lib/suspenders/app_builder.rb, line 477 def raise_on_missing_translations_in(environment) config = 'config.action_view.raise_on_missing_translations = true' uncomment_lines("config/environments/#{environment}.rb", config) end