Rails + Next.jsでWebアプリを作る方法（初歩）

## はじめに

Yasuと申します．私は2024年10月より，内定直結型エンジニア学習プログラム「アプレンティス」に参加しています．

https://apprentice.jp/lp

現在，オリジナルプロダクトの開発をスタートしています．このプロダクトは Ruby on Rails と Next.js を連携させて開発する予定です．本記事では初学者向けに，この2つを連携させてデータを表示するまでの流れを解説します．

## 前提条件
- rbenvを用いて，Rubyをインストール済みであること
- nvmを用いて，Node.jsをインストール済みであること

## ステップ1: RailsでバックエンドAPIを構築する
### 1.1 プロジェクトの作成
まず，プロジェクトのフォルダを作成します．
``` bash 
mkdir sample-app
cd sample-app
```
プロジェクトで使用するRubyのバージョン（今回は3.3.6）を指定します．
``` bash
rbenv local 3.3.6
```
Gemファイルを初期化し，Rails（今回は7.2.2.1）をインストールします．
``` bash 
bundle init
```

`Gemfile`に次の記述を追加します．
``` rb
gem "rails", "7.2.2.1"
```

以下のコマンドでGemをインストールします．．
``` bash
bundle config set path '.bundle' # プロジェクト内の .bundle にGemをインストール
bundle install
```

RailsプロジェクトをAPIモードで作成します．

``` bash
bundle exec rails new backend-app --api
cd backend-app
```
### 1.2 モデルとマイグレーションの作成
シンプルな記事（Article）データを管理するモデルを作成します．

``` bash
bundle exec rails generate model Article title:string content:text
bundle exec rails db:migrate
```

### 1.3 サンプルデータを追加
`db/seeds.rb`に以下を記述してサンプルデータを作成します．

``` ruby
Article.create(title: 'サンプル記事1', content: 'これはサンプルコンテンツ1です．')
Article.create(title: 'サンプル記事2', content: 'これはサンプルコンテンツ2です．')
```
以下のコマンドを実行してデータを登録します．

``` bash
bundle exec rails db:seed
```

### 1.4 APIエンドポイントの作成
RailsでAPIを提供するため，ルーティングとコントローラーを設定します．

`config/routes.rb` を以下のように編集します．
``` ruby
Rails.application.routes.draw do
  resources :articles, only: [:index]
end
```

次に，`app/controllers/articles_controller.rb` を作成し，以下の内容を記述します．

``` ruby
class ArticlesController < ApplicationController
  def index
    @articles = Article.all
    render json: @articles
  end
end
```

### 1.5 動作確認
Railsサーバーを起動し，ブラウザでAPIの動作を確認します．

``` bash
bundle exec rails server -p 3001
```
`http://localhost:3001/articles` にアクセスすると，以下のようなJSONが返ってくるはずです．

``` json
[
  { "id": 1, "title": "サンプル記事1", "content": "これはサンプルコンテンツ1です．" },
  { "id": 2, "title": "サンプル記事2", "content": "これはサンプルコンテンツ2です．" }
]
```
Railsサーバーは `Ctrl + C` で一旦終了させます．

## ステップ2: Next.jsでフロントエンドを構築する
### 2.1 プロジェクトの作成
Next.jsプロジェクトを作成します（ターミナルを新しいタブで開くことをおすすめします）．

``` bash
cd sample-app # sample-appのディレクトリに移動する
npx create-next-app@15.1.2 frontend-app 
cd frontend-app
```
インストール中の選択肢はとりあえずデフォルトでOKです．

### 2.2 必要なライブラリのインストール
APIリクエストを行うためにaxiosをインストールします．

``` bash
npm install axios
```

### 2.3 記事データを表示するページの作成
Next.jsの `pages/index.js` を編集して，Rails APIから記事データを取得し表示します．

``` javascript
import { useEffect, useState } from 'react';
import axios from 'axios';

export default function Home() {
  const [articles, setArticles] = useState([]);

  // APIからデータを取得
  useEffect(() => {
    axios.get('http://localhost:3001/articles') // RailsサーバーのURL
      .then(response => {
        setArticles(response.data); // データをステートに保存
      })
      .catch(error => {
        console.error('Error fetching articles:', error);
      });
  }, []);

  return (
    <div>
      <h1>記事一覧</h1>
      <ul>
        {articles.map(article => (
          <li key={article.id}>
            <h2>{article.title}</h2>
            <p>{article.content}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}
```

### 2.4 Next.jsアプリの起動
下のコマンドでNext.jsサーバーを起動します．

``` bash
npm run dev
```
フロントエンドの開発サーバーが起動し， `localhost:3000` で表示されれば成功です．（まだバックエンドとの連携はうまくできていません）
Next.jsサーバーは `Ctrl + C` で一旦終了させます．

## ステップ3: RailsとNext.jsを連携させる
### 3.1 CORSの設定を行う

CORS（Cross-Origin Resource Sharing）は，異なるオリジン間でリソースを共有する際のセキュリティ機能です．例えば，Railsサーバー `localhost:3001` から提供されるAPIを，Next.jsアプリ `localhost:3000` が利用する場合，オリジンが異なるためブラウザがリクエストを制限する可能性があります．

これを解決するために，RailsでCORSの設定を行います．

`backend-app/Gemfile` 内の以下の行のコメントアウトを解除します．
``` ruby 
gem 'rack-cors' # この行のコメントアウトを外す(# を削除する)
```

`sample-app/backend-app`で，以下のコマンドでGemをインストールします．

``` bash
bundle install
```

次に，`config/initializers/cors.rb` を以下のように編集します．

``` ruby
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins "localhost:3000" # Next.jsを動作させているアドレス

    resource "*",
      headers: :any,
      methods: [ :get ] # 今回はgetのみ
  end
end
```
### 動作確認

それぞれのサーバーを起動します．

バックエンド:

``` bash
bundle exec rails server -p 3001
```
フロントエンド:

``` bash
npm run dev
```

ブラウザで `localhost:3000` にアクセスし，RailsのAPIから取得した記事一覧が表示されれば成功です．

## まとめ
今回の記事では，RailsとNext.jsを連携させてデータを表示する基本的な流れを解説しました．
RailsでAPIを構築し，Next.jsを使ってそのデータを表示するまでの一連の手順を通じて，バックエンドとフロントエンドを連携させる基礎を学ぶことができたと思います．

しかし，Next.jsやReactの使い方についてはまだ十分に触れておらず，デザインやインタラクティブな機能の実装は今後の課題です．これからReactやNext.jsの学習を進めることで，より充実したアプリケーションを開発できるようになりたいと考えています．