人生48日目

Railsチュートリアル(12)2週目

走破した。この辺から本当に複雑になってくるなーという印象。
モヤっとしたところがあってSlackで質問しようと思い、

Railsのルートについての質問です。 Railsチュートリアルの中のことなんですが、routes.rbにresources :usersとすると、名前つきルートが使えるようになりますよね。 この場合、editアクションに対応するURLは「/users/1/edit」で「1」の部分はマジックカラムであるid が入っていて、params[:id]のようにして取り出せる。 ここまではわかるのですが(わかってなかったら申し訳ないです)、resources :account_activations, only: [:edit]とした時のeditアクションのURLが「/users/token/edit」になると記載されていて、実際そうなっています。 この時の名前付きルートは「edit_account_activation_url(token)」と記載されているんですが、

まで打って、質問する前に気づいた。
つまりこれが”WEBアプリケーションの仕組み”そのものだった。

「URLがあって、それに対応するHTMLがある」という仕組みではなく、

「URLに情報を乗せて、アクションを呼び出し、アクションがそれに応じたビューを返す」

っていう仕組みになっている。今更何言ってんだって感じだろうけど。

これに気づいた手順を以下に記す。

雑魚ワイがWEBの仕組みに気づくまで

1.「prams[:id]」ってidって書いてあるけど単純にマジックカラムのidを指してるわけじゃねーよな・・・。
だってこれでactivation_token取り出せたもんな。そもそもactivation_tokenってattr_accessorで指定した仮想の属性なのになんで取り出せたんだ?
実際に属性が存在するならまだわからんでもないけど・・・。

2.「edit_user_path」だと「users/1/edit」ってことは、「edit_activation_path」って「/activations/1/edit」のはず。URL叩いてみよう。
→root_urlにリダイレクトされ、エラーメッセージが表示される。

3.例外じゃなくてルートURLに飛ばされてエラーメッセージまで出てる。つまり正常に動いてこういう判断をしたっていうことか。
エラーメッセージは「Invalid activation link」、これを設定してるコードを探そう。

4.コードを検索する

#app/controllers/account_activations_controller.rb
class AccountActivationsController < ApplicationController

  def edit
    user = User.find_by(email: params[:email])
    if user && !user.activated? && user.authenticated?(:activation, params[:id])
      user.activate
      log_in user
      flash[:success] = "Account activated!"
      redirect_to user
    else
      flash[:danger] = "Invalid activation link"
      redirect_to root_url
    end
  end
end

見つけた。ここで定義してあるフラッシュメッセージだった。
ん?そういえば名前付きルートには「edit_account_activation_url(token)」とあって、(token)を渡してる形になってた。

5. そういえばmailerのテンプレートでURLを作るコードがあったな・・・

.
.
<%= link_to "Activate", edit_account_activation_url(@user.activation_token,email: @user.email) %>
.
.

はい、ここでわかりました。

「edit_account_activation_url」は単に「このアプリケーションの地図としてのURL」ではなく、「editアクションに情報を渡すためのトロッコのようなもの」だったんですね。
(@user.activation_token,email: @user.email)となっているのは「:idに当たる部分にはactivation_tokenを乗せて、ついでにemailも乗せてくれ」という意味。
URLは場所を示しているのではなく、対応するアクションに値を送っているのですね。
対応するアクションに値を送るという意味では地図的なものでもあるのか。脳内の言語化難しすぎる。

先ほど「/activations/1/edit」を直接入力してリダイレクトされたのは、editアクションでparams[:email]を取得した結果、nilだったから、その後の処理でリダイレクトされ、エラーメッセージが表示されたと。
mailerのテンプレートでURLを設定したのは、「URLにトークンとメールアドレスを乗せる」ため。
これによってeditアクションはparams(URL)から[:email]を取り出してユーザーを探して次の処理にいけるっていうこと。

こんなことも分からずに、Railsを学んでいたのが本当に恥ずかしい。
みんなは基本情報の勉強、ちゃんとしような!