OmniAICreator/Qiita-1.07M huggingface dataset:
webpack 4 -> 5 移行メモ

webpackを4から5に上げたときに対応したメモです。

# packages

変更したバージョンは以下の通り

- webpack `4.46.0` -> `5.18.0`
- webpack-cli `3.3.12` -> `4.4.0`
- html-webpack-plugin `3.2.0` -> `5.0.0-beta.6`
- image-webpack-loader": `6.0.0` -> `7.0.1`
- optimize-css-assets-webpack-plugin 削除 -> css-minimizer-webpack-plugin `1.2.0`
- terser-webpack-plugin 削除
- crypto-browserify `3.12.0` 追加
- stream-browserify `3.0.0` 追加

# 対応内容

## package.json

### npm-scriptsの変更

![スクリーンショット 2021-02-23 18.13.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70000/1956e524-8ac0-dc17-8f0a-78128a324f65.png)

`webpack-dev-server` -> `webpack serve` にコマンドが変わったようだ。

[参考] https://qiita.com/whiteraccoon/items/f0675297fce333ac9474

あと環境変数の渡し方も以下に沿って変更。
https://webpack.js.org/guides/environment-variables/


## webpack.config.js 

### 環境変数の受け取り方の変更

環境変数の渡し方の変更に伴い、受け取り方も変更。

![スクリーンショット 2021-02-23 18.19.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70000/0794a744-c4ed-5d59-c1bd-6cd2db46fba5.png)


### devtoolの指定の変更

#### でたエラー
>[webpack-cli] Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
 - configuration.devtool should match pattern "^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map$".
   BREAKING CHANGE since webpack 5: The devtool option is more strict.
   Please strictly follow the order of the keywords in the pattern.

#### 原因
noneは指定できなくなって、その場合はdevtoolフィールド自体を指定しないようにするぽい
[参考] https://www.white-space.work/webpack-5-devtool-none/

#### 対処
noneの指定をundefinedに変更
![スクリーンショット 2021-02-23 17.48.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70000/f6e59b4e-0620-9e62-9072-6398cb06615a.png)

### optimizationの指定の変更

optimize-css-assets-webpack-pluginが

> ⚠️ For webpack v5 or above please use css-minimizer-webpack-plugin instead.

とのことなので、css-minimizer-webpack-pluginに入れ替え。

また、terser-webpack-pluginに関しては
>If you are using webpack v5 or above you do not need to install this plugin. Webpack v5 comes with the latest terser-webpack-plugin out of the box. 

とのことなので、
https://webpack.js.org/plugins/css-minimizer-webpack-plugin/
に載ってた書き方に従い、optimizationの指定部分を以下のように修正。

![スクリーンショット 2021-02-23 18.09.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70000/c1ecbbdf-c866-089d-81b2-8759d60a8e6e.png)
![スクリーンショット 2021-02-23 17.57.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70000/b1e75601-2b64-392c-4105-abf4519ee4cd.png)


### aliasの指定を追加

#### でたエラー
> BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

#### 原因
使用しているライブラリの中で、webpack5からpolyfillされなくなったnode core modulesがwarningを吐く

[参考] https://sanchit3b.medium.com/how-to-polyfill-node-core-modules-in-webpack-5-905c1f5504a0

#### 対処

必要なaliasを指定

![スクリーンショット 2021-02-23 18.07.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70000/e9c453ae-12c9-eb29-0804-94e86ade455f.png)
[Rails][Mysql] いまさらだがポートフォリオにDockerを導入したので、コマンドをまとめる[備忘録]

# 導入理由
・祝日で就職活動が進まないので時間があった。
・Dockerの導入自体が現在のデファクトスタンダード（事実上の基準）であるから。
・今後もポートフォリオを改善する予定があるから。

# この記事に関して
記事にしておくことで、脳に焼き付けたいという完全なるワガママ投稿ですので、誤認識の点がありましたらぜひ教えてください。

# 頻出コマンド一覧

| dockerコマンド | 　　　　　　処理　　　　　 |
| :--- | ---: |
| docker run|イメージ、コンテナを生成し、起動|
|docker start| コンテナを起動|
|docker stop | コンテナを停止|
|docker ps|起動中のコンテナを確認|
|docker ps -a|コンテナの一覧を表示|
|docker images|イメージの一覧を表示|
|docker rm|コンテナを削除|
|docker rmi|イメージを削除|
|docker build|dockerfileからイメージを作成|
|docker exec ~ bash|~コンテナにログイン|
|docker compose build|各イメージをまとめて生成|
|docker compose up|各イメージからコンテナを作成し、起動|
|docker compose logs app|指定したサービスのコンテナの起動ログを確認|

# まとめ
アプリの開発に余裕が出てきたので、頻繁に使われているDockerを導入してみました。
まだ毛が生えた程度なので、今後必ず使用しながら理解を深めていきます。
neal - 近辺飲食店検索アプリ について



![neal-serviceimage](https://user-images.githubusercontent.com/64912886/105801408-6b259100-5fdc-11eb-887e-dc3ff9209435.png)
　
　　この度は、nealをご利用いただきありがとうございます。こちらでは、nealの利用方法であったり、作成秘話などについて記載させていただいております。nealを利用する際の助けになると嬉しいです。

# ・ neal - 近辺飲食店検索アプリ とは??
 　現在地から1 km圏内にある飲食店を提示してくれるモバイルアプリケーションとなります。リストのタブでは、店名はもちろん画像が掲載されている店舗からはお店の雰囲気を掴んだり、詳細ページからは、メニューや店舗予約なども行うことができます。


# ・ 機能
### 1. 近辺の飲食店をリストで確認
　先述にもありますが、現在地から1 km圏内にある飲食店を最大15店舗程ピックアップし、リストに表示されます。店舗名、ジャンル(居酒屋、カフェなど)、営業時間などが表示されます。気になった店舗はお気に入り登録したり、詳細ページでより詳しく確認することができます。

### 2. 飲食店イメージの閲覧
　　画像が登録されている店舗では、最大２枚のお店の様子や、料理などの写真が掲載されており、お店の雰囲気を掴むことができます。(画像を登録されている店舗が少なく、ほとんどがNo Imageと表示されてしまうため、今後改善する予定です。)

### 3. マップ表示
　マップでは、現在地と近辺にある飲食店の場所をピンで教えてくれます。

### 4. 店舗詳細の確認
　画像をタップすることで気になる店舗の詳細画面を確認することができます。詳細画面では、詳しい店舗の位置、メニュー、料理の写真などリストからはわからなかった情報を得ることができます。ぐるなびの会員登録をすることで店舗予約もすることができます。

### 5. ジャンル別によるフィルター機能
 検索マークをタップすることで検索バーが表示されます。そこには店舗名、ジャンル、料理名などを入力し、検索することで条件にヒットする店舗を提示してくれます。

### 6. 他サービスへの共有
　店舗詳細画面の右上側にある共有ボタンをタップすることで、LINEやTwitterなどのSNSで店舗情報を共有することができます。

### 7. お気に入りの店舗を登録
　近辺の店舗リストに表示される店舗の☆マークをタップすることでお気に入りに登録することができます。登録した店舗はサイドメニューにあるお気に入りオプションから確認することができ、店舗情報をタップすることでも店舗の詳細ページを確認することができます。またお気に入りオプションの店舗をロングタップすることでお気に入りから、その店舗を省くことができます。

## 開発者
<img src="https://user-images.githubusercontent.com/64912886/101135777-a09ea580-364f-11eb-8e3e-4a7d25158a21.png" width="200">
#### Eiji Shirakazu
###### Ritsumeikan University Student (B3)

## Contact
- [Twitter](https://mobile.twitter.com/cychow_app)  
- [Facebook](https://www.facebook.com/eiji.shira.3)  
- [LinkedIn](https://www.linkedin.com/in/eiji-shirakazu-57077b197/)  
- [Wantedly](https://www.wantedly.com/id/eiji_shirakazu)  

### アプリのインストールはこちら
 https://apps.apple.com/us/app/neal/id1550909765
Macの左Ctrlでかな切替/英数切替を行う。

## 何をした？
karabinerで独自設定を使って、Macの左CTRLで英数切り替えをできるようにしました。
全く同じ位置にあるので地味に厄介なのです。
  
## 対象の方
- Macの左のCtrlキーをWinの英数と同じにしたい人  
(Karabinerを使いこなしたい人は調べた方が早いかも)

## 設定方法
手順は３つです。  

1. キー配列をカスタマイズできるKarabinerをインストール
https://karabiner-elements.pqrs.org/


2.  karabinerの設定ファイル用のディレクトリに移動 
```
cd ~/.config/karabiner/assets/complex_modifications  
```

3. 設定のjsonを配置(コピペ)
```
pbpaste > left_control_en_ja.json
```
<details> <summary>  <b> ☆コピペするjson </B> </summary><div>

```
{
  "title": "Macの左Ctrlでかな切替/英数切替を行う",
  "rules": [
    {
      "description": "左CTRLを単体で押したときに、英数・かなを切り替える",
      "manipulators": [
        {
          "type": "basic",
          "conditions": [
            {
              "input_sources": [
                {
                  "language": "ja"
                }
              ],
              "type": "input_source_if"
            }
          ],
          "from": {
            "key_code": "left_control",
            "modifiers": {
              "optional": [
                "any"
              ]
            }
          },
          "parameters": {
            "basic.to_if_held_down_threshold_milliseconds": 50
          },
          "to": [
            {
              "key_code": "left_control",
              "lazy": true
            }
          ],
          "to_if_held_down": [
            {
              "key_code": "left_control"
            }
          ],
          "to_if_alone": [
            {
              "key_code": "japanese_eisuu"
            }
          ]
        },
        {
          "type": "basic",
          "conditions": [
            {
              "input_sources": [
                {
                  "language": "en"
                }
              ],
              "type": "input_source_if"
            }
          ],
          "from": {
            "key_code": "left_control",
            "modifiers": {
              "optional": [
                "any"
              ]
            }
          },
          "parameters": {
            "basic.to_if_held_down_threshold_milliseconds": 50
          },
          "to": [
            {
              "key_code": "left_control",
              "lazy": true
            }
          ],
          "to_if_held_down": [
            {
              "key_code": "left_control"
            }
          ],
          "to_if_alone": [
            {
              "key_code": "japanese_kana"
            }
          ]
        }
      ]
    }
  ]
}
```

</div></details>


4. karabiner -> Preference -> Complex modifications で作った設定をEnableにする
![スクリーンショット_2021-02-23_18_22_55-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243925/841c1cd2-fa99-1f15-6dd7-490ffea537fc.png)

5. Complex modificationsに表示されれば、準備完了です。
![スクリーンショット 2021-02-23 18.26.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243925/bc181dbb-0d00-3afc-78f2-78a1fa81f50d.png)


## 後記
私はWindowsは社内事務用、Macは開発用で使っています。 
本当はWinのキーボードをMacに寄せたかったのですが会社の事情で実現できませんでした。
リモートワーク主流となった現在、テキストコミュニケーションが更に重要な技術になりました。
タイピングに妥協しないで今後とも改善していけたらと思います。

## 参考
[快適キーボード操作のためのキーカスタマイズ ～Mac編～](https://knowledge.sakura.ad.jp/23355/)
Ubuntu20.04 に Samba を導入して Linux ファイルサーバを構築する

sambaを用いたLinuxファイルサーバ構築の方法と，クライアント側からのマウント方法の作業メモ．
## 本記事の環境
```bash
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.2 LTS
Release:	20.04
Codename:	focal
```
## サーバ側の設定
### sambaのインストール
```
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install samba -y
```
### 共有するディレクトリの作成と設定
#### ディレクトリの作成
好きな場所に共有対象とするディレクトリを作る．
既に共有したいディレクトリが存在する場合は，新たに作る必要はない．

```bash=
$ mkdir /home/username/sambashare
```
#### 共有対象ディレクトリの設定
設定ファイルを開く．

```bash=
$ sudo vi /etc/samba/smb.conf
```
以下の内容をファイルの末尾に追記する．

```
[sambashare]
    comment = Samba on Ubuntu
    path = /home/username/sambashare
    read only = no
    browsable = yes
```

各設定項目（comment, path, ...) の意味は，言葉通り．

#### デーモンの再起動
設定内容を反映させる．

```bash=
$ sudo service smbd restart
```
### Firewallの設定
sambaで利用するポートを開ける．

```bash=
$ sudo ufw allow samba
```
### パスワードの設定
この username は，ubuntu のアカウントに属している必要がある．

```
$ sudo smbpasswd -a username
```

## クライアント側の設定
### ツールのインストール
```
$ sudo apt install smbclient cifs-utils
```

### マウント
```
$ sudo mount.cifs -o username=USERNAME,password=PASSWORD '\\SAMBA_SERVER_IP\sambashare' MOUNT_DIR
```

### fstabの設定
上項のように手動でマウントしただけでは，クライアント側サーバが再起動した際にマウントが外れてしまう．
そこで，fstab（file system table) に設定を記述しておくことで，クライアント側サーバ起動時に自動でマウントする．

以下の内容を `/etc/fstab` に追記する．

```
//SAMBA_SERVER_IP/sambashare MOUNT_DIR cifs credentials=/home/root/.smbcredentials 0 0
```

## 参考記事
* [How to create a Samba share on Ubuntu Server 20.04](https://www.techrepublic.com/article/how-to-create-a-samba-share-on-ubuntu-server-20-04/)
* [Install and configure samba, ubuncu.com](https://ubuntu.com/tutorials/install-and-configure-samba#1-overview)
Android Studio Emulatorがオフラインなってる問題の解決法

#エミュレータがオフラインに・・・
![スクリーンショット 2021-02-23 17.48.14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/d5fcd776-0338-314e-c414-072a10aa4049.jpeg)
ある日、突然Android Studioのエミュレータがオフラインになっていました。。。

オフライン専用のアプリを開発しているのなら構いませんが、、通信環境が必要なアプリの場合は非常に困ります:sweat:

#解決法
絶対にこの方法で治る！とは言えませんが、、**あくまで「僕はこの方法で治った！！」という参考程度に。**

※Macの場合となりますが、参考リンクにWindowsの場合もあります！！

##DNSを追加
`システム環境設定＞ネットワーク＞詳細＞DNS`を開く
![スクリーンショット 2021-02-23 18.02.14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/faed81b4-cac2-d80d-da5e-fa7c569b46d1.jpeg)

```
8.8.8.8
8.8.4.4
```

を追加して、`OK＞適用`を押す
![スクリーンショット 2021-02-23 18.03.52.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/cbca5e56-3e67-113e-3702-ff914e931a19.jpeg)

**「適用」を押さずにウィンドウを消しちゃいがち・・・**

ちなみに、

```
8.8.8.8
8.8.4.4
```

はGoogleのPublic DNSだそうです。（Public DNSが何か良くわかってませんが・・・）

https://developers.google.com/speed/public-dns/


##Cold Boot Nowでエミュレータを再起動
Android Studioの`AVD Manager＞対象のエミュレータ＞Cold Boot Now`
![スクリーンショット 2021-02-23 17.58.14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/4a066589-6ec8-c08a-c9c1-106d6e49f61e.jpeg)
「Cold Boot」は「電源が完全に切れている状態から起動すること」らしいです。

#エミュレータのCellularを確認
![スクリーンショット 2021-02-23 18.11.33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/51b1d61d-9e9d-b78b-ff33-5aae87460e60.jpeg)
「More」を押して、詳細設定？を開く
![スクリーンショット 2021-02-23 17.49.11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/93691d3d-6a92-7331-367f-ffd6223f6858.jpeg)

`Signal strength`がnoneでないことを確認します。

これで解決しました！！:heart_eyes:

#参考
https://stackoverflow.com/questions/50670547/android-studio-android-emulator-wifi-connected-with-no-internet

https://www.youtube.com/watch?v=KbL3Xo5WTOA
【TypeScript】共用体型の拡張メソッドもどき


簡潔で不変なデータ型にいくつもメソッドを生やしていると、なんだか負けた気分になる。データ型の定義だけしておいて、後から必要なメソッドを必要なだけ増やしたい。しかも、共用体型で上手いこと動いて欲しい。
そんな欲望を叶えるために次のような型関数`PipeSpace`と、関数`pipeSpace`を作った。

# 欲望のかたまり

```PipeSpace.ts
export type PipeSpace<T extends object> = Readonly<T & {
    pipe: <U>(callback: (self: PipeSpace<T>) => U) => U
}>;

export function pipeSpace<T extends object>(object: T): PipeSpace<T> {
    const self: PipeSpace<T> = {
        ...object,
        pipe: callback => callback(self)
    };
    return self;
}
```

# データ型の定義例

例えば`Option`型を定義する場合、次のように書く。まず、`PipeSpace`で型の定義を囲み、`pipeSpace`でオブジェクトの生成を囲めば完璧だ。
メソッドは一つも実装していない。だが焦る必要はない。コーヒでも飲んで、一息ついてから取り掛かろう。

```Option.ts
import {PipeSpace, pipeSpace} from './PipeSpace'

export type Option<T> = PipeSpace<None | Some<T>>;

export type None = PipeSpace<{
    isNone: true
}>;
export const none: None = pipeSpace({
    isNone: true
});

export type Some<T> = PipeSpace<{
    isNone: false,
    value: T
}>;
export function some<T>(value: T): Some<T> {
    return pipeSpace({
        isNone: false,
        value
    });
}
```



# 拡張例

さて、`Option`型の値の中身を変換する`map`と、中身を上手いこと取り出してくれる`getOrElse`が欲しくなったとする。
欲しいなら所望のロジックを持った関数を素直に書けばいい。ただし、処理対象のOption型の値は単独で受け取る必要がある。そこだけは注意しよう。

```OptionUtil.ts
import {Option, some} from './Option';

export function map<T, U>(transformer: (value: T) => U) {
    return (option: Option<T>): Option<U> =>
        option.isNone
            ? option
            : some(transformer(option.value));
}

export function getOrElse<T>(defaultValue: T) {
    return (option: Option<T>): T =>
        option.isNone
            ? defaultValue
            : option.value;
}

export function hint<T>(option: Option<T>): Option<T> {
    return option;
}
```

# 使用例

この実装は次のように使える。
え？メソッドじゃないって？？？そんな細かいことは気にするな。`pipe()`に目を瞑れば、見た目はほとんどメソッドじゃないか。十分だろ？

```index.ts
import {some, none} from './Option';
import * as Option from './OptionUtil';

console.log(some(5)
    .pipe(Option.getOrElse(-1)));
// => 5

console.log(some(5)
    .pipe(Option.map(x => x * x))
    .pipe(Option.getOrElse(-1)));
// => 25

console.log(none
    .pipe(Option.getOrElse(-1)));
// => -1

console.log(Option.hint<number>(none)
    .pipe(Option.map(x => x * x))
    .pipe(Option.getOrElse(-1)));
// => -1
```


# おわり

君の欲望は、どんな型（かたち）をしているんだい？
今更ながらAccessVBAで用紙名称からPaperSizeに設定すべき数値を取得する方法

#VBAで用紙を指定する定数が環境ごとに異なることを初めて知った
VBAで用紙を指定するにはPaperSizeプロパティに数値を打ち込むのですが、
ある程度決まったサイズは定数として切ってあります。

が、ユーザー定義用紙や連票など、ドライバにより異なる用紙サイズは定数に存在せず、
環境ごとに異なる数字になることを、大人になって数十年経過して初めて知りました。

ある環境のPCで設定したaccdbファイルを違うPCに持っていって印刷してみるとLetterになって印刷されてしまい、
PCごとにページ設定を行ってあげないと狙った用紙で出力されないなんてことでハマった方は多いんじゃないでしょうか。

結果、ぐぐったら
http://locosoft.cocolog-nifty.com/blog/2012/03/excel-vba-820b.html
こちらのブログで名もなきエンジニアの方がWordのVBAにてWin32APIを使用して用紙名称から用紙番号を取得する方法を公開していらっしゃいましたので、このたび少しだけ汎化したものを、ここに残しておこうと思います。
お礼は↑のブログのコメント欄へどうぞ。

```
Option Compare Database
Option Explicit

'各種宣言（ほぼ丸コピ）
Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, ByVal pDefault As Long) As Long
Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Private Declare Function DeviceCapabilities Lib "winspool.drv" Alias "DeviceCapabilitiesA" (ByVal pDevice As String, ByVal pPort As String, ByVal fwCapability As Long, pOutput As Any, pDevMode As Any) As Long
Private Declare Sub MoveMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Const DC_PAPERNAMES = 16
Private Const DC_PAPERS = 2

'主関数(帳票をプレビューして用紙を設定して印刷する）
Function FuncMain() As Boolean
    DoCmd.OpenReport "DENPYOU", acViewPreview
    Reports("DENPYOU").Printer.PaperSize = GetPaperName2PaperSize("DENPYOU02", "連続紙 15x5inch")
    DoCmd.PrintOut
End Function

'プリンタ名称と用紙名称から、PaperSizeに該当する値を取得する関数（ほぼ丸コピ）
Public Function GetPaperName2PaperSize(printerName As String, paraPaperName As String) As Integer
    Dim lPaperCount As Long
    Dim lCounter As Long
    Dim hPrinter As Long
    Dim sDeviceName As String
    Dim sDevicePort As String
    Dim bytPaper() As Byte
    Dim strPaperName As String * 64
    Dim aintNubytPaper() As Integer
    Dim onePaperName As String
   
    GetPaperName2PaperSize = -1
    sDeviceName = printerName
   
    If OpenPrinter(sDeviceName, hPrinter, 0) <> 0 Then

        ' バッファに必要なサイズ(用紙数)を取得
        lPaperCount = DeviceCapabilities(sDeviceName, sDevicePort, DC_PAPERNAMES, ByVal vbNullString, 0)
        ReDim bytPaper(64 - 1, lPaperCount - 1)
        ReDim aintNubytPaper(1 To lPaperCount)
       
        '用紙名を取得
        Call DeviceCapabilities(sDeviceName, sDevicePort, DC_PAPERNAMES, bytPaper(0, 0), 0)
        '用紙番号を取得
        Call DeviceCapabilities(sDeviceName, sDevicePort, DC_PAPERS, aintNubytPaper(1), ByVal vbNullString)
        For lCounter = 0 To lPaperCount - 1
            ' 用紙名コピー
            MoveMemory ByVal strPaperName, bytPaper(0, lCounter), 64
            ' 用紙名追加
            onePaperName = Left(strPaperName, InStr(strPaperName, vbNullChar) - 1)
            ' 指定の用紙名が入っていたらその用紙番号を返す
            If InStr(LCase(onePaperName), LCase(paraPaperName)) > 0 Then
                GetPaperName2PaperSize = aintNubytPaper(lCounter + 1)
                Exit For
            End If
        Next lCounter
       
        ClosePrinter (hPrinter)
    End If
End Function
```
【Rails】Slackに通知する方法

## はじめに

今回は[Slack Webhook](https://slack.com/intl/ja-jp/help/articles/115005265063-Slack-%E3%81%A7%E3%81%AE-Incoming-Webhook-%E3%81%AE%E5%88%A9%E7%94%A8)を利用して、RailsアプリからSlackに通知してみます。


# Slackに通知させる方法
##必要なGem
``Gemfile``に以下の二つを追記しましょう。

```ruby:Gemfile
gem 'slack-notifier'
gem 'dotenv-rails'
```
```shell:ターミナル
bundle install
```
[slack-notifier](https://github.com/stevenosloan/slack-notifier)はその名の通り、Slackに通知を送る際に利用します。

[dotenv-rails](https://github.com/bkeepers/dotenv/)は``.env``に定義した環境変数を読み込むことのできるgemです。
よく使うgemなので[こちら](https://pikawaka.com/rails/dotenv-rails)も一読しておきましょう。
今回は後述するSlackのWebHooksURLとchannelを環境変数で管理する際に利用します。

##Slack WebHooksURLを取得する

①以下のURLにアクセスする。
https://slack.com/services/new/incoming-webhook

②「Post to Channel」のセレクトボックスから通知したいチャンネルを選ぶ。（私はgeneralにしました）
③「Add Incoming WebHooks integration」を押して発行する。
④以下の画像のようにURLが表示されるため、コピーしておく。他人に見せないよう注意して管理してください。
![スクリーンショット 2021-02-23 13.24.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631045/612ab47e-1358-70d5-237e-9c7b38fd5fee.png)
##Railsに設定する
アプリのルートディレクトリに``.env``というファイルを作成しましょう。
ここで環境変数を設定します。


```ruby:.env
SLACK_WEBHOOK_URL=https://hooks.slack.com~~~~~ #取得したWebHooksURL
SLACK_CHANNEL=general　#指定したチャンネル名
```

続いて、``.env``をgitの管理対象外にします。
ルートディレクトリの``.gitignore``に以下を追記。

```:.gitignore
/.env
```
**もしルートディレクトリに``.gitignore``が作られていない場合は作ってください！**
（PCによっては``rails new``した時に自動で生成されない場合があります。）

これを記述しないとGitHubにpushした時``.env``が公開されてしまいます！！

## 呼び出してみよう

通知したい場所で以下のように記述すればOK

```ruby:○○_controller
notifier = Slack::Notifier.new(
  ENV['SLACK_WEBHOOK_URL'],
  channel: "##{ENV['SLACK_CHANNEL']}",
  username: '通知です'
)
notifier.ping '通知テキスト'

```
これで通知されるようになりました！



#終わりに
お疲れ様でした。
例外や通報機能を実装した際にも設定できそうですね。
GCP-ACEを取得したぞい

[Associate Cloud Engineer](https://cloud.google.com/certification/cloud-engineer?hl=ja)の認定資格を受けてきました。

# 目的
「好きに研修を受けて良いよ」とお触れが出たこともあり、折角の機会なので
実務で使ったことがないGoogle Cloudを体系的に学びたいなと思ったのがきっかけ。
将来に向けてAWS、Azureとの違いを把握しておきたいというのも目的のひとつでしたが、
研修受けるなら資格も取らないと勿体ないよなということで受験しました。

# 勉強方法
認定トレーニングで一通り理解した後に、試験範囲から漏れている項目（Kubernetes関連）や細かい内容を補完した感じ。
Qwiklabsと模擬試験を比べると後者の方が直接的に試験の役には立った割合は大きいかも。

- 認定トレーニング：[Architecting with Google Compute Engine](https://www.trainocate.co.jp/reference/course_details.aspx?code=GGC0018V)
 - 体系的に学べる（特にGoogle Cloudサービス間の繋がりに触れた内容なのがポイント）
 - 座学＋Qwiklabsでのハンズオンの構成なので覚えやすい（理解した上で手を動かすのって大事）
 - Kubernetesは含まれていないので注意（別コースがある）
- [Qwiklabs](https://google.qwiklabs.com/)
 - 認定トレーニングにKubernetesが含まれていない＆模擬試験でCLI系の問題が多かったので利用
 - コマンドの組み立てや機能オプションを覚えるのには有用（＝CLI/オプション以外の設問の対策にはならない）
 - [Google Cloud Essentials](https://google.qwiklabs.com/quests/23), [Baseline: Infrastructure](https://google.qwiklabs.com/quests/33), [Kubernetes in Google Cloud](https://google.qwiklabs.com/quests/29)あたりを実施
- [Cloud Engineer 模擬試験](https://cloud.google.com/certification/sample-questions/cloud-engineer?hl=ja)
 - 試験そのものより、結果解説にあるリンク先の内容が重要
 - 出題の傾向をみて、勉強方針を考えるために使うコンテンツだと思った方がよい
- [【GCP認定資格】Google Cloud Platform Associate Cloud Engineer模擬問題集](https://www.udemy.com/course/gcp-ace-mogi/)
 - みんな大好きUdemy
 - 本家の模擬試験だけだと数が少なくて雰囲気を掴みづらかったので購入
 - こちらも「どのような傾向の問題が出てくるかを掴む」ためのコンテンツ

# 受験
テストベンダーは[Kryterion](https://www.kryteriononline.com/)。

- オンサイトは対応している会場があまり多くない印象（オンライン受験も対応している）
- 4日後以降の枠しか予約できないので受験は計画的に
- 試験申し込みに使うWebassessorのアカウントは他ベンダー試験で使えないので注意（直近で[ServiceNow](https://www.servicenow.co.jp/)の資格試験を受けていてそれもWebassessorだったが、その際に使ったアカウントがGCP試験の申し込みに使えなくてしょんぼりした）
- 試験会場ついてからの手続き等はピアソンと大して違いはない

# 試験の感想
認定トレーニング3日、Qwiklabs１日、模擬試験と関連情報の整理で1日といった感じだったので、そこそこ効率よく取得できたのかなと。

- 一通り回答が終わった時点で40分くらい経過していたので選択式にしては結構かかった方
 - 問題文がやや長めで必要な情報の取捨選択が求められる（読解能力が大事）
 - 「課題/要求は解決できるが、文中の条件や制約によりNGとなる選択肢」を見分けるのがツライ
 - CLIとか迷うポイントがない（1つ1つ制約の照合をしなくて良い）問題はあんまり出題されず
- 認定トレーニングだけだと合格は難しい印象
 - 基本的な概要と特に重要な特徴/制約、サービス間の差異を抑えられるので受講できるならその方が効率は良い
 - 細かい制約や挙動の違いまではカバーしないので、そこは実務や独学で抑える必要がある
 - 模擬試験は効率よく勉強するための足掛かりとしては本当に優秀（似た問題はあんまり出てこなかったのでコレだけで受かることはないと思う）

Prrofessionalを受けるかどうかはまだ未定です。
実務で使っているなら頑張ろうって感じなんですが、今のところは他の資格試験を後回しにするほどのモチベーションがあんまりないですね。。
【サルが書く】クネビンフレームワークを使って、関わっているプロダクトはスクラム開発が有用なのか判断する

わっきょい！

スクラム開発は導入自体そこまで難しくないですが、ほんとに導入して効果があるのかって疑問に思うときがあると思います。
特に業務に導入するときは、効果があるから導入しますと、周りを納得させる必要も出てくると思います。
そんなときにクネビンフレームワークを使って、プロダクトにスクラム開発を導入したときに効果的なのかということを判断したいと思います。

## スクラム開発のメリット
スクラム開発のメリットとして、複雑な領域における検査と適応を行うことができる、という点があります。

ですが、かならずしもソフトウェア開発は複雑な領域に当てはまると安易に判断するのは危ないです。

## クネビンフレームワークとは

>クネビン（カネヴィン）フレームワーク Cynefin Frameworkとは、VUCAの世界において、実際の世界をどのようにとらえて、どのように考えて行動したらいいかを体系づけたものです。

>デイビッド J. スノウドン David J. Snowden とメアリー E. ブーンMary E. Booneにより提言されました。
>引用： https://iandco.jp/ooda/cynefin/

物事を領域に分けて、どのような行動をすればいいか体系づけたものです。

## スクラムが効果的な領域

・**複雑な領域**
物事は予測できないことのほうが多い、後で振り返ることでわかる。
創発的な領域である
検査と適応を行う
安全に失敗できるような環境を作り、重要な情報を見つ出せるようにする必要がある。
このような環境では密なコミュニケーションが欠かせない
革新的な新規開発はこの状態に当てはまり、既存プロダクトに革新的な機能を追加するときも同様である
スクラムはこのように革新的なものを作るときに、検査を行い、適応させることでうまく当てはまる
無秩序かつ持続性のあるもの

## スクラムが効果的でない領域

・**込み入った領域**
専門家が活躍する適切なプラクティス
正解を導き出すために専門家が必要な場合は有用
例えば保守作業のように、パフォーマンスを最適化する場合
シックスシグマのようなアプローチは特に有用
秩序的かつ持続性のあるもの

・**単純な領域**
単純な領域の場合は予め定義されていた解決方法で対応するほうが良い
スクラムを用いるより、手順化したほうが効果的
秩序的かつ瞬時性があるもの

・**カオスな領域**
プロダクトに致命的な不具合が発生したときには、素早い対応が必要である
すぐに解決しなければ、金銭的な損害、訴訟リスク等がある場合
そんなときスクラムを用いる余裕はない
プロダクトバックログの優先順位を決め、次のスプリントでなにをするかを考えている場合ではないから
無秩序かつ瞬時性があるもの

・**無秩序**
自分が上記の4つの領域にいない場合は、まずどれかの領域に状態を変化させることを優先させるべき
無秩序な状態でスクラムをする必要はない

・**割り込み駆動**
スプリント内で割り込みが多い場合はスクラムはあまり向かない状態です
割り込みが多いことで、スプリント内で終わるタスクに自身が持てなくなるため
バックログの中身や優先順位も頻繁に変更しなければなりません
割り込み駆動の場合はカンバン手法を取り入れることを検討したほうが良い
スクラムとカンバンはどちらもアジャイルなアプローチであります。
メリットデメリットはあるので、自分の関わっている領域を考慮して、プロダクトにあった手法で開発を行うことが大事
状況によっては新規開発はスクラム、保守はカンバンで行うのもいいかも

## 結局どんなときに効果的なの？
**無秩序かつ持続性のあるものを扱うとき**
はスクラムを導入すると効果的です。

手順を作ったほうがいい定期的な作業や、一つのことに深く踏み入れる必要がもの、スクラムをやっている暇がない短納期なもの、割り込みが多い場合はスクラムは効果的にでない場合が多いと思います。

## 参考文献
[エッセンシャルスクラム](https://amzn.to/3dA3Zkl)
[クネビンフレームワーク Cynefin Framework](https://iandco.jp/ooda/cynefin/)
２進数の乗算と除算

##２進数の乗算##

・❓✖︎7の計算の場合
＝❓✖️  （4+2+１）→　２^nの形で  ばらす 
＝❓✖️（２^２＋２＾１＋２^０）
＝（❓✖️２^２）＋（❓✖️２^１)＋❓
という計算となる。

##２進数の除算##

ex.15-３の計算

**STEP１　二進数に直す**
15＝1111 3＝11　→1111＝11
ここから**元の数字から１１は何回引くことが出来る**のかを考える。

**STEP2 元の数字を超えない範囲で割る数字11を左シフト**
１１を左シフトすると・・・１１００（左へ２シフト）...①
これを元の数字から引いていく。
１１１１-１１００＝１１

**STEP３　上記の引き算の結果を超えない範囲で割る数字を左へシフト**
１１＝１１（左へ０シフト）...②
１１−１１＝０

**STEP４　元の数から引くことができた回数を求めるにはこの二つを足せば良い。**

2^2(①）＋2^0(②）＝４＋１＝５→**引くことの出来た回数**

##参考文献##
キミタ式基本情報技術者P50〜P55
この令和時代にサーバーレス知らないのはヤバみ

## Serverless とは

サーバー管理が不要なアーキテクチャです。

自前でサーバーを用意/管理するとなると様々な課題と向き合うかと思います。例えば、OS設定や容量管理、負荷管理、ランニングコスト、アイドル時のリソース管理、アクセス制御、セキュリティ管理などキリないですが、サーバーレスアーキテクチャを利用することで、そんなものは気にしなくて良くなり、プログラムロジック（本質）の開発に注力することができるかと思います。熱盛ですね。

現代では、モノリシックよりもマイクロサービスなどの疎結合な特性を持つアーキテクチャが注目されていると思いますが、その一部として、サーバーレスアーキテクチャを導入するという形も考えられると思います。


## [Serverless Framework](https://www.serverless.com/) とは

サーバーレスアーキテクチャを簡単に構築するためのオープンソースフレームワークです。AWSやGCP、他にも様々なクラウドプラットフォームに対応しています。似たものとして、SAM（~~いや EZ DO DANCE じゃないです~~）というAWS公式が提供しているフレームワークもあります。サーバーレス環境をどうやって管理するかという話になった時に使います。

フレームワークを使用せず、AWS上にサーバーレス環境を作るとなると、なかなか大変かと思います。今回であれば、AWS Lambda、CloudWatch Events、S3など手で用意したりすることになり、ある程度の知識も必要になると思いますが、フレームワークを使用することで、設定ファイル1つ、コマンド1発でサーバーレス環境を自動構築してくれちゃいます！！設定ファイルなどを見るだけで、現在の環境を簡単に把握することが出来るって良いですよね。いわゆる `IaC` です。美しい！

> zero-friction serverless development

と公式にあります。このストレス社会の中で、ノンストレスなサーバーレス開発をしよう的な意味でしょうか。感無量。脱帽です。

やっちゃえ SERVERLESS :angel_tone2:


## AWS Lambda とは

`Faas` であり、AWS上のサーバーレスサービスの代表格。フルマネージドで、インフラは管理する必要がなく、コードさえあれば実行可能。スケーラビリティが高く、リクエストに応じて、AWSがリソースを柔軟に確保（スケール）してくれます。`S3`、`SES`、`CloudWatch Events` 等のAWSリソースを活用しており、イベントが発生した時に何かを実行させたりすることができます。ユースケースとしては、定期的なタスクやインベント処理、例えば「S3にファイルが追加されたら〇〇する」、「メールが届いたら△△する」とか「定期的に☆☆通知をSNSにアップ」とかでしょうか。

事実的にはサーバーが存在するのですが、AWS Lambdaではプログラムが実行される際、`lambdaコンテナ` というものが一時作成され、プログラムの実行が終わると無くなるようでして、この部分がサーバーレスと言われる所以みたいです。

クラウド依存ですので、特定の書式で実装する必要があったり、使用可能な言語、メモリ、実行時間等に制限があったりと、制約はありますが、うまく付き合いながらツールを使いこなせれば、使える場面は多岐にわたると思います。

凄くザックリとした説明ですが、凄く便利そうですよね。簡単なAPIとかなら、わざわざEC2とか用意せずにLambdaでイケる！ :)


## 実際に作ったやつ

ソースは以下。Docker環境用意してあるので、ぜひ試してみてください。欲を言えば「PR欲しい :flushed:」。

<a href='https://github.com/yudaiogawa/notify-aws-billing'><img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127525/611ddb22-4b52-c61a-1ef5-fe7f6a207123.png' width='512px' /></a>

#### 全体イメージ図

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127525/77c03532-316f-71a8-4a82-69aee46ff869.png' width='576px' />

#### 概要

Cronによりスケジュールされた `CloudWatch Events` をトリガーに `Lambda Function` が実行されます。`Lambda Function` は `CostExplorer` からコストを取得し、Slackに通知するというプログラムになってます。

#### 内容

以下のように通知されます（2020年12月3日の実行イメージ）。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127525/2837554a-c251-3317-8650-38f08c660a5b.png' width='576px' />

「実行月の1日から昨日までの料金」と「サービス毎の料金（内訳）」をSlackに通知します。毎月1日には「前月の料金」が通知され、料金が0の場合（ほぼ無いけど）は、内訳が通知されないようにしてます。

ローカルのターミナル上で実行したり、ローカルからデプロイされた関数を呼び出すことが可能です。`個人のWEBHOOK_URL` 等を指定して実行を行い、通知確認したり、Slack上での表示を確認したり等が比較的簡単に行えるように工夫しているつもりです。

まだまだ改良の余地があるので、引き続き育てていこうと思います。

#### デプロイ

デプロイは以下コマンド1発。`CloudFormation` 経由で `Stack` および `CloudWatch Events` 、`Lambda` が作成され、ソースは `S3` に格納されます。そう。コマンド1発で。

```zsh
% sls deploy --aws-profile foo --url https://hooks.slack.com/services/T00/B00/XXX
```

#### Docker環境

[lambci/lambda](https://hub.docker.com/r/lambci/lambda/) をイメージを使用しています。`AWS Lambda` の環境を実現しているよう（完全再現では無いようなので注意が必要）でして、良さそうだなと思って使用させてもらっています。
SlackのIncoming Webhooksの新仕様について

# はじめに
いつからかはわからないのですがslackがIncoming Webhooksの仕様を変えたらしくかなり戸惑いました。
自分なりにわかりにくかった点をまとめてます。
旧仕様の方はあまり自信がないですので知見ある方は教えてください。
他にも認識間違っているところあれば教えていただけると幸いです！

# アプリとwebhook URLとチャンネルについて
## アプリ
### 旧仕様
たしかそもそもwebhooksを利用するのに必須ではなかった。
そのためIncoming webhooksと言う名の名前だけでは判断できない謎アプリが大量にslackのワークスペースにあった気がする…

### 新仕様
webhooksの利用に必須。名前も必須

## webhookURL
### 旧仕様
ワークスペース？アプリ？に一つだったっけ？

### 新仕様
発行する際にアプリが必須に。
チャンネルごとに発行される。

## アプリとwebhook URLとチャンネルの関係
・webhook URLはチャンネルと一対一
・アプリはwebhook URLと一対多
の関係になっている。
アプリが対応するチャンネルのwebhook URLを発行されていない場合はメッセージを送っても「チャンネルがないよ」と返してくる。
webhook URLが発行されているチャンネルでないとアプリがそもそも追加できないようになっている。

# メッセージの送信のカスタマイズ（めっちゃ大切）
### 旧仕様
一つwebhookURLがあれば、そのURLに値をPOSTすればなんでもできた。
username(なんて名前で送るか)
channel（どのチャンネルに送るか）
icon(どんなアイコンをつけるか)

### 新仕様
上記の設定がPOSTする値から設定できなくなった。（webhookURL経由では変更できなくなった）
代わりにそれらの設定がアプリごとに固定になった。（まぁこっちの方が自然だよな…）
blocksという新しい引数が追加された

# 旧仕様を用いて作成された既存アプリについて
現状は動くが、いずれ動かなくなるかも。

# 参考文献
https://api.slack.com/messaging/webhooks
https://github.com/laravel/slack-notification-channel/issues/34#issuecomment-608376575

# 終わりに
webhookURLがチャンネルごとなのはちょっと不便になったかな…と思いますが、それ以外は逆に自然になった気がする。
破壊的変更ではないので、実はこれに伴う変更が意外とライブラリで整備されてなかったりする(blocksとか)のでissueを立ててみるのも良いかも。
入れているVSCodeの拡張機能

## テーマ

### GitHub Theme
https://marketplace.visualstudio.com/items?itemName=GitHub.github-vscode-theme

### Material Icon Theme
https://marketplace.visualstudio.com/items?itemName=PKief.material-icon-theme


## 日本語化 (Japanese Language Pack for Visual Studio Code)

https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-ja

## IDE (Code Runner)
https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner


## C/C++
https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools

## Python
https://marketplace.visualstudio.com/items?itemName=ms-python.python
データテーブルの連結ー交差結合

テテーブルとテーブルの連結には、縦方向（行が増える）と横方向（列が増える）の場合があります。
縦方向の場合は__集合__、横方向の場合は__結合__と言います。

これまで横方向の結合に関して、完全外部結合、内部結合、左(右)外部結合を述べてきたが、今回は交差結合についてSQLを用いた例を示します。
行う操作は下記を想定しています。table_1 と table_2 の各項目を総当たりで組み合わせて、横方向に連結させています。
内部結合や完全外部結合などと違い、キーとなる共通の変数は必要ありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287001/7798ce41-19ea-1821-4601-6f260c4d7d57.png)

この交差結合はSQL文では下記のようなコードで行います。

~~~sql
 create table table_3 as
 select *
 from table_1 cross join table_2;
~~~

<font color="Blue"> __SELECT__ </font> 取り出す変数名  <font color="Blue">__from__</font> データセット1 <font color="Red">__cross join__</font> データセット2 
* は、すべての変数を指します。

ちなみに、Pandas での交差結合については、下記サイトで解説されています。
https://esu-ko.hatenablog.com/entry/2020/06/11/Pandas%E3%81%A7cross_join%E3%82%92%E8%A1%8C%E3%81%84%E3%81%9F%E3%81%84


####関連記事
[データテーブルの連結－縦方向 1（異なる列名をそのまま残す場合）](https://qiita.com/MomonekoView/items/78f51b7385bec42d08ed)
[データテーブルの連結－縦方向 2（異なる列名を統合する場合）](https://qiita.com/MomonekoView/items/e63b54b0ae1849c3ddd1)
[データテーブルの連結－縦方向 3（積集合と差集合）](https://qiita.com/MomonekoView/items/14fe790b6993c2b3dad3)
[データテーブルの連結－横方向 1（完全外部結合）](https://qiita.com/MomonekoView/items/86f124e53d372290e2a4)
[データテーブルの連結－横方向 2（内部結合）](https://qiita.com/MomonekoView/items/5d067363c506a0ab2013)
[データテーブルの連結－横方向 3（左右の外部結合）](https://qiita.com/MomonekoView/items/434d8bceab29606568e9)
markdownlint Markdownのチェック項目を意図的にOFFにする

# 目的

- VisualStudioCode（以降VScode）のプラグインであるmarkdownlintの任意のチェック項目をOFFにする方法をまとめる

# markdownlintのチェックは助かるけど・・・

- Markdownの記載ミスを校正してくれるmarkdownlintの機能は素晴らしく、簡単に記載ミスを発見する事ができる。
- しかし若干記載フォーマットがきつく、自分なりの記載方法をするとエラーとして認識されてしまう時がある。
- エラーが出ていても無視すればよいが沢山エラーの下線が表示されていると本当に記載ミスしている時に見つけられない。
- 自分の記載方法にあっていないもののチェックを意図的にOFFにする方法を簡単に記載する。

# 方法

1. VScodeを起動する。
2. 画面左上の「code」から「基本設定」 → 「設定」と進む。

    ![スクリーンショット_2021-02-23_17_08_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/76ecc517-d93e-5f9b-0adf-7bfc01188a0e.png)

1. 設定の検索欄に「settings.json」と入力してヒットした最上位の「settings.jsonで編集」をクリックする。

    ![設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/adef41e7-36b9-18ad-bd0f-95cad3528a12.png)

1. 開いた「settings.json」ファイルに下記のようにOFFにしたいエラーのエラーコードを記載する。

    ```settings.json
    {
        "markdownlint.config": {
            "OFFにしたいエラーのエラーコード": false,
        }
    }
    ```

1. 筆者は「MD025」「MD014」「MD010」「MD009」「MD007」「MD031」「MD040」をOFFとして設定しているので下記のように記載されている。

    ```settings.json
    {
        "markdownlint.config": {
            "MD025": false,
            "MD014": false,
            "MD010": false,
            "MD009": false,
            "MD007": false,
            "MD031": false,
            "MD040": false
        },
    }
    ```

1. 記載した瞬間から設定が反映されて当該のチェックがOFFになる。
1. 「settings.json」の記載例として筆者の「settings.json」の内容を下記に記載する。今回の記事に関係ない設定も記載されている。

    ```settings.json
    {
        "terminal.integrated.shell.osx": "/bin/bash",
        "files.autoSave": "afterDelay",
        "editor.minimap.enabled": false,
        "terminal.integrated.scrollback": 1e+100,
        "workbench.startupEditor": "newUntitledFile",
        "liveServer.settings.donotShowInfoMsg": true,
        "editor.accessibilitySupport": "on",
        "debug.allowBreakpointsEverywhere": true,
        "markdown.extension.katex.macros": {
        
        },
        "markdownlint.config": {
    
            "MD025": false,
            "MD014": false,
            "MD010": false,
            "MD009": false,
            "MD007": false,
            "MD031": false,
            "MD040": false
        },
        "bracket-pair-colorizer-2.activeScopeCSS": [
    
            "borderStyle : solid",
            "borderWidth : 1px",
            "borderColor : {color}",
            "opacity: 0.5"
        ],
        "bracket-pair-colorizer-2.colors": [
    
            "Gold",
            "Orchid",
            "LightSkyBlue"
        ],
        "workbench.iconTheme": "vscode-icons",
        "mssql.connections": [
            {
                "server": "{{put-server-name-here}}",
                "database": "{{put-database-name-here}}",
                "user": "{{put-username-here}}",
                "password": "{{put-password-here}}"
            }
        ],
        "[json]": {
        
            "editor.quickSuggestions": {
                "strings": true
            },
            "editor.suggest.insertMode": "replace",
            "gitlens.codeLens.scopes": [
                "document"
            ]
        }
    }
    ```
vectorとlistの追加処理の時間差を比べてみた

#はじめに
以前、vectorとlistの追加処理に関して記事を書いた際に、ありがたい事に自分の中の「実行時間に関する感覚」がズレているかもしれないという事が発覚したので、しっかり**プログラムを書いて確認しよう**と思いやってみたという感じです。

#目次

 1. 前置き
 2. シンプルに後ろに追加してみる
 3. 真ん中あたりに追加してみる
 4. 先頭に追加してみる
 5. まとめ

#前置き
###どんなプログラムを書いたのか
配列に**数万回値を追加し続ける**という最高にロックな実験プログラムです。

###インクルードについて

```c++
#include <iostream>
#include <vector>
#include <list>
#include <time.h>
```
この記事に乗せているプログラムには、この４つをインクルードしてあります。
###使う関数について
今回は比較のため一括で**「insert」関数を使用**します。
push_backやpush_frontなど便利な関数があるとの事ですが、
今回は知らないふりをします。

#シンプルに後ろに追加してみる
まずはとりあえず**後ろにどんどん追加していく**処理を書いてみた。

```c++
const int LOOP_NUM = 100000;//追加する回数
std::vector<int>vec;
std::list<int>lis;

//vectorについて
clock_t startV = clock();
for (int i = 0; i < LOOP_NUM; i++) {
	vec.insert(vec.end(),1);//今ある配列データの最後に「１」という値を追加する。
}
clock_t endV = clock();

double timeV = (static_cast<double>(endV) - static_cast<double>(startV)) / CLOCKS_PER_SEC * 1000.0;
std::cout << "vectorの追加速度:" << timeV << "ms\n";

//listについて
clock_t startL = clock();
for (int i = 0; i < LOOP_NUM; i++) {
	lis.insert(lis.end(),1);//今ある配列データの最後に「１」という値を追加する。
}
clock_t endL = clock();

double timeL = (static_cast<double>(endL) - static_cast<double>(startL)) / CLOCKS_PER_SEC * 1000.0;
std::cout << "listの追加速度:" << timeL << "ms\n";

```

これを実行してみると、このような結果になった。

```
vectorの追加速度:111ms
listの追加速度:167ms
```

…**vectorのが速いではないか！**

#真ん中あたりに追加してみる
今度は配列の真ん中に追加していく処理を書いた。
（プログラムは上の続きになります。なのですでにLOOP_NUM分のデータが配列に入った状態です。）

```c++
//vectorについて
startV = clock();
for (int i = 0; i < LOOP_NUM; i++) {
	vec.insert(vec.begin() + vec.size() / 2, 1);//配列の先頭から「配列のサイズ÷２」分進んだ場所に追加。
}
endV = clock();

timeV = (static_cast<double>(endV) - static_cast<double>(startV)) / CLOCKS_PER_SEC * 1000.0;
std::cout << "vectorの追加速度:" << timeV << "ms\n";

//listについて
std::list<int>::iterator ite = lis.begin();
for (int cnt = 0; cnt < lis.size() / 2; cnt++) {
	ite++;//イテレーターを配列データの真ん中まで移動させる。
}

startL = clock();
for (int i = 0; i < LOOP_NUM; i++) {
	lis.insert(ite,1);//真ん中あたりに追加。
}
endL = clock();

timeL = (static_cast<double>(endL) - static_cast<double>(startL)) / CLOCKS_PER_SEC * 1000.0;
std::cout << "listの追加速度:" << timeL << "ms\n";
```
こちらの結果は…

```
vectorの追加速度:940ms
listの追加速度:142ms
```
**listのが速い！**

#先頭に追加してみる
最後に先頭に追加してみる。
（プログラムは、先ほどと同じくLOOP_NUM分だけ入った状態の続きです。）

```c++
//vectorについて
startV = clock();
for (int i = 0; i < LOOP_NUM; i++) {
	vec.insert(vec.begin(), 1);//先頭に１を追加。
}
endV = clock();

timeV = (static_cast<double>(endV) - static_cast<double>(startV)) / CLOCKS_PER_SEC * 1000.0;
std::cout << "vectorの追加速度:" << timeV << "ms\n";

//listについて
startL = clock();
for (int i = 0; i < LOOP_NUM; i++) {
	lis.insert(lis.begin(), 1);//先頭に１を追加。
}
endL = clock();

timeL = (static_cast<double>(endL) - static_cast<double>(startL)) / CLOCKS_PER_SEC * 1000.0;
std::cout << "listの追加速度:" << timeL << "ms\n";
```
実行結果は…

```
vectorの追加速度:1867ms
listの追加速度:161ms
```

**これまたlistのが速い！**

#まとめ
雑にまとめるとこんな感じ。

|種類|先頭に追加|中央に追加|最後に追加|
|:---:|:---:|:---:|:---:|
|vector|負け|負け|勝ち|
|list|勝ち|勝ち|負け|

**いつでもlistのが速いという訳ではない**という事が分かった。
そしてlistは、前中後のどこに追加処理を書いても実行時間がほぼ変わらないのは面白いなと思った。
…だがなぜ真ん中への追加処理が一番早いのだろうか。begin、endの関数がちょっと重たいのかな？
[AWS] Systems Manager Run Command (プライベートサブネット)

# はじめに
Systems Manager Run CommandをプライベートサブネットのEC2インスタンスに対して実行する際にハマったので備忘録。
※あくまで動作確認につき権限周りガバガバ。。。
#前提
・プライベートサブネット上にSSMエージェントがインストールされたEC2インスタンスが存在すること。
　[SSMエージェントについてはこちら](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/ssm-agent.html)
・コマンド出力にS3を使用する。

#手順
1. EC2に割り当てるIAMロールにAWS管理ポリシー「AmazonEC2RoleforSSM」をアタッチする。

2. 実行するIAMユーザーに下記のポリシーをアタッチする。
　AWS管理ポリシー「AmazonEC2FullAccess」
　AWS管理ポリシー「AmazonSSMFullAccess」

3. VPCエンドポイント作成 (←ここでハマった)
 下記の4つのエンドポイントを作成。
　「com.amazonaws.ap-northeast-1.ssm」
　「com.amazonaws.ap-northeast-1.ec2messages」
　「com.amazonaws.ap-northeast-1.ssmmessages」
　「com.amazonaws.ap-northeast-1.s3」

　SSMのエンドポイントのみで実行できると思い込んでしまったのが失敗。
　「com.amazonaws.ap-northeast-1.ssm」のみ作成してSystems Manager Run Commandのコンソール
　からコマンド実行したところ、進行中のステータスのまま完了しませんでした。

上記1〜3の設定でコマンドのステータスが完了となり、ログも出力されました。

# おわりに
エンドポイントの不足でコマンドが完了しないということに気づくまでが長かったです。。
私自身、権限周りを設定する機会があまり無く、そちらばかり疑っていました。
勉強不足ですね。。

参考サイト
[Systems Manager Run Command をプライベートサブネット上の EC2インスタンスに対して実行する手順と注意点](https://dev.classmethod.jp/articles/ssm-run-command-on-purivate-subnet/)
↑こちらのサイトがより詳しく、丁寧です。

[AWS Systems Managerユーザーガイド](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/what-is-systems-manager.html)
↑公式サイト
Chatwork API利用方法

#はじめに
GASでChatwork APIを使用する機会があったためマニュアル化します。

#Chatwork API Token取得方法
Chatworkにログインして、メニューから「サービス連携」をクリックします。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246142/87eedce0-99e1-171e-1f73-87691fdac977.png)

「API Token」をクリックします。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246142/e66c11ab-77e2-ddd5-664d-f530b384151a.png)

APIトークン発行にログインパスワードが求められますので、パスワードを入力して「表示」をクリックします。
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246142/824b94be-7efc-9233-1855-76d0fac313d2.png)

APIトークンが表示されますのでコピーします。
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246142/a1289043-7c5a-19d6-e199-d22253e992b5.png)

#最後に
特に難しい手順はないですね！最後まで読んでいただきありがとうございます。
アジャイルサムライ　第１０章　アジャイルな意思疎通

# アジャイルな意思疎通

**各イテレーション毎に次の４つのミーティングをするべきである**

- 今回のイテレーションの作業に備える(ストーリー計画）
- 今回のイテレーションのフィードバックを得る（ショーケース）
- 次回のイテレーション計画を立てる（イテレーション計画）
- 次回のイテレーションで改善できる余地を探す（ミニふりかえり）

## ストーリー計画
**これから始まるイテレーションで取り組むストーリーの準備が整っていることを全員で確かめる**

- 顧客と一緒に受け入れテスト条件をレビュー
- 開発チームが見積もりを確認

**想定していたストーリーが大きいことに気づいた場合**
一回のイテレーションで収まるようにストーリーを分割して計画を更新すればいい。

## ショーケース
チームが成し遂げた成果をお披露目して本物のフィードバックを得る

## イテレーション計画
主に三つのやるべきことがある。

- 開発チームと顧客が一緒になって次回のイテレーションの作業を計画する
- チームのベロシティを確認し、次に取り掛かるストーリーを整理する
- チームがコミットメントする作業量を見極める

**何か話しておくべきことを話すのはこのタイミング**

## ミニ振り返り
**チーム全員が集まってすごくうまいったことやもっとうまくいくために必要なことを話し合う**

重要なことは、
**「チーム全員が安心できる雰囲気であること」**

前提理解として
**「チームメンバーそれぞれはその時々わかっていたこと、備えていた自分自身のスキルと能力、手に入れる事の出来たリソース、そして現場の状況に応じて、自分の力が及ぶ限りの全力を尽くした」**


## 番外編：デイリースタンドアップ
毎日、自主的に集まって自分の作業の状況について話し合うミーティング。
内容は

- 昨日やったこと
- 今日やること
- チームの開発速度を下げてしまうことがあればなんでも

だけでもいいけれど、新たなひらめきとかチームのふるまいを変えるには少し物足りない。

- 昨日、世界をどう変えたのか
- 今日は何をぶちかますのか

など少し大げさなくらいに、今日はこれをしますと言うコミットメントを表明することが大事。
Rspec・予期せぬPENDINGに動揺した話(モデル単体テスト実行中)

- Ruby2.6.5
- Rails6.0.0

初学者です。
exampleの整理中に出現し、何が起こったのか分からず迷走した為、忘れないように記述しておきます。

いつも通りにRspecを使いテストコードに記述をし、実行しましたが、、、
ターミナル上に黄色文字で**「PENDING」**の文字が出現しました。。

***
### **PENDINGとは？**
そもそもpendingとは、Rspecに備わっているコマンドに一つです。保留中にしたい場合や、何らかの事情で example が失敗する原因を修正できない場合に使うものだそうです。
詳細をまとめてくださっている方がいらっしゃいました。
https://qiita.com/tyamagu2/items/fe75ebfcfd643d3d760d
***

まだ詳細のコードを書いていた訳ではないのに何が原因だったのか、初学者の未熟な自分には理解できませんでしたが、、

```
describe 'ユーザー新規登録' do
      context '新規登録できないとき' do
        it 'nicknameが空では登録できない' do
        end
        it 'emailが空では登録できない' do
        end
        it 'emailは一意性がないと登録できない' 
        end
        it 'emailは@が含まれていないと登録できない' do
        end

     　　　　(以下略)      
```

## 原因

**doの書き忘れ**が原因でした。
「emailが空では登録できない」の記述部分に注目すると、　doを書き忘れています！
これを書かないとpendingになるということを知りました。。
ただの凡ミスですが、同じ状態になってしまった方は是非記述の見直しをしてみてください！
ASP.NET Core MVCのWebアプリをIIS 10.0に公開する

##バージョン
IIS 10.0
ASP.NET Core 3.1
Windows 10

##.NET Core ランタイムインストール
[.NET Core 3.1のランタイムはここからダウンロード](https://dotnet.microsoft.com/download/dotnet/3.1)
[.NET Core 5.0のランタイムはここからダウンロード](https://dotnet.microsoft.com/download/dotnet/5.0)

ダウンロードページに用意されているランタイムは３種類あります

* ASP.NET Core Runtime(Webシステムなどのアプリを実行するための物)
* .NET Desktop Runtime（Windows デスクトップアプリを実行するための物、.NET Runtimeを含まれている）
* .NET Runtime(コンソールアプリを実行するための物)

必要に応じてダウンロードすればいい、今回はWindows + IISで稼働するのでASP.NET Core Runtimeの「Hosting Bundle」をインストールする、「Hosting Bundle」の中には .NET Runtime と IISサポートを含まれている

ASP.NET Core のプロジェクトでは既定としてKestrelを使用している、IISはリバース プロキシサーバーとしてASP.NET Coreアプリの中のKestrelと連携する [詳細はこちらから](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/servers/kestrel/when-to-use-a-reverse-proxy?view=aspnetcore-5.0)

[Kestrel Web サーバーに関してはクリックで確認](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/servers/kestrel?view=aspnetcore-5.0)

ASP.NET Core 3.1のアプリは5.0のランタイムでも問題なく動けるみたい、でもクリーンな環境で実際に検証していないので動作しなかったら3.1のランタイムをインストールしてください。
自分のローカル環境で問題なく動いているので多分大丈夫、ローカル環境に関しては下図のように
![ローカル環境図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1088099/7f6abd73-9e49-fe3b-530b-44da9f2f9520.png)


「Hosting Bundle」のインストールが出来たら、IISを起動して確認してください。
IISのモジュールの中に「AspNetCoreModuleV2」が入っていれば無事インストール完了

##IISへの発行
####アプリケーション プールの作成
![アプリケーションプールの追加](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1088099/f1043d4d-5b87-6657-63fd-370e0535d674.png)

図のように.Net CLRバージョンには「マネージドコードなし」にする必要がある。

####Webサイト作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1088099/4ba2407c-2013-1776-711e-d82f68664215.png)

####Webサイトに関する設定

作成されたWebサイトの構成エディターの「system.webServer/aspNetCore」
stdoutLogEnabledとstdoutLogFileの二つには発行したサイトが立ち上がらない際のエラー調査には役に立ちますので、必要な際は「True」に変更すれば、エラーが発生した場合Webサイトの配置先の直下のlogフォルダーにログが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1088099/15f40042-3565-4b03-c550-eed1083c3592.png)


####Webサイトの発行

ここではVisual Studioの発行を利用してWebサイトを発行する、発行したファイルをIISでの設定先にコピーして配置する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1088099/186aaecb-8c47-ea63-5df0-b9bcebfab453.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1088099/997c53a1-7256-fe5c-e4df-51ca88321096.png)

※注意事項
　　ASP.NETみたいにただビルドしたファイルを配置しても動かないです、Coreでは必ず発行したファイルを配置すること


##まとめ

* IISがインストールされていなければ、IISをインストール
* ASP.NET Core Runtimeの「Hosting Bundle」をインストール
* IISに「マネージドコードなし」のアプリケーションプールを作成
* IISに「マネージドコードなし」のアプリケーションプールを利用するWebサイトを作成
* 発行したアプリファイルをIISの設定先に配置する


[MicrosoftのIIS に ASP.NET Core アプリを発行する](https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/publish-to-iis?view=aspnetcore-5.0&tabs=visual-studio)を参照
VIEWカードサイトにPythonとSeleniumを使ってログインする

VIEWカードのサイトにPythonとSelenium使ってログインする方法を解説します。

※2021/02/23時点の情報です

## 環境
- Windows 10
- Python 3.8
- Selenium 3.141.0

## 全体の処理の流れと注意点
全体の処理の流れについては、下記記事に詳しく書いたのでこちらもあわせて確認してみてください。楽天銀行の例になっていますが、処理の流れは同じです。

https://qiita.com/yoshi2045/items/2fff5bf5f0fa763f7104

また、下記記事では他サイトのサンプル一覧と注意点を解説しているのでこちらも参考にしてみてください。

https://qiita.com/yoshi2045/items/a58a7fbebcb9faad3e15


## サンプルコード全文

```python
#
# Viewカードサイトへログイン
#

import json
from selenium.webdriver import Firefox, FirefoxOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec

# 設定ファイルを取得
login_info = json.load(open("login_info.json", "r", encoding="utf-8"))

# ログインサイト名
site_name = "card_view"

# ログイン画面URL
url_login = login_info[site_name]["url"]

# ユーザー名とパスワードの指定
USER = login_info[site_name]["id"]
PASS = login_info[site_name]["pass"]

# Firefoxのヘッドレスモードを有効にする
options = FirefoxOptions()
options.add_argument('--headless')

# Firefoxを起動する
browser = Firefox(options=options)

# ログイン画面取得
browser.get(url_login)

# 入力
e = browser.find_element_by_id("id")
e.clear()
e.send_keys(USER)
e = browser.find_element_by_id("pass")
e.clear()
e.send_keys(PASS)

# ログイン
button = browser.find_element_by_xpath("//input[@type='image']")
button.click()

# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.CLASS_NAME, "details_left_01"))
)

# ログインできたか確認（画面キャプチャ取る）
browser.save_screenshot("../screenshots/card_view/home.png")

browser.quit()
```


## ログイン情報設定ファイル
サイトURLやログイン情報（IDやパスワード）は、JSON形式のファイルに保持するようにしています。以下のサンプルでは楽天銀行とVIEWカードの2サイトの情報と設定しています。

"id", "pass"の値を書き換えればそのまま使えるはずです。

なお、このファイルだけは絶対に漏洩しないよう、管理方法に注意しましょう！

```json:login_info.json
{
  "bank_rakuten": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://fes.rakuten-bank.co.jp/MS/main/RbS?CurrentPageID=START&&COMMAND=LOGIN"
  },
  "card_view": {
    "id": "1234567890",
    "pass": "password",
    "url": "https://viewsnet.jp/default.htm"
  }
}
```
ターミナルから隠しファイルの表示

# 隠しファイルの表示

※環境　Mac 10.15.7 catalina

例） .sshディレクトリの場合
```~ % cd .ssh/```　←.ssh ディレクトリに移動

```.ssh % open . ```　←.sshディレクトリを開く

するとFinderで.sshディレクトリが表示されます。
【Rails バリデーション基礎（小学生でも分かる解説）】

#バリデーションとは#

バリデーションとは、
`入力されたものをチェックすること`

例えるなら、飛行機に乗る前の荷物検査。

・重量オーバーしてたらダメ
・危ないもの持ってたらダメ

とか。

プログラミングは、主にログインや登録で使われる。

・入力されていないとダメ
・長いタイトルはダメ

とか。

#バリデーションの使い方（まずざっくり）#

大きく分けると、この3つを書く。

`①モデルに、バリデーション書く`

`②コントローラに、通った時と通らなかった時の動きを書く`

`③ビューに、通らなかった時のエラーメッセージを書く`

#バリデーションの使い方（具体的）#

先ほどの3つの流れに沿って。

###`①モデルに、バリデーション書く`###

```models/sample.rb

validates :name, presence: true
（validates :チェックするもの, 何が: どう？）
```
この場合だと、
「name」を、「存在」が「ある」かどうかチェックする。

「name」に何も書いてないとfalse
「name」に何か書いてあるとtrue

チェックできる項目は他にもたくさんあるから、下記を参考に。

[Railsバリデーションまとめ](https://qiita.com/h1kita/items/772b81a1cc066e67930e)

###`②コントローラに、通った時と通らなかった時の動きを書く`###

```controllers/sample.controller.rb
  def create
    if @name.save
      redirect_to page_path
    else
      render :new
    end 
  end
```
この場合だと、
「name」を「save」できたら「page_path」に飛ぶ
「name」を「save」できなかったら「new」に飛ぶ

通らなかったとき（else）は、
基本「redirect_to」はダメで、「render」を使う。

理由は、ざっくり言うと、

・「redirect_to」だと通らなかったことを受けとった後、すぐそれを忘れちゃうから。
すると、エラーしたことを忘れて、エラーメッセージが出なくなっちゃう。
→「new」のアクションに戻す

・「render」 だと通らなかったことを受け取って、二度とくるなって感じだから。
エラーしたことを覚えたまま、エラーメッセージを出す。
→「new」のビューに戻す

###`③ビューに、通らなかった時のエラーメッセージを書く`###

```views/sample/sample.html.erb
  <% if @name.errors.any? %>
    <%= @name.errors.count %>件のエラーが発生しました
    <% @name.errors.full_messages.each do |message| %>
      <%= message %>
    <% end %>
  <% end %>
```

これでエラーの数も含めて、エラーメッセージを出せる。

以上。
laravelのリクエストクラスのバリデーションで気を付けること

laravelでのバリデーションはformRequestクラスで定義しているのですが、
小一時間つまらぬミスで、苦闘していたので共有します。

```php:app/Http/Requests/UpdateRequest.php
/**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        $rules = [
            'name' => 'required|string',
            'detail' => 'required',
            'movie_file' => 'required|mimes:mp4, zip|max:2048',
            'image_file.*' => 'required|mimes:jpg, png, jpeg',
        ];
        return $rules;
    }
```
上記、実はバリデーション通過時に通りません。

mimesタイプのmimes:mp4, zipの空欄があるとバリデーション通過しません。
なぜかは、分からないのでどなたか教えて頂けると助かります！

カンマの後は、スペース入れる癖があるので気を付けないとですね。。
色々なコマンドで dyld: Library not loaded エラーが出るのを解決する

macOS Big Surに更新した頃から (?) 色々なコマンドで `dyld: Library not loaded: /path/to/foo.dylib` というようなエラーが出るようになり，それを解決したのでメモしておきます．

結論としては，シェルの起動時に`DYLD_SHARED_REGION`という環境変数を`avoid`に設定していることが原因でした．`DYLD_SHARED_REGION`は，デフォルトでは`use`に設定されているようですが（https://www.unix.com/man-page/OSX/1/dyld/ ），あえてこれを変更してしまっていたようです．このため，この設定を削除する（`fish.config`や`.bash_profile`から削除する）ことで問題は解決しました．

## 環境

* OS：macOS Big Sur 11.2.1
* シェル：fish 3.1.2 や bash 3.2.57

# エラー内容

エラーとしては以下のようなものが出ていました．

## git

```
dyld: Library not loaded: /usr/lib/libz.1.dylib
  Referenced from: /usr/local/bin/git
  Reason: image not found
fish: 'git' terminated by signal SIGABRT (Abort)
```

## fishでcdした時に出るエラー

```
$ cd ..
fish: Job 2, 'command awk -v path="$PWD" -v n…' terminated by signal SIGABRT (Abort)
```

## awk

```
$ awk
dyld: Library not loaded: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
  Referenced from: /usr/local/bin/awk
  Reason: image not found
fish: 'awk' terminated by signal SIGABRT (Abort)
```

# 修正

```{..bash_profile}
export DYLD_SHARED_REGION=avoid # <- 削除
```

```{fish.config}
set -x DYLD_SHARED_REGION avoid # <- 削除
```