OmniAICreator/Qiita-1.07M huggingface dataset:
gitコマンドにエイリアスをつけて作業効率をあげる

##はじめに
gitをターミナルから扱えるように学習中です。
gitに限らずではあると思うのですが、alias(エイリアス)をつけることによってコマンドを省略して打ち込めるのでその方法を記事にします。

##コマンドにエイリアスをつけてコマンドを簡単にする
エイリアスを和訳すると別名という意味があります。

例えば、私は慎重な性格なので、よく現在の状態をわかっていても```git status```コマンドを多用して確認作業をしまくります。

git statusぐらいすぐ打てるだろ！って思われる方多いと思いますが、めちゃくちゃ使うので```git st```と打つだけでgit statusできたら小さなことですがめちゃ楽です。

他にもよく使うコマンドとして、```git checkout```なんかもよく使います。
これも```git co```で実行できたらすごい楽なんですよ。

↑のようなことができるように設定していきます。

ターミナルで下記のようなコマンドで設定できます。

```terminal
git config --global alias.<別名> <本来のコマンド>
```

configは設定をいじるときのコマンドで--globalはpc全体に反映させます。--globalをつけない場合は今いるプロジェクト上だけでこれが反映されるようになります。

はじめに説明したようなgit stやgit coはこんなふうに設定します。↓

```terminal
git config --global alias.st status
git config --global alias.co checkout
```

これで楽にコマンドが打てるようになります。
ちなみにエイリアスは別名をつけているだけなので、上記の設定を行った後でも、本来のgit statusやgit checkoutを入力しても使用することができます。
【学習記録】フラグ管理 (paizaランク D 相当)

## 目次
- 問題文
- 書いたコード
- 解答例
- 学んだこと
- 振り返り

## 問題文 
[詳細はコチラ](https://paiza.jp/works/mondai/c_rank_level_up_problems/c_rank_for_step2)

###問題文の要約
一行目に以降の入力件数を、二行目以降に7があればTrue、なければFalseを表示せよ。

>入力例2
3
4
11
35

>出力例2
NO

## 書いたコード（その１）

``` main.py
count = int(input())

for (a, i) in enumerate(range(count)):
    b = input().split()
    if str(7) in b:
        print("YES")
        break
    else:
        if (a+1) == count:
            print("NO")
```

今までは一つ一つYES,NOを表示していくパターンが多かったので、どうやって一度だけprintを表示すればいいのか迷いました。酷いな…。
今まで使ったことなかったbreakを使えたのは収穫です（苦し紛れ…。）

## 書いたコード（その２）

``` main.py
count = int(input())
box = []
for i in range(count):
    box.append(input())
    
if str(7) in box:
    print("YES")
else:
    print("NO")
```

この記事を書いている間に思いつきました。単純に最後に評価すればいいじゃんと思ったのがこちら。
判定する値が一つだけじゃなくて複数になったらsetを使えばよさそう。
[参考URL](https://note.nkmk.me/python-in-basic/)


## 解答例

``` main.py
n = int(input())

flag = False

for i in range(n):
    a = int(input())
    if a == 7:
        flag = True

if flag:
    print("YES")
else:
    print("NO")
```

最初の段階でFalseを入れておいて、見つかったらTrueを代入する。
この方法なら条件を7の倍数とかにしても簡単に対応できるので応用が効く。
タイトルがフラグ管理、となっているのにも納得です。

## 学んだこと
1. フラグの管理

## 一言
無駄だらけのコードではあったけど、enumerateの使い方には慣れてきた実感。
一つの問題に複数コードが書けたのは多少なりとも引き出しが広がった感じがします。
TypeORMでSQLiteを指定してQueryFailedError: SQLITE_CONSTRAINT: NOT NULL constraint failed エラーが出たときの対処法

## 解決方法
解決策は４つあります。４つ目が本命です。

### 1. synchronizeをやめる

これでエラーはなくなるけど、エンティティが同期されなくなるので不便。。。

```json:ormconfig.json
{
   "synchronize": true
}
```

### 2. カラムをnullableにする

これも根本的な解決じゃない。。。

```typescript:entity/user.ts
@Column({ nullable: true })
name: string;
```

### 3. SQLiteを使わない

身も蓋もないですが、ありだと思います。

### 4. トランスパイルする

私の環境では、`ts-node`を使わないようにすると、エラーが解決されました。
以下の手順を行ってください。

#### STEP 1

`tsconfig.json`のCompilerOptionsに`"skipLibCheck": true`を指定する。
これは、STEP3の`tsc`コマンド実行時にエラーを表示させないためです。
基本的に推奨されるオプションではないので、エラーが出なかったら消してください。

```json:tsconfig.json
{
   "compilerOptions": {
      "lib": [
         "es5",
         "es6"
      ],
      "module": "commonjs",
      "moduleResolution": "node",
      "outDir": "./build",
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "sourceMap": true,
      "skipLibCheck": true
   }
}
```

#### STEP 2

`ormconfig.json`を以下のように書き換えます。
これは、トランスパイルしたJavaScriptを実行するためにパスを変更しています。

* `/src` → `/build`
* `.ts` → `.js`

```json:ormconfig.json
{
   "type": "sqlite",
   "database": "database.sqlite",
   "synchronize": true,
   "logging": false,
   "entities": [
      "build/entity/**/*.js"
   ],
   "migrations": [
      "build/migration/**/*.js"
   ],
   "subscribers": [
      "build/subscriber/**/*.js"
   ],
   "cli": {
      "entitiesDir": "build/entity",
      "migrationsDir": "build/migration",
      "subscribersDir": "build/subscriber"
   }
}
```

#### STEP 3

`tsc`でトランスパイルします。

```
$ tsc
```

すると、`build`ディレクトリに`.js`ファイルがたくさん書き出されるはずです。

> 実行できないときは、`typescript`をグローバルにインストールしてください。
> 
> ```sh
$ npm i -g typescript
```

#### STEP 4

`node`でトランスパイルしたJavaScriptファイルを実行します。

```sh
$ node build/index.js 
```

これでエラーが出なければOKです。

#### STEP 5

毎回コマンドを打ち込むのは大変なので、`package.json`に書き加えてスクリプトにします。

```json:package.json
{
   ...
   "scripts": {
      "start": "tsc && node build/index.js",
   }
}

```

#### 最初は実行できたけど、後でエラーになった場合

自分は遭遇してませんが、前の実行で出力したJavaScriptファイルが残っていると、エラーになる場合があるようです。その場合、以下のようなコマンドで実行前に`build`ディレクトリを削除してください。

```sh
$ rm -r build && tsc && node dist/index.js
```

> 参考： [[typeORM] NOT NULL constraint Failedなどのsynchronize回りのエラーの解決方法](https://akitoshiblogsite.com/typeorm-sqlite-not-null-constraint-failed/)



## 発生したエラーの詳細

```sh
$ ts-node src/index.ts
QueryFailedError: SQLITE_CONSTRAINT: NOT NULL constraint failed: temporary_user.name
    at new QueryFailedError (/Users/src/error/QueryFailedError.ts:11:9)
    at Statement.handler (/Users/src/driver/sqlite/SqliteQueryRunner.ts:79:26) {
  errno: 19,
  code: 'SQLITE_CONSTRAINT',
  query: 'INSERT INTO "temporary_user"("id") SELECT "id" FROM "user"',
  parameters: []
}
```
React + Reduxを基本からまとめてみた【7】【Redux Middleware】

## Middlewareとは

『Middleware』は、ActionをdispatchしてからreducerにActionを引き渡すまでの媒介の役割を果たす。全てのdispatchを聞き取り、Actionの詳細や現在の状態を把握してコードを実行する。複数のMiddlewareを組み合わせて新しい機能を追加することも可能で、それぞれMiddlewareが前後の状況を理解する必要はない。


『Middleware』の例としては、非同期リクエストの処理（サーバーへのHTTPコールなど）、ロギング、ルーティングなどがある。

『Middleware』は、主にアプリケーション内の非同期Actionを処理するために使用でき、Reduxでは、副作用や非同期Actionを可能にするミドルウェアライブラリとして、Redux-thunkやRedux-Sagaが有名。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/64992770-69ac-963d-ef7c-d156ef7ef05c.png)

##なぜReactのMiddlewareが必要なのか

Reduxが同期型である一方で、Reduxが非同期操作でどのように動作するのか疑問に思うかもしれない。Redux Middlewareがその答えで、基本的なReduxStoreがあれば、それは同期的な更新のみを行うことができる。Redux Middlewareは、storeの機能を拡張するのに適したツールで、Redux Middlewareは、reducerの前にdispatchされたアクションと対話するための媒体として機能する。

高次関数を使ってReactでカスタマイズしたMiddlewareを作ることができる。また、Reduxの複数のMiddlewareは、組み合わせることができる。このようにして、新しい機能を追加することができる。ただし、reactのMiddlewareはどれも、前後の知識を必要としない。一言で言えば、reactのMiddlewareはdispatchされたActionとreducerの間に入る。

ReduxのMiddlewareはapplyMiddlewareというAPIにアクセスでき、これにより、reactのカスタムミドルウェアだけでなく、redux-thunkやredux promiseのようなMiddlewareも利用できるようになる。

##参考サイト
[Redux Middleware: A Perfect Beginner’s Guide]
(https://www.cronj.com/blog/redux-middleware-a-perfect-beginners-guide/)
MATLABをUbuntu20.04にインストールする

# 目次
[はじめに](#-はじめに)
[1. 実装環境など](#1-実装環境など)
[2. 実装手順](#2-実装手順)
[3. 参考文献リスト](#3-参考文献リスト)

# はじめに
この記事は，自分がUbuntu20.04にMATLAB(R2021b)をインストールする際に，既存の記事では円滑に導入できなかったため作成しました。

#1 実装環境など
・Ubuntu20.04
・MATLAB R2021b

#2 実装手順
**・MATLABのダウンロード**
まず初めに実装したいバージョンのMATLABを[公式サイト](https://jp.mathworks.com/downloads/web_downloads/)よりダウンロードします。本記事でのダウンロード先は"Downloads"にしました。

**・MATLABファイルの展開**
次に先ほどダウンロードした圧縮ファイル(.zip)を下のコードを実行して"Downloads"フォルダに展開します。
ここで，コード内の""(ダブルクォート)の中はダウンロードした圧縮ファイルの名前なので，R2021bのところはバージョンによって異なります。

```
~$ cd Downloads
~/Downloads$ unzip "matlab_R2021b_glnxa64.zip"
```

**・MATLABのインストール**
ダウンロードした圧縮ファイルの展開が終わったら，MATLABのインストーラーを下のコードより起動します。

```
~/Downloads$ ./install
```

MATLABインストーラーが起動したら，表示されている手順に従いインストールを進めていきますが，インストールする際に「ファイルが存在しません」や「書き込み権限がありません」と表示されることがあります。

**ファイルが存在しない場合**
ファイルが存在しない場合はsudo権限を用いた下のコードによりMATLABのファイルを作成します。作成した後に，所有者，所有グループ，その他に対して，読み取り，書き込み，実行のすべての権限を与えます。
下のコードでは"Downloads"のディレクトリでやっていますが，おそらくどこでも大丈夫です。また，作成するディレクトリ名は導入したいMATLABのバージョンを入力してください。

```
~/Downloads$ sudo mkdir -p /usr/local/MATLAB/R2021b
~/Downloads$ sudo chmod 777 /usr/local/MATLAB/R2021b
```

**書き込み権限がない場合**
上記の手順を行った後にインストーラーを再度実行して，表示された手順に従うことで，インストールは完了するはずです。
しかし，"chmod 777"で権限を渡したのにも関わらず，「書き込み権限がありません」と表示されることがあります。
その場合，下のコードを実行して，rootアカウントがGUI表示することを可能にし，その後再度インストーラーを実行し，表示された手順に従いインストールを進めます。

```
~$ xhost +SI:localuser:root
~$ sudo ./install
```

以上でUbuntu20.04にMATLAB(R2021b)のインストールが完了すると思います。
本記事を作成するにあたって参考にさせていただいた記事[1]を書かれた@chicken9様，MATLABの質問[2]にて回答していらしたEl'ad Gips様には非常に感謝しております。


#3 参考文献リスト
1.
[UbuntuにMATLABをインストールする](https://qiita.com/chicken9/items/65799a63cccb9a4a947a)

2.
[MATLAB Answers,"Installer hang when installing Matlab R2021b as root on Ubuntu 20.04"](https://jp.mathworks.com/matlabcentral/answers/1459909-installer-hang-when-installing-matlab-r2021b-as-root-on-ubuntu-20-04#comment_1759029
)
Pythonによる統計学〜t検定編〜

# はじめに
教育心理学系の学部の方から対応の無いt検定をPythonで行いたいという質問をいただきました。

今回紹介する対応の無いt検定は実際の分析でも使用することも多く、統計的仮説検定を実務に活用するというとっかかりとしても勉強しておいて損はないと思います。

また、2標本t検定の中でも等分散性を仮定できない場合に実行するウェルチのt検定を中心に解説しようと思います。（汎用性が高く、例えばRではデフォルトの設定がウェルチのt検定です。）

※最後にでも記載しましたが、統計的仮説検定そのものに対する問題点やp値についての議論はここでは行いません。


## 主に使用する関数

```Python
#　 両側検定（SciPyのデフォルト）
stats.ttest_ind(data1, data2, equal_var=False)

# 片側検定
stats.ttest_ind(data1, data2, equal_var=False, alternative="less")
# または、
stats.ttest_ind(data1, data2, equal_var=False, alternative="greater")
```

データを所有しており、すぐにでも実行したいという方向けに先に関数だけ紹介しておきます。
data1, data2には配列を入れてください。


## データ生成
サンプルデータを作成します。

```Python
group1 = np.array([82, 82, 80, 78, 81, 76, 80])
group2 = np.array([83, 80, 83, 83, 84, 83, 83, 83])

# それぞれのデータの平均値
np.mean(group1)
np.mean(group2)
```
出力

```
>>> group1
array([82, 82, 80, 78, 81, 76, 80])
>>> group2
array([83, 80, 83, 83, 84, 83, 83, 83])

>>> np.mean(group1)
79.85714285714286
>>> np.mean(group2)
82.75
```

平均値が79.86と82.75でこの違いに意味があるのかを見ることがt検定の目的です。

また、group1のサンプルサイズは７で、group2のサンプルサイズは8です。サンプルサイズが違うことにより対応がないこともお分かりいただけるかと思います。

（教育分野のお話でしたので、指導法別にグループを分けて、なんらかのテストを行ったことを想定しています。）

## 対応の無いt検定(両側検定)の実行

ウェルチ(Welch)のt検定を行います。
有意水準をα=0.05と設定し、帰無仮説を「2グループ間の平均値に差がないこと」とします。

こちらの式で検定統計量を計算します。

```math
t_0 = \frac{| \overline{x}_1 - \overline{x}_2 |}
{\sqrt{\frac{s_1^2}{n_1} + \frac{s_2^2}{n_2}}}

```



```Python
stats.ttest_ind(group1, group2, equal_var=False)
```

出力

```
Ttest_indResult(statistic=-3.125418086176548, pvalue=0.012436368672610056)
```

p値を(pvalue)を見ると p < 0.05 なので帰無仮説は棄却されます。


## 対応の無いt検定(片側検定)

両側検定のみで片側検定のやり方が記載されていない記事が多かったので、片側検定のやり方についても共有しようと思います。
SciPyの古いバージョン（version 1.6.0以前）では、パラメータを変更するだけで実行することができなかったということが関係しているのかもしれません。


### 対応の無いt検定(片側検定)の実行

有意水準をα=0.05と設定し、帰無仮説を「2グループ間の平均値に差がないこと」とします。
上記両側検定との違いは、片側検定なので対立仮説が「group1はgroup2より平均値が小さい」というようなものになります。

```Python
stats.ttest_ind(group1, group2, equal_var= False, alternative="less")
```

出力

```
Ttest_indResult(statistic=-3.125418086176548, pvalue=0.006218184336305028)
```

p < 0.05 なので帰無仮説は棄却されます。


## 最後に
本記事では、対応のない2標本t検定の実行方法について紹介しました。実行だけであれば一行のコードで済むのは便利に感じます。

また、統計的仮説検定そのものに対する問題点やp値についての議論はここでは行わないようにしますのでご了承くださいませ。


この記事は以下の情報を参考にして執筆しました。

https://bellcurve.jp/statistics/course/9446.html

https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.ttest_ind.html

https://bellcurve.jp/statistics/glossary/1898.html
応用技術者試験対策　情報セキュリティ

#まとめ
##共通鍵暗号方式　秘密鍵暗号方式
| 方式|概要 | メリット | デメリット | 暗号技術の例 |
|:-:|:-:|:-:|:-:|:-:|
|  共通鍵暗号方式 | 暗号化と複合に使う鍵が同じ  | 計算コストが比較的小さい  | 事前に鍵の共有が必要・管理する鍵の数が膨大（nC2）  | DES・AES  |
|  秘密鍵暗号方式 |  暗号化と複合に使う鍵が異なる（暗号化に使った鍵では複合できない） |事前の鍵共有が不要・管理する鍵の数が少ない（2ｎ）   |  計算コストが比較的大きい | RSA・楕円曲線暗号  |

##ディジタル署名
・途中で改ざんされていないか・誰が送信したものかを確認できるようにしたもの

##CA(認証局)
信用できる第三者が「この鍵は本人のものです」と証明する機構のこと

##ハッシュ化によるディジタル署名の作り方
1.ハッシュ関数を使ってメッセージダイジェストを作成
2.メッセージダイジェストを秘密鍵で暗号化する

##ディジタル署名とハッシュ化で改ざんを検知する流れ
1.ディジタル署名をくっつけて、メッセージを送信
2.受信者は公開鍵を使ってディジタル署名を復号する
3.メッセージ本文をハッシュ化、メッセージダイジェストを取得する
4.両者が同一であれば、改ざんがされていない！
【JavaScript】スコープの学習の振り返り④　即時関数


#はじめに

Udemyの[【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)の講座の振り返りです。

前回の記事

https://qiita.com/nao0725/items/9e0f9201945c8d79dd45

#目的

* スコープについての理解を深める


#本題
###1.即時関数（IIFE）

即時関数とは**関数定義と同時に一度だけ実行される関数**のこと。

→実行結果が呼び出し元に返される。

基本構文

````javascript
let result = (function (仮引数){
  return 戻り値;
})(実引数);
````

戻り値はresultに返ります。

````javascript

function a() {
  console.log("called");
}
a();

// 上記と下記は同じ結果が出力される
(function(){
  console.log("called");
  return 
})();

// 最後に実行する（）がないとSyntaxエラーが発生する
// 関数式の場合は()がいらない（エラーにならない）
````

即時関数で表すと下記のとおりになります。

```javascript
// 即時関数
let c = (function(d){
  console.log("called" + d);
  // 呼び出し元変数ｃに0が返される
  return 0;
  // 仮にここに引数10を渡すと上記dに返される
})(10);
`````

この即時関数はどのようなタイミングで使用するのか。
それは、関数スコープを利用して関数の中でしか使えない変数や関数と関数の外で使う変数や関数を明確に区別したいときに使用します。


````javascript
let c = (function(){
  console.log("called");
  // 変数privateValを定義 関数内でしか使えない
  let privateVal　 = 0;
  // 変数publicValを定義　これは関数の外で使えるようにしたい
  let publicVal = 10;

  // 関数も上記の様に生成
  function privateFn(){
    console.log("privateFn is called");
  }
  function publicFn(){
    console.log("publicFn is called");
  }

  // 戻り値を設定してこの結果が変数cに格納される
  return {
    privateVal,
    publicFn
  };
})()

// 関数の外から下記のように呼び出すとコンソールに出力される
c.publicFn();
console.log(c.publicVal);

// c.privateValと書くことはできない
`````


今日はここまで！

#参考にさせて頂いた記事

* [【JS】ガチで学びたい人のためのJavaScriptメカニズム](https://www.udemy.com/course/javascript-essence/)
git push heroku masterが失敗する

#書いた理由
備忘メモ

#起こったこと

rails tutorialを第3章を進める過程で
`git push heroku master`
を実行したとき、コケた

```
remote:        We will use "yarn" to install the CLI via "yarn add -D webpack-cli".
remote:        Do you want to install 'webpack-cli' (yes/no): 
remote: 
remote:  !
remote:  !     Precompiling assets failed.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed
```

#解決したこと
webpack-cliを再インストールしたり、webpackを再インストールした上で、
最終的に再度以下を実行したらできた
`git commit -am "hogehoge"`
`git push`
`git push heroku master`


#思ったこと
ただ、デプロイを試みる前にコミットをしていなかったため、
対策を打ったつもりが打ててなかった、という状況と思われる。
herokuの理解が足りていないが、コミットしたものしか上げられないものだったのだろう。
MacにJenkinsをインストールして構築メモ

↓ 基本ここを参考にインストール。

https://qiita.com/shirasaya0201/items/863a05117c934856e532

同じネットワークの他のPCからアクセスできるように、下記ファイルの設定を編集して保存。

```
$ sudo vi /usr/local/opt/jenkins/homebrew.mxcl.jenkins.plist

[編集前]
<string>--httpListenAddress=127.0.0.1</string>

[編集後]
<string>--httpListenAddress=0.0.0.0</string>
```
編集したらJenkinsを再起動

```
$ brew services restart jenkins
```
expressとmysqlを使ったDBにbcryptでハッシュ化したデータを挿入する

全体のコードです。

sqlでinsertしているpasswordをハッシュ化してから、DBに保存している。

```
//モジュールをインストール
const { request } = require('express')
const express = require('express')
const app = express()
const port = 5000
const bcrypt = require('bcrypt')
//saltRoundsを使って何回ハッシュ化を行うのか設定
const saltRounds = 10

const mysql = require('mysql');

//DBに接続
const con = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: '',
  database: 'express_db'
})

//データを挿入するSQL文
const insert = 'INSERT INTO USERS (name, email, password) value (?,?,?)'

//
bcrypt.hash("password", saltRounds, (err, hash) => {
//DB操作
  con.query(insert,["johndoe","john@example.com",hash],function(err, result, fields){
    if (err) throw err;
//結果をログで表示する
    console.log(result);
  })
})


app.get('/',(request, response) => response.send('hello'))

app.listen(port, () => console.log(`example app listening on port ${port}!`))
```
GKEにデプロイしたアプリケーションをIAP(Identity-Aware Proxy)で保護したあと、どのようなことが出来るかを検証した

# はじめに

[前回の記事](https://qiita.com/keiichi-hikita/items/bc0c4d54633777cda17a) でIAPの環境はできたので、それを受けて実際のユースケースに即してどのような事が可能かを検証してみました。

私達が今実装しているアプリケーションにおいて、IAPに求める要件には以下のようなものがあります。それぞれについて確認をしていきました。


# ユーザーをなんらかのまとまりで認可させたい

ユーザー個々に対してIAPへのプリンシパル登録をしていくのは煩雑なので、なんらかのグループ的なものにユーザを所属させる・抜くというだけで認可対象を切り替えていきたいと考えていました。


## 要件を満たせるか？

満たせる。

## やりかた

Google Groupでやればよい。例えばこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317673/3a536fec-17da-c6f7-8fda-c00107827aa6.png)


このようにグループを作っておき、それをIAPに対して登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317673/091c8ca1-d819-abab-e22e-69c246754ad0.png)


`IAP-secured Web App User` として、先ほど作成したGoogle Groupのメールアドレスを登録している状態です。

こうしておけば、このグループに登録したGoogleアカウントならIAPを通過して画面を表示することが出来ますし、それ以外のアカウントはアクセスが抑止されます。


# IAPを通過したユーザーの情報を後段のアプリケーションに渡したい

認証・認可に使用するという用途もあるが、それ以外にも実作業者の情報をログにを残す等の監査目的で仕様が考えられるためです。

## 要件を満たせるか？

満たせる。

## やりかた

[こちら](https://cloud.google.com/iap/docs/identity-howto) に書かれています。

実際に [試しに作ったこんな](https://github.com/keiichi-hikita/gke-iap/blob/main/server-middleware/headercheck.js) コードをデプロイすると、IAP通過時に以下のように結果が取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317673/bad7da33-9d82-84db-10f0-e4ba7959674f.png)

```javascript
res.send(`userEmail: ${userEmail}, userID: ${userID}`)
```

expressで上記のように出力しているのですが、それぞれの冒頭に `accounts.google.com` が固定でつくのは、グループにも所属しているからなのですかね。ちょっとこのあたりは調査が必要かもしれないなと思いました。

# IAPが停止した場合のヘッダ偽造に対応したい

IAPで保護するということは、逆に言えばIAPが停止してしまえばだれでも素通りできてしまうということです。
しかもその場合ヘッダの偽造などいくらでも可能です。
なので、IAPを通過した場合にのみ付与される情報をしっかりと検証して、NGの場合は強制的に通常ページへのアクセスを遮断するような手法が必要です。

## 要件を満たせるか？

満たせる。（と思いますが未検証）

## やりかた

未検証ですが、 [こちら](https://cloud.google.com/iap/docs/signed-headers-howto) に書かれています。
`x-goog-iap-jwt-assertion` ヘッダを検証すれば良いようですね。

IAPの画面からだと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317673/529a52b1-335d-9550-5894-d7ddbc2b778e.png)

まずメニューを選択すると、 `JWTオーディエンスコードの取得` というものが出るのでそれをクリックします。で、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317673/b2775189-eb7b-5a4a-12fe-b13ad4df311b.png)

それがこのように表示されると。

で何かしらこれを使って署名検証するのだろうと推測しています。
まだ未検証ですがこれは出来るのだろうと踏んでます。

# 同一クラスタ内のサービス個々にIAPの適用有無をon/off可能としたい

自分たちのユースケースだと、１つのクラスタに複数のGUIをデプロイし、それぞれについてIAPのon/offを制御したいと考えています。それができるかどうかです。

## 要件を満たせるか？

満たせる。

## やりかた

deploymentのexpose、ingressの作成(w/ TLS)までを含めてもう一式立ち上げます。
そうすると以下のような状態になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317673/529a52b1-335d-9550-5894-d7ddbc2b778e.png)


ここで2つめのINGRESSはIAPがOFFになっていますが、こちらにはIAP制御無しでアクセスできることが確認できてます。
もちろんIAPをonすれば両方ともアクセス制限をかけることも出来ました。


# まとめ

とりあえずおおよその要件には対応できるように見えます。
現時点で確認できたのはここまでなのですが、追加で `URL単位での認可が出来ること` を確認しようと思っています。

この意図は例えば以下のようなことをやりたいためです。

- デプロイしたアプリケーションを2つの部門が使用する
- 部門ごとにアクセス可能なURLをコントロールする
  - 例えば部門Aは `/site-a` のみ接続できる
  - 例えば部門Bは `/site-b` のみ接続できる


ただこれは普通に公式手順に基づいてIAP構築をするだけでは無理そうに見えているので一旦調査しようと思います。

また次の記事にでも。
seleniumで遊ぼう！　〜自動ログイン編〜

スクレイピングやブラウザの自動操作に興味が湧いたので、
とりあえずselenium使ってみることにしました！
とりあえず、使ってみるにしても何か身の回りの作業をやってもらいたかったので、今回は、大学のオンライン授業サイトに自動でログインするツールを作ってみました！

最初にソースコードを、

``` python:loginTool

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import chromedriver_binary


# ブラウザを開く。
driver = webdriver.Chrome()

# 授業サイトを開く。
driver.get("ここに自分の大学のURLを貼り付けてね")

#ユーザーidの要素を取得
element1 = driver.find_element_by_id("username")
#ユーザーidの入力
element1.send_keys("ここにユーザーidを入力してね！")
#パスワードの要素を取得
element2 = driver.find_element_by_id("password")
#パスワードを入力
element2.send_keys("パスワード入力してね！")
#ログインボタンの要素を取得
btn = driver.find_element_by_id("LoginBtn")
#ログインボタンをクリック
btn.send_keys(Keys.ENTER)


```

とりあえずこんな感じです。
pythonで初めて作ったツールなのでかけた時は嬉しかったですね。
とりあえず初回なのでここで終わります。読んでくれた方ありがとうございました！
GraphQLに触れてみた

## PCローカルでGraphQLを試す

### 背景

僕は現在SEとしてフルスタックな開発業務推進＆実務をやっています。

自社の営業サイドから仕事が回ってくるとき、

- フワッとした要件定義でやっちゃえ、とにかく動かしちゃえ
- 仕様・設計バグがあってもアジャイルで改善すればいいんじゃね？（誤用）

という開発風土があるため、フロントエンド周りの改修が多発し、結合度高めなREST APIも改修が発生しやすいという状況があります。

そこで、フロントエンドの改修頻度高めを前提としたうえで、API改修頻度の方を下げられないか、と今回はじめてGraphQLを試してみました。

### 手順

windows10で実施。

1) Apollo Serverインストール

```
> mkdir C:\Works\Projects\gqlserver
> cd C:\Works\Projects\gqlserver
> npm init --yes
> npm i apollo-server graphql
```

2) 実装

gqlserver\src\index.js を作成（中身は後掲載）

3) 起動

```
> cd C:\Works\Projects\gqlserver
> node .\src\index.js
```

4) 動作確認

VSCode拡張機能のThunder Clientを使用

### 結果


実装、起動、動作確認を1shotにした図が以下です。

![ApolloServer2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42790/9fbbdd50-0e4f-15c5-63a7-8ec72c3ce54b.png)

① データ取得だから`GET`だと思い込み「何で動かないんだGraphQL...」とそこそこ悩んだ時間があり心が挫けそうになりました。

（ここを読んでいる方にはそんな心配はありませんね。congratulation!!）

② index.jsの実装

@ozaki さんの「[【now】ApolloServerを無料でサーバにデプロイする](https://qiita.com/ozaki25/items/b09412fe7df24fba4627)」より。
ありがとうございます。

③ server起動

### 結論

今回はじめてGraphQLを動かしましたが、正直REST APIとの差をまだ感じられていません。

REST APIからGraphQLに移行したところで、アジャイル開発（誤用）なAPI改修工数削減に効果があるのかが理解できていません。
（ただ単に社内のAPI設計が不十分なだけで、設計強化でなんとかなる内容なのかもしれません）

継続して学習が必要です。

以上
IBM Cloud: ibmcloudコマンドのセッションを複数同時に利用する方法

#1. はじめに

ある環境でibmcloudコマンドを実施する際に、

- ある画面でibmcloudコマンドを実行して東京リージョンのつつ、別の画面でibmcloudコマンドを実行して大阪リージョンにアクセスする
- ある画面でibmcloudコマンドを実行してアカウント1にアクセスしつつ、別の画面でibmcloudコマンドを実行してアカウント2にアクセスする

とかいうのはそのままではできず、セッション情報が共有されていることがわかる。これを回避する方法の紹介。

#2. 方法

`IBMCLOUD_HOME`という環境変数を明示的に指定する。

例えば、Terminal1とTerminal2がある時、

```shell:Terminal1
$ export IBMCLOUD_HOME=~/.bluemix_xxxxxxx
$ ibmcloud login --apikey @ibmcloud_apikey_xxxxxxx -r jp-tok
```

```shell:Terminal2
$ export IBMCLOUD_HOME=~/.bluemix_yyyyyyy
$ ibmcloud login --apikey @ibmcloud_apikey_yyyyyyy -r us-south
```

としてやれば同一環境上であろうとセッションやプラグイン情報は分離される。

#3. 解説
ibmcloudコマンドはデフォルトでホームディレクトリに`.bluemix`というディレクトリを作成しており、そこでセッション情報やプラグイン情報を管理している。これを１つの環境で共有しているために、ターミナルなどが変わってもセッションが分離されない。
この管理情報の保管場所を明示的に指定するのが`IBMCLOUD_HOME`という環境変数である。これを切り替えることで、セッションもプラグインも全て独立で管理される。

```
$ ls -l ~/.bluemix
total 16
-rw-------.  1 root root 4431 Oct  7 06:16 config.json
drwx------. 11 root root 4096 Sep 13 09:50 plugins
drwx------.  3 root root 4096 Sep 27 20:36 tmp
$ ls -l ~/.bluemix/plugins/
total 1964
drwx------. 2 root root    4096 May 20 09:20 cloud-functions
drwx------. 2 root root    4096 Jul 22 22:15 cloud-internet-services
drwx------. 2 root root    4096 Jul 26 09:37 cloud-object-storage
-rw-------. 1 root root 1972059 Oct  7 06:16 config.json
drwx------. 2 root root    4096 Sep 23 21:16 container-registry
drwx------. 3 root root    4096 Aug 25 14:03 container-service
drwx------. 2 root root    4096 Oct  5 15:36 power-iaas
drwx------. 2 root root    4096 Sep 13 09:50 tke
drwx------. 2 root root    4096 Sep 27 20:36 vpc-infrastructure
```
Vivaldiのスピードダイヤルに登録したブックマークで使われている画像

#はじめに
Vivaldiユーザーです。

スピードダイヤルにブックマークしたサイトのホームページの様子が表示されます。区別しにくいのでロゴ画像を引っ張ってきて、登録していました。

最近、自分で画像を登録する必要のないサイトがあることに気づいたので、HTMLの記述を調べました。

#HTML

ブラウザーの開発者ツールで確認した内容です。``property="og:image"`` が設定箇所でした。

![property="og:image"](https://i.gyazo.com/d2bfb138f74db57177d4a561992c0fc7.png)

#サンプル

teratail

![terartail](https://teratail.com/img/imgFacebookShare.png)

※Qiitaは設定されていませんでした。

#以上
Gzip圧縮したデータを連結したデータはRubyのZlib::GzipReaderでは読めない

### 複数のGzipデータを連結した1つのデータ

gzipコマンドは複数のgzip圧縮されたファイルをcatで結合したものでも展開することができます。簡単な例をbashで見てみましょう

``` bash
date --iso-8601=ns | gzip > a.gz
date --iso-8601=ns | gzip > b.gz
cat a.gz b.gz > all.gz
gzip -dc all.gz # 2行出てくる
```

RFC1952でファイルフォーマットについて説明があります。

https://datatracker.ietf.org/doc/html/rfc1952

Gzipファイルフォーマットは先頭10byteは必ずメンバ情報になっており、あとはメンバ情報のFLGによって可変長データが続くような形になっています。

この繰り返しなので、複数の圧縮されたデータがあっても、ひたすら展開して連結することで1つのデータが得られる仕組みになっているようです。上記の通り、gzipコマンドやzcatコマンドや著名なアーカイバ(7-zipとか)はサポートしています。

### RubyのZlib::GzipReaderはサポートしているか？

2021/10/05時点の実装では`Zlib::GzipReader.zcat`でサポートしているようですが、RubyGemsで公開されているバージョン(1.1.0)ではまだ入っていないようで、まだサポートされていない、といえる状態です。

- Issue: https://github.com/ruby/zlib/issues/7
- 実装箇所: https://github.com/ruby/zlib/blob/master/ext/zlib/zlib.c#L3861
- RubyGems: https://rubygems.org/gems/zlib/versions/1.1.0

なので、適当に処理するしかないので、こんな感じにします。Rubyは全く書かないので、この実装で良いかは怪しいです。

``` ruby
def uncompress(gzip_data)
      decoded_data = ""
      while gzip_data do
        Zlib::GzipReader.wrap(StringIO.new(gzip_data.b)) do |gz|
          decoded_data << gz.read
          gzip_data = gz.unused
        end
      end
      decoded_data
end
```

readで1つ分は読めて、unusedに余ったデータが残るので、残ったデータに対してまたreadを繰り返して連結していきます。
雑過ぎますが、テストコードで必要になった実装なので雑でいいんです（いいのか？）

zcatが待ち遠しいですね。
【unity】clusterハロウィンかぼちゃを光らせてみたよぉ

環境メモ
⭐️Mac Book Pro（Mac OS Catalina）
⭐️Unity 2019.４.２２f1

↓↓↓完成内容
![ 2021-10-07 4.15.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/fd97cc35-a9b8-1db7-5370-5bfc10001cb1.png)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">🎃Unity 🎃<br>☀️Blenderで作った３D🎃ハロウィン🎃かぼちゃをUnityで✨光らせてみたよぉ✨🤩<br>👻あやしい🌛月の夜空🌠も加わって🎃なんだか🎃ハロウィンっぽく不気味な雰囲気になってきたぞぉ💕<br>🎃ハロウィン🎃VR作るぞ😘<br>↓↓手順書<a href="https://t.co/5TppaJL9rs">https://t.co/5TppaJL9rs</a><a href="https://twitter.com/hashtag/cluster?src=hash&amp;ref_src=twsrc%5Etfw">#cluster</a> <a href="https://twitter.com/hashtag/Unity?src=hash&amp;ref_src=twsrc%5Etfw">#Unity</a> <a href="https://t.co/LAi3IYtnrY">pic.twitter.com/LAi3IYtnrY</a></p>&mdash; non (@nonnonkapibara) <a href="https://twitter.com/nonnonkapibara/status/1445847308457832451?ref_src=twsrc%5Etfw">October 6, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

clusterのオフィシャルサイト「Creators Guid」に載っているPostProcessingの設定をやってみました。

以下、clusterのオフィシャルサイトの手順書
PostProcessingを使ってワールドをより魅力的にする
https://creator.cluster.mu/2020/04/01/howto-postprocessing/

# PostProcessingをインストールする
私は、「Cluster Creator Kit」を使っているので、PostProcessingをインストールする必要がありました。
「ClusterCreatorKitSample-master」を使っている場合は、PostProcessingのインストールは不要です。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/ee1644b1-1d3b-b7b7-34f4-6e3e6a37995b.png)

![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/cbcc3e32-8b65-6125-3b2d-f6b7c38a3bf2.png)

Creator Kitで利用可能なバージョンについてはclusterドキュメントPost Processingページを参照。
現時点 2020.10.08時点では、「Version 2.3.0」でした。
https://clustervr.gitbook.io/creatorkit/world/asset#post-processing

![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/a424b7af-a981-338b-7d51-a54e08b51b9a.png)

# Post Processingを設定する
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/5bfd1ace-4801-0191-71a4-0c03b86fa19b.png)

![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/9547ad00-8a94-67f9-7b25-e0ff5bd44145.png)

![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/73902d7e-eee2-2602-0e99-3fc8bd4f99f0.png)

![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/9cffa76c-d75f-08a4-a99d-4a42fdfe5f92.png)

![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/4ab534e0-4905-ec76-334b-b0ab474cb107.png)

![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/6ad0c7e7-8a26-9984-9006-c704b22ffc20.png)

![010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/fe6d5811-0333-e3ea-6e4f-af4272541241.png)

# マテリアルを光らせる設定

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/094c76a1-5a5b-118b-0190-df41a26ce14e.png)


![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/3ef78a98-85d3-21f7-5276-16dcc3a3d44c.png)

完成！
VSCodeの拡張を自作する：3_イベントを取得する

# この記事について

概要は
[概要のページ](https://qiita.com/wakakusa_ryuuzi/items/49d08f56a3ca653db025)
をご確認ください。

この記事で出来ることは、アクティブなエディタを切り替えた時にポップアップに表示するところまでです。



# イベントに関して

イベントの概要に関しては、API Patternsの部分に記載があります
基本的なところや命名規則などが記載されています。

[ドキュメントの該当箇所](https://code.visualstudio.com/api/references/vscode-api#events)

また、仕様としては下記に記載されています。

[ドキュメントの該当箇所](https://code.visualstudio.com/api/references/vscode-api#Event)

windowなどの各オブジェクトが、イベントを持っています。
これにコールバック関数をかましてやると、該当のイベントを取得する事が可能です。



# イベント実装

## packeage.json側

※ちょっとここまだわかり切っていないところなのですが…
onComandだとダメな気がするので、onStartupFinishedに変更しています。

## extensions.ts側

APIドキュメントに従って、受けたいイベントに対してコールバック関数を実装すればよいです。


# アクティブなエディタを変更した際にファイル名と実行した回数を表示するサンプル

## 例のイベント

[ドキュメントの該当箇所](https://code.visualstudio.com/api/references/vscode-api#window)

## コード

```typescript

let count: number = 0;

let listnerTest: vscode.Disposable;

let showSelectedFileNameInInformation = ( e: vscode.TextEditor|undefined , thisArgs:number = count ): any => {
	count++;
	vscode.window.showInformationMessage(count.toString());
	

	const filenName:string | undefined = e?.document.fileName;
	switch (typeof filenName){
		case "string": {
			vscode.window.showInformationMessage(filenName);
			break;
		}
		case "undefined": {
			vscode.window.showInformationMessage("undefined");
			break;
		}
	}
}

export function activate(context: vscode.ExtensionContext) {

	//イベントハンドラ
	listnerTest = vscode.window.onDidChangeActiveTextEditor( showSelectedFileNameInInformation )
}

```
共通のtypescriptの型をフロントエンドとバックエンドで使う

# はじめに
フロントエンドとバックエンドでtypescriptを使っていると、リクエストやレスポンスの型を共有したくなります。
別々で型を管理すると、面倒なコピペをするハメになったり、ミスって不整合が起きたりするので大変ですよね。
そこで、一箇所に型を置いて、一回の変更でどちらにも変更が適用されるようにします。

# 1. プロジェクトをモノレポにする

型情報が即時に反映されるように、プロジェクトを一つにまとめます。

```:ディレクトリ構成の例
/api
/common/requests
/web
```

# 2. 型だけを定義したパッケージを作る

型パッケージは最低限`package.json`と`index.d.ts`があれば大丈夫です。

```json:/common/requests/package.json
{
  "name": "@types/your-requests",
  "version": "1.0.0",
  "description": "",
  "main": "",
  "types": "index.d.ts",
  "author": "",
  "license": "UNLICENSED"
}
```

```typescript:/common/requests/index.d.ts
export type SampleRequestBody = {id: string; amount: number};
```

# 3. 型へのシンボリックリンクを張る

普通のローカルパッケージのインストールではなく、シンボリックリンクを使います。
これだと型情報を変更するたびにインストールをしなくてもよくなります。

```bash:yarnを使った例
cd api
yarn add link:../common/requests

cd ../web
yarn add link:../common/requests
```

これで、型情報の編集がそれぞれのパッケージに伝わるようになります。
WEBrickを使って動的なhtmlを返す（〜 GETとPOSTの違い 〜）

前回の記事（[Webrickを使って静的なhtmlを返す](https://qiita.com/sonoyuki13/items/3dcfac99b05eca29cc19)）の続き

### 前回作ったページ
##### 投稿フォーム

[![Image from Gyazo](https://i.gyazo.com/15917b5c8ef1b5665b08dc4a95d4f7d5.png)](https://gyazo.com/15917b5c8ef1b5665b08dc4a95d4f7d5)

##### 対応するhtml(一部)
```html
<h2>GETで送る</h2>
  <ul>
  <form action="/form_get" method="get">  
    <li><label for="user_name">ユーザー名</label>
    <input type="text" name="user_name"></li>

    <li><label for="age">年齢</label>
    <input type="text" name="age"></li> 
  
  <button type="submit">投稿</button>
</form>
  </ul>

<h2>POSTで送る</h2>
  <ul>
  <form action="/form_post" method="post">  
    <li><label for="user_name">ユーザー名</label>
    <input type="text" name="user_name"></li>

    <li><label for="age">年齢</label>
    <input type="text" name="age"></li> 
  
  <button type="submit">投稿</button>
</form>
  </ul>
```

<br/>

### 今回は、ユーザーが入力した情報に合わせた動的なページを作成する



#### webrick.rbに追記
```ruby
webrick.rb

require 'webrick'

server = WEBrick::HTTPServer.new({ 
  :DocumentRoot => './',
  :BindAddress => '127.0.0.1',
  :Port => 8000
})

# 以下追記

  server.mount_proc("/form_get") do |req, res|
    # レスポンス内容を出力
    x = req.query
    body = 
    "<html><body><head><meta charset='utf-8'></head><p>クエリパラメータは#{x}です</p></br>
    <p>こんにちは#{x["user_name"]}さん。あなたの年齢は#{x["age"]}ですね</p></body></html>"
    res.status = 200
    res['Content-Type'] = 'text/html'
    res.body = body
    end

    server.mount_proc("/form_post") do |req, res|
      # レスポンス内容を出力
      x = req.query
      body = 
      "<html><body><head><meta charset='utf-8'></head><p>フォームデータは#{x}です</p></br>
      <p>こんにちは#{x["user_name"]}さん。あなたの年齢は#{x["age"]}ですね</p></body></html>"
      res.status = 200
      res['Content-Type'] = 'text/html'
      res.body = body
      end

  
    server.start
```
#### 解説
※ 追記部分の上段がGETリクエストを受けた場合の処理で下段がPOSTリクエストの処理

※ `req`に入るのは`WEBrick::HTTPRequest オブジェクト`であるため、WEBrick::HTTPRequest クラスのインスタンスメソッドである`queryメソッド`がreqに対して使える。

※ `queryメソッド`は、リクエストのクエリーまたはクライアントがフォームへ入力した値をハッシュにして返すメソッド。   
つまり、フォームのユーザー名の欄に「太郎」、年齢の欄に「25」と入力した場合、`req.query`の返り値は`{ "user_name" => "太郎", "age" => "25" }`となる
（参考：[instance method WEBrick::HTTPServer#mount_proc](https://docs.ruby-lang.org/ja/latest/method/WEBrick=3a=3aHTTPServer/i/mount_proc.html)）

<br/>

### 入力情報をGETで送った場合とPOSTで送った場合の違い

#### GETリクエストの場合
フォームのユーザー名の欄に「太郎」、年齢の欄に「25」と入力し、『投稿』を押すと、`/form_get?user_name=太郎&age=25`に対して`GET `リクエストを送れる。   
これを受けたサーバーは「太郎」「25」に対応したhtml、すなわち『こんにちは太郎さん。あなたの年齢は25ですね』というページを返してくれる。
 
ユーザーの入力に応じて無限に変化可能なページを返せるので、まさに__動的なページ__である

<br/>

#### POSTリクエストの場合
フォームのユーザー名の欄に「太郎」、年齢の欄に「25」と入力し、『投稿』を押すと、`/form_post`に対して`POST`リクエストを送れる。   
これを受けたサーバーは「太郎」「25」に対応したhtml、すなわち『こんにちは太郎さん。あなたの年齢は25ですね』というページを返してくれる。

もちろんこちらもユーザーの入力に応じて無限に変化可能なページを返せるので、動的なページが実現している

<br/>

#### GETとPOSTの違い
ユーザーがフォームに情報を入力した場合、GETの場合は`/form_get?user_name=太郎&age=25`というクエリパラメーターが発行されるのに対して、POSTの場合は発行されない。その代わりにPOSTでは、ユーザーが入力した情報はリクエストbodyのForm Dateに格納される
WEBrickを使って静的なhtmlを返す

WEBrickを使ってHTMLを返すというのを学習したので、アウトプットしようと思います。

####`http://localhost:8000/fom.html`にアクセスして以下の画面が表示されるようにする

[![Image from Gyazo](https://i.gyazo.com/15917b5c8ef1b5665b08dc4a95d4f7d5.png)](https://gyazo.com/15917b5c8ef1b5665b08dc4a95d4f7d5)

<br/>

##### （１）まずWEBrickというライブラリを使ってWebサーバーを構築する  
webrick.rbファイルを作成し以下のコードを記述

```ruby:webrick.rb
require 'webrick'

server = WEBrick::HTTPServer.new({ 
  :DocumentRoot => './',
  :BindAddress => '127.0.0.1',
  :Port => 8000
})  
```
##### 解説
・ __require 'ライブラリ'__　：外部ライブラリを読み込むメソッド  
  ・`server = WEBrick::HTTPServer.new()`：newメソッドでWEBrick::HTTPServerクラスからインスタンスを作り、返り値をserverに代入する。   
・`:DocumentRoot => './',`　：アクセス先はhttp~~/  
・`:BindAddress => '127.0.0.1'`　：127.0.0.1は自分のパソコンにアクセスできる特別なipアドレス  
・`:Port => 8000`　：ポート番号8000番  


##### （２）次にHTMLの作成  

WEBrickはデフォルトで同一ディレクトリにあるindex.htmlファイルをレスポンスとして返す。なのでwebrick.rbファイルがあるディレクトリにform.htmlディレクトリを作り、そこにindex.htmlを入れる。    
これで`http://localhost:8000/fom.html`にアクセスしたときにindex.htmlが返ってくる

`form.html/index.html`に以下を記述

```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h2>GETで送る</h2>
  <ul>
  <form action="/form_get" method="get">  
    <li><label for="user_name">ユーザー名</label>
    <input type="text" name="user_name"></li>

    <li><label for="age">年齢</label>
    <input type="text" name="age"></li> 
  
  <button type="submit">投稿</button>
</form>
  </ul>


  <h2>POSTで送る</h2>
  <ul>
  <form action="/form_post" method="post">  
    <li><label for="user_name">ユーザー名</label>
    <input type="text" name="user_name"></li>

    <li><label for="age">年齢</label>
    <input type="text" name="age"></li> 
  
  <button type="submit">投稿</button>
</form>
  </ul>
</body>
</html>
```

#### 解説
* action 属性は、フォームで収集したデータを送信すべき場所 (URL) を定義します
* method 属性は、データを送信するために使用する HTTP メソッド ( get または post ) を定義します
* name 属性は、送るデータの名前（サーバーはその名前で受け取る）
*  value属性は、入力された値が入る

####これは、単なる静的なページを返している（HTMLの限界）
#### [次回Rubyを使って投稿者ごとに異なるページを返すプログラムを作る（動的ページの作成）](https://qiita.com/sonoyuki13/items/2f480816493cfec3c620)
【Git】fetch・mergeコマンドでリモートの情報をローカルに持ってくる方法！！！

## fetchコマンド
git fetchはリモートを追跡するブランチ（リモート追跡ブランチ）を最新化するためのコマンド。

```git
# 例
git fetch <リモート名> <ブランチ名>

# originのmainブランチ
git fetch origin main

# origin のすべてのブランチ
git fetch origin

# origin のすべてのブランチ（ショートハンド）
git fetch
```

## リモート追跡ブランチ？
fetchを理解するにはリモート追跡ブランチを理解する必要がある（英語ではリモートトラッキングブランチという）。
リモート追跡ブランチとは、リモーリポジトリにあるリモートブランチを追跡するローカルにあるブランチのこと。

注意する点としては、リモートのブランチではなくローカルのブランチであること。また、リモート追跡ブランチは自動的には最新化されず、fetchコマンドを使って最新化する必要がある。（追跡という名前から自動でやってくれそうだがやってくれない）

リモート追跡ブランチをコンソール上で確認するには以下のコマンドで確認できる。-aオプションを忘れずに。
remotes/~から始まるブランチ。

```git
$ git branch -a
* develop
  main

  remotes/origin/HEAD -> origin/main
  remotes/origin/develop
  remotes/origin/main
```

例えば、git fetch origin mainをすると、origin/main に対してリモートリポジトリの状態が反映される。

## mergeコマンド
リモート追跡ブランチ（remotes/origin/developなど）の状態を現在のブランチに取り込むコマンド。
fetchでリモートリポジトリ（GitHubなど）から最新情報を取ってきても最新化されるのはリモート追跡ブランチだけ。
ので、リモート追跡ブランチの状態を現在作業しているブランチへ落としてくる必要がある。

以下を想定してmergeの使い方を確認する。
`リモートリポジトリにある、developブランチから伸びているfeatureAブランチをローカルに取り込みたい`

```git
# まずは、ブランチの状態と自分の場所を確認する。
$ git branch -a
  develop
  featureA
* main
  remotes/origin/HEAD -> origin/main
  remotes/origin/develop
  remotes/origin/featureA
  remotes/origin/main

# 次にリモーリポジトリにあるfeatureAをリモート追跡ブランチに反映させる
$ git fetch origin featureA

# リモート追跡ブランチを最新化できたらmergeする
$ git merge remotes/origin/featureA としてはいけない。

# まだmergeはダメ。mergeは現在のブランチに取り込みを行うという機能である。
# 冒頭でgit branch -a を実行したが、そのときはmainにいるのでfeatureAに移動する必要がある
$ git checkout featureA

# 再度、git branch で場所を確認
$ git branch
  develop
* featureA
  main

# merge実行
$ git merge remotes/origin/featureA 
```
```
# 上記で実行したコマンドだけ抜き出し
$ git branch -a
$ git fetch origin featureA
$ git checkout featureA
$ git branch
$ git merge remotes/origin/featureA 

# 初めからfeatureAにいる場合
# 最低以下だけでOK
$ git fetch origin featureA
$ git merge remotes/origin/featureA 
```
ちなみにmergeの際は以下のように少し短くできる。

```
$ git merge origin/featureA
```
`上記のようにリモート追跡ブランチはコミュニケーションのなかでも「remotes/origin/featureAの～」ではなく
「origin/featureAの～」と使われることが多いので、覚えておかないと何の話しているんだ（　＾ω＾）・・・となる。`

## まだ自分のローカルにfeatureAがなくてローカルに持ってきたい場合
その場合もfetchを利用する。

```
# ローカルの状況を確認
$ git branch -a
  develop
* main
  remotes/origin/HEAD -> origin/main
  remotes/origin/develop
  remotes/origin/main

# リモートのfeatureAブランチの情報をローカルに持ってくる
$ git fetch origin featureA

# 再度ローカルの状況を確認
$ git branch -a
  develop
* main
  remotes/origin/HEAD -> origin/main
  remotes/origin/develop
  remotes/origin/featureA
  remotes/origin/main

# 現状だとリモート追跡ブランチにしか存在しない。ここで作業したいのでローカルでfeatureAブランチを切る。
$ git checkout featureA

# ローカルの状況を確認
$ git branch
  develop
* main
  featureA
```
以上のように、git checkout featureAで自動的にリモート追跡ブランチの状態のブランチを切ってくれる。
また、上記手順の冒頭で git fetch origin featureAとしているがgit fetch origin でもよい。
しかし、その場合はoriginにあるすべてのブランチを最新の状態に書き換えるので注意。

### おまけ
以下はすべてリモートトラッキングブランチを指す可能性があることを留意する。

```
・追跡ブランチ
・リモートブランチ
・リモート追跡ブランチ
・remotes/origin/featureA 
・/origin/featureA 
・上流ブランチ
```

### 上流ブランチについて
リモート追跡ブランチは上流ブランチといわれることがある。
なぜか。それは追跡している状況を想像するとわかりやすい。
リモートブランチを追跡するリモート追跡ブランチがあり、リモート追跡ブランチを追跡しているブランチであるmainブランチやgit branch コマンドで作成したブランチがあるとする。
そのとき、mainブランチからみてリモート追跡ブランチが上流にあるため、リモート追跡ブランチは上流のブランチという。
(ちょっと疑問なのはリモート追跡ブランチから見てリモートブランチも上流ブランチといわれるのかな？)
iOS長期インターンに参加してから４ヶ月経って、学んだこと

# 自己紹介 ＆ はじめに
都内の情報系の大学に通う大学生です。iOS開発は今年はじめくらいから勉強していて、６月から長期インターンに参加しています。
インターン初めて３ヶ月ちょいですがこの間でもたくさんのことを学び、技術面に関わらず人間的な面でも色々気付かされたので、**「長期インターンは楽しいぞ！」**ということが少しでも伝えられればいいなと思います。

![Screenshot-from-2021-09-28-19-15-48-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/861241/916169d6-8d29-f54e-aa8d-5bb155d0d5cd.png)


# 学んだこと、気づいたこと

### モチベーションは爆上がりする
インターンシップは、学んだことが社会に出て価値になる環境の１つであるので、やはり嬉しいです。

### 独学では学ばない部分にも手が届いて楽しい！
アプリ開発は
- 提案
- 設計（デザイン？）
- 実装
の３つに集約されると思うのですが、やはり**提案**と**設計**は独学ではあまりやってこなかったので、貴重な経験だと思いました。この３つができて初めて「０の状態から価値を生み出す」ということができるようになり、これがプロダクトづくりの醍醐味みたいなところもあるので、**提案**と**設計**あたりは今ではガツガツ関わっている部分でもありますｗ

### ３ヶ月位で一気にできるようになる
社員さんもインターン時代皆なったらしいのですが、最初の数カ月はわからないことだらけであまり貢献できず、少しきつい思いをしていたのですが、３ヶ月位でプロジェクト把握したり緊張がほぐれて提案とかリファクタリングとかの余裕も出てきて、**「イイ感じ」**になりました。おそらく僕に限った話ではなく、割とどこでもそうだと思います。
インターンきついなと思ったら、とりあえず３ヶ月くらいを目標に頑張ってみるのがいいかもしれません！

### メガネ生活楽
らくちんです

### 提案は楽しい
やはり言われたものをただやるのは貢献感なく性に合ってなかったので、企画とか提案とかをエンジニアでもどんどんできる環境があるという軸でインターンを探して、現在のインターンとご縁がありました。
とはいうものの独学ではコーディングは経験できますが、他人への提案は経験できないので多少不安はありました。しかしそこは社員さんが「自信３割くらいでもどんどん言ってくれていい。野球で打率３割だったらすごいじゃん。」というふうに安心させてくれて、この部分は本当にインターン先に恵まれているなと思いました。

### 提案➣デザイン➣実装の楽しさ
「ここのUIわかりづらくね？？」というちょっとした提案も真摯に受け止めてくれました。独学にはない初めての経験だったので少し勇気がいり、また既存のものを壊すのはちょっと抵抗がありましたが、全然やってくれていいよというふうに後押ししてくれたので、実装を進めることができました。自分が０から提案したものが自分でデザイン、コーディングできて、実際に世に出されて利用者さんから「使いやすい」との言葉を頂いたときは、本当に達成感がありました。この経験ができるのはあまり他のインターンでは無いのかなと思います。
この経験から、段々と提案に対する障壁がなくなってきました。

### MTGありがたい！
社員さんに自分の現状や悩み、今後の行動方針とかを聞ける1on1でのMTGの時間があったのですが、普段の業務ではあまり話にならないことがたくさん聞けて、不安も解消されて、自分のマインドの良いところ、改善していけることろ、がどんどん明らかになっていき、よりクリアな感情でモチベーションも高くなったので、本当に**「MTGありがたい！」**って感じです！
野球の打率の話もここで聞きましたｗ

### 仕事中に参考した部分はとりあえず全部ブックマーク！
おすすめです。懐かしさを感じつつ復習することができます。

### デザインしたよ
自分は個人開発ではデザインカンプを作るということはあまりしなかったのですが、書き起こしたほうがより良いプロダクトが作れるということに、インターンを通して気付かされました。
**「figma」**というデザインツールがあるのですが、iPhoneのフレームおいて、そこにいろんなパーツおいていろんなUIのパターン出しして、そこから取捨選択していくイメージです。
大事なのは**「なぜこのデザインにしたのか言語化する」、「デザインで何を解決したいか都度思い出す」、「頭で考えるより書き出す」**あたりだと思いました。
自分はUI設計の問題点を指摘して新規UIのデザインカンプを作っていたのですが、この３つを意識して創出したデザインは自分も社員さんも納得できるようなものであったし、実際にリリースされても「使いやすい！」という声が聞けたときは本当に嬉しかったです。

### できなさそうだな、、ということでも割とできる
個人開発のことは**「できることベース」**で実装していたものが、インターンでは**「やりたいことベース」**でした。おそらく個人開発のときは実装する自信があまりなかったからです。しかしインターンでいざ実装するとなると引き下がるわけには行かないので実装するのですが、意外とできるようなものでした。やはりできることベースよりもやりたいことベースのほうがプロダクトとして成功するだろうし、「やりたいこと」➣「実装」の逆算の経験を何度も何度も積むと、割ともう何でもいけんじゃね？という自身がつきました。

### 好きでやれているので、すばらしい
就職に有利だから、周りに差をつけたいから、みたいな理由で長期インターンを始める学生も多いと思います。全然悪いことではないし僕が口出しする権利はまったくないのですが、イチ個人のひとりごととして、楽しくなかったらやる意味がないのかなと思います。
好きでやれている、という状況を作ってくれている今のインターン先には本当に感謝していますし、だからこそもっと貢献していきたいと思えます。

# さいごに
何も言うこと思いつかないので、「プロダクトづくりたのしいぞ！」とだけ言っておきます！
#1.5 ユーザー編集機能

#はじめに
自己学習復習シリーズの#1.5になります。
自己学習の為に記事作成しております。
この記事が誰か1人の役に立ったら幸いです。
今回はユーザー編集機能編です。

##ユーザー編集機能作成においてすべき事
- users controllerにてeditアクション、updateアクションの作成&ストロングパラメーターの作成
- routes.rbにてルーティングの作成
- views/usersにedit.html.erbを作成し、編集フォームを作成
- マイページや編集ページに遷移できるようにリンクを作成する

以上の4点を行えば、ユーザー編集機能の実装を終える事ができる。

今回は丁寧に、
(1)ルーティングの作成(editとupdate/routes.rbにて)。
(2)editアクションの記述(users controllerにて)。
(3)edit.html.erbにて編集フォームを作成。
(4)updateアクションの記述(users controllerにて)&ストロングパラメーターの作成。
(5)マイページと編集ページにリンク作成。
の順で説明していきます！


###(1)ルーティングの作成
```:routes.rb
resources :users, only: [:show, :edit, :update]
```
resourcesで作成しているので、そこにeditアクションとupdateアクションのルーティングを作成。

###(2)editアクションの記述
```ruby:users_controller.rb
def edit
  @user = User.find(params[:id])
end
```

###(3)edit.html.erbにて編集フォームを作成
```ruby:users/edit.html.erb
<h3><%= @user.name %>さんの編集画面</h3>

<%= form_with model:@user, local: true do |f| %>
<%= f.label :"名前" %>
<%= f.text_field :name %>

<%= f.label :"自己紹介" %>
<%= f.text_field :introduction %>

<%= f.label :"ステータス" %>
<%= f.text_field :status %>

<%= f.label :"画像" %>
<%= f.file_field :image %>

<%= f.submit '編集する' %>
<% end %>
```
form_withを用いて編集フォームを作成する。
ちなみにこの記述の状態だと、横並びのフォームになっている。
ーーーーーーー以下参考写真ーーーーーーーーーー
![スクリーンショット 2021-10-07 2.12.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2109393/c4264ccd-27fa-a11c-cc90-53305c09b6aa.png)
ーーーーーーーーーーーーーーーーーーーーーーー


###(4)updateアクションの記述&ストロングパラメーターの作成
```ruby:users_controller.rb
def update
  @user = User.find(params[:id])
  @user.update(user_params)
  redirect_to user_path(@user)
end
```
deviseによって作成されたuserなので、
user_controller.rbにcreateの時に作成されたストロングパラメーターが存在しない。
なので、private内にストロングパラメーターを記述する。

```ruby:users_controller.rb
private

def user_params
  params.require(:user).permit(:name, :image, :introduction, :status)
end

```

###(5)マイページと編集ページにリンク作成
今のままだと編集ページに遷移できない&編集ページからは編集しないと戻れないので、、

```ruby:users/show.html.erb
:
:
<%= link_to '編集する', edit_user_path(@user) %>
```

```ruby:users/edit.html.erb
:
:
<%= link_to 'マイページへ戻る', user_path(@user) %>
```

#最後に
以上でユーザー編集機能の実装が終わりました。
ユーザー編集機能は慣れたら簡単だと思うので、復習を重ねて早く慣れましょう！！
今回も見てくださった方はありがとうございました！
【Swift】URLからAppleMusicを開く方法

SwiftでAppleMusicのURLを取得した後、AppleMusicアプリを開く方法に躓いたのでメモとして残しておきます。

```swift
//AppleMusicを開くための関数、urlを引数としている
func openAppMusic(url: String) {
    DispatchQueue.main.async {
        
        guard let url: URL = URL(string: url) else { return }

        // URLを開く
        UIApplication.shared.open(url, options: [:]) { success in
            if success {

            }
        }
    }
}

//ボタンをタップしたらAppleMusicのURLを開く関数（例）
@objc func onPressButton(_ sender : Any){
    self.openAppMusic(url: "AppleMusicのURL")
}


```

メインスレッドで開くのを忘れがちなので注意が必要。

## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
画像をたくさん読み込む

##画像の取り込みをコントロールする

```javascript:javascript
var images = document.getElementsByTagName('img'); 
var count = 0;
for (var i = 0; i < images.length; i++) {
	var img = new Image(); 
	img.onload = function() {
			count += 1;
	}
	img.onerror = function() {
			count += 1;
	}
	img.src = images[i].src;
};
var waiting = setInterval(function() {
	if(count == images.length) {
		clearInterval(waiting);
		ここに画像を取り込んだ後の処理を書く
	}
}, 100);

```

-----------------------------


参考

https://note.affi-sapo-sv.com/js-img-dynamic-loading.php


https://ja.javascript.info/onload-onerror
JavaScriptでPythonのrange コンストラクタを実装する

# はじめに

これらと同じことをJavaScriptでやる。

```py
for i in range(10):
    print(i)
```

```py
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list(range(10))

# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list(range(1, 11))

# [0, 5, 10, 15, 20, 25]
list(range(0, 30, 5))

# [0, 3, 6, 9]
list(range(0, 10, 3))

# [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
list(range(0, -10, -1))

# []
list(range(0))

# []
list(range(1, 0))
```


# 仕様

 - すべて数値型の range(end) と range(start, end[, step]) の引数を受け取る。
 - 渡された引数がない場合はエラーを投げる。
 - step引数に0が渡された場合はエラーを投げる。
 - 最初に載せたPythonのコードと同じ挙動をする。


# 実装

範囲などは事前に計算し、Symbol.iterator メソッドを実装したイテラブルなオブジェクトを返す。

```js
/**
 * @param {number} start
 * @param {number} end
 * @param {number} [step = 1]
 * @returns {{ start: number, end: number, step: number, size: number, [Symbol.iterator](): Generator<number, void, unknown> }}
 */
const range = (start, end, step = 1) => {
  // range()
  if (typeof start === 'undefined' && typeof end === 'undefined') {
    throw new TypeError('range expected at least 1 argument, got 0')
  }

  // range(start, end, 0)
  if (step === 0) {
    throw new RangeError('range() arg 3 must not be zero')
  }

  // overload range(end)
  if (typeof end === 'undefined') {
    end = start
    start = 0
  }

  /**
   * @type {number}
   */
  const size = Math.max(0, Math.ceil((end - start) / step))

  return {
    start,
    end,
    step,
    size,
    *[Symbol.iterator]() {
      for (let i = 0; i < size; i++) {
        yield start + step * i
      }
    }
  }
}
```


# 使い方

以下のように使用する。

```js
for (const i of range(10)) {
  console.log(i)
}
```

```js
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
const array = [...range(10)] // Array.from(range(10))
```
【PostgreSQL・psql】チートシート

# btreeって何？
<img width="300" alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498057/378ecc50-42f7-b1da-e106-5d1cf1072773.png">

prod表の主キーを確認しようと「\d prod」を実行したらこう表示された。
btreeって何？？
→**インデックスの種類とのこと。デフォルトのインデックスはB-tree**。
>B-tree、Hash、GiST、SP-GiST、GINといった複数の種類のインデックスを使用可能です。 
（中略）
>デフォルトでCREATE INDEXコマンドは、B-treeインデックスを作成し、それはほとんどの一般的状況に適合します。
（引用：[PostgreSQL 9.2.4文書　第11章インデックス](https://www.postgresql.jp/docs/9.2/indexes-types.html)）

# EXPLAIN文（SQL実行プランの分析）で返される内容の意味

```:VSCode
postgers=# EXPLAIN SELECT * FROM zip WHERE newzip = '1500002';
                       QUERY PLAN                       
--------------------------------------------------------
 Seq Scan on zip  (cost=0.00..4312.62 rows=1 width=145)
   Filter: (newzip = '1500002'::bpchar)
(2 rows)
```

【Seq Scan以降の意味】
「cost=」の後にある「0.00」：始動コスト（一件目のデータを返すのにかかる想定のコスト）
「..」の後にある「4312.62」：総コスト（処理完了までにかかる想定のコスト）
「rows=」の後にある「1」：行数（プランナによって見積もられた、ノード実行によって返却される行数
(※実際に取得した結果の行数ではない)）
「width=」の後にある「145」：行の長さ（同上の行の平均の長さ）
↓こちら参考にした。

https://www.casleyconsulting.co.jp/blog/engineer/259/

【未消化部分】
上記のような意味である、ということはわかったけれど、その「コスト」「ノード」の意味がわからない。
以下の通り調べ、
「コスト」＝処理にかかる時間。コスト変数は相対的な値。
「ノード」＝実行計画で処理を行う単位。
というところまでは、言葉としてはわかった。が、それが何を指しているのか、具体的なところがわからない。今後PostgeSQLを使う中で具体例に遭遇しながら学ぶ必要あり。

【調べたこと】
[ドキュメント](https://www.postgresql.jp/document/8.2/html/using-explain.html)には
>●初期処理の推定コスト（出力用のスキャンが開始されるまでに消費される時間、例えばSORTノードで実行されるソート処理の時間）。
●全体の推定コスト（結果の行全体が抽出される場合のコスト。とは言っても、LIMIT句を使った問い合わせの場合は、Limit計画ノードへの入力ノードの総コスト計算をする前に停止します）。
●この計画ノードが出力する行の推定数（これも、実行が完了した場合のみ）。
●この計画ノードが出力する行の（バイト単位での）推定平均幅。
コストはプランナのコストパラメータ（項17.6.2参照）によって決まる任意の単位で測定されます。

とあった。「[コスト変数は、相対的な値](https://www.postgresql.jp/document/8.2/html/runtime-config-query.html#RUNTIME-CONFIG-QUERY-CONSTANTS)」なのだそうだ。

●ノードとは？
↓
>実行計画で処理を行う単位をノードと呼び、ツリー構造となっています。
（引用元：[Casley Consulting Inc技術ブログ](https://www.casleyconsulting.co.jp/blog/engineer/259/)）

----

https://tech-blog.rakus.co.jp/entry/20200612/postgreSQL#1-%E5%AE%9F%E8%A1%8C%E8%A8%88%E7%94%BB%E3%81%A8%E3%81%AF

https://www.slideshare.net/MikiShimogai/postgre-sql-explain

# コマンド読み解き
##tarコマンドでPostgreSQLの関連ファイルが格納されているデータディレクトリ $PGDATA 以下をアーカイブ 

```
[postgres@ localhost ~]$ pg_ctl stop -m fast 
サーバ停止処理の完了を待っています....完了
サーバは停止しました
[postgres@ localhost ~]$ tar cvf backup.tar $PGDATA
（・・・返答がつづく）
（引用：『オープンソースデータベース標準教科書 -PostgreSQL-（Ver.2.0.0）』 9.2ファイルのコピー）
```
→以下↓記事へ

https://qiita.com/ume-san/items/cc29ceb804b21b2d333f

# psql
##「postgres-#」になった場合の入力キャンセル方法

```:psql
ostgres=# create table
postgres-# ¥r
問い合わせバッファがリセット（クリア）されました。
postgres=#
```
参考記事＝https://www.dbonline.jp/postgresql/connect/index4.html

## 終了
`\q`または`Ctrl+D`

## メタコマンドとは
>PstgreSQLの操作のためのコマンドをメタコマンドと呼びます。
メタコマンドはpostgresにログイン後、postgres=#のプロンプトが出ている状態で入力できます。

http://fksekiguchi.sakura.ne.jp/wp/it_basic_understanding/databese/postgresql/pstgresqlmetacommand

## プロンプトとは
「ここから入力しなさい」なマーク。

https://wa3.i-3-i.info/word11367.html

## テーブル一覧の表示
`\dt;`

## テーブル構造の表示
`\d テーブル名;`
Windowsでrust-analyzerをエラーなく使うには

## 前提
筆者はrust初心者です。

## 背景
WindowsでRustいれてRust開発しようかなと思って、vscodeにrust-analyzerを入れたはいいが、
以下のようなエラーになってしまう。あとなんかすごい重いので、対策に乗り出した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152020/712701ad-5c93-9f0e-b55b-39f461abdeef.png)

```
cargo check failed:
error: failed to run custom build command for `openssl-sys` v0.9.63

Caused by:
 process did'nt exit ....
..
..(省略)
..
note: vcpkg did not find openssl: Could not find Vcpkg tree:...

```

## やったこと
### vcpkgのインストール
https://github.com/Microsoft/vcpkg#quick-start-windows このリポジトリをcloneして、`bootstrap-vcpkg.bat` を実行する。

```
bootstrap-vcpkg.bat
```

終わったら、vcpkg.exeが作成されるので、そのフォルダへのパスを通しておく。

その後、`VCPKG_ROOT`という環境変数名で登録する。

### Visual Studioに英語の言語パックのインストール
自分の環境の場合は、Visual Studio2019だったが、以下で必要なopensslのvcpkg経由でのインストールに英語の言語パックが必要らしいので、インストールする(Visual Studio2017のBuild Toolだった。ここは個々の環境で違うかも)

Visual Studio Installerを開いて、言語パックのタブを選択→英語の言語パックをインストールする。


### opensslのインストール
vcpkg経由でインストールする。かなり時間かかる。15分くらい。

```
vcpkg.exe install openssl:x64-windows-static-md
```

## まとめ
- 今回初めてvcpkgを触ってみたが、いろいろ罠がある感じだった。
- rust-analyzerにかなり障壁があった
- 簡単なhello worldレベルではrust-analyzerのエラーにならなかったので、なんか他の要因もあるのかもしれない。参照しているクレートの関係か？