まさ@ブログ書き込み中

まさ@ブログ書き込み中

まさの旅、英語、プログラミング、プライベートについて、色々記録しています。

Railsチュートリアルの7章の内容が思ってたより深い【要約編】

 

こんばんは、昨日のバスケの筋肉痛で体中が痛いまさです。

 

やっとこさRailsチュートリアルの7章を終えたので、そのまとめを書いていきたいと思います。

 

次の予定もあるのでパパッと1時間で終わらせるように頑張ります。

 

 

7章のテーマは「ユーザー登録」

6章でユーザーモデルをつくったので、7章ではユーザー登録をするための機能をつくっていきます。具体的には、ユーザー情報を入力するためのフォームをつくったり、登録後にリダイレクトさせる予定のユーザー表示画面をつくったりするわけですね。

 

一度ユーザー登録をして利用するアプリケーションを作ったことのある僕は

「余裕っしょ」

としか思わなかったわけです。

 

だがしかし、Railsの世界は広かった。

今振り返ってみれば、ユーザー登録に関する機能の実装よりも、その周りのことについて学ぶべきことが多かった気がする。

 

 

ではまとめていきます!

 

 

Railsには3つの環境がある

サイトのレイアウトにデバッグ情報を追加するために、

      <%= debug(params) if Rails.env.development? %>

というコードをapplication.html.erbに書き込むところから7章はスタートします。

 

ここで注目すべきは、if文のところ。env.develppment?とはそのまま環境(environment)が開発(development)のものかどうか、を聞いているわけですが、Railsにはtestとdevelopmentとproduction(本番)環境の3つの環境があるということをここで学びました。

 

rails consoleを立ち上げたらデフォでdevelopment環境として立ち上がるようです。

 

 

RESTfulであるためにUserリソースを追加

Usersリソースをroutesファイルに追加するためにresources :usersを書くわけですが、このUsers「リソース」ってのがあまり理解できていませんでした。

 

本章によると、

サンプルアプリケーションにこの1行を追加すると、ユーザーのURLを生成するための多数の名前付きルートと共に、RESTfulなUsersリソースで必要となるすべてのアクションが利用できるようになるのです。

 

??????????????

 

専門用語のオンパレードに一度思考停止したので、一つずつ調べて行くことに。

 

リソースとは

以下のサイトによれば、

qiita.com

 

リソースとは「データモデルとwebインターフェイスが組み合わさったもの」だそうです。データモデルとは「現実世界のあるモノを分類/抽象化して落とし込んだカタマリ」だそうで、例えば 「id」「name」「email」などのカラムや、「integer」や「string」などのタイプのことだそう。

 

Webインターフェースとは、「データモデルをWebで取り扱えるようにしたもの」。

 

よってリソースとは

HTTPプロトコル経由で自由にCURD(作成/読み出し/更新/削除)できる(分類された)データ群

とみなすことができる。

そうな。

 

RESTとは

ずっと前に学習したものの、何だか腑に落ちていないREST。

このサイトによると

RESTとは、アプリケーションを構成するコンポーネント(Userなど)を、
RDBMSCRUD(Create/Read/Update/Delete)
・HTTPRequestの各メソッド(GET/POST/PUT/DELETE)
に対応させて、自由に作成/読み出し/更新/削除できるもの(リソース)として扱うアーキテクチャ

だそうな。

 

 

要するにRESTfulなUsersリソースとは、HTTPプロトコル経由で自由にCRUD操作ができるだけでなく、HTTPリクエストの各メソッドに対応している(分類された)データ群のことと言えそうですね。

 

例えば、HTTPリエクストのGETメソッドでURLが/usersであれば、indexアクションと結びつくようになっているのは、resources :usersの一行でRESTfulなUsersリソース(Userに関するデータ群)をReadするためのアクション(ここではindex)が利用できるようになっているからなのですね。

 

 

form_forの不思議

こうやって、これから利用するUsersリソースをRESTfulに使えるようにしたので、次はフォームを作成してユーザ情報を登録できるようにします。

 

僕が以前作ったアプリケーションではフレームワークSinatraを利用していて、HTMLでViewをせっせと作っていたのですが今回はRailsということもあってform_forヘルパーメソッドを利用しました。

 

ちなみに、こんな風にコードは書かれます。

    <%= form_for(@user) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>

 

ここで僕が興味深いと思った点は、まず引数に@userを取っていること。HTMLのフォームの概念からすると、引数を取ること自体が「?」となってしまいそうです。

 

また、もう一つ僕が面白いと思ったのはメソッドが書かれていないことなんですね。HTMLであればmethod="post"または"get"と書くのですが・・・どうなっているのでしょう?

 

実は、引数に@userを取ることでそれ以降のフォームは「@userの属性を設定するために特別に設計されたHTML」を返すようなのです。

 

また、フォームの内容を送信する際のHTTPリクエストのメソッドについてですが

Railsはformタグを作成するときに@userオブジェクトを使います。すべてのRubyオブジェクトは自分のクラスを知っているので、Railsは@userのクラスがUserであることを認識します。また、@userは新しいユーザーなので、 Railsはpostメソッドを使ってフォームを構築すべきだと判断します。 

 とあるように、Railsが勝手に判断してpostメソッドを使うことを選んでいるようです。SUGEEEEEEEEE!!!!

 

ちなみに、form_forに@userを与えるためにも、そのページを表示する前のnewアクションで@user=User.newで空のユーザーを作っておかなければなりません。

 

 

 Strong Parameters

 さて、RESTfulなUsersリソースをうまくルーティングとして使い、フォームをform_forヘルパーメソッドで作りました。このフォームのSubmitボタンを押せば、データが送信されます。

 

そのデータをどう扱うかという点においても、これまた面白いお話が本章で出ました。それはStrong Parametersという仕組みです。

 

name属性の値とデータ送信

HTMLをご存知の方であればわかると思いますが、フォームタグの中のinputタグのnameの値に対応してデータは送信されます。

<input id="user_email" name="email" type="email" />

 であれば、送られてくるデータを受け取るには"email"を受け取ればいいわけです。

 

ちなみに

<input id="user_email" name="user[email]" type="email" />

であればuserハッシュの:emailキーの値と一致します。

 

この調子で、user[email], user[name], user[password]...というフォーム名にしていけば、フォームのデータを送信するとUsersコントローラにはparamsとして以下のような情報が渡されます。

"user" => { "name" => "Foo Bar",
            "email" => "foo@invalid",
            "password" => "[FILTERED]",
            "password_confirmation" => "[FILTERED]"
          }

 

さて、ここまでくるとユーザー登録の際に

@user = User.new(params[:user])

としてユーザー情報を渡すことが考えられそうです(実際に昔のバージョンのRailsではこのコードで動いたそうです)が、悪意のあるユーザーによってアプリケーションのデータベースが書き換えられないようにRails 4.0 以降ではStrong Parametersと呼ばれるテクニックで対策することが標準とされました。

 

悪意のあるユーザーによるparamsの改変

データベースが書き換えられるな簡単な例としては、URLの末尾に?admin=1などを書き込むことが挙げられます。adminとはWebサイトの管理者であるかどうか(管理者であればadmin="1")をチェックする属性ですが、/users/new?admin=1と打ち込むだけで、paramsにadmin属性が含まれてしまうのです。

f:id:masaincebu:20170828003258p:plain

 

その対策としてrequireメソッドやpermitメソッドを使ったStrong Parametersというテクニックを使います。今回の場合、admin属性をいじられないように、以下のように書きます。

params.require(:user).permit(:name, :email, :password, :password_confirmation)

:user属性を必須とし、admin属性を許可しないようにしています。

 

 本当はテストコード周りも書こうと思ったのですが、思ったよりも長くなったので、今回は割愛させていただきますー

 

ではまた。

 

 

追記

Railsのリソースにおける概念に関する説明が不十分だったので、補足説明を翌日の記事の内容として書き込みました。 よかったらどうぞ。

masa-world.hateblo.jp