勉強履歴(と雑記)

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

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)

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

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