-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtemplate.rb
329 lines (268 loc) · 9.64 KB
/
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
# Copied from: https://github.com/excid3/jumpstart/
# 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__.match?(%r{\Ahttps?://})
require 'tmpdir'
source_paths.unshift(tempdir = Dir.mktmpdir('hyperloop-'))
at_exit { FileUtils.remove_entry(tempdir) }
git clone: [
'--quiet',
'https://github.com/anthony-robin/hyperloop.git',
tempdir
].map(&:shellescape).join(' ')
if (branch = __FILE__[%r{hyperloop/(.+)/template.rb}, 1])
Dir.chdir(tempdir) { git checkout: branch }
end
else
source_paths.unshift(File.dirname(__FILE__))
end
end
say '=============================================================', :green
say 'Hyperloop 🚄 is building a fresh new Rails app for you ✨', :green
say 'It could take while, please be patient...', :green
say '=============================================================', :green
# @port = 3000
@port = ask('What port do you want the app to run ?', default: 3000)
@authentication = yes?('Do you want authentication ? (Y/n)')
add_template_repository_to_source_path
gem 'action_policy'
gem 'active_storage_validations' unless options.skip_active_storage?
gem 'dotenv-rails'
gem 'ffaker'
gem 'meta-tags'
gem 'mission_control-jobs'
gem 'pagy'
gem 'rails-i18n'
gem 'ribbonit'
gem 'simple_form'
gem 'slim-rails'
gem_group :development do
gem 'annotaterb'
gem 'bullet'
gem 'chusaku', require: false
gem 'hotwire-spark'
gem 'letter_opener_web' unless options.skip_action_mailer?
end
unless options.skip_rubocop?
gem_group :development, :test do
gem 'rubocop'
gem 'rubocop-performance'
gem 'rubocop-rails'
end
copy_file '.rubocop.yml', force: true
copy_file '.rubocop-custom.yml'
copy_file '.rubocop-disabled.yml'
gsub_file 'Gemfile', '# Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/]', ''
gsub_file 'Gemfile', 'gem "rubocop-rails-omakase", require: false', ''
gsub_file 'config/environments/development.rb',
'# config.generators.apply_rubocop_autocorrect_after_generate!',
'config.generators.apply_rubocop_autocorrect_after_generate!'
end
template 'docker-compose.yml.tt' if options[:database] == 'postgresql' && !options.skip_docker?
directory 'app/services'
template 'app/controllers/application_controller.rb.tt', force: true
template 'app/helpers/application_helper.rb', force: true
copy_file 'app/jobs/callable_job.rb'
copy_file 'app/models/application_record.rb', force: true
directory 'app/views/application'
template 'config/routes.rb.tt', force: true
directory 'config/routes'
copy_file 'config/initializers/generators.rb'
copy_file 'config/initializers/inflections.rb', force: true
copy_file 'config/initializers/pagy.rb'
copy_file 'config/initializers/ribbonit.rb'
copy_file 'lib/tasks/annotaterb.rake'
copy_file '.annotaterb.yml'
file '.env', <<~ENV
PORT=#{@port.presence || 3000}
# SOLID_QUEUE_IN_PUMA="true"
ENV
after_bundle do
run 'dotenv -t .env'
install_and_configure_simple_form
template 'app/views/layouts/application.html.slim.tt'
template 'app/views/layouts/session.html.slim.tt'
template 'app/views/layouts/admin.html.slim.tt'
gsub_file 'config/application.rb', /# config.time_zone = .+/, "config.time_zone = 'Europe/Paris'"
inject_into_file 'config/application.rb', after: /# config.eager_load_paths .+/ do
<<~RUBY
\n
config.i18n.default_locale = :fr
config.i18n.available_locales = %i[fr en]
RUBY
end
if @authentication
install_and_configure_authentication
install_and_configure_action_policy
end
generate('action_text:install') unless options.skip_action_text?
rails_command('active_storage:install') unless options.skip_active_storage?
install_and_configure_tailwindcss if options[:css] == 'tailwind'
template 'config/initializers/mission_control.rb.tt'
generate(:controller, 'homes', 'show', '--skip-routes')
run 'bundle exec chusaku'
unless options.skip_action_mailer?
inject_into_file 'config/environments/development.rb', before: "# Don't care if the mailer can't send." do
<<-RUBY
config.action_mailer.default_url_options = {
host: 'http://localhost', port: ENV.fetch('PORT', 3000)
}
config.action_mailer.delivery_method = :letter_opener_web
config.action_mailer.perform_deliveries = true
RUBY
end
end
copy_file 'config/locales/fr.yml', force: true
if @authentication
copy_file 'config/locales/activerecord.en.yml'
template 'config/locales/activerecord.fr.yml'
end
setup_seo_module
add_and_configure_bullet
create_pretty_confirm
run_migrations_and_seed_database
finalize
initial_commit unless options.skip_git?
print_final_instructions
end
def run_migrations_and_seed_database
template 'db/seeds.rb.tt', force: true
rails_command('db:migrate')
rails_command('db:seed')
end
def finalize
remove_file 'app/views/layouts/application.html.erb'
run 'bin/rubocop -A --fail-level=E' unless options.skip_rubocop?
end
def install_and_configure_tailwindcss
directory 'app/assets/stylesheets', force: true
copy_file 'config/tailwind.config.js', force: true
inject_into_file 'config/importmap.rb' do
<<-RUBY
pin 'flowbite', to: 'https://cdnjs.cloudflare.com/ajax/libs/flowbite/2.5.2/flowbite.turbo.min.js'
RUBY
end
inject_into_file 'app/javascript/application.js' do
<<~JAVASCRIPT
import 'flowbite'
JAVASCRIPT
end
end
def install_and_configure_simple_form
generate('simple_form:install')
gsub_file 'config/initializers/simple_form.rb', "config.button_class = 'btn'", "config.button_class = 'button'"
gsub_file 'config/initializers/simple_form.rb', '# config.label_class = nil', "config.label_class = 'block'"
gsub_file 'config/initializers/simple_form.rb', '# config.input_class = nil', "config.input_class = 'w-full'"
template 'config/locales/simple_form.en.yml', force: true
template 'config/locales/simple_form.fr.yml'
end
def install_and_configure_authentication
generate('authentication')
generate('migration add_fields_to_user first_name:string last_name:string role:integer')
# Update migration null and default value for role
migration_file = Dir.glob('db/migrate/*add_fields_to_user.rb').first
content = File.read(migration_file)
updated_content = content.gsub('add_column :users, :role, :integer', 'add_column :users, :role, :integer, null: false, default: 0')
File.open(migration_file, 'w') { |file| file.puts updated_content }
copy_file 'app/controllers/registrations_controller.rb'
directory 'app/controllers/me'
directory 'app/controllers/admin'
template 'app/models/user.rb.tt', force: true
# Views not generated in slim :(
directory 'app/views/registrations'
directory 'app/views/sessions', force: true
directory 'app/views/passwords', force: true unless options.skip_action_mailer?
directory 'app/views/me'
directory 'app/views/admin'
inject_into_file 'app/controllers/sessions_controller.rb',
after: 'class SessionsController < ApplicationController' do
<<-RUBY
\n
layout 'session'
RUBY
end
inject_into_file 'app/controllers/passwords_controller.rb',
after: 'class PasswordsController < ApplicationController' do
<<-RUBY
\n
layout 'session'
RUBY
end
inject_into_file 'app/controllers/registrations_controller.rb',
after: 'class RegistrationsController < ApplicationController' do
<<-RUBY
\n
layout 'session'
RUBY
end
end
def install_and_configure_action_policy
generate('action_policy:install')
directory 'app/policies', force: true
copy_file 'config/locales/action_policy.en.yml'
copy_file 'config/locales/action_policy.fr.yml'
end
def setup_seo_module
template 'app/helpers/seo_helper.rb.tt'
template 'config/locales/seo.en.yml'
template 'config/locales/seo.fr.yml'
end
def add_and_configure_bullet
inject_into_file 'config/environments/development.rb', before: /^end/ do
<<~RUBY
\n
config.after_initialize do
Bullet.enable = true
Bullet.bullet_logger = true
Bullet.add_footer = true
end
RUBY
end
end
def create_pretty_confirm
inject_into_file 'app/javascript/application.js' do
<<~JAVASCRIPT
// @see https://gorails.com/episodes/custom-hotwire-turbo-confirm-modals
Turbo.setConfirmMethod((message, element) => {
let dialog = document.getElementById('turbo-confirm')
dialog.querySelector('p').textContent = message
dialog.showModal()
return new Promise((resolve, reject) => {
dialog.addEventListener('close', () => {
resolve(dialog.returnValue == 'confirm')
}, { once: true })
})
})
JAVASCRIPT
end
end
def initial_commit
inject_into_file '.gitignore' do
<<~GITIGNORE
!/.env.template
.DS_Store
GITIGNORE
end
git :init
git add: '.'
git commit: %( -m 'Initial commit' )
end
def print_final_instructions
say '============================================================='
say 'Hyperloop 🚄 successfully created your Rails app ! 🎉🎉🎉', :green
say
say 'Switch to your app by running:'
say "$ cd #{app_name}", :yellow
say
say 'Then run:'
say '$ bin/dev', :yellow
say
say 'Then open:'
say "http://localhost:#{@port}", :yellow
say
say 'Database is already filled with default values of db/seeds.rb. Enjoy!'
say '============================================================='
end