Ruby on Railsでフロントエンドを扱うための基礎と具体的な実装方法
はじめに
皆さんはRuby on Railsというと、サーバーサイドのフレームワークというイメージを持っているかもしれません。 実はRailsにはフロントエンドの開発を効率化するための仕組みも数多く用意されています。 テンプレートエンジンやアセット管理など、初心者でも学びやすいポイントが豊富です。 うまく活用できれば、デザインを変更したりJavaScriptを組み込んだりする作業をスムーズに行うことが可能です。 この記事では、Railsでフロントエンドを扱うときに押さえるべき基本や、具体的な実装方法を解説します。
この記事を読むとわかること
- Railsプロジェクトでフロントエンドを管理する仕組み
- JavaScriptやCSSの取り扱い方
- ReactやVue.jsなどのフロントエンドフレームワークをRailsに組み込む手順
- テンプレートとルーティングを連携させる際のポイント
- 実務でも応用できる具体的な実装例
フロントエンドをRailsで扱う基本的な考え方
Railsにおけるフロントエンドの位置づけ
Railsはサーバーサイドの処理が中心と思われがちですが、実際にはビューと呼ばれるテンプレートを通してHTMLやCSSを生成し、JavaScriptの組み込みも簡単に行えます。
このテンプレートはERB形式のファイル(.html.erb
)として用意されており、RubyのコードをHTMLに埋め込む形で動的にページを生成します。
サーバーサイドでデータを処理し、その結果をテンプレートに渡すことで、ユーザーがアクセスするたびに必要な情報をページに反映する構造になっています。
一方で、フロントエンドでしか表現できないアニメーションや動的操作も増えています。 Railsではこうした動きを実現するために、JavaScriptファイルを使ってHTML要素を操作したり、Ajax通信で非同期にデータをやり取りすることが可能です。 つまり、サーバーサイドとフロントエンドの両面を一貫して管理できる点がRailsの強みと言えるでしょう。
アセットパイプラインとWebpackerの仕組み
Railsのアセットパイプラインは、CSSやJavaScript、画像ファイルといったフロントエンド資産を一元管理する機能です。 この機能を使うと、複数のCSSやJavaScriptファイルをまとめて読み込んだり、圧縮してページの表示速度を高めることができます。 従来はSprocketsという仕組みで管理されていましたが、よりリッチなフロントエンド開発を行う場合はWebpackなどが使われるケースが増えています。
Railsには標準でWebpackerという仕組みが存在し、JavaScriptファイルをモジュールとして扱えるメリットがあります。
たとえばapp/javascript
ディレクトリ内でファイルを管理し、エントリーポイントを指定するだけで複雑なJavaScriptコードを整理可能です。
こうした統合的な管理のおかげで、ビューとスクリプトをスムーズに連携させやすくなります。
JavaScriptとRailsの組み合わせ方
RailsでJavaScriptを活用する方法は大きく分けて2つあります。
1つ目はサーバーサイドで生成されたHTMLをもとに、JavaScriptによる動的な機能を追加する方法です。
この場合、app/javascript/packs
や app/assets/javascripts
にスクリプトを配置し、ERBテンプレートで読み込むだけで基本的な処理ができます。
2つ目はフロントエンドの一部、あるいは全部をSPA(Single Page Application)として構築し、そのデータ取得をRails側のAPIに委ねる方法です。 このスタイルではRailsをバックエンドのAPIサーバーとし、ReactやVue.jsといったフレームワークをメインに使うケースが多いです。 どちらの手法をとるかは、アプリケーションの規模や開発チームのスキルセットによって変わってきます。
代表的なフロントエンドフレームワークとの連携
ReactをRailsで使う
RailsプロジェクトにReactを導入する方法はいくつかあります。 Webpackerを使う場合、Railsに標準で用意されたジェネレータコマンドを実行するとReact用の設定が自動で組み込まれることが多いです。 ジェネレータコマンドの例を以下に示します。
rails webpacker:install:react
上記コマンドを実行すると、React関連のライブラリがインストールされ、app/javascript/packs
内にReactのエントリーポイントが生成されます。
そこにコンポーネントを作成し、ERBテンプレートから <%= javascript_pack_tag 'application' %>
のように読み込めば、Rails側で管理しているページ上でReactを活用できます。
フロントエンドだけで画面遷移や状態管理を行いたい場合は、RailsのルーティングをAPI専用に切り替えて、React RouterやReduxなどの仕組みと併用することが考えられます。 こうするとRailsとReactを役割分担させる形になり、大規模アプリケーションでも整理しやすくなるでしょう。
Vue.jsをRailsで使う
Vue.jsもReact同様にWebpackerとの相性が良く、コマンド一発で基本的なセットアップが可能です。 Vue.jsの場合は以下のようなコマンドを使うことがあります。
rails webpacker:install:vue
Reactのケースとほぼ同じ流れで、app/javascript/packs
にVue用のエントリーポイントが自動生成され、Vueインスタンスを定義するファイルをそこに置きます。
あとはERBテンプレートの中で <div id="app"></div>
のようにマウント用の要素を設置しておき、JavaScriptパックを呼び出すとVueのコンポーネントが表示される仕組みです。
Vue.jsはコンポーネントの読みやすさや、単一ファイルコンポーネント(.vue
ファイル)の扱いやすさが特徴です。
Railsのテンプレートエンジンを併用しながら、必要に応じて部分的にVue.jsを使う設計も可能です。
小規模な部分的UIをVueで作り込みたいときにも対応しやすく、Railsとの住み分けがはっきりするため初心者でも導入しやすいでしょう。
Railsでのフロントエンド実装におけるポイント
ERBによるテンプレート活用
Railsで画面を表示する場合、多くのケースでERBテンプレートを利用します。 たとえば以下のように、Rubyの変数をそのまま埋め込みながら、HTMLを生成できます。
<!-- app/views/home/index.html.erb --> <h1>こんにちは、<%= @user_name %>さん</h1> <p>今日は<%= @current_date %>です</p>
このようにサーバーサイドで取得したデータをビューに反映できるため、データの表示やカスタムメッセージの出力が簡単です。 JavaScriptが必要ない場合はこの仕組みだけで動的なページを実現できます。 また、後述の部分テンプレートを活用すれば、重複したHTMLのパターンをまとめて管理できるため、メンテナンス性が高まります。
レイアウトや部分テンプレートの管理
Railsにはレイアウト機能があり、ヘッダーやフッターといった共通部分を一元管理できます。
app/views/layouts/application.html.erb
を見れば全体の構造が分かるので、サイト全体の見た目を変更する際にはこのファイルを編集するだけで済むことが多いです。
また、部分テンプレート(パーシャル)を使うと、細かいUI要素を一つの.html.erb
ファイルにまとめ、それを本体のテンプレートで呼び出す仕組みになります。
たとえば _navbar.html.erb
のような名前をつけておけば、他のテンプレートで <%= render 'navbar' %>
と呼び出すだけで同じ構造を再利用できます。
下記はパーシャルを利用した例です。
<!-- app/views/layouts/application.html.erb --> <!DOCTYPE html> <html> <head> <title>My Rails App</title> <%= stylesheet_link_tag 'application', media: 'all' %> <%= javascript_pack_tag 'application' %> </head> <body> <%= render 'shared/navbar' %> <%= yield %> </body> </html>
<!-- app/views/shared/_navbar.html.erb --> <nav> <ul> <li><%= link_to 'Home', root_path %></li> <li><%= link_to 'About', about_path %></li> </ul> </nav>
こうした仕組みを使うことで、デザイン変更時の作業量を減らしながら、フロントエンドの更新をスピーディに行えます。
Railsのルーティングとビューの連携
Railsでフロントエンドを扱う場合、ルーティングの設定が重要です。
config/routes.rb
にルートを定義すると、対応するコントローラがHTTPリクエストを受け取り、処理結果をビューへ渡します。
必要なデータをデータベースから取り出し、それを変数に格納してビューに送る流れが基本パターンです。
たとえば /home/index
というリクエストが来たら、以下のようにコントローラが起動します。
# app/controllers/home_controller.rb class HomeController < ApplicationController def index @user_name = "田中" @current_date = Date.today end end
この例では @user_name
と @current_date
をビューに渡しているだけですが、さらにJavaScriptの動作に必要なデータを含めることもできます。
Railsのルーティングとビューの連携をしっかり理解しておけば、フロントエンド側で参照する値を自由にカスタマイズできます。
コントローラ内でビューに渡す変数を必要最小限に絞ると、可読性が高まります。 複雑なロジックはモデルで処理し、コントローラはデータの受け渡しに専念させる設計が分かりやすいです。
フロントエンドで非同期処理を実装する
Railsを使うと、非同期通信によってユーザーの操作感を向上させることも容易です。 JavaScriptでAjaxリクエストを送り、Rails側でJSONを返すことでページを再読み込みせずに部分的に情報を更新できます。 また、RailsにはRemote: trueと呼ばれる仕組みをサポートする方法もあり、フォームやリンクをAjax化するのもスムーズです。
以下は簡易的なAjax処理の例です。 JavaScript側でFetch APIを使い、RailsコントローラにJSON形式でリクエストを送るパターンを示します。
// app/javascript/packs/ajax_example.js document.getElementById("fetchDataBtn").addEventListener("click", () => { fetch("/api/sample_data", { method: "GET", headers: { "Content-Type": "application/json" } }) .then(response => response.json()) .then(data => { const resultArea = document.getElementById("resultArea"); resultArea.innerText = data.message; }); });
# app/controllers/api_controller.rb class ApiController < ApplicationController def sample_data render json: { message: "非同期で取得したデータです" } end end
ERBテンプレートに <button id="fetchDataBtn">取得</button>
と <div id="resultArea"></div>
を用意しておけば、このスクリプトを読み込むだけで非同期通信が実行されます。
これにより、ページの一部だけを更新するインタラクティブなWebアプリケーションを作ることができるでしょう。
大規模な非同期通信を行う場合は、エラー処理や認証まわりの設計が複雑になりやすいです。 RailsのAPIモードを使うなど、適切に責務を分けて実装することをおすすめします。
まとめ
Ruby on Railsはフロントエンドとバックエンドを一体的に扱えるフレームワークです。 テンプレートエンジンのERBやアセットパイプライン(Webpacker含む)をうまく使うことで、HTMLやJavaScript、CSSを効率よく管理できます。 ReactやVue.jsと連携すれば、SPAのような高度に動的なUIも容易に開発できるでしょう。
初心者の皆さんがまず取り組みやすいのは、ERBテンプレートにデータを埋め込んでページを生成する方法です。 さらにステップアップとして、WebpackerでJavaScriptを扱いながら部分的にReactやVue.jsを導入してみると、フロントエンドのスキルが高まりやすくなります。 Railsのルーティングやコントローラの仕組みと合わせて学ぶことで、サーバーサイドとフロントエンド双方の理解が深まるのではないでしょうか。
最終的には、APIモードとフロントエンドフレームワークを組み合わせて本格的なWebアプリケーションを作ることも視野に入れられます。 Railsが持つ多彩な機能を上手に活用して、フロントエンドでも幅広く活躍できるようにしてください。