はじめに
今回、新しいプロジェクトで、Ruby on Rails 7、React.jsによるフロントエンド開発に着手することになったので、開発手順の備忘録記載。
Railsは1年半ぶりくらいに触ることになり、いつの間にかVersion7になっていたことにビックリ。忘れている部分も多い。また、Reactは初めてなので、TypeScriptとともに0から学びながら開発していく。
jsbundling-railsを使ったTypeScriptのセットアップ方法、Reactコンポーネントの作成と組み込み方法、そしてRailsのERBファイルでのコンポーネントの呼び出し方法について記載。
全体構成
RailsとReactの組み合わせによるアプリケーションの全体構成は、以下
- View (Actionごと): Reactコンポーネントを使用して、各画面ごとに独立したtsxファイルを作成し、RailsのViewがそれを呼び出す。
- Controller (Ruby): 各Actionに対応するRailsのコントローラーがあり、必要なデータを処理し、Reactコンポーネントに渡すためのデータを準備する。
- Model: データベースとやり取りを行い、ビジネスロジックを実行。
環境構築
JSアセットパイプライン:jsbundling-rails + esbuild の導入
Rails 7では、JavaScript (JS) と Cascading Style Sheets (CSS) のバンドル方法が変更された。従来のWebpackerに代わって、jsbundling-railsとcssbundling-railsが導入され、バンドル方法がよりシンプルかつ直感的になった。
jsbundling-railsは、JavaScriptのバンドルに関する新しいアプローチで、esbuildやrollup.js、webpackなど、複数のバンドラーをサポートしている。
esbuildは極めて高速なJavaScriptバンドラーおよびミニファイヤーで、大規模なJavaScriptコードベースでも素早くバンドルすることができる。
Railsプロジェクトにjsbundling-railsとesbuildを導入するには、以下の手順を実行。
jsbundling-railsをGemfileに追加してインストール:
# Gemfile
gem 'jsbundling-rails'その後、bundle installを実行。
esbuildをセットアップ:
bin/rails javascript:install:esbuildこれにより、esbuildがセットアップされ、app/javascriptディレクトリ内で利用可能になる。
TypeScriptのセットアップ
RailsプロジェクトにTypeScriptを導入するためには、まず以下のコマンドを実行して必要なパッケージをインストールする。
yarn add typescript @types/react @types/react-dom @babel/preset-typescriptこのコマンドにより、TypeScriptとそのReact用の型定義、そしてBabelのTypeScriptプリセットがプロジェクトに追加される。
RailsでのPathとアクションの設定
まず、Railsで画面を描画するためのPathを作成する
Dockerコマンドを利用したコントローラーとアクションの自動生成
下記コマンドで新しいコントローラーとアクションを自動生成する。
$ docker-compose run --rm app bin/rails generate controller [コントローラー名] [アクション名]例えば、「Users」というコントローラーに「show」というアクションを追加したい場合、次のようにコマンドを実行する。
$ docker-compose run --rm app bin/rails generate controller Users show
Creating app_run ... done
invoke rails
create app/controllers/users_controller.rb
route get 'users/show'
invoke erb
create app/views/users
create app/views/users/show.html.erb
invoke test_unit
create test/controllers/users_controller_test.rb
invoke helper
create app/helpers/users_helper.rb
invoke test_unit
invoke assets
invoke scss
create app/assets/stylesheets/users.scssこれにより、app/controllers/users_controller.rbにshowメソッドが追加され、関連するViewファイルがapp/views/usersディレクトリに作成される。
このとき、自動的にtestファイルやhelperファイルも作成される。もし不要であれば、削除する。
Routingの設定
Railsにおいて、RoutingはURLとコントローラーのアクションを結びつける役割を持つ。config/routes.rbファイルを編集することで、ルーティングを設定できる。
以下は、UsersControllerのshowアクションに対応するルートを定義する例。ここで:idはパラメータとして、ユーザーのIDを動的に受け取ることを示している。
Rails.application.routes.draw do
get 'users/:id', to: 'users#show'
endapp/controllers/users_controller.rb にshowアクションを定義する。このアクションは、対応するビューをレンダリングするために使用される。
class UsersController < ApplicationController
def show
# ここに必要なロジックを追加
end
endRailsの命名規則:snake_case
スネークケース (snake_case)
- ファイル名、ディレクトリ名、変数名、関数名(またはメソッド名)で使用
- 単語はアンダースコアで区切られ、全て小文字で記述(例:
user_profile.rb,calculate_age)
コントローラー名やモデル名などは、単数形や複数形の使用がルールによって定義されており、それらは自動的に関連するファイル名やクラス名に反映される。例えば、UsersControllerクラスはusers_controller.rbに、Userモデルはuser.rbに対応する。
TypeScriptで画面作成
Reactコンポーネントを作成
app/javascript/components/User.tsxファイルを作成し、以下のように記述する。
Reactでは、UIの一部を表すコンポーネントを作成するために関数またはクラスを使用する。この場合、Userは関数コンポーネントとして定義されており、特定のユーザーの名前(name)と年齢(age)を表示するためのもの。
関数コンポーネントは、propsとして受け取ったデータをもとにReactのElementを返す。このUserコンポーネントはUserProps型のpropsを引数に取り、nameとageプロパティを使ってUIを構築し、それを返している。
ここでのUser変数は、Reactのコンテキストでは「コンポーネント」として扱われる。これを他のReactコンポーネントから<User name="John Doe" age={30} />のように使用することで、そのユーザー情報を表示することができる。
文字列などのプリミティブな値を直接渡す場合は引用符("")を使用。
JavaScriptの式や変数の値を渡す場合は、波括弧{}を使用してその式を囲む。
// app/javascript/components/User.tsx
import React from 'react';
type UserProps = {
name: string;
age: number;
};
// React.FCを使用せずにコンポーネントを定義
const User = ({ name, age }: UserProps) => {
return (
<div>
<h1>{name}</h1>
<p>{age} years old</p>
</div>
);
};
export default User;TypeScriptとDartの共通点と違いに関する記事は、こちら。
ファイル名とコンポーネント名(const名)、export名に関して
ファイル内で記載するコンポーネント名(const)とexport名は一致していなければならない。
Show.tsx ファイル内で const Show1 と定義し、export default Show2 とする場合、これは構文的に正しくないため、コンパイルエラーまたは実行時エラーになる。export default でエクスポートする値は、そのファイル内で定義された変数、関数、クラスなどの実際のエンティティでなければならない。
Show.tsx ファイル内で const Show1 と定義し、export default Show1 とする場合、これは構文的に正しいため、実行できる。
ただし、可読性・保守性の観点からファイル名とコンポーネント名(const名)を一致させることが推奨されている。
つまり、結論としては、ファイル名とコンポーネント名(const名)、export名はすべて一致させた方が良い。ちなみに、このコンポーネント名をどのような名前で使用するかもインポート先のファイル名で設定できる。
TypeScriptの命名規則:PascalCase・camelCase
パスカルケース(PascalCase)
- すべての単語の最初の文字は大文字で始まる。例:
UserProfile,UserInterface。 - コンポーネントやクラスを定義するファイル名
- クラス名やインターフェイス名、コンポーネント名
キャメルケース(camelCase)
- 最初の単語は小文字で始まり、後続の単語の最初の文字は大文字で始まる。例:
userName,calculateAge。 - ユーティリティファイルや単一関数を定義するファイル名
- 変数名や関数名
Userページの作成(ファイルパスと命名)
app/javascript/controllers/users/Show.tsxファイルを作成し、以下のように記述する。
ファイルのパスと命名:
app/javascript/controllers/users/Show.tsxこの構造では、app/javascript/controllers/ ディレクトリの下にバックエンドのコントローラー名に対応するディレクトリを作成し(この場合は users/)、その中に対応するアクションメソッド名に基づいた .tsx ファイルを作成している。
ここでは、UsersController の show アクションに対応して Show.tsx というファイルを作成。
UserコンポーネントをUserという名前でインポートし、固定のデータを渡してユーザー情報を表示。
// app/javascript/controllers/users/Show.tsx
import React from 'react';
// Userコンポーネントのインポートパス。適宜調整
import User from '../components/User';
const Show = () => {
return (
<div>
<h1>User Information</h1>
<User name="John Doe" age={30} />
</div>
);
};
export default Show;ちなみに、下記は正しく実行される。
コンポーネントファイルのUser.tsx で User1 コンポーネントを定義し、デフォルトエクスポートし、別のファイルでこのコンポーネントを import User3 from '../components/User'; としてインポートしている。ただし、基本的には可読性の観点から、すべてUserで統一した方が良い。
// app/javascript/components/User.tsx
import React from 'react';
type UserProps = {
name: string;
age: number;
};
// React.FCを使用せずにコンポーネントを定義
const User1 = ({ name, age }: UserProps) => {
return (
<div>
<h1>{name}</h1>
<p>{age} years old</p>
</div>
);
};
export default User1;
// app/javascript/controllers/users/Show.tsx
import React from 'react';
// Userコンポーネントのインポートパス。適宜調整
import User3 from '../components/User';
const Show = () => {
return (
<div>
<h1>User Information</h1>
<User3 name="John Doe" age={30} />
</div>
);
};
export default Show;RailsのViewでReactコンポーネントを呼び出す
app/views/users/show.html.erb ビューファイルに javascript_include_tag を使用して、Show.tsx コンポーネントを含むJavaScriptファイルを含める。
<%= javascript_include_tag "controllers/users/Show", defer: true %>defer: trueオプションを使用することで、スクリプトがHTMLの解析後に実行されるようになり、ページの読み込み速度が向上する。
動作確認
この設定により、Railsのルーティングとビューが正しく設定されている場合、ブラウザで http://localhost:3000/users/show (または適切なポート番号)にアクセスすると、Show.tsx に定義されたReactコンポーネントによってレンダリングされたページが表示される。
このページは、”User Information” という見出しとともに、”John Doe” の名前と 30 歳という年齢が表示される。
【Rails7】動的なカスタムエラー画面を作成し、共通デザインを適用する 方法に関しては、こちら。





コメント