-
-
Notifications
You must be signed in to change notification settings - Fork 530
/
app_builder.rb
543 lines (428 loc) · 13.9 KB
/
app_builder.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
require "forwardable"
module Suspenders
class AppBuilder < Rails::AppBuilder
include Suspenders::Actions
extend Forwardable
def_delegators :heroku_adapter,
:set_heroku_remotes,
:set_up_heroku_specific_gems,
:set_heroku_rails_secrets
def readme
template 'README.md.erb', 'README.md'
end
def raise_on_missing_assets_in_test
inject_into_file(
"config/environments/test.rb",
"\n config.assets.raise_runtime_errors = true",
after: "Rails.application.configure do",
)
end
def raise_on_delivery_errors
replace_in_file 'config/environments/development.rb',
'raise_delivery_errors = false', 'raise_delivery_errors = true'
end
def set_test_delivery_method
inject_into_file(
"config/environments/development.rb",
"\n config.action_mailer.delivery_method = :test",
after: "config.action_mailer.raise_delivery_errors = true",
)
end
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
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
def configure_quiet_assets
config = <<-RUBY
config.quiet_assets = true
RUBY
inject_into_class "config/application.rb", "Application", config
end
def provide_setup_script
template "bin_setup.erb", "bin/setup", force: true
run "chmod a+x bin/setup"
end
def provide_dev_prime_task
copy_file 'dev.rake', 'lib/tasks/dev.rake'
end
def configure_generators
config = <<-RUBY
config.generators do |generate|
generate.helper false
generate.javascript_engine 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
def set_up_factory_girl_for_rspec
copy_file 'factory_girl_rspec.rb', 'spec/support/factory_girl.rb'
end
def generate_factories_file
copy_file "factories.rb", "spec/factories.rb"
end
def set_up_hound
copy_file "hound.yml", ".hound.yml"
end
def configure_newrelic
template 'newrelic.yml.erb', 'config/newrelic.yml'
end
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
def enable_rack_canonical_host
config = <<-RUBY
# Ensure requests are only served from one, canonical host name
config.middleware.use Rack::CanonicalHost, ENV.fetch("APPLICATION_HOST")
RUBY
inject_into_file(
"config/environments/production.rb",
config,
after: serve_static_files_line
)
end
def enable_rack_deflater
config = <<-RUBY
# Enable deflate / gzip compression of controller-generated responses
config.middleware.use Rack::Deflater
RUBY
inject_into_file(
"config/environments/production.rb",
config,
after: serve_static_files_line
)
end
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")'
inject_into_file(
"config/environments/production.rb",
' config.static_cache_control = "public, max-age=#{1.year.to_i}"',
after: serve_static_files_line
)
end
def setup_staging_environment
staging_file = 'config/environments/staging.rb'
copy_file 'staging.rb', staging_file
config = <<-RUBY
Rails.application.configure do
# ...
end
RUBY
append_file staging_file, config
end
def setup_secret_token
template 'secrets.yml', 'config/secrets.yml', force: true
end
def disallow_wrapping_parameters
remove_file "config/initializers/wrap_parameters.rb"
end
def create_partials_directory
empty_directory 'app/views/application'
end
def create_shared_flashes
copy_file "_flashes.html.erb", "app/views/application/_flashes.html.erb"
copy_file "flashes_helper.rb", "app/helpers/flashes_helper.rb"
end
def create_shared_javascripts
copy_file '_javascript.html.erb', 'app/views/application/_javascript.html.erb'
end
def create_application_layout
template 'suspenders_layout.html.erb.erb',
'app/views/layouts/application.html.erb',
force: true
end
def use_postgres_config_template
template 'postgresql_database.yml.erb', 'config/database.yml',
force: true
end
def create_database
bundle_command 'exec rake db:create db:migrate'
end
def replace_gemfile
remove_file 'Gemfile'
template 'Gemfile.erb', 'Gemfile'
end
def set_ruby_to_version_being_used
create_file '.ruby-version', "#{Suspenders::RUBY_VERSION}\n"
end
def enable_database_cleaner
copy_file 'database_cleaner_rspec.rb', 'spec/support/database_cleaner.rb'
end
def provide_shoulda_matchers_config
copy_file(
"shoulda_matchers_config_rspec.rb",
"spec/support/shoulda_matchers.rb"
)
end
def configure_spec_support_features
empty_directory_with_keep_file 'spec/features'
empty_directory_with_keep_file 'spec/support/features'
end
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
def configure_ci
template "circle.yml.erb", "circle.yml"
end
def configure_i18n_for_test_environment
copy_file "i18n.rb", "spec/support/i18n.rb"
end
def configure_i18n_for_missing_translations
raise_on_missing_translations_in("development")
raise_on_missing_translations_in("test")
end
def configure_i18n_tasks
run "cp $(i18n-tasks gem-path)/templates/rspec/i18n_spec.rb spec/"
copy_file "config_i18n_tasks.yml", "config/i18n-tasks.yml"
end
def configure_background_jobs_for_rspec
run 'rails g delayed_job:active_record'
end
def configure_action_mailer_in_specs
copy_file 'action_mailer.rb', 'spec/support/action_mailer.rb'
end
def configure_capybara_webkit
copy_file "capybara_webkit.rb", "spec/support/capybara_webkit.rb"
end
def configure_time_formats
remove_file "config/locales/en.yml"
template "config_locales_en.yml.erb", "config/locales/en.yml"
end
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
def configure_simple_form
bundle_command "exec rails generate simple_form:install"
end
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
def configure_active_job
configure_application_file(
"config.active_job.queue_adapter = :delayed_job"
)
configure_environment "test", "config.active_job.queue_adapter = :inline"
end
def fix_i18n_deprecation_warning
config = <<-RUBY
config.i18n.enforce_available_locales = true
RUBY
inject_into_class 'config/application.rb', 'Application', config
end
def generate_rspec
generate 'rspec:install'
end
def configure_puma
copy_file "puma.rb", "config/puma.rb"
end
def set_up_forego
copy_file 'sample.env', '.sample.env'
copy_file 'Procfile', 'Procfile'
end
def setup_stylesheets
remove_file "app/assets/stylesheets/application.css"
copy_file "application.scss",
"app/assets/stylesheets/application.scss"
end
def install_refills
run "rails generate refills:import flashes"
run "rm app/views/refills/_flashes.html.erb"
run "rmdir app/views/refills"
end
def install_bitters
run "bitters install --path app/assets/stylesheets"
end
def gitignore_files
remove_file '.gitignore'
copy_file 'suspenders_gitignore', '.gitignore'
[
'app/views/pages',
'spec/lib',
'spec/controllers',
'spec/helpers',
'spec/support/matchers',
'spec/support/mixins',
'spec/support/shared_examples'
].each do |dir|
run "mkdir #{dir}"
run "touch #{dir}/.keep"
end
end
def copy_dotfiles
directory("dotfiles", ".")
end
def init_git
run 'git init'
end
def create_staging_heroku_app(flags)
rack_env = "RACK_ENV=staging RAILS_ENV=staging"
app_name = heroku_app_name_for("staging")
run_heroku "create #{app_name} #{flags}", "staging"
run_heroku "config:add #{rack_env}", "staging"
end
def create_production_heroku_app(flags)
app_name = heroku_app_name_for("production")
run_heroku "create #{app_name} #{flags}", "production"
end
def create_heroku_apps(flags)
create_staging_heroku_app(flags)
create_production_heroku_app(flags)
end
def set_heroku_serve_static_files
%w(staging production).each do |environment|
run_heroku "config:add RAILS_SERVE_STATIC_FILES=true", environment
end
end
def provide_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
def configure_automatic_deployment
staging_remote_name = heroku_app_name_for("staging")
deploy_command = <<-YML.strip_heredoc
deployment:
staging:
branch: master
commands:
- bin/deploy staging
YML
append_file "circle.yml", deploy_command
end
def create_github_repo(repo_name)
run "hub create #{repo_name}"
end
def setup_segment
copy_file '_analytics.html.erb',
'app/views/application/_analytics.html.erb'
end
def setup_bundler_audit
copy_file "bundler_audit.rake", "lib/tasks/bundler_audit.rake"
append_file "Rakefile", %{\ntask default: "bundler:audit"\n}
end
def setup_spring
bundle_command "exec spring binstub --all"
end
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
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
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
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
def disable_xml_params
copy_file 'disable_xml_params.rb', 'config/initializers/disable_xml_params.rb'
end
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
private
def raise_on_missing_translations_in(environment)
config = 'config.action_view.raise_on_missing_translations = true'
uncomment_lines("config/environments/#{environment}.rb", config)
end
def run_heroku(command, environment)
run "heroku #{command} --remote #{environment}"
end
def heroku_adapter
@heroku_adapter ||= Adapters::Heroku.new(self)
end
def serve_static_files_line
"config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?\n"
end
def heroku_app_name_for(environment)
"#{app_name.dasherize}-#{environment}"
end
end
end