stimulus.jsを利用したrails開発フロー。

# Stimulus.js を利用した Rails 開発フロー

Rails で JavaScript を利用するのに滅茶苦茶苦労したので、整理の為に記事を作成してみました。

Rails でJavaScriptを使用するにあたって方法が幾つかありますが、そのうちの一つに **Stimulus.js** というフレームワークがあります。

railsにおけるJavascriptのファイル構造に焦点を当てつつ、`Stimulus`について解説していこうと思います。

なお、本記事では`Stimulus`の基本構文は控えめに解説し、全体像を掴む事に主眼を置いた記事になること了承の上一読ください。

⚠️**この記事はプログラミング初心者が書いている記事になる事ご留意ください。もし記事の内容に間違いなどがあれば、指摘いただけますと幸いです。**

## Stimulus って何だ？

冒頭でも述べましたが、`Stimulus`は

**JavaScript フレームワーク** です。

この認識が最初できておらず、厄介者扱いしていました。

フレームワークの性質として深掘りすると、

**「HTMLを主体とした、控えめなフレームワーク」**

との事です。主流なReactとVueとは異なり、小規模な機能追加に適しています。

## ディレクトリ構成

`Rails new`を実行した時のディレクトリ構成を見てみます。
それぞれのファイルには、以下の役割があります：

```
javascript/
├── application.js          # JS の全ての始まりとなるファイル
└── controllers
    ├── application.js      # 初期設定
    ├── index.js            # コントローラー登録
    └── hello_controller.js # サンプル
```

初心者目線の大前提として、
**`javascript/application.js` にコードを書けば、とりあえず動く**
という認識が必要だと思いました。

勿論、だからと言ってここに全ての JS を書いていくと滅茶苦茶なコードになり管理が煩雑になります。

その為、より JS を使いやすくするフレームワークとして、`Stimulus` を利用していくというわけです。

## Stimulus のざっくりフロー

1. `javascript/application.js` がエントリーポイントになる

2. `controller` ディレクトリの中に個別の`JSファイル`を作成

3. `controller`の中から、必要な時に必要な`JSファイル`を呼び出して使う

大体こんな感じです。

それぞれについて詳しく見ていきます。

### 1. javascript/application.js がエントリーポイントになる

```
javascript/
├── application.js 👈 JS の全ての始まりとなるファイル
└── controllers
    ├── application.js     
    ├── index.js           
    └── hello_controller.js 
```

このファイルは JavaScript のすべての始まりです。

ブラウザがこのファイルを最初に読み込み、ここから他のモジュールを必要に応じて呼び出します。

アプリケーションが開始されるとき、必要な初期設定やグローバルな振る舞いをここで定義します。

```javascript
// application.js
import "@hotwired/turbo-rails"
import "./controllers"  // Stimulus コントローラーを読み込む

// グローバル設定
document.addEventListener("turbo:load", () => {
  console.log("ページが読み込まれました")
})
```

上記のコードでは"ページが読み込まれました"　が全てのページのコンソールで確認できます。

このことから、このファイルがJSを扱う時に必ず読み込まれる、全ての始まりのファイルであることが確認できます。

### 2.controllers ディレクトリに機能ごとの JS ファイルを作成する

```
javascript/
├── application.js 
└── controllers       👈 ここに機能ごとのjsを追加してく
    ├── application.js     
    ├── index.js           
    └── hello_controller.js 
```

各コントローラーファイルは、特定の機能に対して適用させたいJSのコードを書いていきます。

例えば、

- google mapを扱うコントローラー
- ドラッグ&ドロップ機能を実装するコントローラー
- モーダルを表示させるコントローラー

など、機能ごとに分けて記述していきます。

今回はボタンをクリックした時にモーダルを表示させるJavaScriptを実装してみましょう。

ターミナルで以下のコマンドを実行します。

```
rails generate stimulus modal
```

すると、controllersディレクトリにファイルが追加されます。

```
javascript/
├── application.js 
└── controllers       
    ├── application.js     
    ├── index.js           
    └── hello_controller.js 
    └── modal.js      👈 今回追加したmodal.js
```

modal.jsに処理を追加していきます（コードの解説は割愛）。

```javascript
// controllers/modal_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["dialog"]
  
  open() {
    this.dialogTarget.classList.remove("hidden")
  }
  
  close() {
    this.dialogTarget.classList.add("hidden")
  }
}
```

特に以下のコードに注目です。

```javascript
  static targets = ["dialog"]　// ここでHTML要素に接続する！
```

HTMLとどのように接続して、jsを適用させていくのかは次で解説します。

### 3.必要な時に必要な機能を呼び出す
Stimulusでは、HTMLとJavaScriptコントローラーを接続するために特別な属性を使います。

それが、

- **data-controller** = "名前"
- **data-[コントローラー名]-target** = "ターゲット名"
- **data-action** = "イベント->コントローラー名#メソッド"

これら三つの**data属性**です。

具体例を示します。

以下のviewに、モーダル表示の機能を盛り込みたいと思います。

```html
<div data-controller="modal"> 👈 適用
  <div data-modal-target="dialog" class="hidden"> 👈 接続
    モーダルの内容
  </div>
  <button data-action="click->modal#open">開く</button> 👈 呼び出し
  <button data-action="click->modal#close">閉じる</button> 👈 呼び出し
</div>
```
**⚠️重要なポイント⚠️**

1. **data-controller="modal"**
  このHTML要素にmodalコントローラーを**適用**
2. **data-modal-target="dialog"**
  modalコントローラー内のtarget要素を指定して**接続**

3. **data-action="click->modal#open"**
   **data-action="click->modal#close"**
  クリックした時にmodalコントローラー内の**open（close）メソッドを呼び出す**

この３ステップでHTMLとJavaScriptが宣言的に結びつき、コードの中の指定した処理が実行されます。

このように機能を追加したいhtml要素にdata属性を付与することで、ボタンを押した時にモーダルを開いたり閉じたりできるようになります。

必要な時に必要なコントローラーと接続することで、HTML主体の控えめなフレームワークとして機能していることがわかるかと思います。

## まとめ

`Stimulus`は開発を楽にしてくれるフレームワークである、という認識が第一歩かなと思いました。

それをより実感したのは、`Stimulus`の適用範囲外のjsコードを実装していた時で、`target`のありがたみにその時気づくことができました。

これは何も`Stimulus`に対してだけでなく、当たり前にフレームワーク全般に言えることだと思いました。

今回初めてフロント周りの実装をするにあたって苦労したポイントの一つでしたが、これからうまく付き合っていきたいと思います。