Skip to content

Instantly share code, notes, and snippets.

@bdavidxyz
Created December 2, 2024 10:38
Show Gist options
  • Save bdavidxyz/27258cfb940cc01bb24101efaca1de9e to your computer and use it in GitHub Desktop.
Save bdavidxyz/27258cfb940cc01bb24101efaca1de9e to your computer and use it in GitHub Desktop.
Create new Rails 8 app with better defaults
#
# Will be built with VITE, PG, and different bin/dev
# $> cnrav railsvite 8.0.0
# cnrav myapp 8.0.0 --skip-docker --skip-kamal --skip-jbuilder --skip-action-text
#
cnrav ()
{
# Create directory, initialize Rails project
mkdir -p -- "$1" && cd -P -- "$1"
echo "source 'https://rubygems.org'" > Gemfile
echo "gem 'rails', '$2'" >> Gemfile
# Install Rails and create the project
bundle config set path 'vendor/bundle'
bundle install
bundle exec rails new . --database=postgresql --skip-javascript --force ${@:3:99}
bundle update
# Add additional gems to the Gemfile
echo "gem 'vite_rails'" >> Gemfile
echo "gem 'dotenv-rails', groups: [:development, :test]" >> Gemfile
# Re-run bundle install
bundle install
# Install Vite in the project
bundle exec vite install
# Add `vite-plugin-full-reload` as a dev dependency
yarn add -D vite-plugin-full-reload
# Configure Vite by overwriting vite.config.ts
cat > vite.config.ts <<EOL
import { defineConfig } from 'vite'
import RubyPlugin from 'vite-plugin-ruby'
import FullReload from 'vite-plugin-full-reload'
import tailwindcss from "tailwindcss";
export default defineConfig({
plugins: [
RubyPlugin(),
FullReload(['config/routes.rb', 'app/views/**/*'], { delay: 200 })
],
css: {
postcss: {
plugins: [tailwindcss()],
},
},
})
EOL
# Add vendor/bundle to .gitignore
echo "vendor/bundle" >> .gitignore
# Add run-pty in development mode
yarn add run-pty --dev
# Create run-pty.json configuration file
cat > run-pty.json <<EOL
[
{
"command": ["bin/rails", "server"],
"status": {
"Listening on": null
},
"defaultStatus": ["⏳", "S"]
},
{
"command": ["bin/vite", "dev"],
"status": {
"ready in": null
},
"defaultStatus": ["⏳", "S"]
},
{
"command": ["bin/jobs"],
"status": {
"Starting jobs...": null
},
"defaultStatus": ["⏳", "S"]
}
]
EOL
# Replace the content of bin/dev
cat > bin/dev <<EOL
#!/usr/bin/env ruby
exec "npx", "run-pty", "run-pty.json", *ARGV
EOL
# Ensure bin/dev is executable
chmod +x bin/dev
# Create a default controller
echo "class HomeController < ApplicationController" > app/controllers/home_controller.rb
echo "end" >> app/controllers/home_controller.rb
# Create a default route
echo "Rails.application.routes.draw do" > config/routes.rb
echo ' get "home/index"' >> config/routes.rb
echo ' root to: "home#index"' >> config/routes.rb
echo 'end' >> config/routes.rb
# Create a default view
mkdir -p app/views/home
echo '<h1 class="text-4xl font-extrabold">This is h1 title</h1>' > app/views/home/index.html.erb
# Add TailwindCSS configuration
mkdir -p app/frontend/entrypoints
cat > app/frontend/entrypoints/application.css <<EOL
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
EOL
yarn add -D tailwindcss @tailwindcss/typography autoprefixer postcss
yarn add -D eslint prettier eslint-plugin-prettier eslint-config-prettier eslint-plugin-tailwindcss path
# Initialize TailwindCSS
npx tailwindcss init
# Configure TailwindCSS
cat > tailwind.config.js <<EOL
/** @type {import('tailwindcss').Config} */
const colors = require('tailwindcss/colors')
const defaultTheme = require('tailwindcss/defaultTheme')
module.exports = {
content: [
'./app/helpers/**/*.rb',
'./app/assets/stylesheets/**/*.css',
'./app/views/**/*.{html,html.erb,erb}',
'./app/javascript/components/**/*.js',
],
theme: {
extend: {
},
},
corePlugins: {
aspectRatio: false,
},
plugins: [
require('@tailwindcss/typography'),
],
}
EOL
# Configure config/database.yml
cat > config/database.yml <<EOL
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
cache: &cache
<<: *default
migrations_paths: db/cache_migrate
queue: &queue
<<: *default
migrations_paths: db/queue_migrate
cable: &cable
<<: *default
migrations_paths: db/cable_migrate
development:
primary:
<<: *default
url: <%= ENV['DATABASE_URL'] %>
cache:
<<: *cache
url: <%= ENV['DATABASE_URL']&.+('_cache') %>
queue:
<<: *queue
url: <%= ENV['DATABASE_URL']&.+('_queue') %>
cable:
<<: *cable
url: <%= ENV['DATABASE_URL']&.+('_cable') %>
test:
primary:
<<: *default
url: <%= ENV['DATABASE_URL_TEST'] %>
production:
primary:
<<: *default
url: <%= ENV['DATABASE_URL'] %>
cache:
<<: *cache
url: <%= ENV['DATABASE_URL']&.+('_cache') %>
queue:
<<: *queue
url: <%= ENV['DATABASE_URL']&.+('_queue') %>
cable:
<<: *cable
url: <%= ENV['DATABASE_URL']&.+('_cable') %>
EOL
# add .env file
echo "DATABASE_URL=postgres://localhost:5432/$1_development" > .env
echo "DATABASE_URL_TEST=postgres://localhost:5432/$1_test" >> .env
# Add stylesheet tag to layout
sed -i '/<%= vite_javascript_tag '\''application'\'' %>/a\
<%= vite_stylesheet_tag '\''application'\'' %>' app/views/layouts/application.html.erb
sed -i '/Rails.application.configure do/a\
# Replace the default in-process memory cache store with a durable alternative.\
config.cache_store = :solid_cache_store\
\
# Replace the default in-process and non-durable queuing backend for Active Job.\
config.active_job.queue_adapter = :solid_queue\
config.solid_queue.connects_to = { database: { writing: :queue } }' config/environments/development.rb
sed -i '/SolidQueue::Cli.start(ARGV)/i\puts "Starting jobs..."' bin/jobs
# Create database and schema.rb
RAILS_ENV=development bin/rails db:create
RAILS_ENV=development bin/rails db:migrate
RAILS_ENV=test bin/rails db:create
git add . && git commit -m 'first commit'
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment