ほげほげパッチ

有る事無い事 徒然なるままに

例外処理

例外、例外処理

例外とは、事前に想定される、期待と違う挙動。想定されるエラー。(コーディングしてて出くわすエラーとは少し違う)

Exceptionクラスを承継したNoMethodErrorとかSyntaxError。

activerecord-import (Gem)

importメソッドが使えるようになる。

配列 -> import -> 一気にレコード作成

データベースにアクセスする回数を減らせる。

(db/seeds.rb)
users = []
10000.times do |i|
 # usersに10000件新規ユーザーの情報を格納する
  users << User.new(name: "dummy-#{i+1}", ticket_count: 0)
end
# importメソッドの引数に配列を渡して、まとめてレコードを作成する
User.import users


reils db:seed

db/seeds.rbに基づいてレコードを作成

Rakeレイクタスク

タスクを実行するためのツール。タスク = コマンド?

(ターミナル)
# タスクファイル作成
% rails g task タスクファイル名
(lib/tasks/タスクファイル名.rake)
namespace :ここにグループ名を記述する do
  desc "ここに処理の説明を記述する"
  task タスク名: :environment do

         ここに実際のタスクを記述する

  end
end
# 実行コマンド
rails namespaceの名前:taskの名前


environmentエンバイロメントメソッド

タスクの処理をアプリケーション(Rails環境に依存させる。

Rails上のUserモデルとかを扱えるようになる。

incrementインクリメントメソッド

User.find_each do |user|
  # tichket_countカラムの値を10増やす
  user.increment!(:ticket_count, 10)
end


beginビギン

例外処理を想定している箇所を囲う

rescueレスキュー

例外が起きたら実行される

繰り返し処理(each,time,while)の中に begin,rescueを書くとループが途中で止まらない。

    User.find_each do |user|
      begin
        user.increment!(:ticket_count, 10)
      rescue => e #発生した例外を変数eに格納
        # エラーをログに記録
        Rails.logger.debug e.message
      end
    end


例外を発生させる !

save, create, destroy => true/false

save!, create!, destroy! => falseじゃなく例外

raiseレイズ

自分で例外を発生させて「不具合の原因となる箇所で例外を明示して、処理を止めたいとき」

raise 発生させたい例外クラス, 'エラーメッセージ'

例外クラス・・・NoMethodError, RuntimeError, SyntaxError, NameErrorなど

トランザクション transaction: 処理

個別に処理ではなく、一気に処理。 100か0か。

「途中まで処理ができて、例外以降の処理ができない」みたいな状態を避けれる。(商品の注文と支払いとか、セットじゃないと困るもの)



レスポンシブwebデザイン

「Noto Sans JP」

Web制作でよく使うフォント

Webウェブフォント

インターネット上から読み込めるフォント

Noto Sans JPもwebフォント

GoogleFontsグーグルフォンツ

Googleのwebフォント

ことば

HTMLのコードを書くことを「マークアップ」、CSSのコードを書くことを「スタイリング」

メディアクエリ

表示画面に応じて適用するスタイルを切り替える機能

<!-- 500px以下の時に適用 -->
@media (max-width: 500px) {
  p {
    font-size: 10px;
  }
}


ブレークポイント

切り替えの分岐点

PCとタブレットスマホのどれを想定するかでブレークポイントの数も変わる。



ライブラリの種類

標準ライブラリ

インストールは不要。読み込み要Dateクラス

組み込みライブラリ

元々使えるライブラリ。String, Integer, Array, Hash

外部ライブラリ

Rubyでいうとgemのこと。インストール要読み込み要

読み込み
require "date"
# これ以降の記述で、ライブラリ内のメソッドが使えるようになる。


インストール
$ gem install faker


まとめ

requireの要不要、インストールの要不要は、ライブラリの種類による。



テストコード #2

FactoryBot × 中間テーブル

(spec/factories/room_users.rb)
# アソシエーションのみ定義
FactoryBot.define do
  factory :room_user do
    association :user
    association :room
  end
end
(messages_spec.rb)
# userとroomを自動で追加
@room_user = FactoryBot.create(:room_user)
 => <#RoomUser:0x0000000110b662f8
  id: 2,
  room_id: 2,
  user_id: 4,
  created_at: Sat, 02 Sep 2023 09:10:04.633423000 JST +09:00,
  updated_at: Sat, 02 Sep 2023 09:10:04.633423000 JST +09:00>
(コンソール)
pry(main)> Room.find(2)
=> [#<Room:0x0000000110ca1a50
  id: 2,
  name: "New Jersey goblins",
  created_at: Sat, 02 Sep 2023 09:10:04.631154000 JST +09:00,
  updated_at: Sat, 02 Sep 2023 09:10:04.631154000 JST +09:00>,


Rails.root.joinレイルズ ルート ジョイン

# トップ階層〜Railsアプリ のパス
pry(main)> Rails.root
=> #<Pathname:/Users/ユーザー名/projects/sample-app>

# joinで後ろにパスを結合
pry(main)> Rails.root.join('public/images/test_image.png')
=> #<Pathname:/Users/ユーザー名/projects/sample-app/public/images/test_image.png>


attach_fileアタッチ ファイルメソッド

input要素[type: file]に、テスト用の画像を添付(アタッチ)できる。

# 引数(input要素のname属性, ファイルのパス)
attach_file('message[image]', image_path)

# 非表示(display:none;)のinput要素を表示
attach_file('message[image]', image_path, make_visible: true)


create_listクリエイトリスト

# FactoryBotを量産
FactoryBot.create_list(:message, 3, )
# オプションで、カラムの内容を指定できる。
# 外部キーも指定できる。
FactoryBot.create_list(:message, 1, content: 'hoge', room_id: @room_user.room.id)


ドットは3種類

  1. アソシエーションのドット
  2. メソッドのドット
  3. カラムをつなぐドッド



テストコード #1

テスト結果のログ表示

(.rspec)
<!-- ログが詳細に表示される -->
--format documentation


エラーメッセージを英語に

(spec/rails_helper.rb)
I18n.locale = "en"


after アフターメソッド

文字通り、〜の後に動作させたい時

FactoryBot.define do
  factory :message do
    content {Faker::Lorem.sentence}

    # インスタンスがbuildされた後に
    after(:build) do |message|
      # 指定したパスのファイルを名前をつけて保存
      # ioはinput/outputの略
      # ファイルをフルパスにすると、他の環境では使えなくなるので注意
      message.image.attach(io: File.open('public/images/test_image.png'), filename: 'test_image.png')
    end
  end
end


attach

ファイルを紐づける。

外す時はpurge

by chatGPT
messageはアクティブレコードモデルのインスタンス
imageはそのモデルに関連付けられたActive Storageアタッチメント名。

アタッチメントとは、ファイルをモデルに関連付けて管理するための仕組み。

attached?

画像がattachできているか確認。

# 変数に格納
pry(main)> message = FactoryBot.create(:message)

pry(main)> message.image.attached?

=> true


RSpecは外部ライブラリ

ライブラリの種類を学習してからだと、requireの意味がわかって少しおもしろ。

# 共通の設定とかメソッドを読み込むためのrequire
require 'rails_helper'

(rails_helper内に、その下部ディレクトリを読み込む設定が書かれている。)

単体テストの基本

基本は、インスタンス生成とエクスペクテーション

rails g rspec:model user

先にFactoryBotのファイルを手作業で作ってるとconflictってなってる。なんかなるほど。

(conflict: 衝突)

(ターミナル)
% rails g rspec:model user
    create  spec/models/user_spec.rb
    invoke  factory_bot
  conflict    spec/factories/users.rb
  # 上書きしますか?
  Overwrite /Users/shigeshige/projects/chat-app/spec/factories/users.rb? (enter "h" for help) [Ynaqdhm] 
([Ynaqdhm] : 返答方法)
 Y - yes, overwrite #上書する。
  n - no, do not overwrite #上書きしない。
  a - all, overwrite this and all others #全てを上書きする
  q - quit, abort #実行の中断をする
  d - diff, show the differences between the old and the new #ファイルを古いデータ、新しいデータで比較する?
  h - help, show this help #ヘルプを呼び出す
  m - merge, run merge tool #マージする

出典: (enter "h" for help) [Ynaqdhm]の対処方法 - Qiita


belongs_to :user の時に注意

外部キー(user_id)のバリデーションは不要!

class Message< ApplicationRecord
  belongs_to :user
  # ↑この時点で、':user_idの有無'というバリデーションはデフォルトで設定されている。
  validates :user_id presence: true ←不要
  # このバリデーションを設定した場合のエラーメッセージは、'User can’t be blank'
  # 設定しなかった場合は、'User must exist'
end


click_on

click_on('hoge')
# テキストリンク(a要素とか) or ボタン要素 をクリックしてくれる。
# テキストを検索 or value属性 を検索


英単語

invoke

in(上)とvocare(呼ぶ) -> 法令を発動する

  • vocal: vocalis(声を出すこと) -> 声の
  • vocation: 語源はvocatus(呼ばれる) -> 転職
  • provoke: pro(前)とvocare(呼ぶ) -> 怒らせる
  • revoke: re(後ろ)とvocare(呼ぶ) -> 取り消す
  • advocate: ad(方向)とvocare(呼ぶ) -> 支持する
  • convocation: con(一緒)とvocare(呼ぶ) -> 招集
  • evoke: ex(外)とvocare(呼ぶ) -> 感情を引き起こす

参考

語源voc (声)の英単語の意味まとめ | 読む語源学



Ruby 深掘り #2

クラスの継承

親から子に引き継ぐ。

親クラス(スーパークラス

共通する部分を記載

子クラス(サブクラス)

個別の情報を記載

class Chichi
  def initialize(eye_type, height)
    @eye_type = eye_type
    @height = height
  end
  
  def attitude
    puts "目は#{@eye_type}で、背は#{@height}"
  end
end

# ChichiからMusukoへ承継
# インスタンス変数とインスタンスメソッドが引き継がれる
class Musuko < Chichi
end

chounan = Musuko.new("一重", "高い")

chounan.attitude
# => 目は一重で、背は高い


独自メソッドの定義

子クラス(Musuko)内にdef〜endで定義したものは、その子クラス独自のメソッドとなる

オーバーライド

親クラスに対して、同名の子クラスを定義 => 上書き

上記の例で言えば、Musuko内にattitudeメソッドを定義する

class Musuko < Chichi
  def attitude
    puts "目は#{@eye_type}で、背は#{@height}、長男"
  end
end




Ruby 深掘り #1

caseケース文

条件分岐が多い時に使う。elseif的な。

  • case - when - else - end

  • if - elseif - else - end

whileワイル文

繰り返し構文

while 条件式 do
  # 条件式を満たす間は、ずっと繰り返す
end


無限ループ

元はプログラミングの用語。

while true
  # 常にtrue -> 無限ループ
end

大きな負荷がかかるので避けましょう

breakブレーク

繰り返し処理から強制脱出

ブロック

do〜endのことをRubyではブロックと呼ぶ

|〜|をブロック変数と呼ぶ。

  • eachとかtimesはブロック自体(do〜endの処理)を引数として受け取って(繰り返して)いる

{〜}もブロック。do〜endと同義。1行で収まるなら{ }推奨。

yieldイールド

application.html.erbに各ビューファイルの内容を展開する時にも出てきた。)

ブロックごと渡すような時にも使えるらしい。

def hoge
  puts "hogehoge"
  yield
  # 渡されたブロックがyieldと取って代わる。
end

hoge do
  puts "fugafuga"
end

# => hogehoge
# => fugafuga


ブロック引数

&blockをつけると、ブロックを引数として渡せる。

callで呼び出し。

# blockを引数として受け取るために &block 
def hoge(&block)
  puts "hogehoge"
  # callに引数"fugafuga"を渡して、ブロック引数を呼び出し。
  block.call("fugafuga")
end

# hogeというメソッドに do~end のブロックを引数として渡す。
# textという変数に、fugafugaが代入されて呼び出される。
hoge do |text|
  puts text
end

# => hogehoge
# => fugafuga