├── README.md
├── minimal.rb
├── devise.rb
├── minimal_rspec_factory_bot.rb
└── devise_rspec_factory_bot.rb
/README.md:
--------------------------------------------------------------------------------
1 | # Rails Tailwind template
2 |
3 | Quickly generate a rails app with Tailwind css library and the gem devise.
4 | Thanks to Le Wagon : https://github.com/lewagon/rails-templates (same template with bootstrap )
5 |
6 | # Get started
7 |
8 | ## Issue with Minimal template - it will be settled quickly
9 | ## Minimal
10 | Get a minimal rails app ready to be deployed on Heroku with Tailwind, Simple form and debugging gems.
11 |
12 | ```sh
13 | $ rails new \
14 | --database postgresql \
15 | --webpack \
16 | -m https://raw.githubusercontent.com/lioruby/rails-tailwind-template/master/minimal.rb \
17 | CHANGE_THIS_TO_YOUR_RAILS_APP_NAME
18 | ```
19 |
20 | ### Minimal with rspec, factory_bot and shoulda-matchers gems
21 | ```sh
22 | $ rails new \
23 | --database postgresql \
24 | --webpack \
25 | -m https://raw.githubusercontent.com/lioruby/rails-tailwind-template/master/minimal_rspec_factory_bot.rb \
26 | CHANGE_THIS_TO_YOUR_RAILS_APP_NAME
27 | ```
28 |
29 | ## Devise
30 | Same as minimal plus a Devise install with a generated User model.
31 |
32 | ```sh
33 | $ rails new \
34 | --database postgresql \
35 | --webpack \
36 | -m https://raw.githubusercontent.com/lioruby/rails-tailwind-template/master/devise.rb \
37 | CHANGE_THIS_TO_YOUR_RAILS_APP_NAME
38 | ```
39 |
40 | ### Devise with rspec, factory_bot and shoulda-matchers gems
41 | it generate a spec directly for the user model
42 |
43 | ```sh
44 | $ rails new \
45 | --database postgresql \
46 | --webpack \
47 | -m https://raw.githubusercontent.com/lioruby/rails-tailwind-template/master/devise_rspec_factory_bot.rb \
48 | CHANGE_THIS_TO_YOUR_RAILS_APP_NAME
49 | ```
50 |
--------------------------------------------------------------------------------
/minimal.rb:
--------------------------------------------------------------------------------
1 | run "if uname | grep -q 'Darwin'; then pgrep spring | xargs kill -9; fi"
2 |
3 | # GEMFILE
4 | ########################################
5 | inject_into_file 'Gemfile', before: 'group :development, :test do' do
6 | <<~RUBY
7 |
8 | gem 'autoprefixer-rails'
9 | gem 'font-awesome-sass'
10 | gem 'simple_form'
11 | RUBY
12 | end
13 |
14 | inject_into_file 'Gemfile', after: 'group :development, :test do' do
15 | <<-RUBY
16 |
17 | gem 'pry-byebug'
18 | gem 'pry-rails'
19 | gem 'dotenv-rails'
20 | RUBY
21 | end
22 |
23 | # Procfile
24 | ########################################
25 | file 'Procfile', <<~YAML
26 | web: bundle exec puma -C config/puma.rb
27 | YAML
28 |
29 | # Assets in javascript file
30 | ########################################
31 | run 'mkdir app/javascript/stylesheets'
32 | run 'touch app/javascript/stylesheets/application.scss'
33 |
34 | # Dev environment
35 | ########################################
36 | gsub_file('config/environments/development.rb', /config\.assets\.debug.*/, 'config.assets.debug = false')
37 |
38 | # Layout
39 | ########################################
40 | if Rails.version < "6"
41 | scripts = <<~HTML
42 | <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>
43 | <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
44 | <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
45 | HTML
46 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>", scripts)
47 | else
48 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>", "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>")
49 | inject_into_file 'app/views/layouts/application.html.erb', before: "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>" do
50 | <<~HTML
51 | <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
52 | HTML
53 | end
54 | end
55 |
56 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>", "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>")
57 | style = <<~HTML
58 |
59 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
60 | HTML
61 | gsub_file('app/views/layouts/application.html.erb', "<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>", style)
62 |
63 |
64 | # Generators
65 | ########################################
66 | generators = <<~RUBY
67 | config.generators do |generate|
68 | generate.assets false
69 | generate.helper false
70 | generate.test_framework :test_unit, fixture: false
71 | end
72 | RUBY
73 |
74 | environment generators
75 |
76 | ########################################
77 | # AFTER BUNDLE
78 | ########################################
79 | after_bundle do
80 | # Generators: db + simple form + pages controller
81 | ########################################
82 | rails_command 'db:drop db:create db:migrate'
83 | generate('simple_form:install')
84 | generate(:controller, 'pages', 'home', '--skip-routes', '--no-test-framework')
85 |
86 | # Routes
87 | ########################################
88 | route "root to: 'pages#home'"
89 |
90 | # Git ignore
91 | ########################################
92 | append_file '.gitignore', <<~TXT
93 | # Ignore .env file containing credentials.
94 | .env*
95 | # Ignore Mac and Linux file system files
96 | *.swp
97 | .DS_Store
98 | TXT
99 |
100 | # Webpacker / Yarn
101 | ########################################
102 | run 'yarn add tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9'
103 | append_file 'app/javascript/packs/application.js', <<~JS
104 | // ----------------------------------------------------
105 | // WRITE YOUR OWN JS STARTING FROM HERE 👇
106 | // ----------------------------------------------------
107 | // External imports
108 |
109 | // Internal imports, e.g:
110 | import '../stylesheets/application.scss';
111 |
112 |
113 | document.addEventListener('turbolinks:load', () => {
114 | // Call your functions here, e.g:
115 | });
116 | JS
117 |
118 | # Postcss.config.js
119 | ########################################
120 |
121 | gsub_file('./postcss.config.js', /.+/, '')
122 |
123 | inject_into_file './postcss.config.js' do
124 | <<~JS
125 | module.exports = {
126 | plugins: [
127 | require('postcss-import'),
128 | require('postcss-flexbugs-fixes'),
129 | require('postcss-preset-env')({
130 | autoprefixer: {
131 | flexbox: 'no-2009'
132 | },
133 | stage: 3
134 | }),
135 | require('tailwindcss'),
136 | require('autoprefixer'),
137 | ]
138 | };
139 | JS
140 | end
141 |
142 | # Create Tailwind.config.js file
143 |
144 | run 'touch tailwind.config.js'
145 |
146 | inject_into_file './tailwind.config.js' do
147 | <<~JS
148 | module.exports = {
149 | purge: [],
150 | darkMode: false, // or 'media' or 'class'
151 | theme: {
152 | extend: {},
153 | },
154 | variants: {
155 | extend: {},
156 | },
157 | plugins: [],
158 | };
159 | JS
160 |
161 | end
162 |
163 | # Include Tailwind in app
164 |
165 | inject_into_file 'app/javascript/stylesheets/application.scss' do
166 | <<~SCSS
167 | @import "tailwindcss/base";
168 | @import "tailwindcss/components";
169 | @import "tailwindcss/utilities";
170 | SCSS
171 | end
172 |
173 | # Include FontAwesome in app
174 | run 'mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss'
175 | inject_into_file 'app/assets/stylesheets/application.scss' do
176 | <<~SCSS
177 | @import "font-awesome-sprockets";
178 | @import "font-awesome";
179 | SCSS
180 | end
181 |
182 | # Dotenv
183 | ########################################
184 | run 'touch .env'
185 |
186 | # Rubocop
187 | ########################################
188 | run 'curl -L https://raw.githubusercontent.com/lewagon/rails-templates/master/.rubocop.yml > .rubocop.yml'
189 |
190 | # Git
191 | ########################################
192 | git add: '.'
193 | git commit: "-m 'Initial commit'"
194 |
195 | # Fix puma config
196 | gsub_file('config/puma.rb', 'pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }', '# pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }')
197 | end
198 |
--------------------------------------------------------------------------------
/devise.rb:
--------------------------------------------------------------------------------
1 | run "if uname | grep -q 'Darwin'; then pgrep spring | xargs kill -9; fi"
2 |
3 | # GEMFILE
4 | ########################################
5 | inject_into_file 'Gemfile', before: 'group :development, :test do' do
6 | <<~RUBY
7 |
8 | gem 'devise'
9 | gem 'autoprefixer-rails'
10 | gem 'font-awesome-sass'
11 | gem 'simple_form'
12 | RUBY
13 | end
14 |
15 | inject_into_file 'Gemfile', after: 'group :development, :test do' do
16 | <<-RUBY
17 |
18 | gem 'pry-byebug'
19 | gem 'pry-rails'
20 | gem 'dotenv-rails'
21 | RUBY
22 | end
23 |
24 | # Procfile
25 | ########################################
26 | file 'Procfile', <<~YAML
27 | web: bundle exec puma -C config/puma.rb
28 | YAML
29 |
30 | # Assets in javascript file
31 | ########################################
32 | run 'mkdir app/javascript/stylesheets'
33 | run 'touch app/javascript/stylesheets/application.scss'
34 |
35 | # Dev environment
36 | ########################################
37 | gsub_file('config/environments/development.rb', /config\.assets\.debug.*/, 'config.assets.debug = false')
38 |
39 | # Layout
40 | ########################################
41 | if Rails.version < "6"
42 | scripts = <<~HTML
43 | <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>
44 | <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
45 | <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
46 | HTML
47 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>", scripts)
48 | else
49 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>", "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>")
50 | inject_into_file 'app/views/layouts/application.html.erb', before: "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>" do
51 | <<~HTML
52 | <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
53 | HTML
54 | end
55 | end
56 |
57 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>", "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>")
58 | style = <<~HTML
59 |
60 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
61 | HTML
62 | gsub_file('app/views/layouts/application.html.erb', "<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>", style)
63 |
64 |
65 | # Generators
66 | ########################################
67 | generators = <<~RUBY
68 | config.generators do |generate|
69 | generate.assets false
70 | generate.helper false
71 | generate.test_framework :test_unit, fixture: false
72 | end
73 | RUBY
74 |
75 | environment generators
76 |
77 | # Insert Devise flashes
78 | file 'app/views/shared/_flashes.html.erb', <<~HTML
79 | <% if notice %>
80 |
81 | <%= notice %>
82 |
85 |
86 | <% end %>
87 | <% if alert %>
88 |
89 | <%= alert %>
90 |
93 |
94 | <% end %>
95 | HTML
96 |
97 | inject_into_file 'app/views/layouts/application.html.erb', after: "<%= yield %>" do
98 | <<-HTML
99 | <%= render 'shared/flashes' %>
100 | HTML
101 | end
102 |
103 | ########################################
104 | # AFTER BUNDLE
105 | ########################################
106 | after_bundle do
107 | # Generators: db + simple form + pages controller
108 | ########################################
109 | rails_command 'db:drop db:create db:migrate'
110 | generate('simple_form:install')
111 | generate(:controller, 'pages', 'home', '--skip-routes', '--no-test-framework')
112 |
113 | # Routes
114 | ########################################
115 | route "root to: 'pages#home'"
116 |
117 | # Git ignore
118 | ########################################
119 | append_file '.gitignore', <<~TXT
120 | # Ignore .env file containing credentials.
121 | .env*
122 | # Ignore Mac and Linux file system files
123 | *.swp
124 | .DS_Store
125 | TXT
126 |
127 | # Devise install + user
128 | ########################################
129 | generate('devise:install')
130 | generate('devise', 'User')
131 | # App controller
132 | ########################################
133 | run 'rm app/controllers/application_controller.rb'
134 | file 'app/controllers/application_controller.rb', <<~RUBY
135 | class ApplicationController < ActionController::Base
136 | #{ "protect_from_forgery with: :exception\n" if Rails.version < "5.2"} before_action :authenticate_user!
137 | end
138 | RUBY
139 |
140 | # migrate + devise views
141 | ########################################
142 | rails_command 'db:migrate'
143 | generate('devise:views')
144 |
145 | # Pages Controller
146 | ########################################
147 | run 'rm app/controllers/pages_controller.rb'
148 | file 'app/controllers/pages_controller.rb', <<~RUBY
149 | class PagesController < ApplicationController
150 | skip_before_action :authenticate_user!, only: [ :home ]
151 | def home
152 | end
153 | end
154 | RUBY
155 |
156 | # Environments
157 | ########################################
158 | environment 'config.action_mailer.default_url_options = { host: "http://localhost:3000" }', env: 'development'
159 | environment 'config.action_mailer.default_url_options = { host: "http://TODO_PUT_YOUR_DOMAIN_HERE" }', env: 'production'
160 |
161 | # Webpacker / Yarn
162 | ########################################
163 | run 'yarn add tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9'
164 | append_file 'app/javascript/packs/application.js', <<~JS
165 | // ----------------------------------------------------
166 | // WRITE YOUR OWN JS STARTING FROM HERE 👇
167 | // ----------------------------------------------------
168 | // External imports
169 |
170 | // Internal imports, e.g:
171 | import '../stylesheets/application.scss';
172 |
173 |
174 | document.addEventListener('turbolinks:load', () => {
175 | // Call your functions here, e.g:
176 | });
177 | JS
178 |
179 | # Postcss.config.js
180 | ########################################
181 |
182 | gsub_file('./postcss.config.js', /.+/, '')
183 |
184 | inject_into_file './postcss.config.js' do
185 | <<~JS
186 | module.exports = {
187 | plugins: [
188 | require('postcss-import'),
189 | require('postcss-flexbugs-fixes'),
190 | require('postcss-preset-env')({
191 | autoprefixer: {
192 | flexbox: 'no-2009'
193 | },
194 | stage: 3
195 | }),
196 | require('tailwindcss'),
197 | require('autoprefixer'),
198 | ]
199 | };
200 | JS
201 | end
202 |
203 | # Create Tailwind.config.js file
204 |
205 | run 'touch tailwind.config.js'
206 |
207 | inject_into_file './tailwind.config.js' do
208 | <<~JS
209 | module.exports = {
210 | purge: [],
211 | darkMode: false, // or 'media' or 'class'
212 | theme: {
213 | extend: {},
214 | },
215 | variants: {
216 | extend: {},
217 | },
218 | plugins: [],
219 | };
220 | JS
221 | end
222 |
223 | # Include Tailwind in app
224 |
225 | inject_into_file 'app/javascript/stylesheets/application.scss' do
226 | <<~SCSS
227 | @import "tailwindcss/base";
228 | @import "tailwindcss/components";
229 | @import "tailwindcss/utilities";
230 |
231 | .alert {
232 | position: fixed;
233 | bottom: 8px;
234 | right: 8px;
235 | z-index: 1000;
236 | background-color: #F7F4EA;
237 | padding: 4px;
238 | font-size: 10px;
239 | border-radius: 2px;
240 | }
241 | SCSS
242 | end
243 |
244 | # Include FontAwesome in app
245 | run 'mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss'
246 | inject_into_file 'app/assets/stylesheets/application.scss' do
247 | <<~SCSS
248 | @import "font-awesome-sprockets";
249 | @import "font-awesome";
250 | SCSS
251 | end
252 |
253 | # Dotenv
254 | ########################################
255 | run 'touch .env'
256 |
257 | # Rubocop
258 | ########################################
259 | run 'curl -L https://raw.githubusercontent.com/lewagon/rails-templates/master/.rubocop.yml > .rubocop.yml'
260 |
261 | # Git
262 | ########################################
263 | git add: '.'
264 | git commit: "-m 'Initial commit'"
265 |
266 | # Fix puma config
267 | gsub_file('config/puma.rb', 'pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }', '# pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }')
268 | end
269 |
--------------------------------------------------------------------------------
/minimal_rspec_factory_bot.rb:
--------------------------------------------------------------------------------
1 | run "if uname | grep -q 'Darwin'; then pgrep spring | xargs kill -9; fi"
2 |
3 | # GEMFILE
4 | ########################################
5 | inject_into_file 'Gemfile', before: 'group :development, :test do' do
6 | <<~RUBY
7 |
8 | gem 'autoprefixer-rails'
9 | gem 'font-awesome-sass'
10 | gem 'simple_form'
11 | RUBY
12 | end
13 |
14 | inject_into_file 'Gemfile', after: 'group :development, :test do' do
15 | <<-RUBY
16 |
17 | gem 'pry-byebug'
18 | gem 'pry-rails'
19 | gem 'dotenv-rails'
20 | gem 'rspec-rails', '~> 4.0.1'
21 | gem 'factory_bot_rails', '~> 6.1'
22 | gem 'shoulda-matchers', '~> 4.0'
23 | RUBY
24 | end
25 |
26 | # Procfile
27 | ########################################
28 | file 'Procfile', <<~YAML
29 | web: bundle exec puma -C config/puma.rb
30 | YAML
31 |
32 | # Assets in javascript file
33 | ########################################
34 | run 'mkdir app/javascript/stylesheets'
35 | run 'touch app/javascript/stylesheets/application.scss'
36 |
37 | # Dev environment
38 | ########################################
39 | gsub_file('config/environments/development.rb', /config\.assets\.debug.*/, 'config.assets.debug = false')
40 |
41 | # Layout
42 | ########################################
43 | if Rails.version < "6"
44 | scripts = <<~HTML
45 | <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>
46 | <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
47 | <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
48 | HTML
49 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>", scripts)
50 | else
51 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>", "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>")
52 | inject_into_file 'app/views/layouts/application.html.erb', before: "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>" do
53 | <<~HTML
54 | <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
55 | HTML
56 | end
57 | end
58 |
59 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>", "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>")
60 | style = <<~HTML
61 |
62 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
63 | HTML
64 | gsub_file('app/views/layouts/application.html.erb', "<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>", style)
65 |
66 |
67 | # Generators
68 | ########################################
69 | generators = <<~RUBY
70 | config.generators do |generate|
71 | generate.assets false
72 | generate.helper false
73 | generate.test_framework :test_unit, fixture: false
74 | end
75 | RUBY
76 |
77 | environment generators
78 |
79 | ########################################
80 | # AFTER BUNDLE
81 | ########################################
82 | after_bundle do
83 | # Generators: db + simple form + pages controller
84 | ########################################
85 | rails_command 'db:drop db:create db:migrate'
86 | generate('simple_form:install')
87 | generate(:controller, 'pages', 'home', '--skip-routes', '--no-test-framework')
88 |
89 |
90 | # Generators: rspec
91 | ######################################
92 | generate('rspec:install')
93 |
94 | # FACTORY BOT GEM
95 | # factory_bot.rb
96 | #####################################
97 | run 'mkdir ./spec/support'
98 | run 'touch ./spec/support/factory_bot.rb'
99 | insert_into_file './spec/support/factory_bot.rb' do
100 | <<~RUBY
101 | require 'factory_bot'
102 |
103 | RSpec.configure do |config|
104 | config.include FactoryBot::Syntax::Methods
105 | end
106 | RUBY
107 | end
108 |
109 | # rails_helper.rb
110 | gsub_file('./spec/rails_helper.rb', /.+/, '')
111 |
112 | insert_into_file './spec/rails_helper.rb' do
113 | <<~RUBY
114 | require 'rails'
115 | # This file is copied to spec/ when you run 'rails generate rspec:install'
116 | require 'spec_helper'
117 | ENV['RAILS_ENV'] ||= 'test'
118 | require File.expand_path('../config/environment', __dir__)
119 | # Prevent database truncation if the environment is production
120 | abort("The Rails environment is running in production mode!") if Rails.env.production?
121 | require 'rspec/rails'
122 | require 'support/factory_bot'
123 |
124 | Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |file| require file }
125 |
126 | begin
127 | ActiveRecord::Migration.maintain_test_schema!
128 | rescue ActiveRecord::PendingMigrationError => e
129 | puts e.to_s.strip
130 | exit 1
131 | end
132 | RSpec.configure do |config|
133 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
134 | # config.fixture_path = "#{::Rails.root}/spec/fixtures"
135 |
136 | config.use_transactional_fixtures = true
137 |
138 | config.infer_spec_type_from_file_location!
139 |
140 | # Filter lines from Rails gems in backtraces.
141 | config.filter_rails_from_backtrace!
142 | # arbitrary gems may also be filtered via:
143 | # config.filter_gems_from_backtrace("gem name")
144 | end
145 |
146 | Shoulda::Matchers.configure do |config|
147 | config.integrate do |with|
148 | with.test_framework :rspec
149 | with.library :rails
150 | end
151 | end
152 |
153 | RUBY
154 | end
155 |
156 | # Delete factories folder in './test/factories'
157 | run 'rm -rf ./test/factories'
158 |
159 |
160 | # Routes
161 | ########################################
162 | route "root to: 'pages#home'"
163 |
164 | # Git ignore
165 | ########################################
166 | append_file '.gitignore', <<~TXT
167 | # Ignore .env file containing credentials.
168 | .env*
169 | # Ignore Mac and Linux file system files
170 | *.swp
171 | .DS_Store
172 | TXT
173 |
174 | # Webpacker / Yarn
175 | ########################################
176 | run 'yarn add tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9'
177 | append_file 'app/javascript/packs/application.js', <<~JS
178 | // ----------------------------------------------------
179 | // WRITE YOUR OWN JS STARTING FROM HERE 👇
180 | // ----------------------------------------------------
181 | // External imports
182 |
183 | // Internal imports, e.g:
184 | import '../stylesheets/application.scss';
185 |
186 |
187 | document.addEventListener('turbolinks:load', () => {
188 | // Call your functions here, e.g:
189 | });
190 | JS
191 |
192 | # Postcss.config.js
193 | ########################################
194 |
195 | gsub_file('./postcss.config.js', /.+/, '')
196 |
197 | inject_into_file './postcss.config.js' do
198 | <<~JS
199 | module.exports = {
200 | plugins: [
201 | require('postcss-import'),
202 | require('postcss-flexbugs-fixes'),
203 | require('postcss-preset-env')({
204 | autoprefixer: {
205 | flexbox: 'no-2009'
206 | },
207 | stage: 3
208 | }),
209 | require('tailwindcss'),
210 | require('autoprefixer'),
211 | ]
212 | };
213 | JS
214 | end
215 |
216 | # Create Tailwind.config.js file
217 |
218 | run 'touch tailwind.config.js'
219 |
220 | inject_into_file './tailwind.config.js' do
221 | <<~JS
222 | module.exports = {
223 | purge: [],
224 | darkMode: false, // or 'media' or 'class'
225 | theme: {
226 | extend: {},
227 | },
228 | variants: {
229 | extend: {},
230 | },
231 | plugins: [],
232 | };
233 | JS
234 |
235 | end
236 |
237 | # Include Tailwind in app
238 |
239 | inject_into_file 'app/javascript/stylesheets/application.scss' do
240 | <<~SCSS
241 | @import "tailwindcss/base";
242 | @import "tailwindcss/components";
243 | @import "tailwindcss/utilities";
244 | SCSS
245 | end
246 |
247 | # Include FontAwesome in app
248 | run 'mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss'
249 | inject_into_file 'app/assets/stylesheets/application.scss' do
250 | <<~SCSS
251 | @import "font-awesome-sprockets";
252 | @import "font-awesome";
253 | SCSS
254 | end
255 |
256 | # Dotenv
257 | ########################################
258 | run 'touch .env'
259 |
260 | # Rubocop
261 | ########################################
262 | run 'curl -L https://raw.githubusercontent.com/lewagon/rails-templates/master/.rubocop.yml > .rubocop.yml'
263 |
264 | # Git
265 | ########################################
266 | git add: '.'
267 | git commit: "-m 'Initial commit'"
268 |
269 | # Fix puma config
270 | gsub_file('config/puma.rb', 'pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }', '# pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }')
271 | end
272 |
--------------------------------------------------------------------------------
/devise_rspec_factory_bot.rb:
--------------------------------------------------------------------------------
1 | run "if uname | grep -q 'Darwin'; then pgrep spring | xargs kill -9; fi"
2 |
3 | # GEMFILE
4 | ########################################
5 | inject_into_file 'Gemfile', before: 'group :development, :test do' do
6 | <<~RUBY
7 |
8 | gem 'devise'
9 | gem 'autoprefixer-rails'
10 | gem 'font-awesome-sass'
11 | gem 'simple_form'
12 | RUBY
13 | end
14 |
15 | inject_into_file 'Gemfile', after: 'group :development, :test do' do
16 | <<-RUBY
17 |
18 | gem 'pry-byebug'
19 | gem 'pry-rails'
20 | gem 'dotenv-rails'
21 | gem 'rspec-rails', '~> 4.0.1'
22 | gem 'factory_bot_rails', '~> 6.1'
23 | gem 'shoulda-matchers', '~> 4.0'
24 | RUBY
25 | end
26 |
27 | # Procfile
28 | ########################################
29 | file 'Procfile', <<~YAML
30 | web: bundle exec puma -C config/puma.rb
31 | YAML
32 |
33 | # Assets in javascript file
34 | ########################################
35 | run 'mkdir app/javascript/stylesheets'
36 | run 'touch app/javascript/stylesheets/application.scss'
37 |
38 | # Dev environment
39 | ########################################
40 | gsub_file('config/environments/development.rb', /config\.assets\.debug.*/, 'config.assets.debug = false')
41 |
42 | # Layout
43 | ########################################
44 | if Rails.version < "6"
45 | scripts = <<~HTML
46 | <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>
47 | <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
48 | <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
49 | HTML
50 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>", scripts)
51 | else
52 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>", "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>")
53 | inject_into_file 'app/views/layouts/application.html.erb', before: "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>" do
54 | <<~HTML
55 | <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
56 | HTML
57 | end
58 | end
59 |
60 | gsub_file('app/views/layouts/application.html.erb', "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>", "<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload', defer: true %>")
61 | style = <<~HTML
62 |
63 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
64 | HTML
65 | gsub_file('app/views/layouts/application.html.erb', "<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>", style)
66 |
67 |
68 | # Generators
69 | ########################################
70 | generators = <<~RUBY
71 | config.generators do |generate|
72 | generate.assets false
73 | generate.helper false
74 | generate.test_framework :test_unit, fixture: false
75 | end
76 | RUBY
77 |
78 | environment generators
79 |
80 | # Insert Devise flashes
81 | file 'app/views/shared/_flashes.html.erb', <<~HTML
82 | <% if notice %>
83 |
84 | <%= notice %>
85 |
88 |
89 | <% end %>
90 | <% if alert %>
91 |
92 | <%= alert %>
93 |
96 |
97 | <% end %>
98 | HTML
99 |
100 | inject_into_file 'app/views/layouts/application.html.erb', after: "<%= yield %>" do
101 | <<-HTML
102 | <%= render 'shared/flashes' %>
103 | HTML
104 | end
105 |
106 | ########################################
107 | # AFTER BUNDLE
108 | ########################################
109 | after_bundle do
110 | # Generators: db + simple form + pages controller
111 | ########################################
112 | rails_command 'db:drop db:create db:migrate'
113 | generate('simple_form:install')
114 | generate(:controller, 'pages', 'home', '--skip-routes', '--no-test-framework')
115 |
116 | # Routes
117 | ########################################
118 | route "root to: 'pages#home'"
119 |
120 | # Git ignore
121 | ########################################
122 | append_file '.gitignore', <<~TXT
123 | # Ignore .env file containing credentials.
124 | .env*
125 | # Ignore Mac and Linux file system files
126 | *.swp
127 | .DS_Store
128 | TXT
129 |
130 | # Devise install + user
131 | ########################################
132 | generate('devise:install')
133 | generate('devise', 'User')
134 |
135 | # Generators: rspec + rspec User model
136 | ######################################
137 | generate('rspec:install')
138 | generate('rspec:model user')
139 |
140 | # FACTORY BOT GEM
141 | # factory_bot.rb
142 | #####################################
143 | run 'mkdir ./spec/support'
144 | run 'touch ./spec/support/factory_bot.rb'
145 | insert_into_file './spec/support/factory_bot.rb' do
146 | <<~RUBY
147 | require 'factory_bot'
148 |
149 | RSpec.configure do |config|
150 | config.include FactoryBot::Syntax::Methods
151 | end
152 | RUBY
153 | end
154 |
155 |
156 | # rails_helper.rb
157 | gsub_file('./spec/rails_helper.rb', /.+/, '')
158 |
159 | insert_into_file './spec/rails_helper.rb' do
160 | <<~RUBY
161 | # This file is copied to spec/ when you run 'rails generate rspec:install'
162 | require 'spec_helper'
163 | ENV['RAILS_ENV'] ||= 'test'
164 | require File.expand_path('../config/environment', __dir__)
165 | # Prevent database truncation if the environment is production
166 | abort("The Rails environment is running in production mode!") if Rails.env.production?
167 | require 'rspec/rails'
168 | require 'support/factory_bot'
169 |
170 | Dir[Rails.root.join("spec/support/**/*.rb")].sort.each { |file| require file }
171 |
172 | begin
173 | ActiveRecord::Migration.maintain_test_schema!
174 | rescue ActiveRecord::PendingMigrationError => e
175 | puts e.to_s.strip
176 | exit 1
177 | end
178 | RSpec.configure do |config|
179 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
180 | config.include Warden::Test::Helpers
181 |
182 | config.use_transactional_fixtures = true
183 |
184 | config.infer_spec_type_from_file_location!
185 |
186 | # Filter lines from Rails gems in backtraces.
187 | config.filter_rails_from_backtrace!
188 | # arbitrary gems may also be filtered via:
189 | # config.filter_gems_from_backtrace("gem name")
190 | end
191 |
192 | Shoulda::Matchers.configure do |config|
193 | config.integrate do |with|
194 | with.test_framework :rspec
195 | with.library :rails
196 | end
197 | end
198 |
199 | RUBY
200 | end
201 |
202 |
203 | # Create factory user.rb
204 | run 'touch spec/support/user.rb'
205 |
206 | insert_into_file './spec/support/user.rb' do
207 | <<~RUBY
208 | FactoryBot.define do
209 | factory :user, class: 'User' do
210 | # Insert your user here
211 | end
212 | end
213 | RUBY
214 | end
215 |
216 | # Delete factories folder in './test/factories'
217 | run 'rm -rf ./test/factories'
218 |
219 | # App controller
220 | ########################################
221 | run 'rm app/controllers/application_controller.rb'
222 | file 'app/controllers/application_controller.rb', <<~RUBY
223 | class ApplicationController < ActionController::Base
224 | #{ "protect_from_forgery with: :exception\n" if Rails.version < "5.2"} before_action :authenticate_user!
225 | end
226 | RUBY
227 |
228 | # migrate + devise views
229 | ########################################
230 | rails_command 'db:migrate'
231 | generate('devise:views')
232 |
233 | # Pages Controller
234 | ########################################
235 | run 'rm app/controllers/pages_controller.rb'
236 | file 'app/controllers/pages_controller.rb', <<~RUBY
237 | class PagesController < ApplicationController
238 | skip_before_action :authenticate_user!, only: [ :home ]
239 | def home
240 | end
241 | end
242 | RUBY
243 |
244 | # Environments
245 | ########################################
246 | environment 'config.action_mailer.default_url_options = { host: "http://localhost:3000" }', env: 'development'
247 | environment 'config.action_mailer.default_url_options = { host: "http://TODO_PUT_YOUR_DOMAIN_HERE" }', env: 'production'
248 |
249 | # Webpacker / Yarn
250 | ########################################
251 | run 'yarn add tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9'
252 | append_file 'app/javascript/packs/application.js', <<~JS
253 | // ----------------------------------------------------
254 | // WRITE YOUR OWN JS STARTING FROM HERE 👇
255 | // ----------------------------------------------------
256 | // External imports
257 |
258 | // Internal imports, e.g:
259 | import '../stylesheets/application.scss';
260 |
261 |
262 | document.addEventListener('turbolinks:load', () => {
263 | // Call your functions here, e.g:
264 | });
265 | JS
266 |
267 | # Postcss.config.js
268 | ########################################
269 |
270 | gsub_file('./postcss.config.js', /.+/, '')
271 |
272 | inject_into_file './postcss.config.js' do
273 | <<~JS
274 | module.exports = {
275 | plugins: [
276 | require('postcss-import'),
277 | require('postcss-flexbugs-fixes'),
278 | require('postcss-preset-env')({
279 | autoprefixer: {
280 | flexbox: 'no-2009'
281 | },
282 | stage: 3
283 | }),
284 | require('tailwindcss'),
285 | require('autoprefixer'),
286 | ]
287 | };
288 | JS
289 | end
290 |
291 | # Create Tailwind.config.js file
292 |
293 | run 'touch tailwind.config.js'
294 |
295 | inject_into_file './tailwind.config.js' do
296 | <<~JS
297 | module.exports = {
298 | purge: [],
299 | darkMode: false, // or 'media' or 'class'
300 | theme: {
301 | extend: {},
302 | },
303 | variants: {
304 | extend: {},
305 | },
306 | plugins: [],
307 | };
308 | JS
309 |
310 | end
311 |
312 | # Include Tailwind in app
313 |
314 | inject_into_file 'app/javascript/stylesheets/application.scss' do
315 | <<~SCSS
316 | @import "tailwindcss/base";
317 | @import "tailwindcss/components";
318 | @import "tailwindcss/utilities";
319 |
320 | .alert {
321 | position: fixed;
322 | bottom: 8px;
323 | right: 8px;
324 | z-index: 1000;
325 | background-color: #F7F4EA;
326 | padding: 4px;
327 | font-size: 10px;
328 | border-radius: 2px;
329 | }
330 | SCSS
331 | end
332 |
333 | # Include FontAwesome in app
334 | run 'mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss'
335 | inject_into_file 'app/assets/stylesheets/application.scss' do
336 | <<~SCSS
337 | @import "font-awesome-sprockets";
338 | @import "font-awesome";
339 | SCSS
340 | end
341 |
342 | # Dotenv
343 | ########################################
344 | run 'touch .env'
345 |
346 | # Rubocop
347 | ########################################
348 | run 'curl -L https://raw.githubusercontent.com/lewagon/rails-templates/master/.rubocop.yml > .rubocop.yml'
349 |
350 | # Git
351 | ########################################
352 | git add: '.'
353 | git commit: "-m 'Initial commit'"
354 |
355 | # Fix puma config
356 | gsub_file('config/puma.rb', 'pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }', '# pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }')
357 | end
358 |
--------------------------------------------------------------------------------