勉強履歴(と雑記)

プログラミング初心者のメモ書きです

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のモデルを使っていないため、

エラーメッセージの代わりにフラッシュメッセージを用意する。

flash:次のリクエストが来るまで表示

flash.now:次のリクエストが発生した時に消滅

 

・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。また、適用されるのはCSSJavaScriptで画像は適用外。

 プリプロセッサエンジン:

 ディレクトリに配置されたアセットを、ブラウザに配信できるようにマニフェスト

 ファイルで結合し、プリプロセッサエンジンで実行する。ファイル名の拡張子で使用

 するエンジンを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)

アプリケーションの動作全てをシミュレートするテスト。ブラウザによるページ間の遷移がある場合、効率良くシミュレートできる。