-
Notifications
You must be signed in to change notification settings - Fork 0
/
application_template.rb
360 lines (312 loc) · 12.6 KB
/
application_template.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
# This is strongly inspired by (and much code was lifted from) the incredible:
# https://github.com/mattbrictson/rails-template
require "bundler"
# Constants
RUBY_VERSION_REQUIREMENT = "~> 2.6.1".freeze
RAILS_VERSION_REQUIREMENT = "~> 6.0.0".freeze
YARN_VERSION_REQUIREMENT = "~> 1.19.1".freeze
# Main template
def lets_go!
# Sanity checks
assert_ruby_version(RUBY_VERSION_REQUIREMENT)
assert_rails_version(RAILS_VERSION_REQUIREMENT)
assert_yarn_version(YARN_VERSION_REQUIREMENT)
assert_valid_options
assert_postgres
# Prepare the application file templates
add_template_repository_to_source_path
confirm_optional_libs
# project root configuration files
template "Gemfile.tt", force: true
template "README.md.tt", force: true
template "example.env.tt"
copy_file "gitignore", ".gitignore", force: true
copy_file "ruby-version", ".ruby-version", force: true
copy_file "Guardfile", "Guardfile"
# app/
copy_file "app/assets/config/manifest.js", force: true
copy_file "app/assets/images/default-profile-photo.png", force: true
copy_file "app/assets/images/spacer-landscape.png", force: true
copy_file "app/assets/images/spacer-portrait.png", force: true
copy_file "app/assets/javascripts/application.js", force: true
copy_file "app/assets/javascripts/general.coffee", force: true
copy_file "app/assets/stylesheets/admin.scss", force: true
copy_file "app/assets/stylesheets/application.css", force: true
copy_file "app/assets/stylesheets/styles.scss", force: true
copy_file "app/assets/stylesheets/variables.scss", force: true
copy_file "app/controllers/admin/admin_base_controller.rb", force: true
copy_file "app/controllers/admin/pages_controller.rb", force: true
copy_file "app/controllers/admin/settings_controller.rb", force: true
copy_file "app/controllers/admin/users_controller.rb", force: true
copy_file "app/controllers/application_controller.rb", force: true
copy_file "app/controllers/pages_controller.rb", force: true
copy_file "app/controllers/users/confirmations_controller.rb", force: true
copy_file "app/controllers/users/omniauth_callbacks_controller.rb", force: true
copy_file "app/controllers/users/passwords_controller.rb", force: true
copy_file "app/controllers/users/registrations_controller.rb", force: true
copy_file "app/controllers/users/sessions_controller.rb", force: true
copy_file "app/controllers/users/unlocks_controller.rb", force: true
copy_file "app/helpers/application_helper.rb", force: true
copy_file "app/models/ahoy/event.rb", force: true
copy_file "app/models/ahoy/visit.rb", force: true
copy_file "app/models/setting.rb", force: true
copy_file "app/models/user.rb", force: true
copy_file "app/views/admin/pages/dashboard.html.haml", force: true
copy_file "app/views/admin/pages/entries.html.haml", force: true
copy_file "app/views/admin/pages/utilities.html.haml", force: true
copy_file "app/views/admin/settings/index.html.haml", force: true
copy_file "app/views/admin/users/index.html.haml", force: true
copy_file "app/views/layouts/_alerts.html.haml", force: true
copy_file "app/views/layouts/_breadcrumbs.html.haml", force: true
copy_file "app/views/layouts/_footer.html.haml", force: true
copy_file "app/views/layouts/_head.html.haml", force: true
copy_file "app/views/layouts/_navigation.html.haml", force: true
copy_file "app/views/layouts/admin.html.haml", force: true
copy_file "app/views/layouts/application.html.haml", force: true
copy_file "app/views/layouts/mailer.html.haml", force: true
copy_file "app/views/layouts/mailer.text.haml", force: true
copy_file "app/views/pages/home.html.haml", force: true
copy_file "app/views/shared/search/_form.html.haml", force: true
copy_file "app/views/users/confirmations/new.html.haml", force: true
copy_file "app/views/users/mailer/confirmation_instructions.html.haml", force: true
copy_file "app/views/users/mailer/email_changed.html.haml", force: true
copy_file "app/views/users/mailer/password_change.html.haml", force: true
copy_file "app/views/users/mailer/reset_password_instructions.html.haml", force: true
copy_file "app/views/users/mailer/unlock_instructions.html.haml", force: true
copy_file "app/views/users/passwords/edit.html.haml", force: true
copy_file "app/views/users/passwords/new.html.haml", force: true
copy_file "app/views/users/registrations/_details.html.haml", force: true
copy_file "app/views/users/registrations/edit.html.haml", force: true
copy_file "app/views/users/registrations/new.html.haml", force: true
copy_file "app/views/users/sessions/new.html.haml", force: true
copy_file "app/views/users/shared/_error_messages.html.haml", force: true
copy_file "app/views/users/shared/_links.html.haml", force: true
copy_file "app/views/users/unlocks/new.html.haml", force: true
Dir["app/views/**/*.erb"].each do |filename|
File.delete(filename)
end
# config/
copy_file "config/routes.rb", force: true
template "config/storage.yml.tt", force: true
# config/environments
environment(<<-DEV, env: "development")
config.action_mailer.default_url_options = { host: 'lvh.me', port: 3000 }
config.action_mailer.delivery_method = :letter_opener
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
DEV
environment(<<-PROD, env: "production")
config.action_mailer.delivery_method = :sparkpost
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false
config.action_mailer.perform_caching = false
config.action_mailer.asset_host = ENV.fetch('DEFAULT_URL')
config.action_mailer.default_url_options = { host: ENV.fetch('DEFAULT_URL') }
PROD
# config/initializers
initializer "ahoy.rb", <<-AHOY
class Ahoy::Store < Ahoy::DatabaseStore
end
# set to true for JavaScript tracking
Ahoy.api = false
# better user agent parsing
Ahoy.user_agent_parser = :device_detector
# better bot detection
Ahoy.bot_detection_version = 2
AHOY
copy_file "config/initializers/devise.rb"
copy_file "config/initializers/friendly_id.rb"
initializer "kaminari.rb", <<-KAMINARI
# frozen_string_literal: true
Kaminari.configure do |config|
# config.default_per_page = 25
# config.max_per_page = nil
# config.window = 4
# config.outer_window = 0
# config.left = 0
# config.right = 0
# config.page_method_name = :page
# config.param_name = :page
# config.params_on_first_page = false
end
KAMINARI
copy_file "config/initializers/meta_tags.rb"
copy_file "config/initializers/simple_form.rb"
initializer "sparkpost_rails.rb", <<-SPARKPOST
SparkPostRails.configure do |c|
c.api_key = ENV['SPARKPOST_KEY']
c.html_content_only = true
end
SPARKPOST
# config/locales
copy_file "config/locales/devise.en.yml"
copy_file "config/locales/simple_form.en.yml"
file "config/locals/loaf.en.yml", <<-LOAF
en:
loaf:
errors:
invalid_options: "Invalid option :%{invalid}. Valid options are: %{valid}, make sure these are the ones you are using."
breadcrumbs:
home: 'Home'
LOAF
# db/
copy_file "db/seeds.rb", force: true
[
"db/migrate/20190720175000_create_settings.rb",
"db/migrate/20190720152159_devise_create_users.rb",
"db/migrate/20190720191740_add_name_and_admin_permission_to_users.rb",
"db/migrate/20190720144752_create_friendly_id_slugs.rb",
"db/migrate/20190720182124_create_ahoy_visits_and_events.rb",
"db/migrate/20190720161737_create_versions.rb",
"db/migrate/20190720190557_create_active_storage_tables.active_storage.rb"
].each do |filename|
copy_file filename
end
# lib/
# investigate lib/templates/haml/scaffold, does this get used?
# spec/
[
"spec/spec_helper.rb",
"spec/models/user_spec.rb",
"spec/support/helpers.rb",
"spec/support/factory_bot.rb",
"spec/support/devise.rb",
"spec/support/database_cleaner.rb",
"spec/support/helpers/session_helpers.rb",
"spec/factories/users.rb",
"spec/controllers/pages_controller_spec.rb",
"spec/controllers/admin/users_controller_spec.rb",
"spec/controllers/admin/pages_controller_spec.rb",
"spec/controllers/admin/settings_controller_spec.rb",
"spec/rails_helper.rb",
"spec/helpers/application_helper_spec.rb"
].each do |filename|
copy_file filename, force: true
end
# set up the database
rails_command "db:create"
rails_command "db:migrate"
rails_command "db:setup"
end
# Helper methods
def assert_ruby_version(required_ruby_version)
current_ruby_version = RUBY_VERSION
assert_minimum_version(required_ruby_version, current_ruby_version, "Ruby")
end
def assert_rails_version(required_rails_version)
current_rails_version = Rails::VERSION::STRING
assert_minimum_version(required_rails_version, current_rails_version, "Rails")
end
def assert_yarn_version(required_yarn_version)
current_yarn_version = `yarn -v`.strip
assert_minimum_version(required_yarn_version, current_yarn_version, "Yarn")
rescue Errno::ENOENT => e
message = if e.message.include?("No such file or directory - yarn")
"Yarn is not installed! Visit: https://yarnpkg.com/lang/en/docs/install/"
else
message = e.message
end
puts red(message)
exit 1
end
def assert_minimum_version(required_version, current_version, lib_name)
print yellow("Checking #{lib_name} version #{current_version} satisfies #{required_version}... ")
# using Gem to compare version strings, even if the target isn't a gem
requirement = Gem::Requirement.new(required_version)
actual_version = Gem::Version.new(current_version)
if requirement.satisfied_by?(actual_version)
puts green("✓")
return
else
puts red("FAIL")
end
exit 1 if no?(%Q(
This template requires #{lib_name} #{required_version}.
You are using #{current_version}. Continue anyway?
), :yellow)
end
def assert_valid_options
# rails new accepts many options, but our template handles a bunch of stuff
# automatically so warn if those options are specified differently
valid_options = {
database: 'postgresql',
skip_gemfile: false,
skip_bundle: false,
skip_git: false,
skip_test: true,
edge: false
}
valid_options.each do |key, expected|
next unless options.key?(key)
actual = options[key]
unless actual == expected
fail Rails::Generators::Error, red("Unsupported option to rails new: #{key}=#{actual}")
end
end
end
def assert_postgres
return if IO.read("Gemfile") =~ /^\s*gem ['"]pg['"]/
fail Rails::Generators::Error, <<-POSTGRES
We always use PostgreSQL, but the pg gem isn’t present in your Gemfile.
Make sure you run `rails new` with the `-d postgresql` flag.
POSTGRES
end
# Add this template directory to source_paths so that Thor actions like
# copy_file and template resolve against our source files. If this file was
# invoked remotely via HTTP, that means the files are not present locally.
# In that case, use `git clone` to download them to a local temporary dir.
def add_template_repository_to_source_path
if __FILE__ =~ %r{\Ahttps?://} # Was a URL specified?
print yellow("Cloning Siderail... ")
require "fileutils"
require "shellwords"
require "tmpdir"
# Make a temp directory and add it to the source paths
source_paths.unshift(tempdir = Dir.mktmpdir("siderail-"))
# Delete the temp dir when we're done
at_exit { FileUtils.remove_entry(tempdir) }
# Clone the template repo into the temp directory
git clone: [
"--quiet",
"https://github.com/PolarNotion/siderail.git",
tempdir
].map(&:shellescape).join(" ")
puts red(__FILE__)
# If there's a branch name in the given template file...
if (branch = __FILE__[%r{siderail/(.+)/application_template.rb}, 1])
# check out that branch
Dir.chdir(tempdir) { git checkout: branch }
end
else # Local file specified? Add its directory to source paths
print yellow("Using local directory... ")
source_paths.unshift(File.dirname(__FILE__))
end
puts green("✓")
end
def confirm_optional_libs
puts yellow("Select Options:")
sidekiq?
redis?
image_uploads?
end
def sidekiq?
ask_once("Sidekiq?")
end
def redis?
sidekiq? || ask_once("Redis?")
end
def image_uploads?
ask_once("Image Uploads?")
end
def ask_once(question)
@answers ||= {}
question_index = question.to_sym
@answers[question_index] ||= yes?(yellow(question)) ? "yes" : "no"
@answers[question_index] == "yes"
end
# Terminal color helpers
def colorize(str, clr_num); "\e[#{clr_num}m#{str}\e[0m"; end
def red(str); colorize(str, 31); end
def green(str); colorize(str, 32); end
def yellow(str); colorize(str, 33); end
lets_go!