日々の積み上げブログ (original) (raw)
この広告は、90日以上更新していないブログに表示しています。
エラー内容
homebrew
で、nodenv
のインストール時に以下のようなPermission denied
エラーが発生しました。
$ brew install nodenv
==> Downloading https://ghcr.io/v2/homebrew/core/nodenv/manifests/1.4.1
Already downloaded: /Users/username/Library/Caches/Homebrew/downloads/1aaf03245ee4323ce2635f6ee8b7d88d03644c3b89e5067550d4d774c3070ae2--nodenv-1.4.1.bottle_manifest.json
==> Fetching dependencies for nodenv: ca-certificates, openssl@3 and node-build
==> Downloading https://ghcr.io/v2/homebrew/core/ca-certificates/manifests/2023-08-22
Already downloaded: /Users/username/Library/Caches/Homebrew/downloads/a8cd32e30cae0b7335779e93a6554f294f09485802fc253a3a8be441337a6115--ca-certificates-2023-08-22.bottle_manifest.json
==> Fetching ca-certificates
==> Downloading https://ghcr.io/v2/homebrew/core/ca-certificates/blobs/sha256:a331e92e7a759571296581f029e5cc2ec7cee70cd92dc0b5f8eb76095f94a21a
Already downloaded: /Users/username/Library/Caches/Homebrew/downloads/9be22fdac2e86ffb3bf6c165d2349e6e7fb9ff474a859890bcd63f79a807641e--ca-certificates--2023-08-22.sonoma.bottle.tar.gz
==> Downloading https://ghcr.io/v2/homebrew/core/openssl/3/manifests/3.1.3
Already downloaded: /Users/username/Library/Caches/Homebrew/downloads/f038f540886a6a94c000296efb3058dc47e867eef00f0c6836b8ff310bc04daa--openssl@3-3.1.3.bottle_manifest.json
==> Fetching openssl@3
==> Downloading https://ghcr.io/v2/homebrew/core/openssl/3/blobs/sha256:b3c246dae84e6fe84b9c1a896bf7392aa457667c580509c6161d71e440636d1e
Already downloaded: /Users/username/Library/Caches/Homebrew/downloads/19a379dd6a9ddeb5f527a01951d160d48d4cbd5db74b4de6f029dd2682f45d23--openssl@3--3.1.3.sonoma.bottle.tar.gz
==> Downloading https://ghcr.io/v2/homebrew/core/node-build/manifests/4.9.126
Already downloaded: /Users/username/Library/Caches/Homebrew/downloads/8e9ab330e6e8c2308db6aa79c81ad2a2230635cf9534c7b0e7cc9abd0ed342e3--node-build-4.9.126.bottle_manifest.json
==> Fetching node-build
==> Downloading https://ghcr.io/v2/homebrew/core/node-build/blobs/sha256:0f69e614e07f45a32854fd1afe1a69a13697d6abbc742cbc01f3f0ac24936be7
Already downloaded: /Users/username/Library/Caches/Homebrew/downloads/f296d5096dd9f65d61d3720b2bab7a21bcba6e160c3d5c3857c5570167278881--node-build--4.9.126.all.bottle.tar.gz
==> Fetching nodenv
==> Downloading https://ghcr.io/v2/homebrew/core/nodenv/blobs/sha256:a4bbb8b27f85d0d3ee3628e9360a1f3eb42f0b3fef3c26bc23182d15da620e42
Already downloaded: /Users/username/Library/Caches/Homebrew/downloads/f955146912b8fe63d53a5c78beb711f3bf5e4a3ed92b19f0464ac2417d10f630--nodenv--1.4.1.sonoma.bottle.tar.gz
==> Installing dependencies for nodenv: ca-certificates, openssl@3 and node-build
==> Installing nodenv dependency: ca-certificates
==> Downloading https://ghcr.io/v2/homebrew/core/ca-certificates/manifests/2023-08-22
Already downloaded: /Users/username/Library/Caches/Homebrew/downloads/a8cd32e30cae0b7335779e93a6554f294f09485802fc253a3a8be441337a6115--ca-certificates-2023-08-22.bottle_manifest.json
==> Pouring ca-certificates--2023-08-22.sonoma.bottle.tar.gz
cp: /usr/local/Cellar/ca-certificates/./2023-08-22: Permission denied
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22: unable to copy extended attributes to /usr/local/Cellar/ca-certificates/./2023-08-22: Permission denied
cp: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/.brew: unable to copy extended attributes to /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew/ca-certificates.rb: No such file or directory
cp: utimensat: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: chown: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: chmod: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: chflags: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/.brew: unable to copy ACL to /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/share: unable to copy extended attributes to /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/share/ca-certificates: unable to copy extended attributes to /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates/cacert.pem: No such file or directory
cp: utimensat: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: chown: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: chmod: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: chflags: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/share/ca-certificates: unable to copy ACL to /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: utimensat: /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: chown: /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: chmod: /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: chflags: /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/share: unable to copy ACL to /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: utimensat: /usr/local/Cellar/ca-certificates/./2023-08-22: No such file or directory
cp: chown: /usr/local/Cellar/ca-certificates/./2023-08-22: No such file or directory
cp: chmod: /usr/local/Cellar/ca-certificates/./2023-08-22: No such file or directory
cp: chflags: /usr/local/Cellar/ca-certificates/./2023-08-22: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22: unable to copy ACL to /usr/local/Cellar/ca-certificates/./2023-08-22: Permission denied
cp: utimensat: /usr/local/Cellar/ca-certificates/.: Permission denied
Error: Failure while executing; /usr/bin/env cp -pR /private/tmp/d20231013-7085-idhfho/ca-certificates/. /usr/local/Cellar/ca-certificates
exited with 1. Here’s the output:
cp: /usr/local/Cellar/ca-certificates/./2023-08-22: Permission denied
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22: unable to copy extended attributes to /usr/local/Cellar/ca-certificates/./2023-08-22: Permission denied
cp: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/.brew: unable to copy extended attributes to /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew/ca-certificates.rb: No such file or directory
cp: utimensat: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: chown: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: chmod: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: chflags: /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/.brew: unable to copy ACL to /usr/local/Cellar/ca-certificates/./2023-08-22/.brew: No such file or directory
cp: /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/share: unable to copy extended attributes to /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/share/ca-certificates: unable to copy extended attributes to /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates/cacert.pem: No such file or directory
cp: utimensat: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: chown: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: chmod: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: chflags: /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/share/ca-certificates: unable to copy ACL to /usr/local/Cellar/ca-certificates/./2023-08-22/share/ca-certificates: No such file or directory
cp: utimensat: /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: chown: /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: chmod: /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: chflags: /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22/share: unable to copy ACL to /usr/local/Cellar/ca-certificates/./2023-08-22/share: No such file or directory
cp: utimensat: /usr/local/Cellar/ca-certificates/./2023-08-22: No such file or directory
cp: chown: /usr/local/Cellar/ca-certificates/./2023-08-22: No such file or directory
cp: chmod: /usr/local/Cellar/ca-certificates/./2023-08-22: No such file or directory
cp: chflags: /usr/local/Cellar/ca-certificates/./2023-08-22: No such file or directory
cp: /private/tmp/d20231013-7085-idhfho/ca-certificates/./2023-08-22: unable to copy ACL to /usr/local/Cellar/ca-certificates/./2023-08-22: Permission denied
cp: utimensat: /usr/local/Cellar/ca-certificates/.: Permission denied
Error: Failure while executing .....Permission denied
エラー原因
nodenvのインストールの際に/usr/local/Cellar/
ディレクトリ配下にあるファイルにnodenvに関する内容を書き込もうとしたが、/usr/local/Cellar/
ディレクトリ配下に書き換えの権限が与えられておらず、書き込めませんという権限エラーが発生したということでした。
通常、/usr/local/Cellar/
ディレクトリは、homebrewなどのパッケージ管理システムを使用してインストールしたパッケージの実行ファイルやライブラリ、設定ファイル等が保存されるディレクトリになります。
構造としては、以下のようになっており、パッケージごとにディレクトリを作成し、各パッケージディレクトリ内には、バージョンごとにサブディレクトリを作成することで、異なるバージョンのパッケージを競合なく管理することができます。さらにバージョン変更も簡単に行うことができます。
/usr/local/Cellar/ ├─ nodenv (package1)/ │ ├─ Node.js version1/ │ │ └─ ... (パッケージ1のバージョン1のファイル) │ └─ Node.js version2/ │ └─ ... (パッケージ1のバージョン2のファイル) ├─ package2/ │ └─ ... (パッケージ2のファイル) └─ ...
これで、homebrewなどのパッケージ管理システムが、ディレクトリを分けることによって、複数のパッケージを競合なく管理できる仕組みを持っていることが分かりました。
解決法
下記のコマンドで、/usr/local/Cellar/
ディレクトリ配下のディレクトリ・ファイル全ての所有者を現在のユーザー (${USER}
・$(whoami)
) に変更し、permission errorを解決します。
$(brew --prefix)/*
は、homebrewのインストール先のすべてのディレクトリ、ファイルことなので、/usr/local/Cellar/
ディレクトリ内のすべてのディレクトリ、ファイルと言い換えることができます。
/usr/local/Cellar/ディレクトリ配下のファイル全ての所有者を${USER}で環境変数を使って取得した現在のユーザー名に変更する
$ sudo chown -R ${USER}:staff /usr/local/Cellar/ または、
Homebrewでインストールしたパッケージのルートディレクトリ配下全ての所有者を$(whoami)で取得した現在のユーザー名に変更する
$ sudo chown -R (whoami)(whoami) (whoami)(brew --prefix)/*
しかし、また新たなエラーが発生!!
$ brew install nodenv ・・・・ ==> Pouring openssl@3--3.1.3.sonoma.bottle.tar.gz Error: Cannot link openssl@3 Another version is already linked: /usr/local/Cellar/openssl@3/3.1.3
原因
brewが、openssl@3をインストールしようとした時に既存のopenssl@3との競合を解決できず、openssl@3とリンクできません。というエラーが発生したようです。
brewを使って、インストールしたopensslの一覧を表示すると、openssl@3/3.1.3がインストールされていました。
$ brew list openssl /usr/local/Cellar/openssl@3/3.1.3/.bottle/etc/ (7 files) /usr/local/Cellar/openssl@3/3.1.3/bin/c_rehash /usr/local/Cellar/openssl@3/3.1.3/bin/openssl /usr/local/Cellar/openssl@3/3.1.3/include/openssl/ (135 files) /usr/local/Cellar/openssl@3/3.1.3/lib/libcrypto.3.dylib /usr/local/Cellar/openssl@3/3.1.3/lib/libssl.3.dylib /usr/local/Cellar/openssl@3/3.1.3/lib/engines-3/ (3 files) /usr/local/Cellar/openssl@3/3.1.3/lib/ossl-modules/legacy.dylib /usr/local/Cellar/openssl@3/3.1.3/lib/pkgconfig/ (3 files) /usr/local/Cellar/openssl@3/3.1.3/lib/ (4 other files) /usr/local/Cellar/openssl@3/3.1.3/share/doc/ (798 files) /usr/local/Cellar/openssl@3/3.1.3/share/man/ (5533 files)
解決法
一度、既存のopenssl@3のリンクを解除して、インストール再設定をすることで解決しました。
既存のopenssl@3のリンクを解除
$ brew unlink openssl@3
openssl@3を再度インストール
$ brew install openssl@3
openssl@3のリンクを再設定
$ brew link openssl@3
参考
https://superuser.com/questions/1425577/brew-install-r-permission-denied
https://gist.github.com/irazasyed/7732946
Railsにおけるバリデーションの設定方法
バリデーションとは、正しいデータのみがデータベースに保存されるようにモデルクラスにて、そのデータが正しいかどうかをチェックするシステムのことを言います。バリデーションに引っかかり、データが不正だと判断された場合は、データベースに保存されません。
バリデーションは、正しいデータだけをデータベースに保存するために行われます。正しいデータだけをデータベースに保存するのであれば、モデルレベルでバリデーションを実行するのが最適です。モデルレベルでのバリデーションは、データベースに依存せず、エンドユーザーがバイパスすることもできず、テストもメンテナンスもやりやすいためです。Railsではバリデーションを簡単に利用できるよう、一般に利用可能なビルトインヘルパーが用意されており、独自のバリデーションメソッドも作成できるようになっています。
バリデーションの設定方法
validates :カラム名, presence: true validates :カラム名, length: { maximum: 30 } validates :カラム名, numericality: { greater_than: 0 }
presence: true
は、カラムのデータは、必ず存在する(空のデータでは、保存できないように制限)ように設定したバリデーションです。length: { maximum: 30 }
は、カラムの文字数を最大30文字に制限するバリデーションです。(30文字以上のデータは、DBに保存されない)numericality: { greater_than: 0 }
は、0以上の数値のみの入力を許可するバリデーションです。
numericalityのオプション | 概要 |
---|---|
only_integer | integerのみ |
equal_to | 指定された値と等しいか |
greater_than_or_equal_to | 指定された値以上 |
less_than_or_equal_to | 指定された値以下 |
greater_than | 指定された値よりも大きいか |
less_than | 指定された値よりも小さいか |
odd | trueに設定した場合、奇数か |
even | trueに設定した場合、偶数か |
has_many :through関連付け
has_many :through
関連付けは、他方のモデルと「多対多」のつながりを設定する場合によく使われます。 この関連付けでは、2つのモデルの間に「第3のモデル」(joinモデル)が介在し、それによって相手のモデルの「0個以上」のインスタンスとマッチします。
class Restaurant < ApplicationRecord has_many :line_foods, through: :foods end
- 1つのRestaurantは中間テーブルFoodsを経由して複数のLine_foodを持っています。
has_many :through
を使うと、1つのレストランにつき仮注文は、複数作成できますが、その仮注文は、foodテーブルを参照していますよという意味になります。
belongs_toのoptionalオプション
optional: true
とは、アソシエーションによって紐づけられた外部キーの値が存在しない値やnilの場合でも、データベースに保存することができるオプションです。
class LineFood < ApplicationRecord belongs_to :order, optional: true end
- 上記の例で言うと、仮注文テーブルの外部キーにorder_idがセットされていない場合でもバリデーションチェックが行われることなくDBに保存できるようになります。
optional: true
を設定すると、**belongs_toの外部キー
のnil
(存在しないこと)を許可**します。
インスタンスメソッドとは?
インスタンスメソッドとは、クラスから作成されたオブジェクトに対して、呼び出せるメソッドのことです。インスタンスメソッドをコントローラーではなく、モデルに記述すると、様々な箇所からオブジェクトに対して呼び出すことができます。
- 特定のデータ(インスタンス)に対する操作は、インスタンスメソッドが使われます。
- 対して、クラスメソッドは、クラス全体に対する共通の操作を行いたい時に使われます。
- クラスメソッドの定義は、
self.メソッド名
のようにメソッド名の前にself
をつける必要があります。
ルーティングの名前空間について
namespace: 名前空間名
で**名前空間**をつけられます。名前空間をつけることのメリットは、コントローラーを名前空間名のディレクトリで、クループ化するとともに、URLにも名前空間の情報をつけることが出来ることです。 つまり、名前空間というディレクトリを作成することにより、分かりやすくグループ化したルーティングを作成できるようになります。
namespace :a do namespace :b do ... end end
- コントローラーを
app/controllers/a/b/
という**ディレクトリに分類し、それをURLにも適用するためにnamespaceが使われています。namespace**であるa
とb
が入ったURLでルーティングを作成できます。
ルーティングを作成するresourcesメソッドとresourceメソッド
どちらもルーティングを簡単に作成するためのメソッドです。基本的なアクション(index、show、new、create、edit、update、destroy)に対応するURLの組み合わせ(ルーティング)を作成します。
resorcesメソッド
「resourcesメソッド」は、7つのアクション(index、show、new、create、edit、update、destroy)のidを付与したルーティングを一括生成してくれるメソッドです。
resourceメソッド
「resourceメソッド」は6つのアクション(show、new、create、edit、update、destroy)のルーティングがidなしで生成されます。加えて、「resourceメソッド」はindexアクションのルーティングが生成されません。
resourcesとresourceの使い分け
resources :restaurants do resources :foods, only: %i[index] end
resources
は、リソースが複数ある場合に使用します。ルーティングに付与されるidを使って、複数あるリソースを識別します。- 上記の例で、レストランは、あちらこちらにたくさん存在するので、
resources
を使用しています。
resources :users do resource :profile end
resource
は、リソースが1つしかない時に使用します。リソースが複数ではないため、リソースの一覧ページを表示する必要性がありません。よって、resource
では、indexアクションに対するルーティングが作成されないのです。- 上記の例では、特定のユーザーに対するプロフィール情報は、1つなので
resource
を使用しています。
saveとsave!メソッド
- saveメソッドは、生成したモデルオブジェクトをデータベースに保存します。データベースに保存できなかった場合は、
false
を返します。 - 一方save!メソッドは、同じく生成したモデルオブジェクトをデータベースに保存しますが、保存に失敗した場合は、例外を発生させます。
- 例外を発生すると、例外が起きた場所で処理を停止します。
参考
【Rails】外部キーのバリデーションチェックを回避するoptional: trueについて簡単にまとめてみた
【Rails】resourcesメソッドとresourceメソッドの違いについて簡単に解説!
RailsにおけるDBとMigrationファイルModelの役割とその関係
- どんなデータベースを作って欲しいかを指示するデータベースの設計図が
Migrationファイル
です。- あるテーブルにこんなカラムが必要、そのカラムに対する型や制約を指示するもので、Migrationファイルを元にDBが作成されます。
- Railsのmodelは、DBのテーブルに対応するRubyのクラスです。テーブル内のデータがどんなもので、テーブル同士の関係がどうかというアソシエーション関係を定義できます。また、データベースとの間で情報のやり取り(データの取得・保存・検索)を行います。
- モデルおよびモデル内のデータを表現する
- モデル同士の関連付け(アソシエーション)を表現する
- 関連付けられているモデル間の継承階層を表現する
- データをデータベースで永続化する前にバリデーション(検証)を行なう
- データベースをオブジェクト指向スタイルで操作する
- 実際にデータが表のように保管されている箱のようなものが
データベース
です。- データベースとのやりとりを行うのは、モデルです。
RailsプロジェクトをAPIモードで作成する
$ rails new プロジェクト名 --api
APIモードとは?
Rails APIモードとは、API作成に特化したモードのことです。
APIモードではMVCのV(ビュー)が存在しないため、rails newを実行した際にビューに関するファイルやGemが生成されません。
また、通常のRailsアプリケーションではerbファイルをレスポンスとして返しますが、APIモードではJSONをレスポンスに返します。
つまり、Reactなどを使って、非同期的にAPIから外部のデータを取得する場合、JSONデータをレスポンスとして返すRailsの**APIモード**を使います。
外部キーの役割
外部キーとはモデル間のリレーションを辿る際の基準となるキーのことです。外部キーを使って、テーブル間のアソシエーション関係を表すことが出来ます。あるテーブルに紐づいたデータを作成したいときに外部キーを使うと自動で紐づいたデータがDBに作成されます。
参考
【Rails】Rails5から追加された機能「APIモード」について初心者向けにまとめてみた
インクリメント演算子とデクリメント演算子
**インクリメント演算子は、値を1加算し、デクリメント演算子**は、1減算します。 - 前置の場合は、加算・減算後の値を返すのに対し、後置の場合は、計算する前の値が返ります。
演算子 | 演算子名 | 説明 |
---|---|---|
++EX1 | インクリメント(前置) | EX1の値に+1する |
- -EX1 | デクリメント(前置) | EX1の値に-1する |
EX1++ | インクリメント(後置) | EX1の値に+1する |
EX1- - | デクリメント(後置) | EX1の値に-1する |
比較演算子
比較演算子は、左オペランドと右オペランドの大きさを比較し、その結果について真偽値(true/false)で返す演算子です。
厳密等価演算子(===)と厳密不等価演算子(! ==)について
厳密等価演算子と厳密不等価演算子は、どちらも2つのオペランドの型と値を比較します。厳密等価演算子は、2つのオペランドの値が合っていても型が合わない場合は、trueが返りません。
3 === 3 3 === "3"
しかし、等価演算子(==)を使うと、型が異なる場合でも同じ値であれば、自動的に暗黙の型変換が行われ、以下のように文字列の3と数値の3は同じとみなされてしまいます。
3 == 3 3 == "3"
厳密等価演算子と厳密不等価演算子を使うメリットは、暗黙的な型変換を防ぎ、型の安全性を保証してくれるという部分です。
等価演算子(==)を利用するケース
「nullまたは、undefined」を一度に判定したい場合は、例外的に等価演算子(==)が使われます。これは、厳密等価演算子がnullとundefinedを比較するとfalseと評価されるのに対し、等価演算子と使うとtrueと評価されるからです。
null === undefined null == undefined
参考
クラスとは
全てのオブジェクトが持つそのオブジェクトの原型のことです。
"おはよう".class => String
- 「おはよう」という文字列のクラスを調べると、Stringクラスということが分かります。
- classというメソッドを使って、どのクラスに属するのかということを調べます。
オブジェクトに対して、どんな機能を持たせるかは、そのオブジェクトがどのクラスに属するかによって決まります。クラスによって予め持っているメソッドなどが異なるためです。
"おはよう".length => 4
4.length
(irb):4:in <main>': undefined method
length' for 4:Integer (NoMethodError)
- 「おはよう」という文字列オブジェクトは、Stringクラスに属するため文字数を調べることができるlengthメソッドを使用することができます。
- 一方で、integerクラスに属する数値の4は、lengthメソッドを使用することができません。これは、integerクラスがlengthメソッドを持っていないからです。
今まで出てきたStringクラスやIntegerクラスのようにRubyが標準的に用意しているクラスの他にも、自分のやりたいことに合わせてクラスを作成することもできます。
クラスとインスタンス
クラスは、オブジェクトの原型であると説明しました。代わって、**インスタンスは、クラスを元にして作られたオブジェクトのことです。 1クラスからは、インスタンス**を生み出すことができ、作成されたインスタンスは、クラスが持つ属性やメソッドを持っています。
例) 分かりやすく例えると、クラスはたい焼きの金型であると言えます。金型を元にして、実際に作られるたい焼きがインスタンスになります。
クラスであるたい焼きの金型があることで、小倉あんのたい焼きや抹茶味のたい焼き、クリーム味のたい焼きなどの様々なたい焼きインスタンスを作り出すことができるのです。
変数
変数とは、コンピュータプログラムのソースコードなどで、データを一時的に記憶しておくための領域に固有の名前を付けたもの。
e-Words
label = "おはよう" => "おはよう"
p label => "おはよう"
- あるオブジェクトを参照したい時にそのオブジェクトの参照口を指し示してアクセスできるように名前をつけたものです。
- labelという変数に文字列「おはよう」を代入すると、変数を使うだけで、文字列「おはよう」を参照できるようになります。
変数には、プログラム中の一定の処理の範囲で使われ、その範囲が終わったら捨てられるローカル変数とオブジェクトの内部に保持されてオブジェクトが存在する限り一緒に存在する**インスタンス変数**があります。
- ローカル変数とは、プログラム中のブロック(関数やメソッドなど)の内部で宣言され、その範囲内でのみ有効な変数のことです。
- インスタンス変数とは、個々のインスタンスごとの固有の変数です。インスタンスの情報が入った変数のことで、メンバ変数、フィールドとも言われます。
メソッド
オブジェクトの振る舞いをメソッドと言います。色々な処理をひとつにまとめてメソッドとして定義することで、何度も再利用(実行)ができるようになります。
インスタンスに対して、呼び出せるメソッドは**インスタンスメソッドと呼ばれ、クラス内に定義します。インスタンスメソッド**をクラス内に定義することで、別のインスタンスにも同じような振る舞いをさせることができるのです。
class Human
def walk
puts "歩きます"
end
end
humanA = Human.new()
humanA.walk
参考
MPAとは
ブラウザから「こういうページがほしい」とHTTPリクエストをもらうと、Webサーバーは内部でHTMLを組み上げ、JavaScriptやCSSと一緒にHTTPレスポンスを返します。重要なのは、この処理がページを遷移するごとに毎回行われるということです。
SPA, SSR, SSGって結局なんなんだっけ?
- SPAと対照的にMPAでは、 差分検出をすることなく、リクエストごとに毎回サーバー側でHTMLの作成が行われページ全体が更新されます。その結果、ページの更新に時間がかかるなどパフォーマンスが悪くなるデメリットがあります。
- MPAでのパフォーマンスの問題を解決するひとつとしてSPAがあります。
SPAとは
初回リクエスト時にページの基本となるHTMLやCSS、JavaScriptをサーバーから受け取り、その後は必要なデータだけをサーバーに要求し、その変更差分を表示する方式で、ページを更新します。 SPA, SSR, SSGの違いについて図解でまとめてみた
- ページ全体を読み込むのは、初回リクエスト時のみで、ページ更新時はサーバーからデータのみを受け取り変更差分を更新します。
- ページの更新時にサーバーから受け取るデータは、**JSON形式**(JavaScript)で非同期に受け取ります。(Ajax通信)
- ブラウザ更新時にJSON形式で受け取ったデータをもとにクライアント側(ブラウザ)で、HTMLを構築し、変更差分を反映させたページを作成します。
- SPAは、クライアント側でページを生成するため、**CSR**(client side rendering)とも呼ばれます。
- SPAは、更新時に非同期で必要なデータのみを受け取るため、更新時間を素早くできるなどのメリットがあります。
- 一方で、SPAは、**SEOに弱い**などのデメリットもあります。
SPA(シングルページアプリケーション)サイトはGoogleに正しく認識されないため、SEO的には最悪だと言われてきました。そのため、SSR(サーバサイドレンダリング)をし、初回画面表示時は本来ReactやAngularが生成するhtmlを、サーバサイドでレンダリングしてクライアント側はそれを表示するだけ、という手法を用います。
SSR無しのReact・Angular製のSPAサイトはGooglebotにどれくらい認識されるのか?
SSRとは
ブラウザ上で初期データをレンダリングするのではなく、サーバー側でAPIを叩き、レンダリングまでを行ってからHTMLファイルを返却する。
SSRでは、初回リクエスト時にサーバーにリクエストが走ります。初回リクエストを受け取ったサーバーは、APIと連携をして初回データを反映したHTMLを構築し、そのHTMLをブラウザに返すレンダリングまでを行います。つまり、SSRでは、サーバー側でページを構築し、ページを返すレンダリングまでが行われるため、Server Side Renderingと呼ばれます。
2回目以降のリクエストは、直接ブラウザからAPIにアクセスしデータを取得しに行きブラウザ上でデータを反映したページを生成してレンダリングを行います。
**SSR**では、SPAで挙げられる問題点を解決するためにSPAと組み合わせて使われるアーキテクチャです。 - 初回ページ表示までの時間が早い - SEOに強い
しかし、サーバー側の負担が大きくなるなどのデメリットもあります。
SSGとは
アプリケーションのビルド時(アプリケーションがサーバーにデプロイされるタイミング)にサーバーが**API**から必要な初期データ等を取得し、そのデータを反映したHTMLを作成します。
重要なのは、HTMLの作成が行われるタイミングがサーバーへのリクエスト時ではなく、ビルド時であることです。
よって、サーバーへリクエストがあると、ビルド時に作成済みのHTMLファイルを返却するだけなので、素早くページの更新ができるようになります。 SPA, SSR, SSGの違いについて図解でまとめてみた
- SSGでは、事前にビルドしたタイミングで、サーバーがデータ取得を行いレンダリングが行われるので、そのことをプリレンダリング(事前描画)と言います。
- レンダリングとは、表示用のデータをもとに、内容を整形して表示することです。
- SSGは、リクエスト時にかかるサーバーへの負荷がかからないのがメリットです。
- ただし、ページ量が多いWebサイトなどだと、ビルド時にかかるサーバーへの負担が大きくなります。
まとめ
- データを取得するには、**API**へアクセスを行う
- SPAでは、ブラウザ側(クライアント)でページを生成するのに対し、SSR、SSGでは、サーバー側でページの生成を行う。
- SPAでは、ブラウザ側(クライアント)でページの生成が行われるため、CSRと呼ばれる
- SPA、SSR、SSGは、それぞれデータ取得のタイミングが異なるのと、ページ生成の場所が異なるだけです。
参考
SPAの基本と3大JavaScriptフレームワーク(Angular、React、Vue.js)の最新動向 ~2020年版~
SSR無しのReact・Angular製のSPAサイトはGooglebotにどれくらい認識されるのか?
誤ってmasterブランチでコミットしてしまっても、そのコミットの変更内容を別のブランチに移すことで対処できます
① どこのコミットまで変更内容を移したいのか確認する
$ git log --oneline master
813c118 (HEAD -> master) Add:
a7ba267 Add: 〇〇〇〇
3dfd56a Add: 〇〇〇〇
7dd0b34 (origin/master) Merge pull request
2a3701c (origin/development)
ede71f6 Add:〇〇〇〇
8a05884 Add: 〇〇〇〇
a1f10f4 first-commit
上記より、7dd0b34
から上の3つのコミットが誤ってコミットしてしまった部分だと分かります。
② 変更の移動先となるブランチがまだ作成されていない場合は、移動先となるブランチを作成します
$ git checkout -b ブランチ名
$ git branch
③ git reset --hard
コマンドでmasterブランチから移動したい変更のコミットを削除します
今回は、3つのコミットを移動させたいので、masterブランチから最新の3つ分のコミット履歴を削除します。ただし、git reset --hard
を使う場合は、プッシュ前のコミットに対してのみ、使うようにしましょう。
HEAD
は、今自分がいるブランチの先頭のことで、自分が作業している場所を示すポインタです。
$ git branch
- master posts
$ git reset --hard HEAD~3 HEAD is now at 7dd0b34 Merge pull request
$ git log --oneline master 7dd0b34 (HEAD -> master, origin/master) Merge pull request 2a3701c (origin/development) Add:〇〇〇〇 ede71f6 Add:〇〇〇〇 8a05884 Add: 〇〇〇〇 a1f10f4 first-commit
これで、今いるmasterブランチの先頭がリモートリポジトリの内容をプルした部分まで巻き戻りました。
④ 移動したいブランチで作業の続きを行います
masterブランチのコミットは削除しましたが、移動したブランチ内ではコミット履歴が残っていることが確認できました。
$ git checkout posts
$ git branch
- master posts
$ git log --oneline posts 813c118 (HEAD -> posts) Add: 〇〇〇〇 a7ba267 Add: 〇〇〇〇 3dfd56a Add: 〇〇〇〇 7dd0b34 (origin/master, master) Merge pull request 2a3701c (origin/development) Add:〇〇〇〇 ede71f6 Add:〇〇〇〇 8a05884 Add: 〇〇〇〇 a1f10f4 first-commit
参考
[Git]誤ったブランチで実施した変更を正しいブランチに移動する | DevelopersIO
第6話 git reset 3種類をどこよりもわかりやすい図解で解説!【連載】マンガでわかるGit ~コマンド編~ - itstaffing エンジニアスタイル