Switch Dreams - Rails Template

Template for switch dreams`s rails apps
Icons/chart bar
Used 40 times
Created by
P Pedro Augusto

Usage
This template install:

# Development (test and linters)
- Rspec
- Factory_bot
- Simplecov
- Switchcop (rubocop for switch)

# FullStack (Choose between react and hotwired)
- ViteRuby
- Tailwind

   ## Hotwired
   - Stimulus
   - ViewComponent

   ## React

  - Inertia
  - React

# API Only
- RestApiGenerate

# Optionals
- AVO

for new apps:
rails new APP_PATH --skip-javascript -T --asset-pipeline=propshaft -m https://railsbytes.com/script/VD7sey

# TODO:
- Eslint

Run this command in your Rails app directory in the terminal:

rails app:template LOCATION="https://railsbytes.com/script/VD7sey"
Template Source

Review the code before running this template on your machine.

# Add default quality gems

# Questions
is_full_stack = yes?("Is full stack rails? (y/n)")
if is_full_stack
  is_react = yes?("Want to use react in frontend? (y/n)")
else
  is_react = false
end

needs_admin = yes?("Needs avo admin? (y/n)")
github_files = yes?("Generate github actions file (y/n)")

# Maybe we can use another template? rails app:template LOCATION='https://railsbytes.com/script/z0gsLX'
gem_group :development, :test do
  gem "rspec-rails"
  gem "factory_bot_rails"
  gem "switchcop"
  gem "simplecov"
end

# Copy switchcop files

file '.rubocop.yaml', <<-CODE
inherit_gem:
  switchcop: rubocop.yml
CODE

# Rspec setup
run "bundle install"
rails_command "generate rspec:install"

# FactoryBot

## Create support file
file 'spec/support/factory_bot.rb', <<-CODE
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end
CODE

# Inject factory bot file inside
inject_into_file "spec/rails_helper.rb", after: "require 'rspec/rails'" do
  <<~EOF
  require 'support/factory_bot'
  EOF
end

# Simplecov
inject_into_file "spec/rails_helper.rb", after: "require 'spec_helper'" do
  <<~EOF
  require "simplecov"
  SimpleCov.start "rails" do
    add_filter "/bin/"
    add_filter "/db/"
    add_filter "/spec/" # for rspec
  end
  EOF
end

# ./bin/dev

file 'bin/dev', <<-CODE
#!/usr/bin/env bash

if ! command -v foreman &> /dev/null
then
echo "Installing foreman..."
gem install foreman
fi

foreman start -f Procfile.dev "$@"
CODE

unless is_full_stack
  gem "rest-api-generator"
end


if is_full_stack
  # Default gems for full stack vite and tailwind
  gem "vite_rails"

  run "bundle install"
  run "bundle exec vite install"

  # Install yarn and tailwind
  run "yarn add -D vite-plugin-rails tailwindcss postcss autoprefixer"

  # Config for vite
  file "vite.config.ts", <<-CODE
import { defineConfig } from 'vite'
import ViteRails from 'vite-plugin-rails'

export default defineConfig({
  plugins: [
    ViteRails(),
  ],
})
  CODE

  # Config for tailwind
  #########################################
  run "npx tailwindcss init -p"

  file "tailwind.config.js", <<-CODE
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
   "app/**/*.html.erb",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
  CODE

  file "app/frontend/entrypoints/application.css", <<-CODE
@tailwind base;
@tailwind components;
@tailwind utilities;
  CODE

  #########################################
  # END Config for tailwind

  inject_into_file "app/frontend/entrypoints/application.js" do
    <<~EOF
import "./application.css"
    EOF
  end
end

if is_react
  # Install Inertia
  gem "inertia_rails"

  run "yarn add react react-dom inertiajs @inertiajs/react @vitejs/plugin-react"

  # Inertia entrypoint file
  file "app/frontend/entrypoints/inertia.jsx", <<-CODE
import React from "react";
import { createRoot } from "react-dom/client";
import { createInertiaApp } from "@inertiajs/react";

createInertiaApp({
  resolve: async (name) => {
    const pages = import.meta.glob("../pages/**/*.tsx", { eager: true });
    let page = pages[`../pages/${name}.tsx`];
    return page;
  },
  setup({ el, App, props }) {
    const container = document.getElementById(el.id);
    const root = createRoot(container);
    root.render(<App {...props} />);
  },
});

  CODE

  inject_into_file "app/frontend/entrypoints/application.js" do
    <<~EOF
import "./inertia";
    EOF
  end
else
  # Install Turbo
  gem "view_component"
  gem "turbo-rails"
  gem "stimulus-rails"

  # Config for hotwired
  run "yarn add @hotwired/turbo-rails @hotwired/stimulus"

  # Stimulus configuration file
  file "app/frontend/controllers/index.js", <<-CODE
import { Application } from "@hotwired/stimulus";
const application = Application.start();

const controllers = import.meta.globEager("./**/*_controller.js");

for (let path in controllers) {
  let module = controllers[path];
  let name = path.match(/\.\/(.+)_controller\.js$/)[1].replaceAll("/", "--");
  application.register(name, module.default);
}
  CODE


  inject_into_file "app/frontend/entrypoints/application.js" do
    <<~EOF
import "@hotwired/turbo-rails"
import "../controllers"
    EOF
  end
end

# Github templates

if github_files
  file '.github/PULL_REQUEST_TEMPLATE.md', <<-CODE
### Descrição
<!-- Descreva brevemente o que foi feito na issue -->

### Observações

<!-- Nesse tópico coloque algum detalhe que faltou ou um possível ponto de melhoria futuro -->

### Prints

<!-- Em caso de uma issue que envolva alguma tela ou componente, coloque aqui o print -->

### Checklist

- [ ] Fiz o link com a task do clickup.
- [ ] Fiz minha própria revisão do código.
- [ ] Realizei os testes que compravam que a funcionalidade está funcionando corretamente.
  CODE

  file '.github/workflows/frontend-ci.yml', <<-CODE
name: Frontend CI
on:
  pull_request:
    branches:
      - '**'
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@master
        with:
          cache: 'yarn'
          registry-url: 'https://npm.pkg.github.com'
          scope: '@switchdreams'

      - name: Install modules
        run: yarn
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GH_PACKAGE_TOKEN }}
      - name: Run ESLint
        run: yarn lint

  end
  CODE
  
  file '.github/workflows/backend-ci.yml', <<-CODE
name: Backend CI
env:
  DB_USER: user
  DB_PASSWORD: password
  POSTGRES_DB: password
  RUBY_VERSION: 3.3.0

on:
  pull_request:
    branches:
      - '**'

jobs:
  rubocop:
    name: Rubocop
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ env.RUBY_VERSION }}

      - name: Install Rubocop
        run: |
          gem install switchcop
          gem install action_policy

      - name: Check code
        run: rubocop
  rspec:
    name: RSpec
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:latest
        ports:
          - 5432:5432
        env:
          POSTGRES_USER: ${{ env.DB_USER }}
          POSTGRES_PASSWORD: ${{ env.DB_PASSWORD }}
    steps:
      - uses: actions/checkout@v4
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ env.RUBY_VERSION }}
          bundler-cache: true

      - uses: actions/setup-node@master
        with:
          registry-url: 'https://npm.pkg.github.com'
          scope: '@switchdreams'
          cache: yarn

      - name: Install postgres client
        run: sudo apt-get install libpq-dev

      - name: Yarn Install
        run: yarn install --frozen-lockfile
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GH_PACKAGE_TOKEN }}

      - name: Install Bundler
        run: gem install bundler

      - name: Bundle Install
        run: bundle install

      - name: Create database
        run: |
          bundle exec rails db:create RAILS_ENV=test
          bundle exec rails db:migrate RAILS_ENV=test

      - name: Assets precompile
        run: bundle exec rails assets:precompile RAILS_ENV=test

      - name: Run tests
        run: bundle exec rspec spec
  CODE
end


gem "avo" if needs_admin
Comments

Sign up or Login to leave a comment.