Railsチュートリアル 第11章 メモ書き
○アカウントの有効化
新規登録したユーザーが本当にそのメールアドレスの持ち主なのかを確認するための有効化。
1)ユーザーの初期状態はunactivated
2)登録時に有効化トークンとそれに対応する有効化ダイジェストを生成
3)有効化ダイジェストはデータベースに保存
4)有効化トークンとメールアドレスを含めたリンクをユーザーにメールに送信
5)ユーザーがリンクをクリックしたら、アドレスをキーとしてデータベース内の有
効化ダイジェストと比較、トークンを認証
6)ユーザーのステータスをactivatedに
・AccountActivationsリソース:
ActiveRecordのモデルではなく、セッション機能を使ってUserモデルに追加する。
注意として、有効化はRESTルールに従うと、PATChリクエストとupdateアクションに
なるはずだが、有効化リンクをメールで送る関係上、ブラウザからのリクエストはGETであり、editアクションに変更する必要がある。
リクエスト URL Action 名前付きルート
GET /account_activation/トークン/edit edit edit_account_activation_url(token)
・データベースにはactivated属性(boolean)とactivated_at属性(datetime)を追加する。
・有効化トークンやダイジェストはユーザーオブジェクトが作成される前に作成する必要がある
→before_createコールバックを定義する。
before_create :create_activation_digest
・privateキーワード:これより下のメソッドは自動的に非公開に
・Action Mailer:
メール送信に必要なライブラリ。メイラーの構成はコントローラのアクションに近似し、メールのテンプレートをビューと同じ要領で定義できる。
・rails generate mailer UserMailer account_activation password_reset
でUserメイラー、account_activateionメソッド、password_resetメソッドが生成される
・メイラーのビューはテキストとHTMLの2つが生成される。
・クエリパラメータ:URLの末尾で?に続けてキーと値のペアを記述したもの
エスケープ:通常URLでは使えない文字(@など)を扱えるように変換する手法。
account_activations/q5lt38hQDc_959PVoo6b7A/edit?email=foo%40example.com
+生成したトークンで一意のURLを作成できる。
・Railsにはメールを送信しなくともメールのプレビューを確認する機能がある。
・メタプログラミング:プログラムでプログラムを作成すること。
式展開を利用してメソッドを引数として別メソッドに渡すこと。
・if user && !user.activated? && user.authenticated?(:activation, params[:id])
→ !user.activated?はユーザーを再度有効化しないために必要
・Herokuで本番環境からメールを送信する場合、
SendGridというアドオンを利用して、アカウントを検証する。
config/environments/production.rbの設定変更後、
heroku addons:create sendgrid:starterを実行
Railsチュートリアル 第10章 メモ書き
○ユーザーの更新・表示・削除
・新規ユーザーとユーザー編集の区別:
POSTリクエストとPATCHリクエストはActive Recordのnew_record論理値
メソッドを使っている。
@user.new_record? → trueではPOST、falseではPATCH
・ユーザー更新失敗時:
paramsハッシュ(user_params)をupdateメソッドに引き渡し、
If文で更新に成功すれば、プロフィールに。
失敗すれば編集ページにrenderする。
・受け入れテスト(Acceptance Tests):
アプリケーションの実装前に書かれた統合テストのこと。
・認証:サイトのユーザーを識別。
認可:ユーザーが実行可能な操作を管理すること。
誰でも自分以外のユーザー情報を編集や更新できるとまずい。
・ユーザーにログインを要求→beforeフィルターを使う:
before_actionメソッド 何らかの処理が実行される直前に特定のメソッドを
実行する仕組み。
例)before_action :logged_in_user, only: [:edit, :update]
edit、updateアクションを実行する前にlogged_in_userアクションを実行する。
デフォルトではコントローラ内の全てのアクションに適用されるが、
onlyオプションでアクションを制限している。
・編集・更新する場合も、正しいユーザーか判断を行うcorrect_userメソッドを
before_actionでedit:updateが実行される前に行うことでセキュリティを保証
・フレンドリーフォワーディング:
ログイン成功時に元々行きたかったページに転送させる機能
リクエスト時点のページをセッション中に保存、URLが保存されていれば
その場所に、なければデフォルトのURLにリダイレクトさせる。
但し、URLの保存はGETリクエストが送られた時だけに限定することで、
ログインしていないユーザーがフォームを使って送信した場合に転送先のURL
を保存させないようにできる(エラーの発生を未然に防ぐ)。
session[:forwarding_url] = request.original_url if request.get?
redirect_to(session[:forwarding_url] || default)
session.delete(:forwarding_url)
※転送用URLを削除しておかなければ次回ログイン時に保護されたページに飛ばされてしまう。
・ユーザーのサンプル:
Faker gem:実際にいそうなユーザー名を作るgem。
Railsでデータベース上にサンプルユーザーを生成する場合は、
db/seeds.rbというファイルを標準として使う。
・ページネーション:
一つのページに大量のユーザーが表示される状態を解決する方法。
1つのページに表示するユーザー数を制限する。
最もシンプルなものはwill_pagineteで、今回はGemfileに
will_paginate gem とbootstrap-will_paginateの両方を含めることで構築可。
ページネーションの動作には、indexビューに<%= will_paginate %>を書く。
(:pageがキーでデフォルトで30のデータを取り出す)
・管理ユーザー:
データベースにboolean型のadmin属性をUserモデルに追加する。
1であれば管理者ユーザーとして、他ユーザーのデータ編集・削除が可能に。
+Strong Parameterでセキュリティ対策
params.require(:user).permit(:name, :email, :password,:password_confirmation)
→admin属性は含めず、任意のユーザーが自身に管理者権限の付与を防ぐ
・render @usersを実行すると、自動的に_user.html.erbパーシャルを参照し、各ユーザーをコレクションとして表示する
Railsチュートリアル 第9章 メモ書き
○発展的なログイン(Remember me)
任意でユーザーのログイン情報を記録しておき、ブラウザ再起動後にすぐ
ログインできる機能。
→永続cookieを使う
・トークン:
コンピュータが作成・管理する秘密情報。パスワードはユーザーが作成・管理する。
セッションの永続化には記憶トークンが使われる。
・セッション永続化の流れ:
1)記憶トークンにランダムな文字列を生成。
2)cookiesに有効期限付のトークンを保存。
3)トークンをハッシュ化してデータベースに保存(remember_digestカラム)。
4)ブラウザのcookiesに保存するユーザーIDも暗号化。
5)IDを受け取ったらデータベースを検索し、記憶トークンのcookiesが
データベース内のハッシュ値と一致することを確認する。
・トークンに使う文字列:
SecureRandom.urlsafe_base64はA–Z、a–z、0–9、"-"、"_"のいずれか
の文字(64種類)からなる長さ22のランダムな文字列を返す。
・ユーザーの暗号化済みIDと記憶トークンをブラウザの永続cookiesに保存して、永続セッション(20年間)を作成。
cookies[:remember_token] = { value: remember_token,
expires: 20.years.from_now.utc }
=> cookies.permanent[:remember_token] = remember_token
params[:session][:remember_me] == '1' ? remember(user) : forget(user)
→paramハッシュの値が1であればremember (user)を実行、1でなければforget(user)を実行(if-then)
Railsチュートリアル 第8章 メモ書き
○基本的なログイン機構
・ログイン:
ブラウザがログイン状態をキープ、ユーザーがブラウザを閉じたら状態を破
棄する仕組み(認証システム:Authentification System)
+
ログイン済のユーザーだけがアクセスできるページや機能
(認可モデル:Authorization Model)
・セッション:
HTTPはリクエストが終わると以前のリクエストの情報を利用できないStatelessなプ
ロトコル。そこで、セッション(Session)という半永続的な接続をコンピュータ間に設定することで、ログイン機構を作る。
・cookies:
Railsでセッションを実装する最も一般的な方法。ユーザーのブラウザに保存される小さ
なテキストデータで、ページの移動で破棄されない。アプリケーションはcookies内の
データを使って、ログイン中のユーザーが所有するデータをデータベースから取り出せ
る。
・セッションのRESTfulな構造:
リクエスト URL ルート アクション 用途
GET /login login_path new 新しいセッションページ(ログイン)
POST /login login_path create 新しいセッションの作成(ログイン)
DELETE /login login_path destroy セッションの削除(ログアウト)
・セッションフォーム:
セッションにはSessionモデルというものがなく、引数に@userが使えない。
そのため、form_withメソッドにはリソースのスコープとそれに対応するURLを
具体的に指定する。
form_with(url: login_path, scope: :session, local: true)
・論理積を活用した記法:
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
→入力されたメールアドレスを持つユーザーがデータベースに存在し、
入力されたパスワードがそのユーザーのパスワードである場合のみ、if文実行
・セッションのflash:
セッションモデルではActive Recordのモデルを使っていないため、
エラーメッセージの代わりにフラッシュメッセージを用意する。
・sessionメソッド:
session[:user_id] = user.id
はユーザーのブラウザ内の一時cookiesに暗号化済のユーザーIDを
自動で生成するコード
・||=記法:
@current_user ||= User.find_by(id: session[:user_id])
@current_userに値が代入されていれば@current_userを、なければfind _byを呼び出す
・fixture:
テストに必要なデータのこと。fixitureファイルに記述する。
・ログインorログアウトしているかについては、ページ内で表示する
リンクを切り替える(上の論理積のif文をビューに書くなど)ことで表す。
Railsチュートリアル 第7章 メモ書き
○ユーザー登録
ユーザー登録フォーム→ユーザー保存→成功でデータベースに登録
→ブラウザの表示をリダイレクト→登録ユーザーのプロフィールを表示+ウェルカムメッセージ
・ミックスイン:
Sassの機能で、CSSルールのグループをパッケージ化することで
複数の要素に適用するようにしたもの。
@mixin box_sizing{}でbox_sizing内のCSSをパッケージ化
@include box_sizing;で他の要素に適用。
・Usersリソースのroutes:
Resources :usersをrouteに追加することで、ユーザーのURLを生成するための
名前付きルートと共に、必要となる全てのアクションが利用可能に。
・debug:
デバッグ情報を表示するためのメソッド。似たようなメソッドにbyebug gem内にあるdebuggerがあり、アプリの挙動がおかしい時にトラブルが発生していそうなコードに差し込む。そうするとbye bugプロンプトが開き、システムの状態を調査することができる。
・form_with:
ヘルパーメソッドの一つで、ActiveRecordのオブジェクトを取り込み、
そのオブジェクトの属性を使ってフォームを構築する。
<%= form_with(model: @user, local: true) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
…
<% end %>
↓HTML生成
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" type="text" />
・マスアサインメント:
値のハッシュを使ってRubyの変数を初期化するもの。
@user = User.new(params[:user])
ユーザーの送信したデータを全てUser.newに渡していることになり、
admin属性(管理者)が1という情報をWebリクエストに紛れ込ませるだけで、
Webサイトの管理者権限を奪い取ることができてしまうため、セキュリティー上危険。
・Strong Parameters:
上に書いた危険を防止する目的で、必須のパラメータと許可されたパラメータを指定
できるようにしたもの。params[:user] の代わりにuser_paramsメソッドを使うのが通例。
params.require(:user).permit(:name, :email, :password, :password_confirmation)
→:user属性を必須とし、名前、メールアドレス、パスワード、パスワード確認の属性を許可
・エラーメッセージ:
RailsにはエラーメッセージをUserモデルの検証時に自動生成する。
errors.full_messagesメソッドで表示可能。
ブラウザに表示する場合は、パーシャルをrenderで出力すれば良い。
※複数のビューで使われるパーシャルは専用のディレクトリsharedによく置かれる。
・redirect_to 〜:
~のURLにリダイレクトするコード。
・flash:
flash[:success] = "Welcome to the Sample App!"
で引数が渡された時(上の場合は成功時)にWelcome to the Sample App!というメッセージを表示。
ページを変えたり、リロードするとこのメッセージは消えている。
Bootstrap CSSにはflash用にsuccess、info、waring、dangerの4つスタイルが用意されている。
・SSL:
現時点のチュートリアルで作成したユーザー登録フォームでは、名前やアドレスなどの
データがネットワーク越しに流されていく欠陥がある。
その前に暗号化を行うのがTLS(Transport Layer Security)でSSLはその一つ。
有効化にはproduction.rbという本番環境の設定ファイルに config.force_ssl = true
を書き加えるだけでOK(本来はSSL 証明書を購入する必要あり)。
・Puma:
多数のリクエストを捌くことに適したRuby/Rackアプリケーション用のサーバー。
HerokuのデフォルトはWEBrickで簡単なセットアップに向く。
サーバーをPumaに変更する場合は、Gemfileにpuma gemを追加することだが、
Rails5.0以降はデフォルトで入っている。
Railsチュートリアル 第6章 メモ書き
○データベースについて
・モデル:
Railsデフォルトのデータ構造。
永続的・長期的にデータを保存する。
データベースにリクエストを行うデフォルトのライブラリはActiveRecord。
データ行で構成されるテーブルを持ち、各列(カラム)はデータ属性(文字列:String、
数値:integerなど)を持つ。
・マイグレーション:
データベースに変更を加えるためchangeメソッドのファイル。コンソールで以下の命令を行うと、idとString型のname、emailカラムを持つ(+作成・更新時のタイムスタンプ)Userテーブルを作るためのマイグレーションが
作成される。
$ rails generate model User name:string email:string
実行自体には次の命令が必要。
rails db:migrate
・ユーザーオブジェクト:
データベースに含まれるユーザーのデータ。
ユーザーモデルはActiveRecordのモデルを継承しているため、ActiveRecordのメソッドを使える。
new、save、create、destroy、find、first、all、updateなど
・バリデーション:
1)存在性 validates :name, presence: true
nameカラムには空白のデータを保存できない
2)長さ validates :email, length: { maximum(minimum): 255(5) }
emaiカラムの最長は255文字(最低5文字)
3)フォーマット format: { with: VALID_EMAIL_REGEX }
指定したフォーマットに従う文字列のみ保存可。valid_email_regexは正規表現
→ VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/I(メールアドレス用)
4)一意性 uniqueness: true
登録ユーザーの重複を避ける
※同時に複数のリクエストが入った場合、一意性を保てない場合が
→マイグレーションでデータベースにindexカラムの追加
add_index :users, :email, unique: true
コールバック:ある特定の時点で呼び出されるメソッド
before_save { self.email = email.downcase }
→ユーザーをデータベースに保存する前にemail属性を強制的に小文字に変換する
・ハッシュ化:
入力されたデータを元に戻せない不可逆なデータにする処理。一般的にはパスワードの保存に使用される。
→モデル中に「has_secure_password」というメソッドを入れることで次の機能が使えるように
1)ハッシュ化パスワードをpassword_digestというデータベース内カラムに保存できるように(マイグレーションは必要)
2)passwordとpassword_confirmationが使えるように+存在性と値一致のバリデーション
3)authenticateメソッドが使用可に
※ハッシュ化にはbcryptGemもGemfileに必要
・Authenticate:
引数に渡された文字列(パスワード)をハッシュ化した値と、データベース内の
password_digestカラムの値を比較し、正しい値が引数に渡されていればtrue、それ以外はfalseを返すメソッド。
■
○HTMLとCSS
・レイアウトを作成するのがHTMLだがそのままでは見栄えが悪いため、
CSSクラス(自前やBootstrapなどの公開フレームワーク)を関連づけることで
デザインを洗練できる。
・app/assets/stylesheets/に置かれたスタイルシートはapplication.cssの一部として
Webサイトのレイアウトに読み込まれる。
・パーシャル:
レイアウトを整理し、コードをリファクタリングするため(効率化)に、
コードの一部をパーシャルファイルに分ける。
パーシャルのファイル名は先頭にアンダースコアをつける。例:_shim.html.erb
呼び出す時はrenderメソッドを用いる。例:<%= render 'layouts/shim' %>
・アセットパイプライン:
開発効率と読み込み時間の両方に配慮した構造。
プログラマにとっては読みやすいままで、本番環境に最適化された接続を提供する。
・アセットディレクトリ:
静的ファイル(アセット)を目的別に分類した標準的な3つのディレクトリ。
2つのサブディレクトリが用意されており、app/assetsの場合は画像用
とCSS用のサブディレクトリがある(config、images、stylesheets)。
マニフェストファイル:
アセットを1つのファイルにまとめる指示を行うファイル。実際にまとめるのは、
Sprocketsというgem。また、適用されるのはCSSとJavaScriptで画像は適用外。
プリプロセッサエンジン:
ディレクトリに配置されたアセットを、ブラウザに配信できるようにマニフェスト
ファイルで結合し、プリプロセッサエンジンで実行する。ファイル名の拡張子で使用
するエンジンをRailsは判断する。Sass用の.scss、CoffeeScript用の.coffee、
ERB用の.erbなどが一般的。
・Sass
CSSに新たな機能を加えた言語。
ネスト:スタイルシート中の共通パターンをネストの内側に含めることで
重複を避ける。
.center {
text-align: center;
h1 {
margin-bottom: 10px;
}
}
変数:何度も用いるコードを変数として定義し、わかりやすく呼び出しやすく
したもの。
$light-gray: #777;
・名前付きルートの定義:
get '/help', to: 'static_pages#help'
→getリクエストが/helpに送信された時にStaticPagesコントローラーの
helpアクションを呼び出す。
・統合テスト(Integration Test)
アプリケーションの動作全てをシミュレートするテスト。ブラウザによるページ間の遷移がある場合、効率良くシミュレートできる。