【Rails】Railsの全体像を理解する【79日目】


【学習内容】


・Railsの全体像を理解する

【Railsを取り巻く世界】

また、RailsはRubyを以外に様々な言語で構成されており、いろいろな関連技術とともに利用することができます。

Railsに詰まっている様々な、ソフトウェア開発において「良い」とされている技術に大きな影響を受けています。

具体的には、「MVC」、「オブジェクト指向」、「自動テスト」、「RESTful」のような概念たち指します。

また、基本的な前提として、RailsはHTTPでクライアントとやり取りをするサーバサイドのプログラムを作るためのフレームワークです。

今後、Railsの知識をより深く、堅牢にしていくためには、HTTPや主要な利用クライアントであるブラウザ、ブラウザを構成するHTMLやJavaScriptなどの理解が重要です。

【ルーティング】

アクセスを受けて適切なアクションへと案内するしくみをルーティングといいます。

「どのようなURLへどのようなHTTPメソッドでアクセスされたら、どのコントローラーを動かし、どのアクションを呼び出すか」をroute.rbに定義します。

なんとなく意味はわかるし、カリキュラムでもさらっと通り過ぎていたので「そういうものだ」と理解していたのですが、Railsのルーティングをより深く理解するには、どうやらルーティングのしくみに大きな影響を与えている「RESTful」という概念について学ぶ必要がありそうです。

【「ルート」を構成する5つの要素】

①HTTPメソッド(GET, POST, PATCH, PUT, DELETE)
サーバーのリクエストの際に指定します。一般的なブラウザから送れるのは、「GET」,「POST」のみです。

しかし、Railsでは:methodの後に:deleteや:patchといったメソッドを記述することで、その他のリクエストを送ることができます。

②URLパターン(/tasks, /tasks/:id)
URLそのものや「:id」のように任意の文字が入るようなパターンを指定します。

③URLパターンの名前(new_task, tasks)
定義したURLパターンごとに一意な名前をつけます。(あだ名みたいなものです)
このあだ名を元に対応するURLを生成するためのnew_task_path, new_task_urlといったヘルパーメソッドが用意されます。

④コントローラ
呼び出したいアクションのコントローラを定義します。

⑤アクション
呼び出したいアクションを指定します。


【1つのルートを定義する】

ここではtasklaafで設定したログインのrouteを例に解説します。

■config/route.rb

get ‘/login’, to: ‘sessions#new’

■解説
GETメソッドで、’/login’というURLに対してリクエストがきたら、SessionsControllerのnewアクションを呼び出す。また、’/login’というURLをlogin_pathというヘルパーメソッドで生成できるようにする。

⇒login_pathというURLパターン名をはっきり定義していませんが、URLの内容から「login」という名詞であると推定されます。

別のrouteも見てみます

■config/route.rb

post ‘/login’, to: ‘sessions#create’

■解説
POSTメソッドで、’/login’というURLに対してリクエストがきたら、SessionsControllerのcreateアクションを呼び出す。また、’/login’というURLをlogin_pathというヘルパーメソッドで生成できるようにする。

【RESTfulの概要】

1つのrouteを設定する方法の次は複数のrouteを設定する方法を学びます。

複数のrouteを設定するにあたって、RESTの概念を一度おさらいします。

「REST」という用語は、「REpresentational State Transfer」を表します。

■RESTの4つの設計原則
①セッションなどの状態管理を行わない。
⇒やり取りされる情報はそれ自体で完結して解釈することができる

②情報を操作する命令の体系が予め定義・共有されている。
⇒HTTPのGETやPOSTメソッドなど

③すべての情報は汎用的な構文で一意に識別される。
⇒URLやURIなど

④情報の内部に、別の情報や(その情報の別の)状態へのリンクを含めることができる。

Railsはアプリケーションを「RESTful」なシステムとして開発しやすくなる機能を提供しています。

●URLが指す情報(1単位)のことをリソースと呼ぶ。
⇒「/task/3」というURLは「3という一意な識別子を持つtaskというリソース」

●個々の情報(リソース)への「操作」の表現がHTTPメソッドとして統一されているため、Railsでは一般的なブラウザがサポートしているGETとPOST以外のHTTPメソッドをサポートする

●RESTfulなシステムでは、操作はHTTPメソッドで表現するものであり、URLで表現するものではない。よって、URLはなるべくリソースの名前を表す形、「名詞」にするという発想。


【RESTfulにするためのRailsの流儀】

「なにをどうしたいか」という思考から、動詞的な意味の内容、そのものの対象、方法等を考慮してURLを作成します。

例)「リソース○○番を取得したいです」というリクエストに対応するURLを考える
⇒「GET/tasks/○○」

CRUDを実現するためのほかのアクションたちについても、RESTfulな設計パターンを考えることができます。

そのような設計パターンを1から10まで考えるのはできなくもないですが、正直骨の折れる作業といえます。

その際に大いに役立つのが、resourcesという機能です。

【resourcesでCRUDのルート一式を定義する】

■config/routes.rb

resources :tasks

Railsでは、一覧・詳細・登録・更新・削除というよくある機能を提供するために必要なroute一式をresourcesというメソッドを使って定義することができます。

この機能を使うと、アクションごとにgetメソッドやpostメソッドを使ってroutesを定義する代わりに、一発で7つのアクションに対応するrouteを定義できます。

また、resourcesにはオプションをつけることができます。

:only、:expectを使うと、7つのrouteから特定のアクションのrouteのみを生成するようになります。

■config/routes.rb

resources :tasks, only: [:index]

⇒indexアクションだけrouteが生成されます

■config/routes.rb

resources :tasks, expect:[:delete, :edit, :update]

また、collectionというオプションもあります。
どこで使うかというと7つのアクション以外のアクション、つまりオリジナルのアクションへのrouteを定義するときに利用します。

■config/routes/rb

resources :tasks do
 collection do
   get ‘export’
 end
end

⇒「/tasks/export」というURLをexportアクションに対応づけます。


【routes.rbの構造化】

ルートを定義する記述は、前提となるURL階層や、コントローラクラスを修飾するモジュール、コントローラクラス、URLパターン名のプリフィックスなどで構造化できます。

構造化するためのメソッドは、「scope」、「namespace」、「controller」などがあります。

●scope
URL階層、モジュール、URLパターン名のプリフィックスなどをオプションに定義するとブロック内の定義にまとめて一定の制約をかけます。

●namespace
URL階層、モジュール、URLパターン名に一括で一定の制約をかけます。
Scopeとの違いは、URL階層だけに制約をかけることはできません

●controller
コントローラーを指定できます

■config/routes.rb

namespace :admin do
 resources :users
end

⇒Admin::UsersControllerのCRUDを、/admin/usersといったURL、admin_users_pathといったURLヘルパーメソッドとともに実現します。


【国際化】

国際化とはなんぞやという話になるのですが、Railsガイドが一番端的にまとまっていました。ご丁寧にやることまで記載してあります。

RubyのI18n (国際化・多言語化を意味する internationalization を短縮したもの) gemはRuby on Rails 2.2以降からRailsに同梱されています。このgemは、アプリケーションの文言を英語以外の 別の1つの言語に翻訳 する機能や 多言語サポート 機能を簡単かつ拡張可能な方式で導入するためのフレームワークを提供します。

アプリケーションの「国際化」プロセスといえば、使われるすべての文言やロケール固有の要素 (日付や通貨フォーマットなど) の抽象化までの作業を指すのが普通です。一方、「ローカライズ(localization)」とは、具体的な翻訳方法を提供したり、そのためのフォーマットを提供したりすることを指します。1

Railsアプリケーションを国際化するプロセスでは以下を行う必要があります。

i18nを確実にサポートすること。
ロケール辞書の置き場所をRailsに指示すること。
ロケールの設定・保存・切替方法をRailsに指示すること。


実際にやる事としては主に下記の3点です。

①利用するlocaleに対応する翻訳データのymlファイルをconfig/localesの下に記載する

②「現在のロケール」を示す118n.localeが正しく設定された状態にする

③目的の翻訳データを利用する。基本的には118n.localeに設定された翻訳データを使う。

日本語オンリーの場合など、1つのlocaleにだけ対応すればいいのであれば、既存のままでOKです。

しかし、日本語と英語など、複数のlocaleのユーザーからのリクエストごとに異なるろけールの翻訳データを利用したい場合は状況に応じて切り替えるのが基本です。

【ユーザーごとに言語を切り替える】

ひとまずユーザーごとに利用言語を設定してDBに保存するとします。

Userクラスのlocale属性に’jp’もしくは’en’を入れるものとします。
フィルタを設けることで、リクエストごとにI18n.localeの値を切り替えることができます。

■ApplicationController

class ApplicationController < ActionContoller::Base
 before_action :set_locale
…
 private
 def set_locale
    I18n.locale = current_user&.locale || :ja
 end
end

ログインしていなければ日本語という設定にします。

【翻訳ファイルの使いかた】

翻訳ファイルでできることとして下記の4点が挙げられます。

①(ActiveRecordベースではない)ActiveModelベースのモデルの翻訳情報
②localizeメソッドによって得られる日や日時の文字列表現
③よくあるボタンのキャプションなど、Railsが内部的に利用する文字列
④その他、任意の階層に任意のデータを定義する

config/locales以下に存在するymlファイルは、全て読まれます。

よって、複数のファイルに分割して整理することもできます。
(モデル系だけ分けたければ、models.ja.ymlなどとすることもできます)

これまで、Task.human_attribute_name(:name)のような方法で属性名の翻訳をしてきました。

ja:
 taskleaf:
   page:
     titles:
       tasks:”タスク一覧”

このとき現在のロケールが:jaの状態でI18n.t(“taskleaf.page.titles.tasks”)を実行すると、”タスク一覧”を得ることが可能になります。

I18n.t(“taskleaf.page.titles.tasks”)とすれば、titles以下の設定を{tasks: “タスク一覧”}というようなハッシュオブジェクトで得ることができます。

Task.model_name.human(locale: :en)  #英語をとってくる
Task.human_attribute_name(:name, locale: :ja) #日本語をとってくる
I18n.t(“taskleaf.page.titles.tasks”, locale: :en) #英語をとってくる

【所感】

なんとなく使っていたresourcesや国際化(知ったかぶり)がクリアになった気がします。

さて、しばらく離れていたTECH::EXPERTですが、来週からメルカリ開発が始まります。

昨日、エンジニアの卵の友人と話していたのですが、僕はどうやらSEよりもSI向きの性格をしているみたいで、仕事内容を聞いたら、そちらの方が楽しそうだなと思ってしまいました。(詳しい仕事内容はあまりわかってはいませんが)

サッカーに例えるのであれば、プレイヤーにあたるのがSEで、監督やコーチ陣にあたるのがSIということらしいのですが、選手としてサッカーをしたことがない人が監督なんて務まるのかということもあり、一旦はSEとして勤務して経験を積みたいと考えています。

具体的には自社開発企業のSEなんかがおすすめだということらしいです。

この辺はメンターさんやCAさんとお話をしながら思考の整理を行なっていきたいと思います


この記事が気に入ったらサポートをしてみませんか?