OmniAICreator/Qiita-1.07M huggingface dataset:
Railsでmigrationかけた後にブランチをチェックアウトしてしまった時の復旧方法

rails db:migrate掛けたことを忘れて、新ブランチにチェックアウトした後
既にテーブルが作成されていることからmigrateができなくなってしまった時の復旧方法

まず、migrateしてしまった時のブランチにチェックアウトします。

そして以下のコマンド
```zsh
rails db:migrate:status
```

そうするとこうなっているはず。
```zsh
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20220606000001  Create hoge
   up     20220606000002  ********** NO FILE **********
  down    20220606000003  Create fuga
```
********** NO FILE **********
これはmigrate した後にコミットしなかったことで、存在しないファイルがmigrateされているということ。

このNO FILEをrollbackさせるときは、同じタイムスタンプのmigarteファイルを作成して、changeの中身を空にします。
```20220606000002_piyo.rb
class Piyo < ActiveRecord::Migration[6.0]
  def change
  end
end
```

そしてrollbackします。

```zsh
rails db:rollback
```

これでチェックアウト前の、間違ってmigarteしたブランチの復旧は完了。

そして問題は、新ブランチ。
ここでもチェックアウト前にmigrateした過去を引き継いでいるので、テーブルが作成されていた。

そのテーブルが存在していることにより、migrate上ではdownになっているが、DBにtableが存在しているためmigrateができない状態となっていた。

なので、MySQLに入ってtableをdropする必要がある。
```zsh
rails db:
# これでMySQLに入る
Enter password:
```

パスワードはdockerを使用していればdocker-compose.ymlに記載があるはず。
パスワード入力したら以下を実行

```zsh
MySQL [hoge]> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| hoge_app           |
| hoge_app_test      |
| performance_schema |
| sys                |
+--------------------+
6 rows in set (0.00 sec)
```
dbを選択する。おそらく他の環境でもhoge_appだと思う、
```zsh
MySQL [hoge]> SHOW TABLES FROM hoge_app;
+-------------------------------+
| Tables_in_hoge_app            |
+-------------------------------+
| user                          |
| post                          |
| company                       |
| etc...                        |
```

色々テーブルがあると思うが、今回dropしたいテーブルがcompanyであれば、以下のコマンドで削除する。
`MySQL [hoge]> DROP TABLE db名.table名;`
```zsh
MySQL [hoge]> DROP TABLE hoge_app.company;
```

この際、自分の環境では以下のエラーが発生した。
```zsh
ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails
```

どうやらforeign keyが消せないぽい。
これは調べたところによると、一旦foreign keyの設定をOFFにすることで回避できるらしい。

```zsh
mysql> SET FOREIGN_KEY_CHECKS = 0;
Query OK, 0 rows affected (0.01 sec)
```

OKが出たら、再度tableをdropする。
```zsh
MySQL [hoge]> DROP TABLE hoge_app.company;
Query OK, 0 rows affected (0.03 sec)
```

これで、companyテーブルは消えている。
```zsh
MySQL [hoge]> SHOW TABLES FROM hoge_app;
+-------------------------------+
| Tables_in_hoge_app            |
+-------------------------------+
| user                          |
| post                          |
| etc...                        |
```
そしたら、foreign keyの設定を元に戻す。
```zsh
mysql> SET FOREIGN_KEY_CHECKS = 1;
Query OK, 0 rows affected (0.01 sec)
```

ここで無事、migrateが通るはず。
```zsh
MySQL [hoge]> exit
Bye

rails db:migrate
```

お疲れ様でした。
以下、参考にさせていただいた記事です。ありがとうございます。

コード上では問題なくても、railsではmigrationを記憶しているので
こういった作業が必要になるわけですね。

次回からブランチを切る時は気をつけたいと思います。

参考：
https://qiita.com/r_sk00002/items/9bf321f81d3b84042694
https://qiita.com/YotaHamasaki/items/4f94dde7dcce4f01f209
https://proengineer.internous.co.jp/content/columnfeature/6745#section700
SSL/TLSとは(整理)

背景：　SSL/TLS周りが仕事で出てきて混乱したので整理

# SSL/TLS
[Wikipediaの要約](https://ja.wikipedia.org/wiki/Transport_Layer_Security)
SSL: Secure Socket Layer
TLS: Transport Layer Security
1. 通信を暗号化
1. 通信相手の認証
1. 改ざんの検出
の機能を提供するプロトコル

>SSL/TLSで得られるのは、機密性"confidentiality"、完全性"integrity"、真正性"authenticity"5の3要素です。
ー[*SSL/TLSの見落とされがちな「認証」という基本機能 - Qiita*](https://qiita.com/angel_p_57/items/dcb12a6a864f9aeba427)

正しい呼び方はTLSで，前身のSSL呼びが習慣で残ってる
2022年現在の最新版はTLS 1.3（まだメジャーバージョン1なんだね)
HTTPはもちろん，多くのアプリケーション層プロトコルで採用されている

- 利用方法
  - 先に下位層(TCPとか)の接続後にTLS接続を確立し，アプリケーションを開始
  - アプリケーション開始してからTLSへ切り替え(STARTTLS方式)
- セキュリティ上の考察
  - TLS適用の有無と使用アルゴリズムの強度
    - TLS導入→セキュリティ確保ではない
    - 計算能力を使うため何でもかんでも導入しないほうが良い(特に画面遷移しまくるWeb)
    - バージョンや使用するアルゴリズムによっては使用できなくはないが褒められない通信になることもある 
  - 証明書の正当性
    - ルート証明書が本当に意図する認証局のものかどうかの注意
    - 正当な証明書を持ったサーバでも，ユーザの意図したサーバかはわからない
    - サーバ証明書は第三者でも取得できるため，サーバ認証局の発行先を確認する必要がある

## 他の言葉との関連
### 公開鍵暗号
>暗号化と復号に個別の鍵(手順)を用い暗号化の鍵を公開できるようにした暗号方式．
デジタル署名も広義には公開鍵暗号方式になる．(秘匿を目的にしない)

SSL/TLSはプロトコルなのに対して公開鍵暗号は暗号方式
SSL/TLSといプロトコルはネットワーク上で通信を暗号化するために公開鍵暗号という方式を利用する．
そこで確率された通信は，通信相手の認証，改ざんの検出まで行ってくれる．
つまり： 公開鍵暗号方式だけでは通信できず，通信するためにいろいろ決めているのがSSL/TLS
補足：　公開鍵暗号で共通鍵を交換し，実際に通信する際は共通鍵暗号を用いている

### HTTPS
> HTTPによる通信をよりセキュアに行うためのプロトコルおよびURIスキーム．
厳密に言えば，HTTP自体はプロトコルではなく，SSL/TLSプロトコルによって提供されるセキュアな接続の上でHTTP通信を行うことをHTTPSと読んでいる．ウェルノウンポートとして443が使用される．

メッセージを平文で送るHTTPを，SSL/TLSプロトコルを用いてサーバの認証・通信内容の暗号化・改ざん検出を行ってから通信することでセキュリティを高める．
SSLはあくまでHTTPにかぶさっているだけ．
つまり：　HTTPだと危ないのでSSL/TLSで暗号化してる
補足：　
・ 導入に関して，
1: HTTPSは無料発行サービスを除き費用がかかる．
2: SSL証明書(サーバ証明書)を定期的(90d/1y)に更新する必要がある．
・ HTTPSの通信時に関して
1: プロキシサーバを用いてアクセスする場合，プロキシサーバをトンネリングする必要がある場合がある．
2: 上記の場合，CONNECTメソッドを使用する．(GET, POSTとかの一種)
> プロキシは、セキュリティー保護されたサーバーへの接続を開き、セキュリティー保護されたトランザクションには介入せず、データを双方向にコピーします。
ー[*Proxy Server を介した SSL のトンネリング*](https://docs.oracle.com/cd/E19438-01/820-6315/adyef/index.html)

### AES
> Advanced Encryption Standard．共通鍵暗号アルゴリズム．共通鍵の一つで，ブロック暗号に分類される．
同じく共通鍵暗号アルゴリズムのストリーム暗号ではRC4などがある．

SSL/TLSが公開鍵暗号方式で交換する共通鍵で使用できるアルゴリズム．
つまり： AESはSSL/TLSの通信暗号に用いることができるアルゴリズム

### RSA
> 発明者であるロナルド・リベスト、アディ・シャミア、レオナルド・エーデルマンの原語表記の頭文字をつなげてこのように呼ばれる．公開鍵暗号の一つ．
SSL/TLSが公開鍵暗号で使用できるアルゴリズム．
つまり： RSAはSSL/TLSの通信暗号化のための共通鍵を暗号化してやりとりするのに用いることができるアルゴリズム．

### CSR
> Certificate Signing Request．証明書署名要求．公開鍵証明書を申し込むために申請者から認証局へ送られるメッセージのこと．

SSL/TLSでの認証機能で用いるサーバ証明書について，その正当性の証明をCA局に依頼するために，サーバがCA局に送るメッセージ．
つまり： サーバからCA局へサーバ証明書に署名を求めるリクエストメッセージ．

### Base64
>エンコード方式．
データを64種類の印字可能な英数字(A-Za-z0-9+/=)のみを用いて、それ以外の文字を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱うために使用される．
メールやHTTPヘッダー，SSL証明書などに使用される．

SSL/TLSでの認証機能で使用するSSL証明書のエンコードの一つ．このエンコード方法で生成された証明書は．PEMファイルとして保存されることが多い．
つまり： SSL証明書.pemファイルのエンコード方式の一つ

### OpenSSL
> SSL/TLSの、オープンソースで開発・提供されるソフトウェアである。中心となっているライブラリ（C言語）は基本的な暗号化関数と様々なユーティリティ関数を実装している。

つまり： SSL/TLSを実装するのに使用できるオープンソースライブラリ．

# 編集履歴
2022/06/06 公開
2022/06/07 他の言葉との関連にAES，RSA，CSR,Base64，OpenSSLを追加
Devterm A06にArmbianをインストール

Armbian 22.05でDevterm A06がサポートされたのでインストールしてみた。

## イメージの取得 ##
下記から取得可能、

https://www.armbian.com/devterm-a06/

記事作成時点では22.05のBullseyeとJammyがダウンロード可能になっていたが、Bullseyeのほうはイメージが壊れている様子。なのでJammyを使った。[balenaEtcher](https://www.balena.io/etcher/)などでmicroSDカードに焼いてDevtermに挿せば起動する。

## 起動後の設定 ##

指示に従っていけば、

* rootのパスワード設定
* 最初のユーザーのユーザー名とパスワードの設定
* bash/zshの選択
* Locale/Time Zoneの設定
* WiFiの接続

ができる。その後、デスクトップが立ち上がるので、ターミナルを起動してお約束の

```
$ sudo update
$ sudo upgrade -y
```

を実行。Software Updaterのダイアログも出てるけど、上記を実行してからのほうが良さそう。その後Software Updaterを実行したら再起動を促される。

## 音が出ない ##

と思う。ターミナルを起動して、

```
$ alsamixer
```
で、右の方にスクロールしていってOutput 2を上げれば音がスピーカーから出るようになる。ヘッドホンを挿してもスピーカーからの音は止まらないけど…。これはどうやって解決するのか不明。
【Node.js】macOS に nodenv を導入する手順

# 概要
macOS に nodenv を導入する流時の備忘録
および、よく使うコマンド一覧

# nodenv とは
nodenv とは、Node.js のバージョン管理ツールです。
プロジェクトごとに任意の Node.js のバージョンを指定する必要がある場合に、ローカル環境（自分のPC）の Node.js のバージョンを変えるのはとても手間なのでそういったケースで活躍するツールです。

# 導入方法

### インストール

今回は、Homebrew でインストール

```bash
# インストールコマンド
brew install nodenv
```

数分と経たずに完了します。

### 動作確認
ちゃんと入ったか、テキトーなコマンドを実行して確認

```bash
# バージョン確認
nodenv -v

# 実行結果
nodenv 1.4.0
```

# よく使うコマンド一覧

### バージョン設定の適用
nodenv で Node.js を新たにインストールしたり、`npm install -g` で新たにパッケージを導入したりした後には、
それを nodenv に認識させるために以下のコマンドを毎回実行する必要があります。

```bash
# nodenv をリフレッシュする
nodenv rehash
```

### インストール済みのバージョン一覧表示

```bash
# インストールされている Node.js のバージョン一覧
nodenv versions

# 実行結果 (* は選択されているバージョン)
system
15.14.0
16.3.0
* 14.17.0 (set by /{設定ファイルまでの絶対バス}/.node-version)
```

※ 後述のコマンドで「ローカルでのバージョン設定」がなされると、「`.node-version`」というファイルが作成され、そのディレクトリでは自動で設定されたバージョンに切り替わるようになります。

#### 小ネタ：もし「`.node-version`」があるのに、対象の Node.js がインストールされてなかったら
下記のようなエラーメッセージが出ます。

```bash
# v14.17.0 を指定する .node-version があるのに、未インストール場合
nodenv: version `14.17.0' is not installed (set by /{設定ファイルまでの絶対バス}/.node-version)
```

### インストール可能バージョン一覧表示

```bash
# インストール可能な Node.js のバージョン一覧
nodenv install -l

# 実行結果
15.14.0
16.0.0
16.1.0
16.2.0
16.3.0
```

### 指定バージョンのインストール

```bash
# Node.js の v15.14.0 をインストールする
$ nodenv install 15.14.0
```

### 指定バージョンのアンインストール

```bash
# Node.js の v14.16.0 をインストールする
$ nodenv install 14.16.0
```

### バージョン切り替えコマンド
利用する Node.js のバージョンを設定する方法（スコープによって異なるバージョンを設定可能）

```bash
# ローカル（カレントディレクトリ配下）で利用するバージョンを設定する
nodenv local 15.14.0

# グローバル（システム全体）で利用するバージョンを設定する
nodenv global 16.3.0
```
【Git】ローカルからリモートリポジトリのブランチが確認できない

## やりたかったこと
リモートリポジトリから派生してブランチを新規作成

### 実行手順
1. vscodeでコマンドパレットを開く（ショートカット：Ctrl+Shift+P）
1. 「git checkout」と入力して、「Git: Checkout to...」を選択
1. 親ブランチを選択　→　**ここで親ブランチにしたいリモートリポジトリがでてこない！！**

## 原因：リモートのブランチがローカルに反映できていなかった

そもそもGitの仕組みがよく分かってない:baby_tone1:
こんな感じで、ブランチごとローカルに持ってきているみたい
（なんとなく今さわってる変更点だけがやりとりされるんだと勘違いしてた）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524160/30ef2a9f-57a4-d5ef-0497-3ff16b49c879.png)

## 解決方法：一度リモートリポジトリの情報を消して、再度追加する

現在のリポジトリからリモートのリポジトリを削除する
```sh:書き方
$ git remote remove [削除するリモートリポジトリ名]
```
```sh:例
$ git remote remove origin
```
リモートリポジトリの追加
```sh:書き方
$ git remote add [追加するリモートリポジトリ名] [追加したいリポジトリ]
```
```sh:例
$ git remote add origin http://xxxxxx.xxx/xxxx
```
リモートリポジトリの最新の履歴の取得
```sh:例
$ git fetch
```
確認
```sh:例
$ git branch
* (HEAD detached at origin/issue/xxx)
  master
  test
  test2
```
masterブランチに移動してみる
```sh:例
$ git checkout master
Previous HEAD position was 096e3bd949 feature(#xxx):ローカルブランチ新規作成
Switched to branch 'master'
```
再確認
```sh:例
$ $ git branch
* issue/xxx
  master
  test
  test2
```
OK!!

## おまけ：git fetch

git fetch ってなにしてるコマンドかいまいちわかってないので、再確認

- リモート リポジトリからローカル リポジトリにコミット、ファイル、参照をダウンロードする
- リモート コンテンツがダウンロードされるが、ローカル リポジトリの作業状態は更新されず、現在の作業がそのまま残る（git pullよりも安全）
- リモートから最新情報をローカルに持ってくるが、場所は「master」ブランチではなく、「origin/master」ブランチに取り込まれる
    - 「master」ブランチ
        - ローカルの中心となる統合ブランチで、他のローカルの作業ブランチと繋がったもの。
    - 「origin/master」ブランチ
        - ローカルにある、リモートのmasterブランチを追跡するリモート追跡ブランチ。

参考

https://www.atlassian.com/ja/git/tutorials/syncing/git-fetch

https://qiita.com/wann/items/688bc17460a457104d7d
【Unity】RayがSceneビューで表示されなくなった!!??【Ray】

もし作業中にSceneビューでRayが表示されなくなったら、「ギズモメニュー」のオンオフを確認しましょう。

下図は、ギズモメニューがオフの状態です。
SceneビューでRayは非表示となっていますが、機能しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/e9fbbe76-0efd-c75a-19d1-82521b9d6869.png)

下図は、ギズモメニューがオンの状態です。
SceneビューでRayが表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/190b2a00-87e3-1cc3-d88c-a0635d2f7e77.png)
Azure Blob Storage(datastore)にデータを保存


# 記事の動機づけ

Azure ML Serviceを使っていて、生成データをAzure Blob Storage(というかdatastore)へ保存をしようとした際に[こんなwarningが出た](https://docs.microsoft.com/ja-jp/python/api/azureml-core/azureml.data.azure_storage_datastore.azureblobdatastore?view=azure-ml-py#azureml-data-azure-storage-datastore-azureblobdatastore-upload-files)ので、回避策のメモ。

```sh
"datastore.upload_files" is deprecated after version 1.0.69
```

# 改めてやりたいこと

- 何かファイル作成した
    - `AAA.csv`, `BBB.csv`, `CCC.csv`のように、全て拡張子が`.csv`で終わる、としましょうか
- 該当ファイル(`AAA.csv` etc)はローカル環境のパス(`source_path`)に存在し、`datastore`内の`target_path`配下に全`.csv`ファイルをuploadしたい


# コード例

```py
## どこに置きたいか、を指定
target = (datastore, target_path)
## どこから(src_dir)、何を(pattern)、どこへ置きたいか(target)
Dataset.File.upload_directory(src_dir=source_path,
                            pattern='*.csv',
                            target=target)
```

より詳細は、[当該リンク参照](https://docs.microsoft.com/ja-jp/python/api/azureml-core/azureml.data.dataset_factory.filedatasetfactory?view=azure-ml-py#azureml-data-dataset-factory-filedatasetfactory-upload-directory)

`datastore.upload_files`をご利用の際はご注意あれ。


# ご参考
- https://azure.github.io/azureml-cheatsheets/docs/cheatsheets/python/v1/data/#from-local-data
Homebrew とは？インストール手順（macOS）

# 概要
macOS に Homebrew を導入する時の備忘録


# Homebrew とは
「[Homebrew](https://brew.sh/index_ja)（ホームブリュー）」は、macOS および Linux 向けに作られた、パッケージマネージャです。
OS に対して CLI ツールなどの導入・管理ができる便利なやつです。

Homebrew をインストールすると「`brew` コマンド」などが使える様になります

![homebrew_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/07d564b0-4824-e5bd-5458-93b57d02cabb.png)

# 導入するメリット
コマンドだけでツールの導入や管理が行えるので、例えば何かツールをPCに導入する際に「GitHubからリポジトリをクローンして、パスを通す設定をして・・・」とか「使わなくなったから対象フォルダのデータを削除して、念の為、不要なパスやゴミも残ってないか確認して・・・」みたいな作業が省略できます。 

# インストール方法

ターミナルを開いて以下のコマンドを実行するだけです。

```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
すると、以下のように処理が走ります。

![homebrew_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/a7eb8417-4923-bf17-756c-d40551de3059.png)

※ インストール途中で「処理を続行していい？OK なら Enter キー押してね」の様なメッセージが出ます。その時は Enter キー押してあげてください

途中で処理に時間がかかる場合があります。
私の場合は、以下のところで数分チカチカしたまま止まりました。
※ 止まってる or 終わっている様に見えても、終わってませんので強制終了しないようにご注意ください。

![homebrew_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/522fa737-6393-3547-f8c5-45c30bde890f.png)

以下の様に「`Installation successful!`」と表示されたらインストール完了

![homebrew_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787582/2c2ccd85-a8e1-ee2b-5825-d9fea2b86015.png)

# 完了確認
正常にインストールできたかを確かめるために、
バージョン確認コマンドなどで、動作することを確認します。

```bash
# バージョン確認
brew -v

# 実行結果 (以下の様にバージョンが表示されれば OK)
Homebrew 3.4.11
```

これで導入完了です。

---

### おまけ： Homebrew 上の概念・用語

ロゴマークにもある様に、「home-brew」は「自家醸造飲料(ビール、酒)」を意味します。
Homebrew は、「自分のPCにパッケージを導入し、ビルドして使う」という流れを、ビールの自家醸造に関する言葉で処理用語を定義して表現している。

具体的には、ビールの表現に習って、
パッケージの定義（調理法 ＝ formula）を
保存先 `/usr/local/celler` （貯蔵庫 = celler） の中に
`/usr/local/Cellar/インストールパッケージ名/バージョン` （タル ＝ keg）というディレクトリを作ってインストールし、
パッケージ定義をビルド（醸造 ＝ brew）して、
`/usr/loca/bin` にリンクして使う（飲む）
みたいな表現をしているようです。

[公式の用語の説明](https://docs.brew.sh/Formula-Cookbook)を参考に、用語をまとめてみました。

|用語|説明|ビールでの例え|
|:---|:---|:---|
|Formula|パッケージの説明書や手順書<br>（Ruby で書かれている）|調理法・レシピ|
|Keg|Formula のインストール先|熟成用タル|
|Keg-only|Keg があるだけで、Homebrew prefix にリンクされていないもの| - |
|opt prefix|現在有効な Keg のバージョンへのリンク|使用中のタルにつけられた目印|
|Cellar|Keg が格納されるディレクトリ|貯蔵室|
|Tap|公式以外のFormulaやコマンドがおいてあるgitリポジトリ| - |
|Bottle|すぐに使えるように事前にビルドされた Keg のプログラム格納場所|ビールを注ぐボトル|
|Cask|macOS のネイティブアプリをインストールする拡張機能|酒樽置き場|
|Brew Bundle|依存関係を記載する拡張機能| - |
【Linux】ssh-keygenコマンドを実行する際に公開鍵にコメントを付与する方法とは？

# はじめに
業務でssh-keygenコマンドを実行する際に公開鍵にコメントを付与する方法で少し迷ったので、コメントを付与する方法を記事として残したいと思います。

:::note warn
ssh-keygenコマンドを知っている前提での内容になります。
:::

# ssh-keygenコマンドのオプション

以下のオプションを付与するとコメントを付与することが可能。

```bash:オプション
-C コメント
```

# 使用例

:::note info
今回はコメント付与の紹介にフォーカスしているため、暗号化方式はデフォルトの`rsa`とさせて頂きます。
:::

## コメントを付与するパターン

- 公開鍵と秘密鍵の作成

```zsh:コマンド
ssh-keygen -f ~/.ssh/id_test_key -C "comment"
```

コマンドを実行すると、パスフレーズ(パスワード)が聞かれるので入力する。
※そのまま`Enter`を押下するとパスフレーズ無しにすることが可能

```zsh:実行例
% ssh-keygen -f ~/.ssh/id_test_key -C "comment"
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/ma-sato/.ssh/id_test_key
Your public key has been saved in /Users/ma-sato/.ssh/id_test_key.pub
The key fingerprint is:
〜〜〜〜省略します〜〜〜〜
%
```

- 公開鍵と秘密鍵の確認

公開鍵と秘密鍵が作成されていることを確認。

```zsh
% ls -la ~/.ssh | grep id_test
-rw-------   1 ma-sato  staff  2590  6  6 20:54 id_test_key
-rw-r--r--   1 ma-sato  staff   561  6  6 20:54 id_test_key.pub
%
```

|  ファイル  |  鍵の種類  |
| ---- | ---- |
|  id_test_key  | 秘密鍵(人に見せてはいけない鍵)  |
|  id_test_key.pub  |  公開鍵(人に見せても問題ない鍵)  |

- 公開鍵にコメントが付与されていることを確認

`comment`という文字が付与されている。

```zsh
% cat id_test_key.pub
ssh-rsa AAAAB3NzaC1yc2E　〜〜長いので省略〜〜 XrZ0R4M= comment
%
```

## デフォルトの場合

- 公開鍵と秘密鍵の作成

```zsh:コマンド
ssh-keygen -f ~/.ssh/id_test_key
```

```zsh:実行例
% ssh-keygen -f ~/.ssh/id_test_key
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/ma-sato/.ssh/id_test_key
Your public key has been saved in /Users/ma-sato/.ssh/id_test_key.pub
The key fingerprint is:
〜〜〜〜省略します〜〜〜〜
%
```


- 公開鍵と秘密鍵の確認

公開鍵と秘密鍵が作成されていることを確認。

```zsh
% ls -la ~/.ssh | grep id_test
-rw-------   1 ma-sato  staff  2610  6  6 21:03 id_test_key
-rw-r--r--   1 ma-sato  staff   577  6  6 21:03 id_test_key.pub
%
```

|  ファイル  |  鍵の種類  |
| ---- | ---- |
|  id_test_key  | 秘密鍵(人に見せてはいけない鍵)  |
|  id_test_key.pub  |  公開鍵(人に見せても問題ない鍵)  |

- 公開鍵に`ユーザー名@ホスト名`が付与されていることを確認

`ユーザー名@ホスト名`がデフォルトで表示されるコメントになります。

```zsh
% cat id_test_key.pub
ssh-rsa AAAAB3NzaC1yc2E　〜〜長いので省略〜〜 XrZ0R4M=  ma-sato@pc.elecom
%
```

補足ですが、ユーザー名とホスト名は以下になります。

|  表示名  |  種類  |
| ---- | ---- |
|  ma-sato  | ユーザー名  |
|  pc.elecom  |  ホスト名  |

# 参考記事
https://dev.classmethod.jp/articles/ssh-keygen-tips/

https://atmarkit.itmedia.co.jp/ait/articles/1908/02/news015.html
ファイルを暗号化したい．初めてのOpenssl．（Windows版）

# Intro

パソコンに保存したファイルは簡単に第三者に閲覧可能である．OpenSSLを使用すれば，windowsやLinuxで共有したファイルを容易に鍵をかけることができる．今回はPowerShellを使った暗号化の１例を紹介する．ファイルの暗号化だけでなく，ディレクトリ（フォルダ）の暗号化も行いたいので，圧縮(Zip)してから暗号化する．一連の手順を備忘録として残しておく．

暗号化してから圧縮したばあい，圧縮率は低くなる．
圧縮と暗号化を同時に利用することで，ファイル名がわからなくなるのでセキュアになる．
圧縮ファイルだとわからなくすることでよりセキュアになる．

# Install OpenSSL for Windows 

- Win64 OpenSSl v3.033 Light

https://slproweb.com/products/Win32OpenSSL.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527627/57754e4d-24d9-4ed4-f661-80242baf1b41.png)



# Command
あるフォルダをまるごと暗号化したい場合の手順は次の通りある．
- 対象フォルダの圧縮
- 圧縮フォルダの暗号化
- 圧縮フォルダの復号
- 圧縮フォルダの解凍

```:PS
PS > Compress-Archive -path .\1_hoge -DestinationPath .\2_hoge.zip -F
PS >  openssl enc -e -aes-256-cbc -base64 -pbkdf2 -md sha256 -salt -k pass -in .\2_hoge.zip -out .\3_hoge.zip.enc
PS >  openssl enc -d -aes-256-cbc -base64 -pbkdf2 -md sha256 -salt -k pass -in .\3_hoge.zip.enc -out .\4_hoge.zip
PS > Expand-Archive -Path .\4_hoge.zip -DestinationPath ./5_hoge
```

# Results

無事にフォルダの中身の暗号化と復号ができました．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527627/20f972be-b079-4ec3-ddf0-ef064a3636f1.png)


# References
以下のサイトを参考にしました．

https://atmarkit.itmedia.co.jp/ait/articles/1601/29/news043.html

https://qiita.com/cmpk/items/6a9aec0b0909c5970e18

http://nagatsuki.la.coocan.jp/bunbackup/help/20073722470187.htm
【自分用】GitHubを用いた開発の流れを整理する。

# はじめに
今回は完全に自分用の投稿になります。
GitHubのルールに沿った開発の流れを整理したかった為、ここに記述します。
※下記はGitHubDesktopを使用した流れを想定しています。
# 流れを確認する前に
### リポジトリ
リポジトリとは、Gitの管理下にあるファイルやディレクトリの変更履歴を保管しておく箱。

### ローカルリポジトリ
ローカルリポジトリとは、自分のPC上（ローカル環境）に置くリポジトリ。(PC上)

### リモートリポジトリ
リモートリポジトリとは、外部サーバー上に置くリポジトリ。(GitHub上)

### commit
ファイルやディレクトリの変更修正を、リポジトリに記録。

### コミットメッセージ
どのような修正か分かるように記述

### push
ローカルリポジトリでのコミットをリモートリポジトリに反映。

### commit log
commitを確認できる。GitHub Desktopの「History」のこと。

### インデックス
変更修正が、一時的に保存される場所。保存内容がcommitの対象。

### add
追加するファイルや変更修正をインデックスに登録して、commitの対象にすること。GitHub上のチェックボタンのこと。

# ブランチ
ファイルやディレクトリの変更の流れ。commitの連なり。
masterブランチを中心にトピックブランチに別れる。

# プルリクエスト
ブランチでのコミット履歴を残し、各コミットの変更修正にコメントをつけることができるGitHubの機能。

# コードレビュー
複数人開発で、コードの記述内容に問題がないか、他の開発メンバー等が確認すること。
コードレビューを担当する人をレビュアーという。

# LGTM
Looks Good To Meの略コードに間違いはない。という意味。

# merge
統合。ブランチをリモートリポジトリのmasterブランチに反映。

# pull
リモートリポジトリの変更をローカルリポジトリに取り込む操作。

# GitHubを用いた開発の流れ
## ローカルリポジトリを作成してコミット
1, 「Current Repository」→「Add」→「Add Existing Repository」
2, Chooseでアプリを選択→「Add Repository」
3, 「first commit」→「commit」

## リモートリポジトリを作成
1, 「Publish repository」
2, 「Keep this code private」のチェックを外す
3, 「Publish repository」
4, ブラウザでリモートリポジトリが作成できているか確認

## ブランチを作成
1, 「Current Branch」→「New Branch」
2, ブランチ名入力→「Create Branch」
3, タブがmasterから切り替わっていることを確認
4, 「Publish branch」

## 作業
1, 作成したブランチで作業
2, 「commit」
3, 「Push origin」

## プルリクエスト作成
1, 「Create　Pull　Request」
2, プルリクエストには、What（何を）とWhy（なぜ）を書く

## コードレビュー
1, プルリクエストのURL（https:// github.com/ユーザー名/アプリ名/pull/1のような形になっているURL）を共有することで、他者にレビューを依頼
---以下レビュアー---
2, プルリクエストにコメント「Files changed」
3, コメントを残したい箇所の「+」をクリック
4, 「Start a review」
5, 「Conversation」タブ
6, コメント記入後クリック
---以下作業者---
7, コードを修正
8, 作業報告
---レビュアー---
9, LGTM

## masterブランチへ反映
1, 「marge pull request」
2, 「Confirm merge」
3, 「Delete branch」

## リモートリポジトリの変更をローカルリポジトリに反映
1, マスターブランチに切り替える
2, 「Fetch origin」
3, 「Pull origin」

# まとめ
流れ
①ブランチを切る
②コミット
③プッシュ
④プルリク作成
⑤レビュアーが確認
⑥レビュアーが作業者に修正依頼(修正があれば)
⑦作業者が修正(⑥が行われたら行い、修正後再度プッシュ)
⑧レビュアーからのLGTM
⑨マージ
⑩プル
忘れたら確認。
パスワードの有効期限の変更方法

# はじめに

以前に書いた[ユーザーのパスワードの有効期限を一覧表示する](https://qiita.com/nkojima/items/502119f460017e9e7c1f)という記事では、（ログイン可能な）全ユーザーのパスワードの有効期限日を一覧表示するスクリプトを作ってみました。

今回は上記の記事よりもう少し初歩的な、パスワードの有効期限の変更方法を備忘録としてまとめてみました。

# パスワードの有効期限の確認

* 一般ユーザーでログインしている場合は、`$ chage -l {自身のユーザー名}`で自身のパスワードの有効期限を確認できます。
  * 他のユーザーのパスワードの有効期限については、確認するための権限が無いのでエラーとなってしまいます。
* rootユーザーでログインしている場合は、`# chage -l {任意のユーザー名}`で任意のユーザーのパスワードの有効期限を確認できます。

```shell-session:一般ユーザーの場合
[nkojima@akagi ~]$ chage -l nkojima
最終パスワード変更日                            : 4月 25, 2020
パスワード期限:                                 : なし
パスワード無効化中                                      : なし
アカウント期限切れ                                              : なし
パスワードが変更できるまでの最短日数            : 0
パスワードを変更しなくてよい最長日数            : 99999
パスワード期限が切れる前に警告される日数                : 7
```

```shell-session:rootユーザーの場合
[root@akagi ~]# chage -l root
最終パスワード変更日                            :なし
パスワード期限:                                 : なし
パスワード無効化中                                      : なし
アカウント期限切れ                                              : なし
パスワードが変更できるまでの最短日数            : 0
パスワードを変更しなくてよい最長日数            : 99999
パスワード期限が切れる前に警告される日数                : 7
```

# パスワードの有効期限の変更

* パスワードの有効期限は、`# chage -M {パスワードの有効期間(日数)} {ユーザー名}`というコマンドで設定します。
  * rootユーザーでしか有効期限の変更はできません。
* パスワードを無期限で使えるようにしたい時は`# chage -M 99999 {ユーザー名}`という形で99999日を設定します。

```shell-session:
// 変更前の状態
[root@akagi ~]# chage -l nkojima
最終パスワード変更日                            : 4月 25, 2020
パスワード期限:                                 : なし
パスワード無効化中                                      : なし
アカウント期限切れ                                              : なし
パスワードが変更できるまでの最短日数            : 0
パスワードを変更しなくてよい最長日数            : 99999
パスワード期限が切れる前に警告される日数                : 7

// パスワードの有効期限の設定
[root@akagi ~]# chage -M 180 nkojima

// 変更後の状態
[root@akagi ~]# chage -l nkojima
最終パスワード変更日                            : 4月 25, 2020
パスワード期限:                                 : 10月 22, 2020
パスワード無効化中                                      : なし
アカウント期限切れ                                              : なし
パスワードが変更できるまでの最短日数            : 0
パスワードを変更しなくてよい最長日数            : 180
パスワード期限が切れる前に警告される日数                : 7
```

# 参考URL

* [ユーザーのパスワードの有効期限を一覧表示する](https://qiita.com/nkojima/items/502119f460017e9e7c1f)
* [パスワードの有効期限の設定](https://www.express.nec.co.jp/linux/distributions/knowledge/system/password.html)
リソースコントローラーを用いた際に、定義済みのルートを上書きしてしまってLaravel Route [ ] not defined.が発生。

<問題の概要>
StepControllerというControllerを用いて、ビューファイル(create.blade.php)を表示。
その際に、Route [step.store] not defined.のエラーが発生。

step.storeは、create.blade.php内でformに組み込んだルートの名称。
つまり、step.storeのルート定義が「web.php」内でうまくいっておらず、エラーが発生した模様。

```エラー発生時のweb.php
<?php

use App\Http\Controllers\StepController;
use Illuminate\Support\Facades\Route;

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth'])->name('dashboard');

Route::resource('step', StepController::class);
Route::post('step', [StepController::class, 'complete'])->name('step.complete');

require __DIR__.'/auth.php';
```

上のコードでは、
Route::resource('step', StepController::class);
の直後に
Route::post('step', [StepController::class, 'complete'])->name('step.complete');
を記載しているが、この記載をしたことにより '/step' のpostメソッドを上書きしてしまったのが原因だった模様。

Route::resource('step', StepController::class);は、リソースコントローラーと言って、いかに示す7行分のrouteを1行でかける優れもの。

```
Route::get('step', [StepController::class, 'index'])->name('step.index');
Route::get('step/create', [StepController::class, 'create'])->name('step.create');
Route::post('step', [StepController::class, 'store'])->name('step.store');
Route::get('step/{step}', [StepController::class, 'show'])->name('step.show');
Route::get('step/{step}/edit', [StepController::class, 'edit'])->name('step.edit');
Route::patch('step/{step}', [StepController::class, 'update'])->name('step.update');
Route::delete('step/{step}', [StepController::class, 'destroy'])->name('step.destroy');
```

この7行の中で、'/step' のpostメソッドは「step.store」で定義しているが、直後に書いた「step.complete」も、'/step' のpostメソッドで定義されている。
そのため、step.storeが定義されていないことになりエラーが発生してしまった。

こういったルート定義の問題解決をするためには下記のコマンドを実行して、定義されているルート一覧を表示するのが有効だと学んだ。
```
php artisan route:list
```
asdf/pyenv/python-buildでPythonをインストールしようとするとModuleNotFoundError: No module named '_socket'が出る

# 問題

asdfを使ってPython 3.10.4をインストールしようとしたら、 `ModuleNotFoundError: No module named '_socket'` が出て失敗した。

# 環境と問題のコマンド

環境は以下のとおり。

* macOS Monterey 12.4
* asdf v0.10.1
* asdf-python 57a4d725e47b8624cc97cabcac2b064f0474b8b2

実行したのは以下のコマンド。

```bash
asdf install python 3.10.4
```

# 原因：pyenv（python-build）が悪い

asdf-pythonは内部的にはpyenvを使っている。
もう少し正確に言うと、pyenvはPythonをダウンロードしローカルビルドするためのツールコマンド `python-build` というものを持っていて、 asdf-pythonは `python-build` を実行することでPythonインストールを実現している。

なので探すべきはpyenvリポジトリーのissueだ。

んで、まさしくドンピシャなのがあった。

* https://github.com/pyenv/pyenv/issues/2042#issuecomment-1131463276
* https://github.com/pyenv/pyenv/issues/2042#issuecomment-1132304772

どうやら環境変数として `SDKROOT` と `MACOSX_DEPLOYMENT_TARGET` を指定すればよいらしい。なぜかはわからないが……。
以下のコマンドを実行することで正常にインストールが完了した。

```bash
SDKROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk \
MACOSX_DEPLOYMENT_TARGET=12.3 \
asdf install python 3.10.4
```
Notepad++ でアウトライン(目次みたいなもの)を表示させたい

## 要件
メモ帳的に使っているNotepad++ に、サクラエディタやCotEditor にあるようなアウトライン機能を付けたい。

![Screenshot_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/0445ed1b-5a8f-8c9f-0530-adc11b222e74.png)

## 調査
タグや関数をリスト表示してくれる、Function List というものをカスタマイズすれば
マークダウン形式のテキスト(.md) で見出しなどをリスト表示することができそう。

実際、ここでそれらしいことを実現している人がいる。

https://community.notepad-plus-plus.org/topic/21148/can-i-use-function-list-in-notepad-7-9-5

## 問題

上のURLに記載されているコードをコピペしてFunction List 用XMLを作成しても機能してくれない。。

### UDL

Notepad++ にはUDL(User Defined Language) というものが備わっている。
これを使うとNotepad++で扱う言語をカスタマイズできる。

そして、それぞれの言語にはNotepad++での名前が付けられる。
いま、マークダウン形式のファイル.mdをNotepad++で開いてみると、

![Screenshot_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/cafd5ab2-811d-ae88-539f-88a2ad2d1a47.png)

Language タブから、このファイルがNotepad++上では`Markdown (preinstalled dark mode)`という名前の言語として扱われていることがわかる。

（余談：このときにすぐ上の`Markdown (preinstalled) `を選択すると、Notepad++がダークモードからライトモードへ切り替わってしまった。）

### 解決策

上記URLのソースコードを以下のように変更する。

``` overrideMap.xml
<?xml version="1.0" encoding="UTF-8" ?>

------------ (省略) ---------------

			<!-- ==================== User Defined Languages ============================ -->
			<association id= "markdown.xml" userDefinedLangName="Markdown (preinstalled dark mode)"/>
			<association id= "krl.xml"				userDefinedLangName="KRL"/>
			<association id= "sinumerik.xml"		userDefinedLangName="Sinumerik"/>
			<association id= "universe_basic.xml"	userDefinedLangName="UniVerse BASIC"/>
			<!-- ======================================================================== -->
		</associationMap>
	</functionList>
</NotepadPlus>
```

※`markdown.xml`ファイルはNotepad++ v8.4 にはデフォルトで存在しなかったので、以下の内容で新規に作成しています。

``` markdown.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- ==========================================================================\
|
|   To learn how to make your own language parser, please check the following
|   link:
|       https://npp-user-manual.org/docs/function-list/
|
\=========================================================================== -->
<NotepadPlus>
    <functionList>
        <parser displayName="Markdown (preinstalled dark mode)"
                id="Markdown (preinstalled dark mode)"
                commentExpr="">
            <function mainExpr="(?x-s)(^[#]+\s*(.*?)$|^(.*)(?=[\r\n]+^([-=])\4{2,}\s*$))"/>
        </parser>
    </functionList>
</NotepadPlus>
```

ポイントは**displayName の値を、上記で確認した言語の名前 `Markdown (preinstalled dark mode)` に変えていること。**

これらをインストール先ディレクトリの`C:\Program Files\Notepad++\functionList`に保存。
Notepad++を再起動。

## 解決
![Screenshot_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532781/aed07368-95b2-a2bf-1223-4e14f657d802.png)

`View > Function List`で.mdファイルの関数リストを表示すると、H1とH2が目次のようにリスト表示されていることがわかる。
これがやりたかったんや。

## 要するに


メモ帳はWinキー＋Rで「notepad」と入力すると開けるけど、Notepad++はメモ帳より全然くろうと向けなんですね！

あとこの記事UDLの名前を持ち出しておいて、問題解決にUDLの機能が絡んでないあたり全然ロジカルじゃなくて反省しています。
基本情報（誤差）

10進数で下記のような計算をするとします。

1 / 3 = 0.3333333333333333333333.....

上記を**無限小数**と呼びます。
実際の数値と、コンピュータ内部で表現できる数値との間に生じたずれを、**誤差**と呼びます。

誤差といっても種類があるようなので見ていきます。

## けたあふれ誤差
演算した結果が、コンピュータの扱える最大値や最小値を超えることによって生じる誤差が**けたあふれ誤差**となります。

```     
        | 表現できる範囲 |
数値------------------------→
       MIN           MAX
```
最小値を超えてしまうことを**アンダーフロー**
最大値を超えてしまうことを**オーバーフロー**
と呼びます。

僕の頭は常にオーバーフローです。

```
0.000000000000000000000001
```
浮動小数点数の指数部がパンクして精度が保てない時にアンダーフローが起きるらしいです。

## 情報落ち
絶対値の大きな値と絶対値の小さな値の力加減を行った時に、絶対値の小さな値が
計算結果に反映されないことによって生じる誤差が**情報落ち**となります。

仮数部を4けたであらわす浮動小数点数があったとすると
```
符号 指数部　仮数部
```
下記の足し算をすると
```
0.1234 * 10⁴ + 0.4321 * 10⁻⁴
```
計算するには指数を揃える必要があります。
```
  0.1234          * 10⁴
+ 0.000000004321  * 10⁴
-----------------------
0.123400004321    * 10⁴
```
浮動小数点数のため正規化をします。
0.1234 * 10⁴

## 打切り誤差
計算処理を完了まで待たずに途中で打ち切ることによって生じる誤差が**打ち切り誤差**
例えば
```
3.14159265358979323846....
```
N桁で終わり！と途中で打ち切ると数に誤差が出ます。
その誤差のことです
## けた落ち
絶対値がほぼ等しい数同士の差を求めた時に、有効なけた数が大きく減ることによって生じる誤差が**けた落ち**です
```
0.556 * 10⁷
0.552 * 10⁷

0.004 * 10⁷
// 正規化されると0が自動で付加されるが
0.400 * 10⁵
　   ↑
この桁が正規化する際に、元々0だったという保証がない
```
信用できないけたが増えるとのことです。

## 丸め誤差
表現できる桁数を超えてしまったため、最小桁より小さい部分について、四捨五入や切上げ、切捨てなどを行うことによって生じる誤差が**丸め誤差**です

```
1.100110011001100110011001100
1.10011001100110011001100✖︎✖︎✖︎✖︎

// 捨てられた数の分だけ誤差がでます
```

## まとめ
この辺りは暗記ですね。
誤差ばかり見ていたので、自分の現実と理想の誤差を考えますね。
Nestjs使い方 個人メモ

## Nestjs概要
- 疎結合で管理され、決まったアーキテクチャで構成されるフレームワーク
- 複数で開発する時管理がしやすい
## インストール
- nestコマンドを使えるようにグローバルにインストール
```terminal
npm i -g @nestjs/cli
```
- ```nest```コマンドを使ってプロジェクトを作成
```terminal
nest new nestjs-practice
```
## 起動
- 単純なサーバーの起動
```terminal
npm run start
```
- ファイルの監視付きサーバー起動
```terminal
npm run start:dev
```
## コントローラー(controller)
- ルーティングをしてくれる役割
- パス・メソッドを設定できる
- ```controller```ファイルで記述される
```typescript
import { Controller, Get } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  //メソッド
  @Get()
  findAll(): string {
    return 'This action returns all cats';
  }
}
```
- ファイルの自動生成
```terminal
nest g controller <ファイル名>
```
- 値の受け取り　@Body、@param、@Queryを使い分けて値を受け取る
```typescript
@Controller('cats')
export class CatsController {
  @Get()
  findAll(@Req() request: Request): string {
    return 'This action returns all cats';
  }
}
```
## プロバイダー(provider)
- より複雑な処理を定義する場所
- 依存関係の挿入が可能
- ```service```ファイルで記述される
- ```@Injectable()```デコレータを使用
```typescript
import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';

@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  create(cat: Cat) {
    this.cats.push(cat);
  }

  findAll(): Cat[] {
    return this.cats;
  }
}
```
- サービスファイルに記述された関数を使うのは```controller```ファイル（下記は```controller```に記述）
- コンストラクターに型として記述するとそれ以降で使用可能
```typescript
import { Controller, Get, Post, Body } from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
import { CatsService } from './cats.service';
//型定義ファイル
import { Cat } from './interfaces/cat.interface';

@Controller('cats')
export class CatsController {
  //依存関係を挿入
  constructor(private catsService: CatsService) {}

  @Post()
  async create(@Body() createCatDto: CreateCatDto) {
    this.catsService.create(createCatDto);
  }

  @Get()
  async findAll(): Promise<Cat[]> {
    return this.catsService.findAll();
  }
}
```
## モジュール(module)
- アプリケーション構造を整理するためのもの
- ```module```ファイルで記述する
- モジュール同士は自動で関連付けされる
```typescript
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}
```
## リゾルバー(resolver)
- `QraphQL`で使うことができる。
- `@Query`や`@Mutation`といったデコレータを使うことで、参照や更新処理を受け付ける。
- serviceファイルを読み込んで使う。
```ts
@Resolver(() => User)
export class UsersResolver {
  constructor(private readonly userService: UsersService) {}

  @Query(() => User)
  user(@Args() args: FindFirstUserArgs) {
    return this.userService.findFirst(args)
  }

  @Mutation(() => User)
  async createUser(@Args() args: CreateOneUserArgs) {
    args.data.password = await bcrypt.hash(args.data.password, 10)
    return this.userService.createUser(args)
  }
}
オブジェクト指向設計とは何か？

# はじめに
オブジェクト指向設計について講義を受けており、知識をまとめるために本記事を執筆しました。

## そもそも"設計"は何のために？
<b>設計の目的</b>：コスト削減
<b>何をすること？</b>：分割と結合を考える

例え話として、100という規模のソフトウェアを開発をするとする。
仮定的に、工数は規模の２乗だとする。
規模100のまま開発すれば100^2 = 10,000の工数になる。
しかし10の規模10個に分けてやれば、　10^2 * 10 = 1,000の工数になる。
（※結合コストなどは考えていない）
1/10に工数を減らせる。

このように「分割と結合によってコスト削減のアイディアを練る」のが、本来の設計の目的になる。

## 設計で考えるコスト
さて、このとき設計で考えるコストには２種類ある。
<dl>
  <dt>イニシャルコスト(開発コスト)</dt>
  <dt>ランニングコスト(保守コスト)</dt>
</dl>
両方同時に下げることは難しい場合が多い。

各コストを下げたいのはどんな場面だろう？

<dl>
  <dt>イニシャルコストを下げたい場面</dt>
  <dd>この世に存在していない全く新しいシステムやサービスを作る場面</dd>
  <dd>理由：ガッツリ開発コストをかけて開発したのにコケたら困るから</dd>

  <dt>ランニングコストを下げたい場面</dt>
  <dd>すでに存在しているものを作りかえる場面</dd>
  <dd>理由：ランニングコストを下げながら、長く変化に耐えて欲しいから</dd>
</dl>

## コスト削減のための設計手法例
各コスト削減に適した設計手法の例を挙げる。
### 構造化設計
構造化設計では
・ユーザーのUIへの入力
・イベント
・データアクセス
・イベント
・ユーザー(UI)
この順で設計を考える。
外側(仕事・業務の流れ)から構造の中身を考える<b>Outside-In principle</b>である。
<dl>
  <dt>メリット</dt>
  <dd>わかりやすい=開発コストが抑えられる</dd>
  <dt>デメリット</dt>
  <dd>変更に弱い=保守コストが上がる</dd>
</dl>
人間が触れる目に見える部分から中身へという順番で考えるので、何より分かりやすい。従って開発コストを抑えやすい。

しかし、最も頻繁に変更されるのはUIという外側から見える部分である。
構造化設計はUIから中身を考えているので、UIを変更した場合、変更しなければいけない範囲があちこちに及びやすい。従って変更に弱い。


### オブジェクト指向設計
構造化設計Outside-In principleに対して、オブジェクト指向設計は<b>Inside-Out principle</b>である。
つまり、中身を決めた後にUIを考えるという設計である。

<dl>
  <dt>メリット</dt>
  <dd>変更されがちな外部(UI)の変更があっても、UIの変更だけで済む=保守コストが抑えられる</dd>
  <dt>デメリット</dt>
  <dd>やや難しい=開発コストが上がる</dd>
</dl>

オブジェクト指向では、"ビジネスロジック","ルール","常識"などを、言語やコードにする。
その言語・コードが「データの扱い方」であり、このデータの扱い方＋データアクセスが「中身」である。
この常識をコードにするのが慣れるまでは難しい。

構造化設計ではUIから中身を考えるので、UIの変更があると中身も変えなければならない。
しかしオブジェクト指向では中身を考えた後にUIを考えるので、変更されがちな外部（UI)の変更があってもUIの変更だけで済む。
これがオブジェクト指向が「<b>仕様変更に強い</b>」設計である理由だ。


# おわりに
「構造化設計よりオブジェクト指向設計が優れている」というわけではない。
オブジェクト指向には常識やルールを言語化するという人間の直感に反した不慣れな作業があり、開発コストが上がってしまうというデメリットがある。
これから新しいサービスを作るという場面では構造化設計を使って作り、軌道に乗ればのちのちオブジェクト指向設計に変えていくというのがよさそうだ。

どの設計が優れているというのではなく、適材適所で使い分けていくのが大切そうだ。

<br><br>
以上となります。お読みいただきありがとうございました！
もし見解の違い等あれば、教えていただけると幸いです。
LookerとDataPortalの比較

LookerとDataPortalはどちらもBIというジャンルのプロダクトでGoogleが開発してる。
しかしこの2つの製品は設計思想が大幅に異なる。その違いを色々考えてみる。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72976/d502c126-2baf-682b-560f-842f9f8ecd47.png)

----

## LookerとDataPortal

基本事項の大雑把な比較

| |契約 |実行環境 |対応DWH |出自 |チャートの作り方 |外部接続|
|-|-|-|-|-|-|-|
|Looker|GCPとは別の契約が必要|契約単位での専用インスタンス|色々|Looker社をGogoleが買収|モデルベース|API,コールバックAPI（コネクタ）|
|DataPortal|無料|フルマネージド|BigQueryのみ|Googleオリジナル|SQLベース|API|

----

## チャートの作り方の比較

ここでは、最大の違いだと思われるチャートの作り方に着目する。
チャートというのは、ダッシュボードを構成する単一のデータ可視化表現（いわゆるグラフ）の事。
LookerもDataPortalもチャートを複数組み合わせてダッシュボードを構成するが、チャートの作り方に大きな違いがある。

**DataPortal**では、1つのSQLから1つのチャートが作られる。チャートとSQLは1:1の関係にある。

**Looker**では、1つのモデルから複数のチャートが作られる。チャートとモデルはN:1の関係にある。
Lookerではチャートを作るのにSQLは書かない。

---

## モデルとExplore

**モデル**とはLookerを特徴づける仕組みであり「とあるデータ探索ニーズの為に設計された、DWHの抽象レイヤ」の事。モデルは**LookML**という定義言語によって記述される。LookMLはテーブル群の関係と属性がSQLの断片として記述されたymlベースのDSLだ。モデルはLookerのランタイムにデプロイされると様々な集計ニーズを実現する「動的ビュー・仮想データマート」のように動作する。

**Explore**はデプロイされたモデルを操作するためのUIで、ユーザーはExploreを操作して集計とその結果を可視化しチャートを作る事ができる。

1つのモデルから複数のチャートを作る事が可能で、モデルとチャートの関係は1:Nとなる。

---

## Lookerはモデルから複数のチャートを作る事ができる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72976/4181893f-d871-82b6-a7ff-730a2a1041df.png)

---
## モデルがあると何が嬉しいのか
DataPortalのような**Chart from SQL**なBIはシンプルで敷居が低いが、長期間運用しチャートの数が増えると色々と問題が起き治安が悪くなる。

* チャート間の仕様の不整合の増大
* ダッシュボード開発者のリソース逼迫とモチベーションの低下
* 似ているようで少しずつ違う大量のSQLの管理の難しさ

Lookerはモデルという中間レイヤによってパターンに沿ったSQLを抽象化し計算仕様を共通化できる。
この思想を**SSOT**(Single source of truth="信頼可能な唯一の情報源")と呼んだりする。
SSOTの思想に則って作られたデータ基盤は、スケーラビリティとガバナンスを大幅に向上させる事ができ、治安を高める事ができる。（データ基盤に秩序と安寧を！！）

---

## ユースケースと役割の違い

DataPortalではビジネスユーザーがSQLを書ける人（アナリストとか）にチャートの作成を依頼する事が多い。
LookerではビジネスユーザーがExploreを操作（=セルフサービスBI）してチャートを作り、SQLを書ける人はLookMLでモデルを記述する。

|ロール|DataPortal|Looker|
|--|--|--|
|ビジネスユーザー|依頼して待つ|自分でExploreを操作してチャートを作る|
|SQLを書ける人|SQLを書いてチャートを作る|LookMLを書いてモデルを作る|


---
##  様子の比較
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72976/f54f87e9-dcbe-c281-93e4-1ab7eb4d4707.png" width=50%>
TECH CAMP 1日目 ~キックオフ~

# 学習内容
tech campの１日目はキックオフと言って、学習カリキュラムをどのように進めていくのかなどを確認したり、メンバーやライフコーチと顔合わせします。
それが終わると、基礎学習を始めていきます。
今日学んだ内容は事前にProgateで予習した内容と殆ど一緒でした。内容に関して苦労したことはありませんでした。

- HTML,CSSの基本（レイアウト構造、ブロックレベル要素やインライン要素等）


## 今週の目標
__今週中に中間試験を実施__
学習カレンダー上は6/16だが今週の金曜日6/10までに行う。
早めに進めることで⇨余裕を持ってカリキュラムに取り組める
　　　　　　　　　　就職活動で使うポートフォリオの作品制作に時間を注げられる
Go 言語でスライスのポインタに対して Index を指定して要素を取得する

# Go 言語でスライスのポインタに対して Index を指定して要素を取得する

普通のデータ型のようにポインタ参照しようとするとできない。

```go:構造体
type Users struct {
	Name  string
	Score *[]int
}

tanaka := Users{Name: "田中", Score: &[]int{1, 2, 3}}
satou := Users{Name: "佐藤", Score: &[]int{1, 2, 3}}
users := &[]Users{tanaka, satou}
```

```go:NG パターン
for i, v := range *users {
	log.Printf("名前 %v", v.Name[i])    // こっちはポインタじゃないので問題なし
	log.Printf("スコア %v", *v.Score[i]) // こっちはポインタ参照してるのにダメ
}
// エラー： invalid operation: cannot index v.Score (variable of type *[]int)
```


ポインタ配列に対してインデックスを指定して要素を取得するには下記のように「()」で囲む。

```go:OK パターン
for i, v := range *users {
	log.Printf("名前 %v", v.Name[i])
	log.Printf("スコア %v", (*v.Score)[i])
}
```

地味にハマるのと検索ワードに困って時間がかかったので一生忘れないように残しておきます。
FlaskでFirebase AuthとFirestoreを同時に使いたい時にしたこと

# 概要
[firebase-admin](https://pypi.org/project/firebase-admin/)をFlaskプロジェクト内で使っていた。

Firebase AuthもFirestoreも使いたかったので、同プロジェクト内でファイルごとに```firebase_admin.initialize_app(cred)```
したら、以下のようなエラーが出た。

```
ValueError: The default Firebase app already exists. This means you called initialize_app() more than once without providing an app name as the second argument. In most cases you only need to call initialize_app() once. But if you do want to initialize multiple apps, pass a second argument to initialize_app() to give each app a unique name.
```

# よくない解決法
既にinitialize済だ！と怒られたので、単純にFirestoreの方のinitialize_appを消してみた。

```
ValueError: The default Firebase app does not exist. Make sure to initialize the SDK by calling initialize_app().
```
今度は存在しなくなってしまった。

逆に、Authにあるinitializeを消すと動くのだが、よくない解決法だと感じた。
これは、Firestoreの方が先にimportされているからである。

# 多分、最適解
classを作ってあげて、firebase_adminを使用するところでそれぞれインスタンスを生成した。
initializeが済んでいなければ実行し、済んでいればしない。

```:ファイル構成
.
├── auth.py
├── firestore.py
└── config
    ├── certificate.py
    └── serviceAccountKey.json
```
```python:certificate.py
import firebase_admin
from firebase_admin import credentials

class Initialize():
    def __init__(self):
        if not firebase_admin._apps:
            cred = credentials.Certificate(
                "config/serviceAccountKey.json")
            firebase_admin.initialize_app(cred)
```
```python:auth.py, firestore.py
from config import certificate
certificate.Initialize()
```
メソッドをcallable型の引数で受け渡す方法！

ここでかなり詰まってしまったためメモ！
```php
<?php
class Hello
{
    public function say(string $name): void
    {
        echo "Hello! ${name}!";
    }
}
class Callback
{
    public function do(callable $callback): void
    {
        $callback('ららっく');
    }
}

$hello = new Hello();
$callback = new Callback();

// これでOK!
$callback->do(function ($name) use ($hello): void
{
    $hello->say($name);
});  // Hello! ららっく!
```

useを忘れてて一生悩んでました...
もっと良い方法がございましたらご教示いただければ幸いです！
【Docker】imageとbuild

# イメージをどこからもってくるか
>docker-compose.yml で定義される各サービスは、 image か build のどちらかを指定する必要があります。
引用：[Docker-docs-ja](http://docs.docker.jp/v1.9/compose/compose-file.html)

## image
- タグもしくはイメージ ID の一部を指定する
- ローカルでもリモートでも指定できる
- Compose はローカルにイメージが存在しなければ、リモートからの取得を試みる



## build
- Dockerfile を含むディレクトリのパスか Git レポジトリの URL を指定する



# 先輩記事

https://qiita.com/yuta-ushijima/items/d3d98177e1b28f736f04

## おまけ

Dockerはわりとハングするので、なんか設定いけてそうなのに動かんなあと思ったら再起動してみる:whale:

### おまけのおまけ

ハングってなに？

>ハングアップ 【hang-up】
動作中のコンピュータやソフトウェアが機能を停止し、操作を受け付けなくなったり外部からの通信に応答しなくなること。
引用元：[e-word](https://e-words.jp/w/%E3%83%8F%E3%83%B3%E3%82%B0%E3%82%A2%E3%83%83%E3%83%97.html)

MadonnaのHung Upと関係あるのかも？

- hung up
    - 引き止められた、ある問題で阻止された、心理的に落ち着かない、情緒不安定で
    - 複合動詞「hang up」の過去形、または過去分詞
- hang up
    - かける、つるす、(…を)手間取らせる、(…の)進行を妨げる、中止する、延ばす

「hung up」＝「電話をガチャンと切る」「がんじがらめ」
「hung up on」＝「夢中になる」
【Laravel】GROUP BYを使ってグループ別に最新情報を取得する

## syntax error or access violation: 1055

DBからGROUP BYを使って、データを取得する時に、以下のようなエラーが発生しました。
解決に3.4時間もかかってしまったため、解決方法を記しておきます。
```
syntax error or access violation: 1055 expression #2 of select list is not in group by clause and contains nonaggregated column...
```

## 環境

今回の環境は以下の通りです。

- PHP8.1
- Laravel8

## ケーススタディ

あなたは、メッセージ機能を開発しています。
メッセージ一覧画面にて、最新のメッセージを取得して、日付とともに表示します。

## テーブル例

サンプルのテーブルを用意しました。

| id      | sender      | message      | sent_at     |
|:------------:|:------------:|:------------:|:------------:|
| 1      | TOM      | おはよう      | 2022-06-01      |
| 2      | TOM      | こんにちは      | 2022-06-03      |
| 3      | HIRO      | 今日暇？      | 2022-06-04      |
| 4      | KAORU      | 遊ぼうよ      | 2022-06-04      |
| 5      | KEN      | ねぇねぇ     | 2022-06-05      |
| 6      | HIRO      | 電話しても良い？      | 2022-06-07      |

## 結論

結論から言うと、
GROUP BY で指定したカラムは、SELECTに入れる必要があります。

例えば、
```
$messages = Message::select('id','sender','message','sent_at')
->groupby('sender')
->get();
```

この場合、エラーが起きます。

```
syntax error or access violation: 1055 expression #2 of select list is not in group by clause and contains nonaggregated column...
```

### GROUP BYの指定カラムを、SELECTにも入れる。

```
$messages = Message::select('id','sender','message','sent_at')
->groupby('id','sender','message','sent_at')
->get();
```
正しくは、GROUP BYの指定カラムを、SELECTにも入れてあげましょう。

## GROUP BY と MAX を活用する

上記のように、GROUP BY と SELECT の数を整理すれば、エラーは解消されますが、本来の目的は達成できません。
GROUP BYは、MAXを併用すると、指定カラムを減らすことができます。

```
$messages = Message::select('id',DB::raw('MAX(sender)'),DB::raw('MAX(message)'),DB::raw('MAX(sent_at)'),)
->groupby(
'id'
)
->get();
```

## まとめ

GROUP BYを使って、エラーが発生し、長時間はまってしまいました、、、。
この記事で、救われる人が増えることを信じてます。
重心座標の計算速度（pythonコード比較）（3次元空間）

# 比較するコード
- `np.mean`
- `np.average`
- `np.sum`してから粒子数で割る（`jit`あり）

`np.mean`と`np.average`はnumbaにサポートされていない。
したがって `jit`で高速化できない。


# 方法
粒子数は 10,000個で、座標の値はランダム：`pos = np.random.rand(10000,3)`。
3つめの`np.sum`の関数は次の通り。
```python
@njit
def calc_CoM(pos):
    return np.sum(pos, axis=0) / len(pos)
```

`%%timeit`を使用し、10,000回の繰り返しを100回実行した平均値を結果として次章に著す。


# 結果
| コード | 平均計算時間 | 1位との比 | ランキング |
|:----------------------:|:-------:|:---:|:---:|
| `np.mean`              | 125 μs  | 5.2 | 3位 |
| `np.average`           | 122 μs  | 5.0 | 2位 |
| `np.sum / len`+`jit`   | 24.2 μs | 1   | 1位 |

:::note info
numpyの`np.mean`や`np.average`を使うよりも、numbaが対応している関数だけを使って`jit`で高速化したほうが速いことがわかった。
:::

:::note warn
上のランキング表には記載しなかったが、不思議なことに、
`np.average`の計算速度の標準偏差は `1.45 μs` なのに対し、
`np.mean`は `15.6 μs` と、10倍程度 長かった。

私の手法が統計的に十分かどうかはわからないが、この結果は
<font color="red">**`np.average`の方が安定した計算速度を出せるということを示す。**</font>
:::

# 参考
`np.mean`と`np.average`の違いは、例えばこのリンクを見るとわかる。

 https://deepage.net/features/numpy-average.html
【React】公式のチュートリアルをやってみる～③propsとstate

[【React】公式のチュートリアルをやってみる～②プロジェクト用ファイル作成](https://qiita.com/asahina820/items/c6b48dbd2232a653c900) の続きです。
三目並べゲームに必要な部品をそろえていきます。

## propsを使って値を受け渡す
### propsとは？
- 親コンポーネントから子コンポーネントにデータを渡すことができるオブジェクトのこと
- propsは読み取り専用で、変更はできない
- propsは、「プロパティ」の意味


### Boardコンポーネントから、Squareコンポーネントに値を渡す
```jsx
class Board extends React.Component {
  renderSquare(i) {
    return <Square value={i}/>;
  }

  render() {
    const status = 'Next player: X';

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}
        </div>
        <div className="board-row">
          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
        <div className="board-row">
          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}
        </div>
      </div>
    );
  }
}
```
- Squareコンポーネントを呼び出し、そのときに props として` {value: i}` を渡す
    - ここでの`i`は引数で受け取った値（0,1など）が入る


### Squareコンポーネントで、Boardコンポーネントから受け取った値を表示する
```jsx
class Square extends React.Component {
  render() {
    return (
      <button className="square">
        {this.props.value}
      </button>
    );
  }
}
```
- Squareコンポーネントは出力として <button>i</button> 要素を返す
    - ここでの`i`は親コンポーネントから受け取った値（0,1など）が入る

![ReactApp3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667439/d290553e-0f72-a5a9-7275-ef886887ce6b.png)
マスごとに数字が表示されました～

## stateを使ってインタラクティブなコンポーネントを作る
### stateとは？
- データを動的に更新することができる
- stateは、コンポーネントの内部で制御される

### this.state の初期状態を設定するコンストラクタを追加する

```jsx
class Square extends React.Component {
  // コンストラクタ
  constructor(props){
    super(props);
    this.state = {
      value: null,
    }
  }
  (略)
}
```

- propsを引数として親クラスのコンストラクタを呼び出す必要がある

### ボタンをクリックするたびにデータ更新する
```jsx
class Square extends React.Component {
  // コンストラクタ
  (略)
  render() {
    return (
      <button className="square" onClick={() => this.setState({value: 'X'})}>
        {this.state.value}
      </button>
    );
  }
}
```

- stateの更新をスケジュールするために this.setState() を使用する
- onClick時にthis.setState() を呼び出すことで、ボタンがクリックされたら常に再レンダーするよう伝えることができる

![ReactApp4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667439/6e005ac1-bc8b-1ea3-3b3c-a9bbcfe39251.png)
ボタンを押したらマスにXが表示されるようになりました～

## 参考文献
- https://ja.reactjs.org/tutorial/tutorial.html
- https://ja.reactjs.org/docs/components-and-props.html
- https://ja.reactjs.org/docs/state-and-lifecycle.html
- https://ja.reactjs.org/docs/faq-state.html
Pythonによる各種入力チェック関数の実装

# 概要
Pythonによる各種入力チェック実装。
サーバーサイドでのチェックを想定しています。
実装するチェックは以下になります。
・必須チェック
・上限桁数判定
・型判定
・半角英数判定
・Base64判定

# ソースコード
```python:checkUtil.py
import re

def checkRequire(checkStr: str):
  # 必須チェック判定
  return len(checkStr)!=0

def checkMaxNum(checkStr: str, maxNum: int):
  # 上限桁数判定
  currentNum = len(checkStr)
  return currentNum <= maxNum

def checkType(checkStr: str, type):
  # 型判定
  if checkStr == None:
    return True
  return type(checkStr) == type

def checkAlphaNum(checkStr: str):
  # 半角英数判定
  alphaNum = re.compile((r'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$')
  return alphaNum.match(checkStr) is not None

def checkBase64(checkStr: str):
  # Base64判定
  Base64 = re.compile(r'^[a-zA-Z0-9=+/:;,]+$')
  return Base64.match(checkStr) is not None


```
5.11 (標準) 確率収束2 マルコフの不等式

## 方針

5.8の方針で「確率収束を示す時は，大数法則を使うか定義通り計算するかのいずれか．定義通り計算する際はマルコフの不等式が足がかりになる．」で述べた通り．ここでは標本平均がiidでないので大数法則ではなくマルコフの不等式を使う．独立標本でなくてもサイズnが大きくなって標本間の相関が小さくなれば平均値が母平均に近づく，ということを示す問題．大数法則の導出とやることは一緒．

## 答案

![5.-19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1702786/7d3cb070-d4dd-4d8f-d0bd-cffba2904d14.jpeg)


## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
テスト66

```vb

Sub Data_Check()

Dim i As Integer
Dim j As Integer
Dim Last_Row  As Integer
Dim Last_Col  As Integer
Dim tmp_str As String
Dim Ans As Integer

'VBA上でのCountIfs関数が15個の条件までしかチェックできない
'(条件範囲を含めると引数は最大30個(Arg30)まで)ので、そのための代替策
'最大127組まで指定できるというのは、おそらくExcel上のCountIfs関数...〆(･ω･｀)

With ThisWorkbook.Sheets("表1")
'各セルの値を行ごとにまとめる
    '最終行取得
    Last_Row = .Cells(Rows.Count, 1).End(xlUp).Row
    
    '最終列取得
    Last_Col = .Cells(1, Columns.Count).End(xlToLeft).Column
    
    For i = 2 To Last_Row       '行方向
    
        For j = 1 To Last_Col       '列方向
        
            tmp_str = tmp_str & .Cells(i, j).Text
        
        Next j
    
        .Cells(i, j + 1).Value = tmp_str
        tmp_str = ""
    
    Next i
'-------------------------
'重複チェック
    For i = 2 To Last_Row       '行方向
    
        Ans = Application.WorksheetFunction.CountIf(.Columns("AH:AH"), Cells(i, Last_Col + 2))
        If Ans >= 2 Then
        
            MsgBox "重複データがあります。", vbCritical, "確認"
            End
            
        End If
    
    Next i

End With

End Sub
Visual C++でwarningの抑制 #pragma warning

### 概要
#pragma warning を使えば警告を抑制することが出来ます。
外部ライブラリの警告を消すために有用ですが、本来は非推奨です。

### 使い方
警告を無視したい内容を #pragma warning で指定する。
#pragma push と pop で囲めば、その範囲のみで抑制することができます。

```objc
#pragma warning(push)
#pragma warning(disable:26812)
#pragma warning(disable:26495)
#include <fbxsdk.h> // このインクルードのみ警告を無視
#pragma warning(pop)
```


### 参考
* [Microsoft Document warning pragma](https://docs.microsoft.com/ja-jp/cpp/preprocessor/warning?view=msvc-170 "Microsoft Document warning pragma")

* [Microsoft Document Pragma directives and the __pragma and _Pragma keywords](https://docs.microsoft.com/en-us/cpp/preprocessor/pragma-directives-and-the-pragma-keyword?view=msvc-170 "Microsoft Document Pragma directives and the __pragma and _Pragma keywords")