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)
アプリケーションの動作全てをシミュレートするテスト。ブラウザによるページ間の遷移がある場合、効率良くシミュレートできる。
Railsチュートリアル 第4章 メモ書き
○Rubyについて
カスタムヘルパー:
ビューで使える新たな組み込み関数(メソッド)のこと。
app/helpers/application_helper.rbにヘルパーとして定義。
Railsコンソール:
Railsアプリケーションを対話的に操作するためのコマンドラインツール。
irb(IRB:Interactive Euby)を拡張して作られ、Rubyの機能を全て使える。
開発・テスト・本番の3つの環境が定義されている。
nil:何もないことを表す特別な値
文字列の出力:
puts:出力の末尾に自動的に改行文字(\n)が追加。
print:出力に末尾に改行文字が入らない。
文字列:
ダブルクォート→式展開あり(#{})
シングルクォート→式展開なし(#を文字列として使える)
ダブルクォートで式展開しない時は\でエスケープ
boolean:
Trueもしくはfalseの論理値のこと
メソッドの定義:
def ~() endで〜がメソッド名、()内が引数、中に具体的な命令のコード。
最後に評価された式の値が自動的に返されるが、returnで明示することが可能。
push(<<):配列に要素を追加
%w:配列の前に置くことで文字列の配列に変換
ブロック:(1..5).each { |i| puts 2 * i }
範囲オブジェクトの(1..5)に対してeachメソッドを呼び出し、
{}(ブロック)の中にある|i|内のローカル変数iに代入、その後のputs 2*iを実行する。
長い時はdo endで囲むこともある。
ブロック内で宣言した引数に対してメソッドを呼び出す場合、次の省略記法が一般的。
%w[A B C].map { |char| char.downcase }
→ %w[A B C].map(&:downcase)
組み込みの基本クラス:
Rubyでは開発者以外でもクラスのメソッドを変更可能
(正当な理由がなければ混乱を防ぐ意味でしない方がいい)。
配列や範囲、ハッシュなどは組み込みクラス。
ハッシュ:
変数に複数の値を代入できる点は配列と同じ。違いはインデックスとして
文字列(キー)を用いることができる点。
値の前にコロンを置いたシンボルがキーとしてよく用いられる。
「”first_name" =>」と「:name => 」と「name:」は同じ。
attr_accessor:
アクセサーを作成し、そのデータを取り出すメソッド(ゲッター)と
データに代入するメソッド(セッター)をそれぞれ定義する。
例)attr_accessor :name,:email
と書くと、インスタンス変数@nameと@emailにアクセスするための
メソッドが用意される。
Initializeメソッド:
User.newを実行すると自動的に呼び出されるメソッド。
def initialize(attributes = {})
@name = attributes[:name]
@email = attributes[:email]
end