りゅうじの学習blog

学習したことをアウトプットしていきます。

2021年9月2日 パーフェクト Ruby on Rails

2-2-4

コールバックによる制御

必ず行いたい前処理後処理を書けます。

before_○○○○○
ahter_○○○○○
around_○○○○○←あんまり使わないかも

ログを残したい場合に条件を自分で設定し作成できます。

ログレベル

ログレベル 名称 内容
0 debug デバッグ情報など
1 info 一般的な情報
2 warn 警告
3 error 制御可能なエラー
4 fatal プログラムをクラッシュさせるような制御不可能なエラー
5 unknown 常に記録されるべき不明なエラー

logger(Rails.logger).leverで設定変更が可能。これは場所を問わない。これを書けば、ログが吐き出される。Railsの記載は省略でき、loggerからで良いです。

2-2-5

enum

数値のカラムに対して別名を与えます。なのでカラムを追加する必要があります。(もしくはmodelかmigrationファイルを作成する)

# db/migration内
add_column :hoge, :category, :integer, null: false, default: 0
# model内
enum category: { bug: 0, request: 1, others: 2 }

enumはモデルに対して定義する必要があります。

enumのメソッドでwhere.notはnotを記載する事で取得する事ができます。

# enumの書き方
Article.not_draft
# これが取得できます。
Article.where.not(status: draft)

2-3-2

フック

コントローラーのアクションの前後に処理を差し込むことができる(コールバックと似ている) onlyexpectを付けることで特定のアクションに対して実行できる。 berore_action :hogehoge, only: [:show, :update]

フック一覧 処理が実行されるタイミング
before_action Actionの実行前
after_action Actionの実行後(正常にActionが実行された場合のみ呼び出される)
around_action Actionの前後
フックのスキップ

例えば、ログインが必要なアプリの時にApplicationControllerに操作を制御するフックを記載した場合、継承先のcontrollerに、skipのクラスメソッドを使用する必要があります。 そうしないと、いつまでもログインができないので注意が必要です。

CSRF適用を無効にしたい時の記述

特定のアクションのみセキュリティトークンの検証を行わないようにするには、下記のように記述します。

protect_from_forgery except: :update

複数のアクションで用いたい場合は配列で記述します。 ですが、基本的によほどのことがない限りセキュリティに穴をあけることになるので無闇に記述するのは辞めましょう。

ひとこと

around_actionなんて知らなかった。

参考

意外と知らないかもしれないRuby, Railsのメソッドとか

https://qiita.com/hc0208/items/45cce0f3f3c843c03c01#increment-decrement
Railsenumを定義している時、自動でscopeが定義される
https://kossy-web-engineer.hatenablog.com/entry/2020/05/31/113615
RailsEnumってどんな子?使えるの?
https://qiita.com/ozackiee/items/17b91e26fad58e147f2e

2021年9月5日 図解入門 TCP/IP

1.2.2 プロトコルは階層で整理する

 プロトコルで定義されている色々な通信機能は、その処理に応じて階層構造になっています。

1.2.3

TCP/IP参照モデル

4層構造になっています。
下の階層によって役割分担がされています。
自分の層の処理画終わったら他の層の処理には関与しません

階層 階層名 役割
第4層 アプリケーション層 ユーザーに対して、アプリケーションを提供する
第3層 トランスポート層 アプリケーションの識別と、それに応じた通信制御を行う
第2層 インターネット層 異なるネットワークにいる端末との接続性を確保する
第1層 リンク層 同じネットワークにいる端末との接続性を確保する

私達的な覚え方・4321層の順番で頭文字を取って、アトイリと覚えます。

送る側 4 → 3 → 2 → 1 ↩️ 受信側 4 ← 3 ← 2 ← 1

層によってプロトコル(約束事)はたくさんあります!その辺はまた後で


OSI参照モデル

7層構造になっています。
TCP/IP参照モデルと同じで階層によって役割分担がされています。
こちらも自分の層の処理画終わったら他の層の処理には関与しません |階層|名称|役割| |----|----|----| | 第7層 |アプリケーション層 |ユーザーに対して、アプリケーションを提供する| | 第6層| プレゼンテーション層 |アプリケーションデータを通信できる方式に変換する| | 第5層 |セッション層 |アプリケーションデータを送受信するため論理的な通信路(セッション)を管理する| | 第4層 |トランスポート層| アプリケーションの識別と、それに応じた通信制御を行う| | 第3層 |ネットワーク層| 異なるネットワークにいる端末との接続性を確保する| | 第2層 |データリンク層| 物理層の信頼性を確保し、同じネットワークにいる端末との接続性を確保する| | 第1層 |物理層 |デジタルデータを電気信号や光信号、電波に変換して、ネットワークに流す|

覚え方、7654321層の順の頭文字で、アプセトネ デブと覚えます。


PDUとは (Protocol Data Unit)

各階層で処理されるひとまとまりのデータ、つまりデータの単位のこと。


私たちなりの例え


本書で使用するモデルは以下のように二つのモデルをいいとこどりした5階層のものです。

各階層別のPDUの名称

階層 名称 PDUの名称
第7層 アプリケーション層 メッセージ
第4層 トランスポート層 セグメント(TCPの場合)、データグラム(UDPの場合)
第3層 ネットワーク層 パケット
第2層 データリンク層 フレーム
第1層 物理層 ビット

  • 今日の覚えること
    アトイリ
    アプセトネ デブ

参考

本書のみ

2021年9月4日 図解入門 TCP/IP

プロトコル(通信プロトコル) ネットワークの世界で、パケットを処理するときの約束事

  • https ブラウザのURLに書く文字で、httpsという約束事に基づき、暗号化してパケットを処理する

プロトコルで決まっていること

  • 物理的な仕様   LANケーブルの素材やコネクタの形状、そのピンアサイン(ピン配列)に至るまで、ネットワークにおいて、目に見えるものは全てプロトコルで定義されています。
  • 送信相手の特定 ネットワークの世界で、現実の世界と同じように住所を割り当てて、送信相手を区別しています。

  • パケットの転送 細かく分けたパケットを相手に送るためにヘッダーにはどんな情報があってどんな順序でやりとりするかが定義されています(たくさんの情報が入っている) そのパケットを届けるために自分と相手のコンピューターの間にあるネットワーク機器がヘッダーを見てバケツリレーの様に転送していきます。

  • 信頼性の確立  パケットは世界中に張り巡らされたネットワークに乗って、ありとあらゆるところを駆け巡っているので、いつどこでどんなときにパケットが壊れたりなくなったりするかわかりません。それでも大丈夫なようにエラーを通知したり、データを再送したりする仕組みを提供しています。また、有限なネットワークリソースがパケットでいっぱいになって、溢れてしまわないための仕組みも提供しています。 通信が多くなる時間帯に通信が重くなったりするのは、限られたネットワーク帯域をみんなで共有できるように、ネットワークで制御されている為です。

  • セキュリティの確保 プロトコルは、重要な情報を安心してやり取りできるように、正しい通信相手であるか認証し、通信を暗号化する仕組みを提供しています。ログインの時はwebブラウザが接続先のサーバーが正しい通信相手であるかをしっかり確認した後、ユーザー名とパスワードを暗号化して送信します。

ここまでまとめ

プロトコルとは … 約束事の名称

パケットという小分けにしたデータを安全に処理するための約束事

例えてみました

プロトコルはネットワーク上での、交通ルールで、これを守るから事故などを起こさずに送ったものを届けることができる。信号があったり、時には渋滞もするから、送信に時間がかかる事態にもなるが、それは安全に届ける為に交通ルールを守っている為です。ヘッダーは伝票に当たるものだと思います。伝票に相手の住所を記載してあるから、送信者も受信者もその届け先が合っていると判断できると思います。

参考

本書のみ

2021年9月3日 図解入門 TCP/IP

1.1.1 ネットワークの歴史

ネットワークの原型は一台の大型コンピュータとみんなで使用するTSS(Time Sharing System)という方式でコンピュータを使用していました。遠隔地にいるユーザーはTSS端末から大型コンピュータに電話でアクセスし、あたかも自分専用のコンピュータであるかのように扱うことができました。

TSSにより、大型コンピュータとTSS端末の2台だけで構成される最もシンプルなネットワークができたのが、ネットワークの始まりです。

APANET 超重要なネットワークで、インターネットのルーツです。

  • パケット ... 小さく分けたデータの単位
    • パケットのやりとりをパケット交換方式という

1.1.2 回線交換方式とパケット交換方式

回線交換方式
固定電話をイメージ。相手が話しても話さなくても電話を切るまで繋ぎっぱなし。

パケット交換方式
必要な時だけ必要な分だけパケットを送る。パケットにはヘッダーをくっつける。

ヘッダー 送信側のコンピュータはデータにつける情報です。宛先となるコンピュータの情報だったり、データの何番目に当たるパケットなのかだったり、様々な情報が含まれます。

パケット交換ネットワーク ヘッダーの情報を見て、宛先のコンピュータにパケットを送り届けます。また、宛先コンピュータはヘッダーの情報を見て、元のデータに復元します。

例: ニトリで家具を買い、家で組み立てる組み立ての説明書がヘッダーです。

参考

本書のみ

2021年9月2日 パーフェクト Ruby on Rails

SQLite3ではnot null制約を付与しつつカラムのデフォルト値を指定しない場合、カラムの追加でエラーになってしまいます。
例)

# NG
class AddNicknameToUsers < ActiveRecord::Migration[6.0]
    def change
        add_column :users, :nickname, :string, null: false
    end
end

# OK
class AddNicknameToUsers < ActiveRecord::Migration[6.0]
    def change
        add_column :users, :nickname, :string, null: false, default: 'sample'
    end
end

# OK
class AddNicknameToUsers < ActiveRecord::Migration[6.0]
    def change
        add_column :users, :nickname, :string
        change_column :users, :nickname, :string, null: false
    end
end

パーフェクト Ruby on Rails p60の例での説明

2-2-2

# 2xxxxxxxxxxxxx_add_publisher_id_to_books.rbdef change
  add_reference :books, :publisher, foreign_key: true  
#rails g migration時にreferencesをつけた事により外部キーであるforeign_keyが生成されており、この行でpublisher_idが作られます。(注:publisher_idとこの行で書いてしまうとpublisher_id_idとなってしまいます。)

  change_column :books, :publisher_id, :integer, null: false  
#ここで1行目に生成されたpublisher_idにnull: falseをつけることでnot null制約を付与しています。

rails c 内でのreloadとは

reloadメソッドとは、データベースに保存されているもともとのレコードをリロードすることです。
以下、検証結果です。

irb(main):021:0> user = User.new(last_name: '田中', first_name: '花子', password: 'password', password_confirmation: 'password', email: 'sample@sample.com' )
=> #<User id: nil, email: "sample@sample.com", crypted_password: nil, salt: nil, created_at: nil, updated_at: nil, last_name: "田中", first_name: "花子", avatar_image: nil, reset_password_token: nil, reset_password_token_expires_at: nil, reset_password_email_sent_at: nil, access_count_to_reset_password_page: 0, role: "general">
irb(main):022:0> user.reload
Traceback (most recent call last):
        1: from (irb):22
ActiveRecord::RecordNotFound (Couldn't find User without an ID')
irb(main):023:0> user.save
   (0.1ms)  begin transaction
  User Exists (0.6ms)  SELECT  1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "sample@sample.com"], ["LIMIT", 1]]
  User Create (1.0ms)  INSERT INTO "users" ("email", "crypted_password", "salt", "created_at", "updated_at", "last_name", "first_name") VALUES (?, ?, ?, ?, ?, ?, ?)  [["email", "sample@sample.com"], ["crypted_password", "$2a$10$FFT.hUH/PZI5ae5ajqeLUe1kM.H0AWS/mJV0.ZIKJo1ev7N1JcDMC"], ["salt", "FNGVQWhJLc3N-nHWvs9H"], ["created_at", "2021-09-03 16:04:23.608038"], ["updated_at", "2021-09-03 16:04:23.608038"], ["last_name", "田中"], ["first_name", "花子"]]
   (1.1ms)  commit transaction
=> true
irb(main):024:0> user.reload
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 15], ["LIMIT", 1]]
=> #<User id: 15, email: "sample@sample.com", crypted_password: "$2a$10$FFT.hUH/PZI5ae5ajqeLUe1kM.H0AWS/mJV0.ZIKJo1...", salt: "FNGVQWhJLc3N-nHWvs9H", created_at: "2021-09-03 07:04:23", updated_at: "2021-09-03 07:04:23", last_name: "田中", first_name: "花子", avatar_image: nil, reset_password_token: nil, reset_password_token_expires_at: nil, reset_password_email_sent_at: nil, access_count_to_reset_password_page: 0, role: "general">
irb(main):025:0> 

SQLiteの出力モード

  • line : 1行ずつ表示。
  • html : html形式で表示。
  • tabs : 各列をタブ区切りで表示。
  • csv : 各列をカンマ区切りで表示。

2-2-3

結論 「バリデーション + データベースでの制約」どっちも必要、安全!!」 Race Conditionが起きないように!!

Race Condition レースコンディションとは、複数の処理が同じデータに同時にアクセスした場合に、機能停止など予期しない処理結果が生じてしまうことです。 つまり 同時にアクセスなどしたときにバリデーションをすり抜ける可能性があるため二重ロックの意味でもバリデーションだけでなくnot null制約もつけるべきです。 バリデーションはDBに渡る前のActiveRecordの段階で制御し、not nullはDBに渡ってからDBで制御されます。

バリデーションヘルパー

ActiveRecord/ActiveModelの機能を使用したバリデーションです。(presence: trueなど)

validates :price, numericality: { greater_than_or_equal_to: 0 }の内訳

numerucality は数値であること、オプションでゼロ以上、偶数かどうかなどを検査します。greater_than_or_equal_to: 0 はゼロ以上であること >= と同義です。

バリデーションでpresence: trueが無く、DBでNot NULL制約がある場合DBには保存はされない。
エラーメッセージを表示したい場合はインスタンス.errors.messageまたはインスタンス.errors.full_messageを記述すると良い。(errorsはメソッド)


メソッドに!をつけるかつけないか

!をつけないとバリデーション失敗時に例外を起こさない !をつけると失敗時に例外を起こす

nullとnil

nilrubyの言語。nullの意味。 -nilでもメソッドのエラーを出したくない時は&.ぼっち演算子を使います。

参考文献

reloadメソッド
https://k-koh.hatenablog.com/entry/2020/12/28/214557
Race Condition
https://enterprisezine.jp/securityonline/word/detail/%E3%83%AC%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%B3%E3%83%87%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%B3

2021年9月2日 パーフェクト Ruby on Rails

第2章 Ruby on RailsMVC

2-1 MVCアーキテクチャ

  • M(Model)
    • データベースとの接続
  • V(View)
    • 視覚表現を行う部分
  • C(Controller)
    • ModelとViewをつなぐ部分

2-1-2

モデルの役割 - データベースと接続し、データベースのレコードをActive Recordオブジェクトを結びつける役割(Active Record) - バリデーションや、レコード保存時などに実行する様々なコールバックなどを実行する役割。(Active Modelが担っている)

Active Record RailsにはModelにActiveRecordが適用されているおかげで、Rubyを用いてDBからデータを探したり、持ってきたりすることができます。 - Active Recordがあるおかげでcreatenew,find,all…などのメソッドが使うことができます。 生のSQLを書かなくていい様にしてくれています。

Active Model Active Recordの多くのモジュール含むライブラリです。

Actioin Pack MVC のうち View と Controller を司るのが ActionPackというライブラリです。

MVCのモデルとは

あるシステムを作るという事は、そのシステムが解決する問題に対して必要な概念を探して、名前を付けたり相互の関係性を整理したりする事であり、その行為をモデリングと呼び、これがMVCのモデルです。

CRUD

データベースのレコードに対する基本的な操作のことです。 Create、Read、Update、Delete

※ Readはデータに影響を与えないので参照系、それ以外はデータに影響を与えるので更新系です。


2-2 モデルを扱う

モデルを通じて検索を行う = Railsの書き方でSQL検索

2-2-1

  • データベースに登録されているレコードを一件だけ検索
    • findメソッド : idを使用してレコードを取得
      • 検索結果が見つからないとActiverecord::RecordNotFound例外が発生
    • find_byメソッド : id以外を使ってレコードを取得
      • 検索結果が見つからないとnilを返す
  • 複数件のレコードを検索する場合
    • whereメソッド

ActiveRecord::Relation

  • SQLのそれぞれの表現に対応したメソッドをチェーンみたいに繋げていくことが可能です。(例:Book.where("price>?", 3000).limit(3).order(:name)みたいな感じ)
  • 実行結果のデータを普通の配列と同じような感覚で扱えます。

メソッドチェインを使うメリット

必要以上にデータベースとの通信が発生してしまうのを防ぐ効果があります。また、処理の流れを明確にできることがあります。 非同期処理を挟まない限り、前から後ろに向けて順番に処理されます。処理がメソッドチェインの各スコープの中で完結するため、一時変数を定義したり命名する手間が省けます。

Query Interface

Active Recordのメソッド(select、where、limitなど)のこと。

クエリ

「問い合わせ」。データベースに対する命令文のことです。
SQLは「言語」でクエリ(SQL文)は「命令(文)」です。

scopeの定義

よく利用する検索条件に名前をつけてひとまとめにしたもの (例:名前を"物件の条件"とした場合、内容を"バス・トイレ別, 室内洗濯機置き場"などにし、その後"物件の条件"という名前で呼び出せば、毎回内容を記載する必要がないため使い回しに便利です。)

scope :高級物件, -> { where("家賃 > ?", 100,000円)}
scope :トイレ, -> (toilet){ find_by(toilet: toilet) }

トイレのscopeを例にするとトイレがない場合はActiveRecord::Relationが返る。。

scopeで定義した場合は結果がnilでもActiveRecord::Relationを返します。もしnilを返したい場合はクラスメソッドとして定義したほうが良いです。

クラスメソッド

モデルで定義するメソッドのことです。

User.hoge # クラス名.クラスの中にあるメソッド名 で呼び出す


class Home
    def self.toilet(toilet)
        Home.find_by("あるよ")
        puts "トイレつきだあ"
    end
end


Home.toilet("あるよ")
=> トイレつきだあ
Home.toilet("ないよ")
=> nil

参照

Active Record https://qiita.com/ryokky59/items/a1d0b4e86bacbd7ef6e8

Action Pack https://magazine.rubyist.net/articles/0008/0008-RubyOnRails.html

クエリとは https://wa3.i-3-i.info/word11290.html

scopeとクエリについて https://qiita.com/ozin/items/24d1b220a002004a6351

クラスメソッドとは https://qiita.com/right1121/items/c74d350bab32113d4f3d

2021年8月31日 パーフェクト Ruby on Rails

1-4-4

http://localhost3000/rails/info/routesにアクセスすると現在のルーティング情報が表示されます。

  • コントローラー内で定義されたpublicメソッドのことをアクションと呼びます。
  • (:format)
    • アクセスしたURLの拡張子によってレスポンスを変化させるために利用 (.htmlや.json等、送りたいデータ形式によって変わります。基本的には表示されません。)
  • Prefix
    • 番号や符号、識別名などの先頭部分に付加し、何らかの意味や情報を表す短い部分のこと

「変数名のプレフィックスは『sayo_』にすること」というルールがあったとしましょう。

その場合、変数の名前を「sayo_a」や「sayo_b」のようにします。 変数名の前に必ず「sayo_」を付けるわけです。

このように、その単語なり何なりの前にくっつける文字列がプレフィックスです。

https://i.imgur.com/3l32dDz.png


PUTとPATCHの違い

  • PUT
    • リソースそのものの更新
  • PATCH
    • リソースの部分の置き換え

ユーザー名を更新する時などは部分更新なのでPATCHを使用します。


RESTとRESTful RESTとはルール(原則) RESTfulはRESTのルールに沿って開発されたWEBシステム

RESTの原則統一インターフェース:あらかじめ定義・共有された方法(WebであればHTTP)で情報がやりとりされるアドレス可能性:すべての情報が一意なURLの構造で示される接続姓:やりとりされる情報にはリンクを含めることができるステートレス性:やりとりは1回ごとに完結し、前のやりとりの結果に影響を受けない


ActionCableの場合RESTfulなの?

WebSocketをActionCableで使うとrubyで記述することができるようになり、RESTfulの思想を受け継ぎ実装することができます。


1-4-5

一章のまとめ

ルーティングでURLとコントローラ内のメソッドをひも付ける事でURLに対するアクションを定義し、そのアクションの中でモデルを通じてデータを取得します。そして、そのデータを元にテンプレートファイルを通じてHTMLを生成、描画しています。

https://i.imgur.com/oX3unL9.png

参照

prefix https://e-words.jp/w/プレフィックス.html

プレフィックスとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典 https://wa3.i-3-i.info/word1208.html

(:format)とpatchとputの違いについて https://books.google.co.jp/books?id=VCFHDwAAQBAJ&pg=PA59&lpg=PA59&dq=URLの拡張子 (:format)&source=bl&ots=Ex3ZaViTRj&sig=ACfU3U0lLws9wQ034U2d5e9nGkLQG8p_4g&hl=ja&sa=X&ved=2ahUKEwiIlceh0dryAhWKGaYKHWWlCUg4ChDoAXoECAwQAw#v=onepage&q=URLの拡張子 (%3Aformat)&f=false&source=bl&ots=Ex3ZaViTRj&sig=ACfU3U0lLws9wQ034U2d5e9nGkLQG8p_4g&hl=ja&sa=X&ved=2ahUKEwiIlceh0dryAhWKGaYKHWWlCUg4ChDoAXoECAwQAw#v=onepage&q=URL%E3%81%AE%E6%8B%A1%E5%BC%B5%E5%AD%90%E3%80%80(%3Aformat)&f=false)