[Rails]boilerplateを作成してGithubのTemplate Repositoryにする方法

  • このエントリーをはてなブックマークに追加

スポンサーリンク

はじめに

Railsアプリケーションを新しく作成するとき、rails newコマンドを実行すると思います。

その後、アプリケーションの設定やGemのインストールなどをやっていきますが、毎回同じようなことをしたり、「あれ、これどうだっけ?」と調べたりする手間があると思います。

同じことを繰り返さないように、ある程度セットアップされたアプリケーションの雛形があると便利です。

今回は、サクッとRailsアプリケーションを作るためのboilerplateというものを紹介します。

また、作ったboilerplateはGithubのTemplate Repositoryとして登録して、簡単に使いまわせるようにしたいと思います。

boilerplateとは?

ボイラープレートコード (: boilerplate code、または単にボイラープレート) は、コンピュータプログラミングでは、殆ど、または全く変化することなく、複数の場所で繰り返される定型コードのセクションのこと。冗長な言語を使用する場合、プログラマーはコードを少しだけ書くだけでも多くのコードを作成する必要がある。このような定型コードはボイラープレートと呼ばれる。

ボイラープレートコード – Wikipedia

Githubで検索してみると色んな人が作ったリポジトリがあります。

https://github.com/topics/rails-boilerplate

GithubのTemplate Repositoryとは?

既存のリポジトリをテンプレート化して、あなたや他の人が、同じディレクトリ構造、ブランチ、ファイルを持つ新しいリポジトリ作成できるようにすることができます。

テンプレートリポジトリを作成する – GitHub Docs

boilerplateに含める内容

ここでは以下の内容でboilerplateを作成していきます。

  • ヘッダー、フッダーなどの基本的なレイアウト
  • deviseを使ったユーザー認証
  • 管理画面の実装
  • Github Actionsの設定

開発を便利するGemも紹介していますので、是非参考にしてください。

開発環境について

この記事では以下のバージョンで動作確認をしています。

ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin21]
Rails 7.1.2
node v20.11.0
yarn 4.0.2

まったく同じバージョンである必要はありませんが、ruby 2.7など古過ぎないようにしてください。

もしRailsの環境構築が必要な場合は、以下の記事を参考にしてください。

boilerplate用のRailsアプリケーションの生成

新しくRailsアプリケーションを生成します。

$ rails new rails-boilerplate -d postgresql -T -j esbuild --css bootstrap

オプションは以下のようにしています。

  • データベースはPostgreSQLを使用
  • Rspecを使うため、デフォルトのテストを除外
  • JavaScriptのバンドルにesbuildを使用
  • CSSフレームワークにbootstrapを使用

完了するとRailsアプリケーションが生成されます。

もし何かエラーが出た場合は、エラーメッセージを頼りにググるなりして解決しましょう。

nodeのバージョンが古い、などが良くあります。

続いて、RailsのHello Worldの画面が表示されることを確認します。

ディレクトリに移動して、DBを作成し、Railsアプリケーションを起動します。

$ cd rails-boilerplate
$ rails db:create
$ bin/dev

うまく表示されたらコミットしましょう。

$ cd rails-boilerplate
$ git add .
$ git commit -m "Initialize 'rails new rails-boilerplate -d postgresql -T -j esbuild --css bootstrap'"

レイアウトを作成

bootstrapを使って基本的なレイアウトを作成していきます。

実装の流れは以下のようになります。

  • トップページを作成
  • フッター用のページを作成
  • 見た目を整える
  • 動作確認

それではいきましょう。

トップページを作成

rootを変更します。ここではトップページはstaticコントローラーという名前にします。

root "static#index"

新しくstatic_controller.rbというファイルを作成して、以下のように実装します。

class StaticController < ApplicationController
  def index
  end
end

コントローラーに対応するViewファイルを作成します。

<h1>Static#index</h1>

フッター用のページを作成

追加するページは、アプリケーションではよくある「利用規約」と「プライバシーポリシー」のページにします。

基本的な流れはトップページと同じです。

Rails.application.routes.draw do
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
  scope controller: :static do
    get :terms
    get :privacy
  end

  # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
  # Can be used by load balancers and uptime monitors to verify that the app is live.
  get "up" => "rails/health#show", as: :rails_health_check

  # Defines the root path route ("/")
  root "static#index"
end
class StaticController < ApplicationController
  def index
  end

  def terms
  end

  def privacy
  end
end
<h1>Static#terms</h1>
<h1>Static#privacy</h1>

Viewファイルの内容は最低限にしているので、必要に応じて変更してください。

見た目を整える

bootstrapで見た目を整えていきます。

ここではヘッダーメニュー、メインコンテンツ、フッターという構成にします

ヘッダーメニューとフッターは部分テンプレートに分けた方が管理しやすいので、ファイルを作成します。

sharedというディレクトリを作成して、ファイルを作成します。

<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container mx-auto">
    <%= link_to "Your App", root_path, class: "navbar-brand" %>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
      </ul>
      <ul class="navbar-nav">
      </ul>
    </div>
  </div>
</nav>
<footer class="footer mt-auto py-3 bg-body-tertiary">
  <div class="container d-flex justify-content-between mx-auto text-muted">
    <span>© <%= Date.today.year %> Your Company</span>
    <ul class="d-inline float-end list-inline mb-0">
      <li class="list-inline-item"><%= link_to "Terms", terms_path %></li>
      <li class="list-inline-item"><%= link_to "Privacy", privacy_path %></li>
    </ul>
  </div>
</footer>

最後にレイアウトファイルで部分テンプレートを呼び出すように変更します。

<!DOCTYPE html>
<html class="h-100">
  <head>
    <title>Your App</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
  </head>

  <body class="d-flex flex-column h-100">
    <main class="flex-shrink-0">
      <%= render "shared/navbar" %>
      <div class="container mt-4 mx-auto">
        <%= yield %>
      </div>
    </main>

    <%= render "shared/footer" %>
  </body>
</html>

見た目は主にbootstrapのコンポーネントを使っていますが、必要に応じて変更してください。

動作確認

bin/devでサーバーを起動、localhost:3000にアクセスして問題なく動作するか確認しておきましょう。

ここまでで問題なければコミットしましょう。

$ git commit -m "Add static pages"

deviseインストール

deviseを使ってユーザー認証機能を作成していきます。

実装の流れは以下のようになります。

  • deviseのインストール
  • Userモデルの作成
  • ログイン前後でルーティングを変える
  • 細かいカスタマイズ

それではいきましょう。

deviseのインストール

$ bundle add devise
$ rails generate devise:install

メーラーのデフォルトURLオプションを設定します。

# Set the default URL for ActionMailer in development.
config.action_mailer.default_url_options = { host: "localhost", port: 3000 }

deviseのviewファイルを生成します。

$ rails g devise:views

Userモデルの作成

deviseのコマンドを使ってUserモデルを生成します。

$ rails generate devise User first_name last_name announcements_read_at:datetime admin:boolean     

上記のコマンドでは、デフォルトのカラムに加えていくつかのカラムを追加しています。後々使います。

  • first_name, last_name: 氏名
  • announcements_read_at: 運営からのお知らせを見た日時
  • admin: 管理者フラグ

生成されたマイグレーションファイルを開いて、adminカラムの初期値を追加します。

# frozen_string_literal: true

class DeviseCreateUsers < ActiveRecord::Migration[7.1]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at

      t.string :first_name
      t.string :last_name
      t.datetime :announcements_read_at
      t.boolean :admin, null: false, default: false

      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

マイグレーションを実行します。

$ rails db:migrate

氏名を登録できるようにします。

モデルに必須バリデーションを追加します。

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  validates :first_name, :last_name, presence: true
end

コントローラーで氏名の値を受け取れるように設定します。

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name])
    devise_parameter_sanitizer.permit(:account_update, keys: [:first_name, :last_name])
  end
end

Viewファイルに氏名の入力欄を追加します。

emailのautofocusも削除します。

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <%= f.label :first_name %><br />
    <%= f.text_field :first_name %>
  </div>

  <div class="field">
    <%= f.label :last_name %><br />
    <%= f.text_field :last_name %>
  </div>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autocomplete: "email" %>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>
<h2>Edit <%= resource_name.to_s.humanize %></h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>

  <div class="field">
    <%= f.label :first_name %><br />
    <%= f.text_field :first_name %>
  </div>

  <div class="field">
    <%= f.label :last_name %><br />
    <%= f.text_field :last_name %>
  </div>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
    <div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
  <% end %>

  <div class="field">
    <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
    <% if @minimum_password_length %>
      <br />
      <em><%= @minimum_password_length %> characters minimum</em>
    <% end %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password, autocomplete: "current-password" %>
  </div>

  <div class="actions">
    <%= f.submit "Update" %>
  </div>
<% end %>

<h3>Cancel my account</h3>

<div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>

<%= link_to "Back", :back %>

ここまでで動作確認をします。

localhost:3000/users/sign_up にアクセスして以下のように表示されることを確認します。

続いて、適当な値を入力してSign upします。

成功するとトップページが表示されます。

localhost:3000/users/edit にアクセスして以下のように表示されることを確認します。

登録情報が変更できることを確認します。

ログインの動線を追加して、ログイン前後でページを変える

navbarに以下のようなログインの動線を追加します。

<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container mx-auto">
    <%= link_to "Your App", root_path, class: "navbar-brand" %>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
      </ul>
      <ul class="navbar-nav">
        <% if user_signed_in? %>
          <li class="nav-item dropdown">
            <%= link_to "#", class: "nav-link dropdown-toggle", data: { bs_toggle: "dropdown" }, aria: { expanded: false } do %>
              <i class="bi bi-person-circle"></i>
            <% end %>
            <div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbar-dropdown">
              <%= link_to "Settings", edit_user_registration_path, class: "dropdown-item" %>
              <div class="dropdown-divider"></div>
              <%= button_to "Logout", destroy_user_session_path, method: :delete, class: "dropdown-item" %>
            </div>
          </li>
        <% else %>
          <li class="nav-item"><%= link_to "Sign Up", new_user_registration_path, class: "nav-link" %></li>
          <li class="nav-item"><%= link_to "Login", new_user_session_path, class: "nav-link" %></li>
        <% end %>
      </ul>
    </div>
  </div>
</nav>

flashが表示されるようにします。

sharedディレクトリに_flash.html.erbというファイルを作成します。

<div id="flash">
  <% if notice %>
    <div class="container mt-4 mx-auto">
      <div class="alert alert-primary alert-dismissible show" role="alert">
        <%= notice %>
        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
      </div>
    </div>
  <% end %>

  <% if alert %>
    <div class="container mt-4 mx-auto">
      <div class="alert alert-warning alert-dismissible show" role="alert">
        <%= alert %>
        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
      </div>
    </div>
  <% end %>
</div>

作成した_flash.html.erbをapplication.html.erbで呼び出します。

<!DOCTYPE html>
<html class="h-100">
  <head>
    <title>Your App</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
  </head>

  <body class="d-flex flex-column h-100">
    <main class="flex-shrink-0">
      <%= render "shared/navbar" %>
      <%= render 'shared/flash' %>

      <div class="container mt-4 mx-auto">
        <%= yield %>
      </div>
    </main>

    <%= render "shared/footer" %>
  </body>
</html>

続いて、ログインしている場合はトップページではなくてダッシュボードを表示させたいと思います。

これはdeviseのカスタマイズによって可能です。

https://github.com/heartcombo/devise/wiki/How-To:-Define-a-different-root-route-for-logged-out-users

routes.rbを変更します。

Rails.application.routes.draw do
  devise_for :users
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
  scope controller: :static do
    get :terms
    get :privacy
  end

  # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
  # Can be used by load balancers and uptime monitors to verify that the app is live.
  get "up" => "rails/health#show", as: :rails_health_check

  # Defines the root path route ("/")
  authenticated :user do
    root "dashboard#show", as: :user_root
  end

  root "static#index"
end

新しくdashboard_controller.rbを作成します。

class DashboardController < ApplicationController
  def show
  end
end

対応するViewファイルを作成します。

<h1>Dashboard#show</h1>

これで、ログイン前はトップページが表示されて、ログイン後にダッシュボードが表示されるようになります。

細かいカスタマイズ

以下のようなカスタマイズをやっていきます。

config/initializers/devise.rbを開いて以下の2箇所を変更します。

  config.send_password_change_notification = true

パスワードを変更したらメール通知されます。

  config.password_length = 8..128

パスワードを8文字以上にできます。

続いて、letter_opener_webを導入して開発環境でメールを確認できようにします。

https://github.com/fgrehm/letter_opener_web

Gemfileを開いて、group :development doのブロック内に以下を追加してbundle installします。

# 省略

group :development do
  # 省略
  
  gem "letter_opener_web", "~> 2.0"
end

config/environments/development.rbを開いて、以下の設定を追加します。

require "active_support/core_ext/integer/time"

Rails.application.configure do
  # 省略

  # Set the default URL for ActionMailer in development.
  config.action_mailer.default_url_options = { host: "localhost", port: 3000 }
  config.action_mailer.delivery_method = :letter_opener_web

end

config/routes.rbを開いて、以下の設定を追加します。

Rails.application.routes.draw do
  if Rails.env.development?
    mount LetterOpenerWeb::Engine, at: "/letter_opener"
  end

  # 省略
end

これで、localhost:3000/letter_openerにアクセスすると以下のような画面でRailsアプリケーションから送信されたメールを確認することができます。

実際にメールを送信しなくても本文などを確認できるようになりました。

動作確認

bin/devでサーバーを起動、localhost:3000にアクセスして問題なく動作するか確認しておきましょう。

ここまでで問題なければコミットしましょう。

$ git commit -m "Add devise"

管理画面を作成

実際にアプリケーションを開発する際に、運用するための管理画面が必要になることがあります。

ここではusersテーブルのadminカラムがtrueの場合は管理者とします。

ここでは、Gemを使って管理者のみアクセスできる管理画面を作成します。

もちろんGemを使わずに管理画面を作成することもできますので、好みに合わせて調整してください。

実装の流れは以下のようになります。

  • administrateのインストール
  • お知らせ機能の実装

それではいきましょう。

administrateのインストール

$ bundle add administrate
$ rails generate administrate:install

localhost:3000/adminにアクセスすると管理画面が表示されます。

ただし、このままだと誰でも管理画面にアクセスできるため制限を追加します。

生成されたapp/controllers/admin/application_controller.rbを変更します。

# All Administrate controllers inherit from this
# `Administrate::ApplicationController`, making it the ideal place to put
# authentication logic or other before_actions.
#
# If you want to add pagination or other controller-level concerns,
# you're free to overwrite the RESTful controller actions.
module Admin
  class ApplicationController < Administrate::ApplicationController
    before_action :authenticate_admin

    def authenticate_admin
      redirect_to "/", alert: "Not authorized." unless user_signed_in? && current_user.admin?
    end

    # Override this value to specify the number of elements to display at a time
    # on index pages. Defaults to 20.
    # def records_per_page
    #   params[:per_page] || 20
    # end
  end
end

さらにセキュリティを強化するため、管理者以外がアクセスした場合は404になるようにします。

Rails.application.routes.draw do
  authenticate :user, lambda { |u| u.admin? } do
    namespace :admin do
      resources :users
      root to: "users#index"
    end
  end

 #省略
end

上記はdeviseのauthenticateを使って認証されたユーザーが管理者だった場合のみ、管理画面のルーティングが有効になるようにしています。これで管理者以外にはページが存在することを知られるリスクが減ります。

動作確認

新規登録したユーザーのadminカラムをtrueにして、管理者にしましょう。

$ rails c
irb(main):001> User.last.update(admin: true)

bin/devでサーバーを起動、localhost:3000/adminにアクセスして問題なく動作するか確認しておきましょう。

ここまでで問題なければコミットしましょう。

$ git commit -m "Add administrate"

administrateは色々カスタマイズできるので、必要に応じてドキュメントを確認してください。

お知らせ機能の実装

以下の要件で、お知らせ機能を実装します。

  • 管理者がお知らせを登録できる
  • ユーザーはお知らせ一覧を見ることができる
  • 未読のお知らせがある場合に、未読マークを表示する

それではいきましょう。

最初にお知らせ用のモデルを作成します。

$ rails g model Announcement kind published_at:datetime title description:text

ここでは、以下のようなカラムにしていますが、必要に応じて調整してください。

  • kind: お知らせの種類
  • published_at: 公開日
  • title: タイトル
  • description: 本文

マイグレーションを実行します。

$ rails db:migrate

Announcementモデルを変更します。

class Announcement < ApplicationRecord
  KINDS = %w[new fix update]

  after_initialize :set_defaults

  validates :kind, :published_at, :title, :description, presence: true
  validates :kind, inclusion: { in: KINDS }

  def set_defaults
    self.kind ||= KINDS.first
    self.published_at ||= Time.current
  end
end

必須バリデーションやkindとpublished_atに初期値を追加するようにしています。

管理者が登録できるようにadministrateのコマンドを実行します。

$ rails generate administrate:dashboard Announcement

routes.rbを以下を追加してください。

Rails.application.routes.draw do
  authenticate :user, lambda { |u| u.admin? } do
    namespace :admin do
      resources :announcements
      resources :users
      root to: "users#index"
    end
  end

  # 省略
end

ここまでで、管理画面からお知らせを作成できるようになります。

続いて、ユーザーがお知らせ一覧を見れるようにroutes.rbを以下を追加してください。

resources :announcements, only: [:index]

コントローラーを作成します。

class AnnouncementsController < ApplicationController
  before_action :mark_as_read, if: :user_signed_in?

  def index
    @announcements = Announcement.order(published_at: :desc)
  end

  private

  def mark_as_read
    current_user.update(announcements_read_at: Time.current)
  end
end

mark_as_readについてですが、ユーザーがログインしている場合は、お知らせ一覧にアクセスしたタイミングで全て既読にするようにしています。

対応するViewファイルを作成します。

<h1>News</h1>

<div class="card">
  <div class="card-body">
    <% @announcements.each_with_index do |announcement, index| %>
      <% if index != 0 %>
        <div class="row"><div class="col"><hr /></div></div>
      <% end %>

      <div class="row announcement" id="<%= dom_id(announcement) %>">
        <div class="col-sm-1 text-center">
          <%= link_to announcements_path(anchor: dom_id(announcement)) do %>
            <strong><%= announcement.published_at.strftime("%b %d") %></strong>
          <% end %>
        </div>
        <div class="col">
          <strong><%= announcement.title %></strong>
          <span class="badge bg-success"><%= announcement.kind.titleize %></span>
          <%= simple_format announcement.description %>
        </div>
      </div>
    <% end %>

    <% if @announcements.empty? %>
      <div>No announcements yet!</div>
    <% end %>
  </div>
</div>

ヘッダーにお知らせへのリンクを追加します。

省略

      <ul class="navbar-nav">
        <li class="nav-item"><%= link_to "News", announcements_path, class: "nav-link #{unread_announcements(current_user)}" %></li>

        <% if user_signed_in? %>

未読マークをつけるため、helperとscssを追加します。

module AnnouncementsHelper
  def unread_announcements(user)
    last_announcement = Announcement.order(published_at: :desc).first
    return if last_announcement.nil?

    if user.nil? || user.announcements_read_at.nil? || user.announcements_read_at < last_announcement.published_at
      "unread-announcements"
    end
  end
end
@import 'bootstrap/scss/bootstrap';
@import 'bootstrap-icons/font/bootstrap-icons';

.unread-announcements:before {
  -moz-border-radius: 50%;
  -webkit-border-radius: 50%;
  border-radius: 50%;
  -moz-background-clip: padding-box;
  -webkit-background-clip: padding-box;
  background-clip: padding-box;
  background: $red;
  content: '';
  display: inline-block;
  height: 8px;
  width: 8px;
  margin-right: 6px;
}

動作確認

管理画面からお知らせを作成して、ユーザーにどのように表示されるか確認しましょう。

未読のお知らせがあれば、以下のように赤い点がつくようになっています。

ここまでで問題なければコミットしましょう。

$ git commit -m "Add announcements"

さらなるカスタマイズ

ここまでの内容に加えて、さらにカスタマイズすることが可能です。

全てを書き出すと長くなってしまうので、あとはご自身の手で色々追加してください。

参考までに以下のようなものがあります。

  • 日本語化
  • スタイルの調整
  • Rspecインストール
  • Sidekiqインストール
  • デプロイ設定 など

ここでのポイントは一気にやらず、少しずつ確認しながら行うことです。

Github Actionsの設定

Github Actionsを設定ファイルを作成します。

ここでは、CIと呼ばれるテストなどを実行するようにします。

開発環境での設定

Linterや脆弱性をテストするためのGemがあるのでインストールしていきます。このあたりは好みがあると思うので調整してください。

https://github.com/presidentbeef/brakeman

https://github.com/Shopify/erb-lint

https://github.com/standardrb/standard

Gemfileのdevelopment、testのグループに以下を追加してbundle installします。

group :development, :test do
  # 省略

  gem "brakeman", require: false
  gem "erb_lint", require: false
  gem "standard", require: false
end

これらをGithub actionsで実行するためのymlファイルを作成します。

name: Tests

on:
  pull_request:
    branches:
      - '*'
  push:
    branches:
      - main

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:latest
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: password
        ports: ['5432:5432']
      redis:
        image: redis
        ports: ['6379:6379']
        options: --entrypoint redis-server

    steps:
      - uses: actions/checkout@v4

      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          bundler: default
          bundler-cache: true

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version-file: .node-version
          cache: yarn

      - name: Install dependencies
        run: |
          sudo apt-get update && sudo apt-get install -y -qq libvips
          yarn install

      - name: Standardrb Check
        run: bundle exec standardrb

      - name: ERB Lint
        run: bundle exec erblint --lint-all

      - name: Brakeman Check
        run: bundle exec brakeman

また、dependabotの通知設定も追加します。

version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
  - package-ecosystem: "bundler"
    directory: "/"
    schedule:
      interval: "weekly"

ここまでの内容をコミットして、GithubにプッシュすればGithub Actionsが実行されるはずです。

テストに失敗した場合は、該当箇所を修正して再度プッシュしましょう。

Tempalte Repositoryの設定

Template Repositoryの設定を行いましょう。

設定はリポジトリのSettingsから簡単にできます。

以下の「Template repository」にチェックを入れるだけです。

そうするとリポジトリに以下のようなバッチが付きます。

これでTemplate Repositoryが作成できました。

Template Repositoryの使い方

Template Repositoryを使う方法は2つあります。

1つ目は、Template Repositoryのメニューから使うことができます。

「Use this template」をクリックすることで、元の内容を新しリポジトリを作成できます。

2つ目は、新しくリポジトリを作成する際に選択できます。

テンプレートから作成されたリポジトリは以下のようにどのテンプレートから作成されたか分かるようになっています。

まとめ

Railsのboilerplateを作成して、GithubのTemplate Repositoryにする方法を紹介しました。

これで毎回rails newした後に色々設定する手間が省けます。

  • サクッと何かの検証をしたいときとき
  • 新しくアプリケーションを作りたいとき
  • 自分のスキルをアピールするポートフォリオとして使いたいとき

など活用方法があると思います。

今回作成したboilerplateはGithubで公開しています。

今後もアップデートしていこうと思います。

この記事を参考にして、自分のよく使う機能をセットアップしたboilerplateを作ってみてください。

スポンサーリンク

  • このエントリーをはてなブックマークに追加