bowties 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/CONTRIBUTING.md +43 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +129 -0
  9. data/LICENSE +21 -0
  10. data/NEWS.md +405 -0
  11. data/README.md +219 -0
  12. data/Rakefile +8 -0
  13. data/bin/bowties +18 -0
  14. data/bin/rake +16 -0
  15. data/bin/rspec +16 -0
  16. data/bin/setup +13 -0
  17. data/bowties.gemspec +34 -0
  18. data/circle.yml +6 -0
  19. data/lib/bowties.rb +4 -0
  20. data/lib/bowties/actions.rb +33 -0
  21. data/lib/bowties/app_builder.rb +499 -0
  22. data/lib/bowties/generators/app_generator.rb +238 -0
  23. data/lib/bowties/version.rb +5 -0
  24. data/spec/fakes/bin/heroku +5 -0
  25. data/spec/fakes/bin/hub +5 -0
  26. data/spec/features/github_spec.rb +15 -0
  27. data/spec/features/heroku_spec.rb +46 -0
  28. data/spec/features/new_project_spec.rb +135 -0
  29. data/spec/spec_helper.rb +20 -0
  30. data/spec/support/bowties.rb +48 -0
  31. data/spec/support/fake_github.rb +21 -0
  32. data/spec/support/fake_heroku.rb +43 -0
  33. data/templates/Gemfile.erb +58 -0
  34. data/templates/Procfile +2 -0
  35. data/templates/README.md.erb +32 -0
  36. data/templates/_analytics.html.erb +7 -0
  37. data/templates/_flashes.html.erb +7 -0
  38. data/templates/_javascript.html.erb +12 -0
  39. data/templates/action_mailer.rb +5 -0
  40. data/templates/application.scss +8 -0
  41. data/templates/bin_deploy +12 -0
  42. data/templates/bin_setup.erb +36 -0
  43. data/templates/browserslist +4 -0
  44. data/templates/bundler_audit.rake +12 -0
  45. data/templates/circle.yml.erb +8 -0
  46. data/templates/config_i18n_tasks.yml +13 -0
  47. data/templates/config_locales_en.yml.erb +19 -0
  48. data/templates/database_cleaner_rspec.rb +21 -0
  49. data/templates/development_seeds.rb +12 -0
  50. data/templates/disable_xml_params.rb +3 -0
  51. data/templates/errors.rb +34 -0
  52. data/templates/factory_girl_rspec.rb +3 -0
  53. data/templates/flashes_helper.rb +5 -0
  54. data/templates/hound.yml +17 -0
  55. data/templates/i18n.rb +3 -0
  56. data/templates/json_encoding.rb +1 -0
  57. data/templates/newrelic.yml.erb +34 -0
  58. data/templates/postgresql_database.yml.erb +12 -0
  59. data/templates/rails_helper.rb +23 -0
  60. data/templates/sample.env +6 -0
  61. data/templates/secrets.yml +14 -0
  62. data/templates/smtp.rb +9 -0
  63. data/templates/spec_helper.rb +23 -0
  64. data/templates/staging.rb +5 -0
  65. data/templates/suspenders_gitignore +14 -0
  66. data/templates/suspenders_layout.html.erb.erb +21 -0
  67. data/templates/unicorn.rb +30 -0
  68. metadata +181 -0
@@ -0,0 +1,219 @@
1
+ # Bowties [![Circle CI](https://circleci.com/gh/wizarddevelopment/bowties.svg?style=svg&circle-token=6964ba6efdd78b60433f87886907afac1ea96b58)](https://circleci.com/gh/wizarddevelopment/bowties)
2
+
3
+ Bowties is the base Rails application used at [Wizard Development](http://www.wizarddevelopment.com) forked from the wonderful [suspenders](https://github.com/thoughtbot/suspenders) project in use at
4
+ [thoughtbot](http://thoughtbot.com).
5
+
6
+ ## Why Fork?
7
+ We work a bit differently. Suspenders has the defaults that makes sense for thoughtbot and Bowties has defaults that make sense for us. You can find our current best practices in our [development guides](https://github.com/wizarddevelopment/guides).
8
+
9
+ ## Installation
10
+
11
+ First install the Bowties gem:
12
+
13
+ gem install bowties
14
+
15
+ Then run:
16
+
17
+ bowties projectname
18
+
19
+ This will create a Rails app in `projectname` using the latest version of Rails.
20
+
21
+ ## Gemfile
22
+
23
+ To see the latest and greatest gems, look at Bowties'
24
+ [Gemfile](templates/Gemfile.erb), which will be appended to the default
25
+ generated projectname/Gemfile.
26
+
27
+ It includes application gems like:
28
+
29
+ * [Airbrake](https://github.com/airbrake/airbrake) for exception notification
30
+ * [Autoprefixer Rails](https://github.com/ai/autoprefixer-rails) for CSS vendor prefixes
31
+ * [Bourbon](https://github.com/thoughtbot/bourbon) for Sass mixins
32
+ * [Bitters](https://github.com/thoughtbot/bitters) for scaffold application styles
33
+ * [Delayed Job](https://github.com/collectiveidea/delayed_job) for background
34
+ processing
35
+ * [Email Validator](https://github.com/balexand/email_validator) for email
36
+ validation
37
+ * [Flutie](https://github.com/thoughtbot/flutie) for `page_title` and `body_class` view
38
+ helpers
39
+ * [High Voltage](https://github.com/thoughtbot/high_voltage) for static pages
40
+ * [jQuery Rails](https://github.com/rails/jquery-rails) for jQuery
41
+ * [Neat](https://github.com/thoughtbot/neat) for semantic grids
42
+ * [New Relic RPM](https://github.com/newrelic/rpm) for monitoring performance
43
+ * [Normalize](https://necolas.github.io/normalize.css/) for resetting browser styles
44
+ * [Postgres](https://github.com/ged/ruby-pg) for access to the Postgres database
45
+ * [Rack Canonical Host](https://github.com/tylerhunt/rack-canonical-host) to
46
+ ensure all requests are served from the same domain
47
+ * [Rack Timeout](https://github.com/kch/rack-timeout) to abort requests that are
48
+ taking too long
49
+ * [Recipient Interceptor](https://github.com/croaky/recipient_interceptor) to
50
+ avoid accidentally sending emails to real people from staging
51
+ * [Refills](https://github.com/thoughtbot/refills) for “copy-paste” components
52
+ and patterns based on Bourbon, Neat and Bitters
53
+ * [Simple Form](https://github.com/plataformatec/simple_form) for form markup
54
+ and style
55
+ * [Title](https://github.com/calebthompson/title) for storing titles in
56
+ translations
57
+ * [Unicorn](https://github.com/defunkt/unicorn) to serve HTTP requests
58
+
59
+ And development gems like:
60
+
61
+ * [Dotenv](https://github.com/bkeepers/dotenv) for loading environment variables
62
+ * [Pry Rails](https://github.com/rweng/pry-rails) for interactively exploring
63
+ objects
64
+ * [ByeBug](https://github.com/deivid-rodriguez/byebug) for interactively
65
+ debugging behavior
66
+ * [Bundler Audit](https://github.com/rubysec/bundler-audit) for scanning the
67
+ Gemfile for insecure dependencies based on published CVEs
68
+ * [Spring](https://github.com/rails/spring) for fast Rails actions via
69
+ pre-loading
70
+ * [Web Console](https://github.com/rails/web-console) for better debugging via
71
+ in-browser IRB consoles.
72
+
73
+ And testing gems like:
74
+
75
+ * [Capybara](https://github.com/jnicklas/capybara) and
76
+ [Capybara Webkit](https://github.com/thoughtbot/capybara-webkit) for
77
+ integration testing
78
+ * [Factory Girl](https://github.com/thoughtbot/factory_girl) for test data
79
+ * [Formulaic](https://github.com/thoughtbot/formulaic) for integration testing
80
+ HTML forms
81
+ * [RSpec](https://github.com/rspec/rspec) for unit testing
82
+ * [RSpec Mocks](https://github.com/rspec/rspec-mocks) for stubbing and spying
83
+ * [Shoulda Matchers](https://github.com/thoughtbot/shoulda-matchers) for common
84
+ RSpec matchers
85
+ * [Timecop](https://github.com/jtrupiano/timecop-console) for testing time
86
+
87
+ ## Other goodies
88
+
89
+ Bowties also comes with:
90
+
91
+ * The [`./bin/setup`][setup] convention for new developer setup
92
+ * The `./bin/deploy` convention for deploying to Heroku
93
+ * Rails' flashes set up and in application layout
94
+ * A few nice time formats set up for localization
95
+ * `Rack::Deflater` to [compress responses with Gzip][compress]
96
+ * A [low database connection pool limit][pool]
97
+ * [Safe binstubs][binstub]
98
+ * [t() and l() in specs without prefixing with I18n][i18n]
99
+ * An automatically-created `SECRET_KEY_BASE` environment variable in all
100
+ environments
101
+ * Configuration for [CircleCI][circle] Continuous Integration (tests)
102
+ * Configuration for [Hound][hound] Continuous Integration (style)
103
+ * The analytics adapter [Segment][segment] (and therefore config for Google
104
+ Analytics, Intercom, Facebook Ads, Twitter Ads, etc.)
105
+
106
+ [setup]: http://robots.thoughtbot.com/bin-setup
107
+ [compress]: http://robots.thoughtbot.com/content-compression-with-rack-deflater/
108
+ [pool]: https://devcenter.heroku.com/articles/concurrency-and-database-connections
109
+ [binstub]: https://github.com/thoughtbot/suspenders/pull/282
110
+ [i18n]: https://github.com/thoughtbot/suspenders/pull/304
111
+ [circle]: https://circleci.com/docs
112
+ [hound]: https://houndci.com
113
+ [segment]: https://segment.com
114
+
115
+ ## Heroku
116
+
117
+ You can optionally create Heroku staging and production apps:
118
+
119
+ bowties app --heroku true
120
+
121
+ This:
122
+
123
+ * Creates a staging and production Heroku app
124
+ * Sets them as `staging` and `production` Git remotes
125
+ * Configures staging with `RACK_ENV` and `RAILS_ENV` environment variables set
126
+ to `staging`
127
+ * Adds the [Rails Stdout Logging][logging-gem] gem
128
+ to configure the app to log to standard out,
129
+ which is how [Heroku's logging][heroku-logging] works.
130
+
131
+ [logging-gem]: https://github.com/heroku/rails_stdout_logging
132
+ [heroku-logging]: https://devcenter.heroku.com/articles/logging#writing-to-your-log
133
+
134
+ You can optionally specify alternate Heroku flags:
135
+
136
+ bowties app \
137
+ --heroku true \
138
+ --heroku-flags "--region eu --addons newrelic,sendgrid,ssl"
139
+
140
+ See all possible Heroku flags:
141
+
142
+ heroku help create
143
+
144
+ ## Git
145
+
146
+ This will initialize a new git repository for your Rails app. You can
147
+ bypass this with the `--skip-git` option:
148
+
149
+ bowties app --skip-git true
150
+
151
+ ## GitHub
152
+
153
+ You can optionally create a GitHub repository for the suspended Rails app. It
154
+ requires that you have [Hub](https://github.com/github/hub) on your system:
155
+
156
+ curl http://hub.github.com/standalone -sLo ~/bin/hub && chmod +x ~/bin/hub
157
+ bowties app --github organization/project
158
+
159
+ This has the same effect as running:
160
+
161
+ hub create organization/project
162
+
163
+ ## Spring
164
+
165
+ Bowties uses [spring](https://github.com/rails/spring) by default.
166
+ It makes Rails applications load faster, but it might introduce confusing issues
167
+ around stale code not being refreshed.
168
+ If you think your application is running old code, run `spring stop`.
169
+ And if you'd rather not use spring, add `DISABLE_SPRING=1` to your login file.
170
+
171
+ ## Dependencies
172
+
173
+ Bowties requires the latest version of Ruby.
174
+
175
+ Some gems included in Bowties have native extensions. You should have GCC
176
+ installed on your machine before generating an app with Bowties.
177
+
178
+ Use [OS X GCC Installer](https://github.com/kennethreitz/osx-gcc-installer/) for
179
+ Snow Leopard (OS X 10.6).
180
+
181
+ Use [Command Line Tools for XCode](https://developer.apple.com/downloads/index.action)
182
+ for Lion (OS X 10.7) or Mountain Lion (OS X 10.8).
183
+
184
+ We use [Capybara Webkit](https://github.com/thoughtbot/capybara-webkit) for
185
+ full-stack JavaScript integration testing. It requires QT. Instructions for
186
+ installing QT are
187
+ [here](https://github.com/thoughtbot/capybara-webkit/wiki/Installing-Qt-and-compiling-capybara-webkit).
188
+
189
+ PostgreSQL needs to be installed and running for the `db:create` rake task.
190
+
191
+ ## Issues
192
+
193
+ If you have problems, please create a
194
+ [GitHub Issue](https://github.com/wizarddevelopment/bowties/issues).
195
+
196
+ ## Contributing
197
+
198
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
199
+
200
+ Thank you, [contributors] and thoughtbot!
201
+
202
+ [contributors]: https://github.com/wizarddevelopment/bowties/graphs/contributors
203
+
204
+ ## License
205
+
206
+ Bowties is Copyright © 2015 Wizard Development.
207
+ It is free software,
208
+ and may be redistributed under the terms specified in the [LICENSE] file.
209
+
210
+ [LICENSE]: LICENSE
211
+
212
+ ## About Wizard Development
213
+
214
+ Bowties is maintained and funded by Wizard Development.
215
+
216
+ We love open source software!
217
+ We are [available for hire][hire].
218
+
219
+ [hire]: https://www.wizarddevelopment.com?utm_source=github
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:rspec)
6
+
7
+ desc 'Run the test suite'
8
+ task default: :rspec
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+
4
+ source_path = (Pathname.new(__FILE__).dirname + '../lib').expand_path
5
+ $LOAD_PATH << source_path
6
+
7
+ require 'bowties'
8
+
9
+ if ['create', '--create'].include? ARGV[0]
10
+ ARGV.shift
11
+ puts "[WARNING] the bowties create argument is deprecated. Just use `bowties #{ARGV.join}` instead"
12
+ end
13
+
14
+ templates_root = File.expand_path(File.join("..", "templates"), File.dirname(__FILE__))
15
+ Bowties::AppGenerator.source_root templates_root
16
+ Bowties::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root << templates_root
17
+
18
+ Bowties::AppGenerator.start
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'rspec')
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env sh
2
+
3
+ # Run this script immediately after cloning the codebase.
4
+
5
+ # Exit if any subcommand fails
6
+ set -e
7
+
8
+ # Set up Ruby dependencies via Bundler
9
+ bundle install
10
+
11
+ # Add binstubs to PATH in ~/.zshenv like this:
12
+ # export PATH=".git/safe/../../bin:$PATH"
13
+ mkdir -p .git/safe
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
3
+ require 'bowties/version'
4
+ require 'date'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.required_ruby_version = ">= #{Bowties::RUBY_VERSION}"
8
+ s.authors = ['Wizard Development']
9
+ s.date = Date.today.strftime('%Y-%m-%d')
10
+
11
+ s.description = <<-HERE
12
+ Bowties is a base Rails project that you can upgrade. It is used by
13
+ Wizard Development to get a jump start on a working app.
14
+ HERE
15
+
16
+ s.email = 'admin@wizarddevelopment.com'
17
+ s.executables = ['bowties']
18
+ s.extra_rdoc_files = %w(README.md LICENSE)
19
+ s.files = `git ls-files`.split("\n")
20
+ s.homepage = 'http://github.com/wizarddevelopment/bowties'
21
+ s.license = 'MIT'
22
+ s.name = 'bowties'
23
+ s.rdoc_options = ['--charset=UTF-8']
24
+ s.require_paths = ['lib']
25
+ s.summary = "Generate a Rails app using Wizard Development's best practices."
26
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
+ s.version = Bowties::VERSION
28
+
29
+ s.add_dependency 'bitters', '~> 1.0.0'
30
+ s.add_dependency 'bundler', '~> 1.3'
31
+ s.add_dependency 'rails', Bowties::RAILS_VERSION
32
+
33
+ s.add_development_dependency 'rspec', '~> 3.2'
34
+ end
@@ -0,0 +1,6 @@
1
+ test:
2
+ pre:
3
+ - git config --global user.name 'Circle'
4
+ - git config --global user.email 'circle@example.com'
5
+ override:
6
+ - bundle exec rake
@@ -0,0 +1,4 @@
1
+ require 'bowties/version'
2
+ require 'bowties/generators/app_generator'
3
+ require 'bowties/actions'
4
+ require 'bowties/app_builder'
@@ -0,0 +1,33 @@
1
+ module Bowties
2
+ module Actions
3
+ def replace_in_file(relative_path, find, replace)
4
+ path = File.join(destination_root, relative_path)
5
+ contents = IO.read(path)
6
+ unless contents.gsub!(find, replace)
7
+ raise "#{find.inspect} not found in #{relative_path}"
8
+ end
9
+ File.open(path, "w") { |file| file.write(contents) }
10
+ end
11
+
12
+ def action_mailer_host(rails_env, host)
13
+ config = "config.action_mailer.default_url_options = { host: #{host} }"
14
+ configure_environment(rails_env, config)
15
+ end
16
+
17
+ def configure_application_file(config)
18
+ inject_into_file(
19
+ "config/application.rb",
20
+ "\n\n #{config}",
21
+ before: "\n end"
22
+ )
23
+ end
24
+
25
+ def configure_environment(rails_env, config)
26
+ inject_into_file(
27
+ "config/environments/#{rails_env}.rb",
28
+ "\n\n #{config}",
29
+ before: "\nend"
30
+ )
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,499 @@
1
+ module Bowties
2
+ class AppBuilder < Rails::AppBuilder
3
+ include Bowties::Actions
4
+
5
+ def readme
6
+ template 'README.md.erb', 'README.md'
7
+ end
8
+
9
+ def raise_on_delivery_errors
10
+ replace_in_file 'config/environments/development.rb',
11
+ 'raise_delivery_errors = false', 'raise_delivery_errors = true'
12
+ end
13
+
14
+ def set_test_delivery_method
15
+ inject_into_file(
16
+ "config/environments/development.rb",
17
+ "\n config.action_mailer.delivery_method = :test",
18
+ after: "config.action_mailer.raise_delivery_errors = true",
19
+ )
20
+ end
21
+
22
+ def raise_on_unpermitted_parameters
23
+ config = <<-RUBY
24
+ config.action_controller.action_on_unpermitted_parameters = :raise
25
+ RUBY
26
+
27
+ inject_into_class "config/application.rb", "Application", config
28
+ end
29
+
30
+ def provide_setup_script
31
+ template "bin_setup.erb", "bin/setup", port_number: port, force: true
32
+ run "chmod a+x bin/setup"
33
+ end
34
+
35
+ def provide_dev_prime_task
36
+ copy_file 'development_seeds.rb', 'lib/tasks/development_seeds.rake'
37
+ end
38
+
39
+ def configure_generators
40
+ config = <<-RUBY
41
+
42
+ config.generators do |generate|
43
+ generate.helper false
44
+ generate.javascript_engine false
45
+ generate.request_specs false
46
+ generate.routing_specs false
47
+ generate.stylesheets false
48
+ generate.test_framework :rspec
49
+ generate.view_specs false
50
+ end
51
+
52
+ RUBY
53
+
54
+ inject_into_class 'config/application.rb', 'Application', config
55
+ end
56
+
57
+ def set_up_factory_girl_for_rspec
58
+ copy_file 'factory_girl_rspec.rb', 'spec/support/factory_girl.rb'
59
+ end
60
+
61
+ def set_up_hound
62
+ copy_file "hound.yml", ".hound.yml"
63
+ end
64
+
65
+ def configure_newrelic
66
+ template 'newrelic.yml.erb', 'config/newrelic.yml'
67
+ end
68
+
69
+ def configure_smtp
70
+ copy_file 'smtp.rb', 'config/smtp.rb'
71
+
72
+ prepend_file 'config/environments/production.rb',
73
+ %{require Rails.root.join("config/smtp")\n}
74
+
75
+ config = <<-RUBY
76
+
77
+ config.action_mailer.delivery_method = :smtp
78
+ config.action_mailer.smtp_settings = SMTP_SETTINGS
79
+ RUBY
80
+
81
+ inject_into_file 'config/environments/production.rb', config,
82
+ :after => 'config.action_mailer.raise_delivery_errors = false'
83
+ end
84
+
85
+ def enable_rack_canonical_host
86
+ config = <<-RUBY
87
+
88
+ # Ensure requests are only served from one, canonical host name
89
+ config.middleware.use Rack::CanonicalHost, ENV.fetch("HOST")
90
+ RUBY
91
+
92
+ inject_into_file(
93
+ "config/environments/production.rb",
94
+ config,
95
+ after: serve_static_files_line
96
+ )
97
+ end
98
+
99
+ def enable_rack_deflater
100
+ config = <<-RUBY
101
+
102
+ # Enable deflate / gzip compression of controller-generated responses
103
+ config.middleware.use Rack::Deflater
104
+ RUBY
105
+
106
+ inject_into_file(
107
+ "config/environments/production.rb",
108
+ config,
109
+ after: serve_static_files_line
110
+ )
111
+ end
112
+
113
+ def setup_asset_host
114
+ replace_in_file 'config/environments/production.rb',
115
+ "# config.action_controller.asset_host = 'http://assets.example.com'",
116
+ 'config.action_controller.asset_host = ENV.fetch("ASSET_HOST", ENV.fetch("HOST"))'
117
+
118
+ replace_in_file 'config/initializers/assets.rb',
119
+ "config.assets.version = '1.0'",
120
+ 'config.assets.version = (ENV["ASSETS_VERSION"] || "1.0")'
121
+
122
+ inject_into_file(
123
+ "config/environments/production.rb",
124
+ ' config.static_cache_control = "public, max-age=#{1.year.to_i}"',
125
+ after: serve_static_files_line
126
+ )
127
+ end
128
+
129
+ def setup_staging_environment
130
+ staging_file = 'config/environments/staging.rb'
131
+ copy_file 'staging.rb', staging_file
132
+
133
+ config = <<-RUBY
134
+
135
+ Rails.application.configure do
136
+ # ...
137
+ end
138
+ RUBY
139
+
140
+ append_file staging_file, config
141
+ end
142
+
143
+ def setup_secret_token
144
+ template 'secrets.yml', 'config/secrets.yml', force: true
145
+ end
146
+
147
+ def disallow_wrapping_parameters
148
+ remove_file "config/initializers/wrap_parameters.rb"
149
+ end
150
+
151
+ def create_partials_directory
152
+ empty_directory 'app/views/application'
153
+ end
154
+
155
+ def create_shared_flashes
156
+ copy_file "_flashes.html.erb", "app/views/application/_flashes.html.erb"
157
+ copy_file "flashes_helper.rb", "app/helpers/flashes_helper.rb"
158
+ end
159
+
160
+ def create_shared_javascripts
161
+ copy_file '_javascript.html.erb', 'app/views/application/_javascript.html.erb'
162
+ end
163
+
164
+ def create_application_layout
165
+ template 'suspenders_layout.html.erb.erb',
166
+ 'app/views/layouts/application.html.erb',
167
+ force: true
168
+ end
169
+
170
+ def use_postgres_config_template
171
+ template 'postgresql_database.yml.erb', 'config/database.yml',
172
+ force: true
173
+ end
174
+
175
+ def create_database
176
+ bundle_command 'exec rake db:create db:migrate'
177
+ end
178
+
179
+ def replace_gemfile
180
+ remove_file 'Gemfile'
181
+ template 'Gemfile.erb', 'Gemfile'
182
+ end
183
+
184
+ def set_ruby_to_version_being_used
185
+ create_file '.ruby-version', "#{Bowties::RUBY_VERSION}\n"
186
+ end
187
+
188
+ def setup_heroku_specific_gems
189
+ inject_into_file(
190
+ "Gemfile",
191
+ %{\n\s\sgem "rails_stdout_logging"},
192
+ after: /group :staging, :production do/
193
+ )
194
+ end
195
+
196
+ def enable_database_cleaner
197
+ copy_file 'database_cleaner_rspec.rb', 'spec/support/database_cleaner.rb'
198
+ end
199
+
200
+ def configure_spec_support_features
201
+ empty_directory_with_keep_file 'spec/features'
202
+ empty_directory_with_keep_file 'spec/support/features'
203
+ end
204
+
205
+ def configure_rspec
206
+ remove_file "spec/rails_helper.rb"
207
+ remove_file "spec/spec_helper.rb"
208
+ copy_file "rails_helper.rb", "spec/rails_helper.rb"
209
+ copy_file "spec_helper.rb", "spec/spec_helper.rb"
210
+ end
211
+
212
+ def configure_ci
213
+ template "circle.yml.erb", "circle.yml"
214
+ end
215
+
216
+ def configure_i18n_for_test_environment
217
+ copy_file "i18n.rb", "spec/support/i18n.rb"
218
+ end
219
+
220
+ def configure_i18n_for_missing_translations
221
+ raise_on_missing_translations_in("development")
222
+ raise_on_missing_translations_in("test")
223
+ end
224
+
225
+ def configure_i18n_tasks
226
+ run "cp $(i18n-tasks gem-path)/templates/rspec/i18n_spec.rb spec/"
227
+ copy_file "config_i18n_tasks.yml", "config/i18n-tasks.yml"
228
+ end
229
+
230
+ def configure_background_jobs_for_rspec
231
+ run 'rails g delayed_job:active_record'
232
+ end
233
+
234
+ def configure_action_mailer_in_specs
235
+ copy_file 'action_mailer.rb', 'spec/support/action_mailer.rb'
236
+ end
237
+
238
+ def configure_time_formats
239
+ remove_file "config/locales/en.yml"
240
+ template "config_locales_en.yml.erb", "config/locales/en.yml"
241
+ end
242
+
243
+ def configure_rack_timeout
244
+ rack_timeout_config = <<-RUBY
245
+ Rack::Timeout.timeout = (ENV["RACK_TIMEOUT"] || 10).to_i
246
+ RUBY
247
+
248
+ append_file "config/environments/production.rb", rack_timeout_config
249
+ end
250
+
251
+ def configure_simple_form
252
+ bundle_command "exec rails generate simple_form:install"
253
+ end
254
+
255
+ def configure_action_mailer
256
+ action_mailer_host "development", %{"localhost:#{port}"}
257
+ action_mailer_host "test", %{"www.example.com"}
258
+ action_mailer_host "staging", %{ENV.fetch("HOST")}
259
+ action_mailer_host "production", %{ENV.fetch("HOST")}
260
+ end
261
+
262
+ def configure_active_job
263
+ configure_application_file(
264
+ "config.active_job.queue_adapter = :delayed_job"
265
+ )
266
+ configure_environment "test", "config.active_job.queue_adapter = :inline"
267
+ end
268
+
269
+ def fix_i18n_deprecation_warning
270
+ config = <<-RUBY
271
+ config.i18n.enforce_available_locales = true
272
+ RUBY
273
+
274
+ inject_into_class 'config/application.rb', 'Application', config
275
+ end
276
+
277
+ def generate_rspec
278
+ generate 'rspec:install'
279
+ end
280
+
281
+ def configure_unicorn
282
+ copy_file 'unicorn.rb', 'config/unicorn.rb'
283
+ end
284
+
285
+ def setup_foreman
286
+ copy_file 'sample.env', '.sample.env'
287
+ copy_file 'Procfile', 'Procfile'
288
+ end
289
+
290
+ def setup_stylesheets
291
+ remove_file "app/assets/stylesheets/application.css"
292
+ copy_file "application.scss",
293
+ "app/assets/stylesheets/application.scss"
294
+ end
295
+
296
+ def install_refills
297
+ run "rails generate refills:import flashes"
298
+ run "rm app/views/refills/_flashes.html.erb"
299
+ run "rmdir app/views/refills"
300
+ end
301
+
302
+ def install_bitters
303
+ run "bitters install --path app/assets/stylesheets"
304
+ end
305
+
306
+ def gitignore_files
307
+ remove_file '.gitignore'
308
+ copy_file 'suspenders_gitignore', '.gitignore'
309
+ [
310
+ 'app/views/pages',
311
+ 'spec/lib',
312
+ 'spec/controllers',
313
+ 'spec/helpers',
314
+ 'spec/support/matchers',
315
+ 'spec/support/mixins',
316
+ 'spec/support/shared_examples'
317
+ ].each do |dir|
318
+ run "mkdir #{dir}"
319
+ run "touch #{dir}/.keep"
320
+ end
321
+ end
322
+
323
+ def init_git
324
+ run 'git init'
325
+ end
326
+
327
+ def create_staging_heroku_app(flags)
328
+ rack_env = "RACK_ENV=staging RAILS_ENV=staging"
329
+ app_name = heroku_app_name_for("staging")
330
+
331
+ run_heroku "create #{app_name} #{flags}", "staging"
332
+ run_heroku "config:add #{rack_env}", "staging"
333
+ end
334
+
335
+ def create_production_heroku_app(flags)
336
+ app_name = heroku_app_name_for("production")
337
+
338
+ run_heroku "create #{app_name} #{flags}", "production"
339
+ end
340
+
341
+ def create_heroku_apps(flags)
342
+ create_staging_heroku_app(flags)
343
+ create_production_heroku_app(flags)
344
+ end
345
+
346
+ def set_heroku_remotes
347
+ remotes = <<-SHELL
348
+
349
+ # Set up the staging and production apps.
350
+ #{join_heroku_app('staging')}
351
+ #{join_heroku_app('production')}
352
+ SHELL
353
+
354
+ append_file 'bin/setup', remotes
355
+ end
356
+
357
+ def join_heroku_app(environment)
358
+ heroku_app_name = heroku_app_name_for(environment)
359
+ <<-SHELL
360
+ if heroku join --app #{heroku_app_name} &> /dev/null; then
361
+ git remote add #{environment} git@heroku.com:#{heroku_app_name}.git || true
362
+ printf 'You are a collaborator on the "#{heroku_app_name}" Heroku app\n'
363
+ else
364
+ printf 'Ask for access to the "#{heroku_app_name}" Heroku app\n'
365
+ fi
366
+ SHELL
367
+ end
368
+
369
+ def set_heroku_rails_secrets
370
+ %w(staging production).each do |environment|
371
+ run_heroku "config:add SECRET_KEY_BASE=#{generate_secret}", environment
372
+ end
373
+ end
374
+
375
+ def set_heroku_serve_static_files
376
+ %w(staging production).each do |environment|
377
+ run_heroku "config:add RAILS_SERVE_STATIC_FILES=true", environment
378
+ end
379
+ end
380
+
381
+ def provide_deploy_script
382
+ copy_file "bin_deploy", "bin/deploy"
383
+
384
+ instructions = <<-MARKDOWN
385
+
386
+ ## Deploying
387
+
388
+ If you have previously run the `./bin/setup` script,
389
+ you can deploy to staging and production with:
390
+
391
+ $ ./bin/deploy staging
392
+ $ ./bin/deploy production
393
+ MARKDOWN
394
+
395
+ append_file "README.md", instructions
396
+ run "chmod a+x bin/deploy"
397
+ end
398
+
399
+ def create_github_repo(repo_name)
400
+ path_addition = override_path_for_tests
401
+ run "#{path_addition} hub create #{repo_name}"
402
+ end
403
+
404
+ def setup_segment
405
+ copy_file '_analytics.html.erb',
406
+ 'app/views/application/_analytics.html.erb'
407
+ end
408
+
409
+ def setup_bundler_audit
410
+ copy_file "bundler_audit.rake", "lib/tasks/bundler_audit.rake"
411
+ append_file "Rakefile", %{\ntask default: "bundler:audit"\n}
412
+ end
413
+
414
+ def setup_spring
415
+ bundle_command "exec spring binstub --all"
416
+ end
417
+
418
+ def copy_miscellaneous_files
419
+ copy_file "browserslist", "browserslist"
420
+ copy_file "errors.rb", "config/initializers/errors.rb"
421
+ copy_file "json_encoding.rb", "config/initializers/json_encoding.rb"
422
+ end
423
+
424
+ def customize_error_pages
425
+ meta_tags =<<-EOS
426
+ <meta charset="utf-8" />
427
+ <meta name="ROBOTS" content="NOODP" />
428
+ <meta name="viewport" content="initial-scale=1" />
429
+ EOS
430
+
431
+ %w(500 404 422).each do |page|
432
+ inject_into_file "public/#{page}.html", meta_tags, :after => "<head>\n"
433
+ replace_in_file "public/#{page}.html", /<!--.+-->\n/, ''
434
+ end
435
+ end
436
+
437
+ def remove_routes_comment_lines
438
+ replace_in_file 'config/routes.rb',
439
+ /Rails\.application\.routes\.draw do.*end/m,
440
+ "Rails.application.routes.draw do\nend"
441
+ end
442
+
443
+ def disable_xml_params
444
+ copy_file 'disable_xml_params.rb', 'config/initializers/disable_xml_params.rb'
445
+ end
446
+
447
+ def setup_default_rake_task
448
+ append_file 'Rakefile' do
449
+ <<-EOS
450
+ task(:default).clear
451
+ task default: [:spec]
452
+
453
+ if defined? RSpec
454
+ task(:spec).clear
455
+ RSpec::Core::RakeTask.new(:spec) do |t|
456
+ t.verbose = false
457
+ end
458
+ end
459
+ EOS
460
+ end
461
+ end
462
+
463
+ private
464
+
465
+ def raise_on_missing_translations_in(environment)
466
+ config = 'config.action_view.raise_on_missing_translations = true'
467
+
468
+ uncomment_lines("config/environments/#{environment}.rb", config)
469
+ end
470
+
471
+ def override_path_for_tests
472
+ if ENV['TESTING']
473
+ support_bin = File.expand_path(File.join('..', '..', 'spec', 'fakes', 'bin'))
474
+ "PATH=#{support_bin}:$PATH"
475
+ end
476
+ end
477
+
478
+ def run_heroku(command, environment)
479
+ path_addition = override_path_for_tests
480
+ run "#{path_addition} heroku #{command} --remote #{environment}"
481
+ end
482
+
483
+ def generate_secret
484
+ SecureRandom.hex(64)
485
+ end
486
+
487
+ def port
488
+ @port ||= [3000, 4000, 5000, 7000, 8000, 9000].sample
489
+ end
490
+
491
+ def serve_static_files_line
492
+ "config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?\n"
493
+ end
494
+
495
+ def heroku_app_name_for(environment)
496
+ "#{app_name.dasherize}-#{environment}"
497
+ end
498
+ end
499
+ end