🐈画面上で猫が邪魔してくださる Rails gem を作って世界を平和にする


こんにちは、とまだです。

**猫ってかわいいですよね 🐈**

私は猫を飼っています。

猫を飼っていると、目の前に猫が出てきて作業の邪魔をされることがありますが、それはそれでご褒美なのです。

ただ、猫アレルギーの人や、猫を飼うことができない環境にいる人にとっては、猫と触れ合う機会がなかなかありません。

そこで私は考えました。

> **誰もが猫に邪魔される幸せを味わえる世界を作りたい！**

この Gem は、そんな世界征服を目指す Ruby on Rails アプリ用の Gem です。

何を言っているか分からないかもしれませんが、**こういうこと**です 👇

![画面収録-2024-10-04-19.45.20.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364501/3ea1765e-93f2-9c3c-a9ec-26572e9bc655.gif)

これであなたの作業も捗ること間違いなしですね！！！！

休日に暇すぎてこの gem をご存知 [RubyGems.org](https://rubygems.org/) に公開しましたので、その紹介をさせていただきます。

https://rubygems.org/gems/catpop

:::note info
大真面目にふざけながら、Ruby on Rails の gem の作り方を学ぶために作成したものです。
どうかご了承ください。
:::

## 作った gem の概要

今回作成した gem の名前は **catpop** です。
（"pop" は突然現れるという意味らしいです）

この gem を Rails アプリに組み込むと、**画面上にランダムな位置で猫の絵文字が表示され、数秒後に消える**という、非常に役に立たない機能が追加されます。

いつか、世界中の Rails アプリが猫でいっぱいになる日が来るかもしれませんね 🐈🐈🐈🐈🐈

## gem の機能

catpop gem の主な機能は以下の通りです。

- Rails アプリの画面にランダムな位置で猫の絵文字（🐱, 🐈, 🐈‍⬛）を表示
- 表示される猫の大きさもランダム
- 猫は 3 秒間表示された後、自動的に消える
- 1 秒ごとに新しい猫が表示される

つまり、Rails アプリを開いていると、画面上に猫が次々と現れては消えてくれます。

使ってみると分かるのですが、**非常に気が散って作業が進まない**という問題があります。

## gem の作り方

それでは、catpop gem の作り方を順を追って説明していきます。

### gem の雛形を作成

まずは、gem の雛形を作成します。以下のコマンドを実行してください。

```sh
bundle gem catpop
```

このコマンドを実行すると、`catpop` というディレクトリが作成され、その中に gem の基本的なファイル構造が生成されます。

### ファイル構成

catpop gem の主要なファイル構成は以下のようになっています。

```sh
catpop/
├── lib/
│   ├── assets/
│   │   └── javascripts/
│   │       └── catpop.js  # 猫を表示する JavaScript ファイル
│   ├── catpop/
│   │   ├── popup_helper.rb  # ヘルパーメソッドを定義
│   │   ├── railtie.rb  # Rails アプリケーションに組み込むための設定
│   │   └── version.rb  # バージョン情報
│   └── catpop.rb  # モジュールの定義
└── catpop.gemspec  # gem の仕様を定義
```

今回、gem とは言いつつも主要なのは JavaScript ファイルです。このファイルが画面に猫を表示するためのコードを記述します。

### 主要なファイルの中身

それでは、各ファイルの中身を見ていきましょう。

#### lib/catpop.rb

このファイルは gem のメインファイルです。必要なファイルを require し、モジュールを定義します。

```ruby:lib/catpop.rb
# frozen_string_literal: true
require "catpop/version"
require "catpop/railtie"
require "catpop/popup_helper"

module Catpop
end
```

#### lib/catpop/railtie.rb

このファイルは、catpop gem を Rails アプリケーションに統合するための設定を行います。

```ruby:lib/catpop/railtie.rb
require "catpop"
require "rails"

module Catpop
  class Railtie < Rails::Railtie
    initializer "catpop.view_helpers" do
      ActiveSupport.on_load(:action_view) do
        include Catpop::PopupHelper
      end
    end

    initializer "catpop.assets" do |app|
      app.config.assets.paths << root.join('lib', 'assets', 'javascripts')
      app.config.assets.precompile += %w(catpop.js)
    end
  end
end
```

上記のポイントは、gem のディレクトリ内で JavaScript ファイルを管理するための設定です。

このファイルでは以下のことを行っています。

- `PopupHelper` を ActionView に include して、ビューで使えるようにする
- JavaScript ファイルのパスを Rails のアセットパイプラインに追加
- `catpop.js` をプリコンパイル対象に追加

#### lib/catpop/popup_helper.rb

このファイルでは、ビューで使用するヘルパーメソッドを定義します。

Rails では「ヘルパーメソッド」という機能を使って、ビューで使えるメソッドを定義できます。

みなさんも `javascript_include_tag` や `stylesheet_link_tag` などのヘルパーメソッドを使ったことがあるかと思います。

今回も同じノリで、`capop_script_tag` というメソッドを定義しています。

```ruby:lib/catpop/popup_helper.rb
module Catpop
  module PopupHelper
    def catpop_script_tag
      javascript_include_tag 'catpop.js'
    end
  end
end
```

`catpop_script_tag` メソッドは、`catpop.js` を読み込むための `script` タグを生成してくれます。

#### lib/assets/javascripts/catpop.js

このファイルが、実際に猫を表示する JavaScript のコードです。

いわば、**猫に邪魔される**ためのコアとなる部分です。

```javascript:lib/assets/javascripts/catpop.js
document.addEventListener('DOMContentLoaded', function() {
  const SHOWING_TIME = 3000;
  const INTERVAL_TIME = 1000;

  function showCat() {
    const emojis = ["🐱", "🐈", "🐈‍⬛"];
    const emoji = emojis[Math.floor(Math.random() * emojis.length)];
    const catSize = Math.floor(Math.random() * 10) + 1;

    const catDiv = document.createElement('div');
    catDiv.className = 'catpop';
    catDiv.style.position = 'fixed';
    catDiv.style.top = Math.floor(Math.random() * 90) + 'vh';
    catDiv.style.left = Math.floor(Math.random() * 90) + 'vw';
    catDiv.style.fontSize = catSize + 'em';
    catDiv.innerText = emoji;

    document.body.appendChild(catDiv);

    setTimeout(() => catDiv.remove(), SHOWING_TIME);
  }

  showCat();
  setInterval(showCat, INTERVAL_TIME);
});
```

このスクリプトでは以下のことを行っています。

- ランダムな猫の絵文字を選択
- ランダムなサイズと位置を決定
- 猫を表示する `div` 要素を作成し、ページに追加
- 3 秒後に猫を消す
- 1 秒ごとに新しい猫を表示

これで、猫が画面に現れては消える機能が実装されました。

では、次に gem のビルドとリリース方法について説明します。

### gem のビルドとリリース

gem のコードが完成したら、以下のコマンドで gem をビルドします。

```sh
gem build catpop.gemspec
```

これで、デフォルトであれば`catpop-0.1.0.gem` というファイルが生成されます。

（バージョン情報は `version.rb` で管理された数字が使われます）

ただ、これだけだと他の人が使えないので、RubyGems.org にリリースする必要があります。

gem を RubyGems.org にリリースするには、以下のコマンドを実行します。

```sh
gem signin # 事前に RubyGems.org に登録＆各種設定が必要
gem push catpop-0.1.0.gem
```

これで、catpop gem が RubyGems.org で公開され、誰でも使えるようになりました！

そう、猫好きのあなたも、猫好きでないあなたも、誰でも猫に邪魔される幸せを味わえるのです 🐈

## Rails アプリでの使い方

では、作成した catpop gem を Rails アプリで使ってみましょう。

### Rails アプリの作成

まずは、適当なディレクトリで新しい Rails アプリを作成します。

もちろん、既に Rails アプリがある場合はそのアプリに組み込んでも構いません！！！！！！

```sh
rails new sample-app
cd sample-app
```

また、scalfold などで適当なコントローラやビューを作成しておくと、猫が邪魔してくれる機会が増えるかもしれません。

```sh
rails g scaffold Post title:string content:text
rails db:migrate
```

では、いよいよ catpop gem を使ってみましょう！

### Gemfile に追加

まず、Rails アプリの `Gemfile` に以下の行を追加します。

```ruby:Gemfile
gem "catpop"
```

そして、以下のコマンドを実行して gem をインストールします：

```sh
bundle install
```

### アプリケーションレイアウトに JavaScript を追加

次に、`app/views/layouts/application.html.erb` ファイルの `<head>` タグ内に以下の行を追加します。

```erb:app/views/layouts/application.html.erb
<%= catpop_script_tag %>
```

これは、gem のヘルパーメソッドを使って、`catpop.js` を読み込むための `script` タグを生成しています。

これで準備完了です！

Rails サーバーを起動して、ブラウザでアプリを開くと、画面上にランダムに猫が現れては消えていく様子が見られるはずです。

![スクリーンショット 2024-10-04 19.58.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364501/6b104261-3d8f-acce-6795-56a1f7bcec96.png)

## まとめ

いかがでしたか？今回は、Rails アプリの画面に猫を出現させる gem を作成しました。

この gem を使えば、リモートワーク中でも「猫に邪魔される」という幸せな体験ができますね 🐈‍⬛

実用性は全くありませんが、gem の作り方や Rails アプリへの統合方法を学ぶ良い練習になったのではないでしょうか。

また、この gem をベースに、もっと面白い機能を追加してみるのも良いかもしれません。

- 猫の種類を増やす
- 猫が鳴く音を追加する
- 猫をクリックすると消える機能を追加する

などなど、アイデア次第で様々な拡張ができそうです。

プログラミングは、こういった「遊び」の要素を取り入れることで、より楽しく学べると思います。ぜひ、自分なりのアイデアを形にしてみてください！