OmniAICreator/Qiita-1.07M huggingface dataset:
通信に関するUbuntuコンテナのコマンド


| コマンド | 意味 |
|:-:|:-:|
|  tcpdump |TCPなどの通信をする際のパケットの内容を見るためのコマンド。src後ろのオプションで、送信元のサイトを限定する。   |
|  ping |相手と通信ができるか確認できるコマンド  |
| curl   |Web ページの内容をコンソールに表示するコマンド。オプション(URL)なしだと、Web ページの HTMLの文字列をそのまま標準出力に表示   |


確認が済んだら、 tcpdump と ping を `Ctrl + C` を押して終了させる。

`Ctrl + C`のショートカットで、ほとんどのコマンドプログラムは終了可能。
初心者向けLookerの表内に日時情報を表示する方法


あんまり需要ないかもですが、Lookerの表内に数字以外の情報を表示する手順のメモです。

# 今回のゴール

![lookerの表内に日時情報を表示する方法1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/9b3dd3e8-485a-d9df-79e1-d0a050f49d38.png)

上記のように表内に日時を表示する


## 対応手順

**１）日付情報のLookML設定**

```yaml
measure: create_datetime {
  type: max
  sql:
      FORMAT_TIMESTAMP('%Y%m%d%H%M%S', TIMESTAMP(${TABLE}.create_datetime))
     ;;
}

```

表内に表示する為に、日付情報をmeasureで定義追加する


**2）Lookerでの初期表示**

![lookerの表内に日時情報を表示する方法2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/75a0c14c-9c77-6fd7-50db-ea517c2c508e.png)

LookMLでmeasure定義した結果、日時情報が数値として表示されてしまう。


**3)設定の変更**

![lookerの表内に日時情報を表示する方法5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242038/98cc90ff-e02d-1a4e-d427-8b0be8bd2ad4.png)

- LookerのVisualizationの右端にある設定ボタンをクリック
- Seriesタブを選択
- 表示を変更したい項目（ここではcreate_datetime）を選択して、FormatからCustomを選択する
- フォーマットに**00"-"00"-"00" "00":"00":"00**と入れる
- 表内の表示が日時情報の表示に変更される
Android applicationIdの変更方法について


Android applicationIdの変更方法するには以下の箇所のファイルをいじります。

- android/app/build.gradle
    - ![スクリーンショット 2021-10-24 0.20.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320838/cb5bc251-c1c1-69fc-b845-cf9a627533cf.png)
- AndroidManifest.xml

    - ![スクリーンショット 2021-10-24 0.22.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320838/80cabfd1-0d35-0089-6cc4-e8a4cc7b15a0.png)

- MainActivity.kt
    - ![スクリーンショット 2021-10-24 0.22.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320838/d45a05c9-2fb6-d11c-2c97-a5f11cbccd03.png)
【Dart】GitHubの認証・取得・更新

#何をやるのか？
Dartを使って、Githubの認証・情報の取得・情報の更新の一連の流れを一部備忘録としてまとめていきます。
今回は以下のDart用ライブラリを使用して実装していきます。
ライブラリの導入方法については本記事では紹介致しませんので、ご了承ください。
https://pub.dev/packages/github

#認証
###ユーバー名・パスワードでの認証
ユーザー名とパスワードのみでログインできるGitHubアカウントへの認証は以下なります。

```dart
var github = GitHub(auth: Authentication.basic('UserName', 'Password'));
```

###個人アクセストークンでの認証
2段階認証を設定しているGitHubアカウントへの認証は個人アクセストークンが必要になります。
個人アクセストークンの取得方法は以下になります。
https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token

```dart
var github = GitHub(auth: Authentication.withToken(token));
```
以下GitHubクラスのリファレンスになります。
https://pub.dev/documentation/github/latest/github/GitHub-class.html

#取得
###リポジトリの取得
以下のようにリポジトリの管理者・Organizationとリポジトリ名を指定することでリポジトリを取得できます。
取得したリポジトリに対して各種プロパティを指定することで、リポジトリ名やクローンURLなどを取得できます。

```dart
// 個人のリポジトリの場合はユーザー名を指定
Repository repo = await github.repositories.getRepository(RepositorySlug('UserName', 'repoName'));

// Organizationのリポジトリの場合はOrganization名を指定
Repository repo = await github.repositories.getRepository(RepositorySlug('OrganizationName','repoName'));

print(repo.name) // リポジトリ名
print(repo.cloneUrl) // クローンURL
print(repo.createdAt) // 生成日
```
以下getRepositoryのリファレンスになります。
https://pub.dev/documentation/github/latest/github/RepositoriesService/getRepository.html

###ファイル内容の取得
プロジェクトの各ファイルの内容を取得するためには、以下のようにリポジトリ管理者・Organization、リポジトリ名、ファイルパスを指定することで取得できます。

```dart
// ファイル内容取得
RepositoryContents contents = await github.repositories.getContents(RepositorySlug('User or OrganizationName', 'RepositoryName'), '/path/fileName');
print('test:' + contents.file!.text);
```
以下getContentsのリファレンスになります。
https://pub.dev/documentation/github/latest/github/RepositoriesService/getContents.html

#更新
対象のファイル内容を更新するには、以下のパラメータを指定しupdateFileメソッドを叩くことで更新できます。
・リポジトリ
・パス
・メッセージ
・Base64エンコードしたファイル内容
・SHA
・ブランチ名
また最新のSHAを取得するには以下の**generateSHAメソッド**で実行しているapiを叩くことで取得できます(**()**で囲んでいる項目を任意でしてください)。対象のリポジトリがprivateの場合はヘッダーに個人アクセストークンを指定してください。

```dart
Future<String> generateSHA(String name, String token) async {
    var request = await HttpClient().getUrl(Uri.parse('https://api.github.com/repos/(UserName 
 or OrganizationName)/(RepositoryName)/contents/(path)'));
    request.headers.add('accept', 'application/vnd.github.v3+json');
    request.headers.add('Authorization', 'token ' + AccessToken); // privateの場合のみ
    var response = await request.close();
    var responseBodyText = await utf8.decodeStream(response);
    var json = jsonDecode(responseBodyText);
    return json['sha'];
}

// sha取得
generateSHA(name!, token!).then((sha) => {
    // ファイル更新
    github.repositories.updateFile(repo.slug(), 'path', 'message', base64.encode(utf8.encode(content)), sha, branch: 'main'),
})
```
以下updateFileのリファレンスになります。
https://pub.dev/documentation/github/latest/github/RepositoriesService/updateFile.html

#参考
GitHubライブラリ
https://pub.dev/packages/github

GitHub api v3 リポジトリに対する操作
http://docs.github.com/en/rest/reference/repos
Fluuter iOS Smart quotes were detected and ignored in your Podfile.と出たとき

Fluuter iOSのPod installの時に以下のエラー内容が表示されました。

```
[!] Smart quotes were detected and ignored in your Podfile. To avoid issues in the future, you should not use TextEdit for editing it. If you are not using TextEdit, you should turn off smart quotes in your editor of choice.
```

DeepLで翻訳してみると、以下の内容になります。

```
[Podfileにスマートクォートが検出され、無視されました。今後の問題を避けるため、編集にTextEditを使用しないようにしてください。TextEditを使用していない場合は、お好みのエディタでスマートクォートをオフにしてください。
```

以下の文章で「バッククォート（`）」の箇所がありました、こちらを「シングルコーテーション(')」に変更し再度 pod installをすればエラー解決になります。

`or pod 'Firebase/AnalyticsWithoutAdIdSupport'`

ややこしいな、、、
[SVG] SVGOでSVGファイルのサイズを半分にする


SVGファイルは画像をコードとして扱うことができて便利ですが、たくさん使いたい場合はファイルのサイズをできるだけ小さくしたいものです。

SVGOを使えばSVGファイルのサイズを半分にすることができます。
https://github.com/svg/svgo

# 手順

## 1. SVGOをグローバルインストール
```
# install
npm -g install svgo

# confirm
svgo -v
```

## 2. 小さくしたいファイルを指定してコマンドを実行
```
# one file
svgo one.svg two.svg -o one.min.svg two.min.svg

# directory
svgo -f ./path/to/folder/with/svg/files -o ./path/to/folder/with/svg/output
```
【学習記録⑧】動的コンポーネントを用いてコンポーネントを入れかえる。

#はじめに
Vue.jsを最近勉強し始めたので学んだ文法などを備忘録としてメモしていこうと思います。
今回の記事では`動的コンポーネント`を用いてコンポーネントを入れかえる方法を記載します。

##componentタグを利用する
動的にコンポーネントを入れかえる場合は`component`タグを用いると便利です。
記法は以下の通りで`is`という属性を用いて任意のコンポーネントを指定します。

https://jp.vuejs.org/v2/guide/components.html#%E5%8B%95%E7%9A%84%E3%81%AA%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88

```vue:App.vue
<template>
  <component v-bind:is="任意のコンポーネント名"></component>
</template>
```

###注意点
しかしながらコンポーネントを入れかえた際に切り替わる前のデータは消えてしまうため、フォームに使用するタグ`input`や`textarea`等を利用する場合には`keep-alive`コンポーネントを用いる必要があります。

https://v3.ja.vuejs.org/api/built-in-components.html#keep-alive

```vue:App.vue
<template>
  <keep-alive>
    <component v-bind:is="任意のコンポーネント名"></component>
  </keep-alive>
</template>
```

###ライフサイクルフック
上記で記載した`keep-alive`コンポーネントで囲んだコンポーネントでは`activated`と`deactivated`というライフサイクルフックが呼び出されます。
`activated`は対象のコンポーネントがアクティブになったときに動き、`deactivated`は対象のコンポーネントが非アクティブになったときに動きます。

https://v3.ja.vuejs.org/api/options-lifecycle-hooks.html#activated

##以上を用いてサンプルを作ってみる
以上をふまえて、それらを利用した簡単なサンプルを作ってみます。
今回は「おはようボタン」「こんにちはボタン」を作り、それらのボタンを押すとそれぞれのコンポーネントが出力されるという感じにしたいと思います。
ライフサイクルフックの動きも見ておきたかったので、「こんにちはコンポーネント」がアクティブになった場合と非アクティブになった場合にアラートが呼び出されるようにしてみました。

```vue:App.vue
<template>
  <div>
    <button @click="greetComponent = 'Morning'">おはようコンポーネント</button>
    <button @click="greetComponent = 'Afternoon'">こんにちはコンポーネント</button>
    <keep-alive>
      <component v-bind:is="greetComponent"></component>
    </keep-alive>
  </div>
</template>

<script>
import Morning from "./components/Morning.vue";
import Afternoon from "./components/Afternoon.vue";

export default {
  data() {
    return {
      greetComponent: "Morning",
    };
  },
  components: {
    Morning,
    Afternoon,
  },
};
</script>
```

```vue:Morning.vue
<template>
  <div>おはよう！</div>
</template>
```

```vue:Afternoon.vue
<template>
  <div>こんにちは！</div>
</template>

<script>
export default {
  activated() {
    alert("こんにちはコンポーネントが開きました！");
  },
  deactivated() {
    alert("こんにちはコンポーネントが閉じました。");
  },
};
</script>
```

##結果
デフォルトは`おはようコンポーネント`が出力されるようにしています。
![pic4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538249/22859bdd-386d-c814-3e87-bbba828358c1.png)

「こんにちはコンポーネント」ボタンをクリックするとライフサイクルフックの`activated`が呼び出されていることが分かります。
![pic1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538249/568eb833-e4d1-eda0-53b4-24b9c6f33b9b.png)

アラートを閉じた後、コンポーネントが`こんにちはコンポーネント`に変更されていることが分かります。
![pic2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538249/18a21d3b-d4a3-3e0b-5c68-d807ae87eb5c.png)

次に「おはようコンポーネント」ボタンをクリックするとライフサイクルフックの`deactivated`が呼び出されていることが分かります。
![pic3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538249/d1975ed9-45bf-ba52-25b5-1b0b895fd5e4.png)

アラートを閉じた後、コンポーネントが`おはようコンポーネント`に変更されていることが分かります。
![pic4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538249/d4d64e02-1685-bf4f-ae57-765af6244341.png)

#おわりに
今回は動的にコンポーネントを入れかえる方法を学びました。
これがSPAを作る上での基礎なのかな・・・と思ったり。

だいぶ楽しいフィールドへ入ってきた感じがするので引き続きしっかり学んでいこうと思います！
ディレクトリ、ファイルのコピーを Golang で書いてみる

# 概要
最近業務であるディレクトリの中身を丸ごとコピーしてたのですが、様々なサイトを見ても処理が分かりにくいものが多かったので今一度分かりやすいコードを書きたいと思います。
他の参考サイトを見ても分かりにくいと感じた点はおそらく以下の点です。

* 再帰処理の複雑さにより、各関数の役割が明確で無くなっている。

参考サイトによっては「ディレクトリを追加しながらファイルを読む関数」等があったりと個人的には分かりにくく、実際に業務においてレビューするのであれば指摘をするかなと。

# 環境
今回私が実行した環境は以下です。

* Go 1.16.8
* VSCode
* Windows10
* WSL2(Ubuntu)
* Docker Desktop

`Windows` の `Docker Desktop` を起動し、 `Ubuntu` 上でコンテナを立ち上げ、 `VSCode` のリモートコンテナより実行しました。
便利な世の中になりましたね。

なお、これから説明する完成したコードは以下に全て配置しています。

[GitHub - hfh3oa](https://github.com/hfh3oa/add-folders-and-files-recursively-in-golang)

# 実装
では実装したコードの概要、実際のコードと見ていきます。

## 処理概要
大まかな処理の内容は以下となります。

``` Go
func entry() {
	// 探索を行い、その探索した結果によって関数を振り分けるエントリ
	return nil
}

func addDir() {
	// ディレクトリ作成処理を行う
	// エントリ追加処理を行う
	return
}

func addFile() {
	// ファイル追加処理を行う
	return
}
```

`entry` 関数は追加されたエントリをひたすら分析する関数です。
また、 `addDir` 関数は新しく追加されたディレクトリやファイルに対してエントリの追加を行う関数です。
`addFile` はファイルを追加する関数です。ファイルを追加するだけであるため、特にエントリを追加する必要はありません。
だいぶスッキリしてるのではないでしょうか。

## 処理コード
全体のコードです。
言語に関わらず同じように記載出来ると思いますが、ここでは簡単に書ける `Go` 言語で書いてみます。

```Go
package main

import (
	"io/ioutil"
	"os"
	"path/filepath"
)

func main() {

	src := "./input"
	dest := "./output"

	err := entry(src, dest, "")
	if err != nil {
		os.Exit(1)
	}
}

func entry(src, dest, path string) error {
	sp := filepath.Join(src, path)
	fs, err := os.Stat(sp)
	if err != nil {
		return err
	}

	if fs.IsDir() { // ディレクトリの場合
		if err := addDir(src, dest, path); err != nil {
			return err
		}
	} else { // ファイルの場合
		if err := addFile(src, dest, path); err != nil {
			return err
		}
	}

	return nil
}

func addDir(src, dest, path string) error {
	dp := filepath.Join(dest, path)
	if err := os.Mkdir(dp, 0700); err != nil {
		return err
	}

	sp := filepath.Join(src, path)
	fi, err := os.ReadDir(sp)
	if err != nil {
		return err
	}
	for _, f := range fi {
		err := entry(sp, dp, f.Name())
		if err != nil {
			return err
		}
	}

	return nil
}

func addFile(src, dest, path string) error {
	d, err := ioutil.ReadFile(filepath.Join(src, path))
	if err != nil {
		return err
	}

	df, err := os.Create(filepath.Join(dest, path))
	if err != nil {
		return err
	}
	defer df.Close()

	if _, err = df.Write(d); err != nil {
		return err
	}

	return nil
}
```

# おわりに
もし他に分かりやすい書き方あれば教えてほしいです。
棒グラフの色をX軸の値に応じて変化させる

```Python
$ cat mc2.py
#!/usr/bin/env python3

import pandas as pd
import matplotlib.pyplot as plt
import os
import sys


def get_color_list(x):

  cl = []

  # print(x)
  for i in x:
    # print(i)
    if i >= 200 and i < 300:
      cl.append('blue')
    elif i >= 300 and i < 400:
      cl.append('green')
    elif i >= 400 and i < 500:
      cl.append('orange')
    elif i >= 500:
      cl.append('red')
  return cl


csv_file = "source.csv"
png_file = csv_file.replace(".csv", ".png")

df = pd.read_csv(csv_file, encoding="UTF8")
print(df)

# 数値型だとその大小に応じたピッチにＸ軸での表示位置が依存して醜いので、文字型に変える
x = df["HTTP status code"].apply(lambda _: str(_))
y = df["count"]

# ステータスコードに合わせて描画色を変える
color_list = get_color_list(df["HTTP status code"])
print(color_list)

plt.figure(figsize=(16, 9))
plt.bar(x, y, color=color_list)

plt.title("HTTP/HTTPS status code frequency")
plt.xlabel("Status code")
plt.ylabel("Count")
plt.grid(True)
plt.yscale("log")  # 対数軸にプロットして表示
plt.subplots_adjust(bottom=0.2, top=0.9)

# plt.show()

plt.savefig(png_file)
print(png_file, "created.")
```
```
$ cat source.csv
HTTP status code,count
200,20000
206,2000
301,200050
302,333
304,33333
400,778877777
401,47777
404,2777777
408,87777
500,6667777
```

![source.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1182287/ea35664a-90f6-c0b9-3b9c-1db0818b3b49.png)
Refile::InvalidID エラーが起きた時のメモ

## 環境
```
gem "refile", require: "refile/rails", github: 'manfe/refile'
gem "refile-mini_magick"

Rails 5.2.6
```

## 1.目標
**Refileの`attachment_image_tag`命令でクラウド上の画像を表示したい。**

## 2.状況
- `attachment_field`フォームで保存した画像を`attachment_image_tag`命令で呼び出そうとしたところ、`Refile::InvalidID in (該当頁)`エラーが発生した。
- マイグレーションファイルに`default: "default.jpg"`等のようなデフォルト値を指定するコードはなかった。(※ https://teratail.com/questions/220379 で、デフォルト値に起因する同挙動エラーの解決報告あり)
- 該当レコードを保存した際にはフォーム・ストロングパラメータ・モデル全てに不手際があった。
- 不手際修正後に作成したレコードを`attachment_image_tag`命令で呼び出そうとしたところ、エラー無く成功した。
- エラーを生じるレコードを消去しようとしてrailsコンソールから削除命令を出したが、下記の表示が出て削除できなかった。

```
2.6.3 :001 > Item.find(1).destroy
  Item Load (0.2ms)  SELECT  "items".* FROM "items" WHERE "items"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  CartItem Load (0.1ms)  SELECT "cart_items".* FROM "cart_items" WHERE "cart_items"."item_id" = ?  [["item_id", 1]]
  Item Destroy (1.2ms)  DELETE FROM "items" WHERE "items"."id" = ?  [["id", 1]]
   (1.1ms)  rollback transaction
Traceback (most recent call last):
        1: from (irb):1
Refile::InvalidID (Refile::InvalidID)
```

## 3.原因
　おそらくレコード投稿時にコードの不手際から誤ったRefileの画像識別子を書き込んでしまったのが原因と思われる。
　直接挙動にまではアクセスできていないものの、不手際解消後に投稿したレコードでは問題無く動いている事から確度は高いと思う。
　正規の手段では削除できない該当レコードを削除した後で、正しいコードで再登録すれば解決すると思われる。

## 4.解決
　**railsターミナルから`rails db:migrate:reset`を送る事で全モデルの全レコードも道連れに異常レコードを削除した。**
　削除後、改めてレコードを投稿した後に該当コードを走らせると、エラー無く描画された。
Linux mint で apt update ができなかった話

# はじめに
Linuxを触り始めてまだ1年経ってないど素人による記事ですので、あしからず。

# 状況

``sudo apt update``を入力してもなんのエラーも出ない。時間が立つといつの間にか再起動されている。挙動がめちゃくちゃ重くなる。

# 問題だったこと
**/root**にアクセス権限がなかった。
> aptがまずいのかと思ってSynapticでaptを再インストールしようとした際にアクセス権限がないことが発覚。
> apt関連のインストールの際、/root配下にいろいろインストールするらしいことを知った。
![524727.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995699/bc40ef61-24db-479d-0d0c-50d54e9d0228.jpeg)

# 解決策

```bash
chmod -R a+rx /root
```
これでアクセス権限を付与。ターミナルでaptもうまく通るようになった。


...なんでアクセス権限なかったんだ？と今は首をかしげています。
ReactNative で Blockchain Symbol の SDK を利用する

https://symbol-community.com

この記事では、Symbol ブロックチェーンの SDK を React Native/Expo 上で利用して、ネイティブアプリケーションにブロックチェーンによる送金やアカウント管理機能を組み込む方法を紹介します。

## 前提条件
この記事を読むにあたって、以下の知識や環境が必要です。

- React Native/Expo の基本的な知識と開発環境
- Node.js と npm のインストール

## 環境
- expo@49
- react-native@0.72
- symbol-sdk@2

https://github.com/symbol/symbol-sdk-typescript-javascript

## expo でのプロジェクト作成

以下の順番で実行してください。ReactNative 環境上では node.js の一部ネイティブモジュールを利用することが出来ません。例えば `crypto` です。これを ReactNative で利用可能なパッケージをインストールして利用する為に rn-nodeify というツールも利用します。

```shell
npx create-expo-app --template bare-minimum
```

必要な依存関係を追加します。

```shell
npm install -D rn-nodeify 
npm install symbol-sdk@2 rxjs 
npx rn-nodeify --install --hack
```

この時点でプロジェクトルートへ `shim.js` というファイルが作成されている為、 `index.js` の先頭でこれを import するようにしてください。

```js 
import "./shim.js";
```

最後にコンソールを再起動してから、以下にてビルドし、エミュレーターで確認出来るようにします。

```shell 
npx expo run:ios
```

:::note warn
警告
symbol-sdk@2 を利用していますが、2024年1月時点で symbol-sdk@3 も公開されています。ただし、 sdk@3 には WASM が利用されており、 ReactNative 上での利用が難しいことから、現時点では sdk@2 を利用しています。
:::

以上、 symbol-sdk を ReactNative 上で利用する方法についての解説となりました。

もし symbol-sdk の使い方を知りたい方は、次の記事も参照してください。

https://learn.ja.symbol-community.com/
あなたの知っているJavaScriptはもう古い(概要編)

## はじめに
JavaScriptは年々進化している、、、。もしかして私の知ってるJavaScriptってもう古い？！
ってことで、最近ずっとフロントエンドに関わる機会がなかったので改めて勉強してみました！

## あなたの時代JavaScriptは？
私がJavaScriptを書いていたころは約10年前(2011年あたり)で、当時は**jQuery使うと便利だよね〜**みたいな時代でした。そこから10年たったいま、、、**React?Vue.js?ES2015?webpacker?Babel?**なんじゃそりゃーっていうギャップが生まれている状態です（反省）。そこで今回は表面だけでもいいから**概要だけでも知っておく**のが目的になります。


## モダンなJavaScriptは昔のJavaScriptと何が違うのか
では、昔と今では何がちがうのか？
いくつかポイントをまとめてみました！

### ◇ ReactやVueという便利なライブラリ/フレームワークがある
名前だけはきいたことある人もおおいとおもいます。これを使えば圧倒的開発がしやすいです。
**PHPでいえばLaravel, RubyでいえばRailsに該当します**

### ◇ npm / yarn　でパッケージ管理ができる
この人の環境では動くのに、わたしの環境では動かない、、、、。そんなことがおきないように使うパッケージのversionとかを管理します。
**PHPでいえばcomposer, Rubyでいえばgemに概要します**

### ◇ ES2015(ES6)という記法がある
なんじゃそりゃ、、、、とはじめは思ってました。が、かんたんでした。**そういうふうに書いてねーっていう指標**です。

かつてJavaScriptは仕様がごちゃごちゃしていたので、ECMAScriptという標準仕様でまとめよう！！って結論になりました。
で、最初はES1（version_1)とかES2(version_2)みたいな感じでversionで読んでたんですが、2015年からversionでなく、**ES2015みたいな西暦**で呼ぶようになりました。なので、**ES2015=ES6、ES2016=ES**7なのです。

またES2015って単語をよくみるのは、**ES2015で大きな仕様改定がおきたから**でした！（なるほど納得）

### ◇ webpackというモジュールバンドラー
ざっくりいうと、複数にわけているJavaScriptやcssを本番用にビルドするときに１つにまとめてくれます。
Ruby on Railsでも5から標準で採用されたので馴染みがある人も多いかとおもいます。

### ◇ Babelというトランスパイラ
webpackが複数のファイルを一つにまとめるものに対して、トランスパイラは**JavaScriptの記法を様々なブラウザで実行できる形に変換＝（Translate+Complile)するものです**
ES2015で述べたように、ECMAScriptという規格がどんどん新しくなるので、ブラウザもどんどんそれに対応していかないといけないです。しかし、対応しきれないブラウザもあるので、**Babelがいい感じに動くように変換**してくれるのです。


### ◇ SPA(Single Page Application)という概念
昔のJavaScriptでは、表示されたHTMLのページに対して何かを操作する（ボタンを押したらアクションするとか）だけで、ページ繊維の度に、サーバーと通信をして新しいHTMLを表示していたと思います。
今のフロントエンドはSPAという概念があります。SPAでは基本的に最初の一回でHTMLファイルを取得したら、ページ遷移をしてもJavaScriptでそのHTMLを書き換えていきます。


![spa1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174291/eed565fe-2d55-4926-9e90-9bbde480f38e.jpeg)


![spa2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174291/b04c5f0c-8e2b-184b-d2a0-ba62ddd8fc6e.jpeg)


このようにSPAではHTMLファイルを読み込むのは1回だけで、その後はJavaScriptがページ遷移の度に要素を書き換えていくことで高速化を実現しています。


## まとめ
改めて概要だけでも知ってみると、フロントエンドにはこんなにも新しい技術が使われているのか、、、！とため息をついてしまいました(笑)
しかしながら、昔にJavaScriptの基礎を学んだ人にとっては、あの頃あんなに苦労したことが今はあっさりできることに驚く点が多々出てくるとおもいます。ということで、その恩恵を味わってみたいので,今後Reactで最新のJavaScript事情を学んで行こうとおもいます！
ということで、次回に続く、、、

https://qiita.com/k-tetsuhiro/items/9900665f200f0ca77e96
[10日間]未経験エンジニアがITパスポートに合格する方法

# はじめに
本記事では、`10日間でITパスポートに合格した方法`を記述します。
本日、受験した結果、630点でした。(超ギリギリw)
(ストラテジ605/マネジメント460/テクノロジ645)

*Twitterには１週間で合格と呟きましたが、数えたら間違いでした。

## テキストなど
テキスト
[令和03年 イメージ&クレバー方式でよくわかる 栢木先生のITパスポート教室 (情報処理技術者試験)](https://www.amazon.co.jp/%E4%BB%A4%E5%92%8C03%E5%B9%B4-%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8-%E3%82%AF%E3%83%AC%E3%83%90%E3%83%BC%E6%96%B9%E5%BC%8F%E3%81%A7%E3%82%88%E3%81%8F%E3%82%8F%E3%81%8B%E3%82%8B-%E6%A0%A2%E6%9C%A8%E5%85%88%E7%94%9F%E3%81%AEIT%E3%83%91%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88%E6%95%99%E5%AE%A4-%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E6%8A%80%E8%A1%93%E8%80%85%E8%A9%A6%E9%A8%93/dp/4297117142)

過去問
[ITパスポート試験ドットコム](https://www.itpassportsiken.com/)

## なぜこの記事を書くのか

- ITパスポートの学習に挫折しそうな方への希望になればと思い
- 今後、資格学習する際に少しでも参考にするため
- 純粋に今後の自分の励みにしたいため

# 実際のスケジュール
学習時間は、平均10時間/日ですので、90~100時間です。
転職活動中なので、面接や面接対策などと並行して学習しました。

```
1日目
試験の申し込みをしてからスタート
テキストでテクノロジ系の1/3のパラ読み

2日目
1/3読んだ部分(ソフトウェアとハードウェアの部分)の過去問1周

3日目
テキストでテクノロジ系の1/4のパラ読み

4日目
1/4読んだ部分(セキュリティ)の過去問1周

5日目
テキストでテクノロジ系の1/3のパラ読み

6日目
1/3読んだ部分(ネットワークとシステム)の過去問1周
(この辺からスケジュール管理に異変を感じる)

7日目
テキストの残りのテクノロジ系をパラ読み
残りのテクノロジの部分の過去問1周

8日目
ストラテジのテキスト一気読み＆過去問1週

9日目
マネジメントのテキスト一気読み＆過去問1週

10日目
試験へ
朝一でテクノロジ系の復習
```

## 反省点

- 試験日の設定を誤った。
- せめて２週間前からにしておくべきだった
- 計画を立ててから学習すればよかった（1日に何をするのか）
- テキストの読書ではなく、過去問を解いて理解する（インプットよりもアウトプット）
- 生活習慣が最悪だった（4時寝~8時起床&スタバで勉強）

## 良かった点

- Qiitaでのアウトプット（知識の定着がすごかった）
- 分野別に過去問を解いた
- 試験前にテクノロジを再確認した

## フィードバック
とにかく、生活習慣が最悪でした。

試験に申し込みする際、
`学習時間の目安`を検索した後に、
試験日を決めることが良いです。

そこから1日の目標を具体的に決めることで、学習することで効率が改善されたと感じます。

また、過去問を繰り返し理解することで、テキスト以上に理解できることがほとんどで、
さらに`分野別(テクノロジのどの項目　など)`に細かく分けて勉強することで、
理解の定着スピードを上げました。

試験日には、`テクノロジの知識の確認`をすることを私は推奨します。
英字の名称が多いので、再確認することで、試験で焦らず済みます。

# 受けてわかった理想のスケジュール
`3週間`の設定。
3週間ミッチリ勉強すれば合格できます。
学習時間は`平均5~7時間/日`はできれば欲しいです。

```
1日目
試験の申し込みをしてからスタート
ざっくりテクノロジ系を一気読み

2日目~3日目
テクノロジの過去問を1週目

4日目~5日目
テクノロジの過去問を2週目~3週目(1週目で理解できなかった部分のみ)

6日目
ざっくりストラテジ系を一気読み

7日目~8日目
ストラテジの過去問を1週目

9日目
ストラテジの過去問を2週目~3週目(1週目で理解できなかった部分のみ)

10日目
ざっくりマネジメント系を一気読み

11日目~12日目
マネジメントの過去問を1週目

13日目
マネジメントの過去問を2週目~3週目(1週目で理解できなかった部分のみ)

14日目
テクノロジの過去問4週目~(1~3週目で理解できなかった部分)

15日目
ストラテジの過去問4週目~(1~3週目で理解できなかった部分)

16日目
マネジメントの過去問4週目~(1~3週目で理解できなかった部分)

17日目
テキストの再確認
過去問の総復習

18日目
試験へ
朝一でテクノロジ系の復習
```

ここまでしていたら合格は近いと思います。

以上です。

# 終わりに
Qiitaの投稿記事がITパスポート関係が多かったので、
次回以降は、別の記事を書こうと思います！

明日も頑張ります！
Ubuntu(20.04.3 LTS)でmatplotlibを使えるようにする

#記事の概要
Ubuntu環境でmatplotlibを使用するためpipでインストールしたところ，matplotlibはインストールされているはずなのに，ModuleNotFoundErrorというエラーが出て使えませんでした。
これを解決するには，pip3を使ってインストールすると上手くいったよという話です。

#目次
1. OSのバージョン
2. pythonのバージョン
3. pipのインストール
4. matplotlibのインストール

###1. OSのバージョン
```
NAME="Ubuntu"
VERSION="20.04.3 LTS (Focal Fossa)"
```

###2. pythonのバージョン
```
$ python3 --version
Python 3.10.0
```

###3. pipのインストール
```
$ sudo apt install python3-pip
```

###4. matplotlibのインストール
```
$ pip install matplotlib
```
でインストール。しかし，プログラムを実行すると，

```
ModuleNotFoundError: No module named 'matplotlib'
```
というエラーが出てしまう。
matplotlibはインストールしているので，matplotlibの場所を確認してみる。

```
$ pip show matplotlib
Name: matplotlib
Version: 3.4.3
Summary: Python plotting package
Home-page: https://matplotlib.org
Author: John D. Hunter, Michael Droettboom
Author-email: matplotlib-users@python.org
License: PSF
Location: /home/user/.local/lib/python3.8/site-packages
Requires: pillow, kiwisolver, cycler, pyparsing, python-dateutil, numpy
Required-by: 
```
どうやら，UbuntuOS標準のpython側にインストールされている模様。
これを解決するためには，pip3でインストールしてやる必要があるようだ。

```
$ pip3 install matplotlib
```
これでエラーなくmatplotlibを使用することができました。
HTML&CSS marginの相殺について

★FlexBoxではmarginの相殺が起きない★
（ドットインストール 「詳解CSS フレックスボックス編 #11 縦方向に要素を配置してみよう」）

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>CSSの練習</title>
  <link rel="stylesheet" href="css/styles.css">
</head>
<body>
  <header>Header</header>
  <div class="container">
    <main>Main</main>
    <nav>Nav</nav>
    <aside>Aside</aside>
  </div>
</body>
</html>

```

CSS

```
html {
  height: 100%;
}

body {
  margin: 0;
  display: flex;
  flex-direction: column;
  height: 100%
}

header {
  background: pink;
  margin-bottom: 100px;
}

.container {
  display: flex;
  flex: 1;
  margin-top: 50px;
}

main {
  background: skyblue;
  flex: 1;
}

nav {
  background: tomato;
  width: 100px;
  order: -1;
}

aside {
  background: orange;
  width: 100px;
}

footer {
  background: silver;
}

```

上のように

header { background: pink; margin-bottom: 100px; }

.container { display: flex; flex: 1; margin-top: 50px; }

だとmarginが打ち消されてmargin-bottom:100pxだけが適用されそうだが、 FlexBoxなので両方適用されて150pxとなる。
+で型を数値型に無理やり変換してisNaNで制御

# 変数の前に+を書くことで数字になる
```javascript
const number123 = 123;
typeof(number123); // number
const string123 = "123";
typeof(string123); // string
const hoge = "hoge"
typeof(hoge); // string
```
変数の前に+を書くことで、`string123`は数値(`123`)になり、`hoge`は`NaN`になる。

```javascript
const changeString123 = +string123;
typeof(changeString123); // number
console.log(changeString123); // 123

const changeHoge = +hoge
typeof(changeHoge); // number
console.log(changeHoge); // NaN
```

# 数字か文字列かはisNaN()で判断

```javascript
isNaN(changeString123); // isNaN(123)⇒false
isNaN(changeHoge); // isNaN(NaN)⇒true
```
## 余談・こんな時に使いました
<i>Next.js</i>にて、現在いるパスが年(2021とか)の数字である定義。それ以外はエラーページを出す。

```javascript
import { useRouter } from 'next/router';

const router = useRouter();
const thisSlug = router.query.year;
/* /[year]/[month]/[day]を想定 */
```

yearもとい`thisSlug`が数値であってほしい設計。`huga`や`foo`など受け取っても、ページとしての整合性が取れなくなる。<br />
よって、上記のやり方を適用した。

```jsx
const router = useRouter();
const thisSlug = +router.query.year;
if (isNaN(thisSlug)){
  return (
    <>
      <p>illegal use of url...</p>
    </>
  )
}
```
VSCode for the Webを使ってみた感想

こんにちは。最近巷で「VSCode for the Webがパブリックプレビューになった!!」と話題ですね。
ということで、僕もVSCode for the Webを使って見ました。今回の記事ではその使い勝手などを紹介していきたいと思います。

https://vscode.dev

# VSCodeって何?
VSCodeというのは無料かつオープンソースのプログラミング用のエディタです。Microsoft社が中心になって開発しています。

https://azure.microsoft.com/ja-jp/products/visual-studio-code/

これはElectronというフレームワークを使っています。

## Electronって何?
Electronは、かんたんに言えばJavaScriptでデスクトップアプリを作るためのフレームワークです。
VSCode以外にも[Atom](https://atom.io)というエディタや[Slack](https://slack.com/intl/ja-jp/)などに使われています。

https://www.electronjs.org/

## なんでブラウザで動くの?
先程お伝えしたようにElectronはJavaScriptを使ってデスクトップアプリを作るためのフレームワークです。つまり、ウェブページをアプリにするのです。そのため、逆のことをすればブラウザでも動く...ということです。
(僕はそういうふうに解釈しています)

# 使い方
使い方はアラ簡単。
まず、 https://vscode.dev にアクセスします。
おしまい。
![vscode.dev_ (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524477/2e5118d4-10c3-ea0e-40b9-3b231de0ae69.png)
これだけで使えます。革命的ですね。

# 既知のサービスとの比較
## GitHub Codespaces

https://github.co.jp/features/codespaces

GitHubがホストしているブラウザで動作するVSCodeです。GitHubレポジトリーで「.」を押すと開くことができます。特にGitHub Pagesを使っているときはよく使いました。
VSCode for the Webとの機能面での違いは特にないように思われました。
ただ、VSCode for the Webはローカルでのプロジェクトも編集できる点が強みになっていると感じられました。(GitHub CodespacesはGitHubレポジトリーを作らないと編集できない)

## Google Cloud Shell Editor

https://cloud.google.com/blog/ja/products/application-development/introducing-cloud-shell-editor

厳密にはVSCodeではなくその派生である[Eclipse Theia](https://theia-ide.org/)のブラウザ版です。~~個人的に好きなエディターです。~~
まだあまり使ったことはありませんが、VSCode for the Webのほうが機能が多いように感じました。

# 使った感想
VSCodeがインストール不要で動くのは非常に便利です。Windowsはもちろんのこと、デスクトップ版VSCodeが使えないChromeOS環境やiPadでも重宝すると思います。ただ、日本語対応ができないのが残念なところです。

# まとめ
VSCode for the Webはまだ可能性を秘めた期待のプロジェクトです。ブラウザさえあればスマホでもタブレットでもパソコンでもいつでも開発ができるようになる未来もそう遠くないかもしれません。
Rails 検索機能

投稿系のアプリを作っている中で、投稿に対してタグを持たせる様にしたいと思いました。
タグは、post : tag = 多　対　多　の関係として登録しています。

<h1>投稿にタグをつける</h1>
投稿の新規作成のためのview`posts/new.html.erb`作っているのでそれを修正してタグを選択できるcheck_boxを加えます。

```ruby:new.html.erb
<%= form_with model: @post, local: true do |f| %>
## 省略
 
  <%= f.collection_check_boxes(:tag_ids, Tag.all, :id, :name) do |tag| %>
    <div class="check-tag">
      <%= tag.label { tag.check_box + tag.text }%>
    </div>
  <% end %>
<% end 
```

これでcheck_boxをにcheckを入れたタグだけ送信されます。

formで新しく:tag_idsというカラムを追加しているので、ストロングパラメーターを指定している場合は追加してください。

```ruby:posts_controller.rb
private
def post_params
  params.require(:post).permit(:title, :description, :image, tag_ids: [])
end
```

これでtagのidを受け取る準備ができたので、実際に送信してみると

```ruby:ターミナル
"title"=>"title", "description"=>"description", "product_link"=>"", "tag_ids"=>["", "41", "45"]}, "commit"=>"投稿"}
```
今回はcheckを２つ入れています。
tag_idsの中に41と45がありますがそれこそが、checkを入れたタグのidなのです。
これで投稿にtag_idを入れることができたので、tagを呼び出したい時は

1つの場合は

```
post = Post.find(1)
post.tags[1]
```

全て表示したい場合は

```
post = Post.find(1)
post.tags
```

関連付けを施しているおかげで、post.tagsと書くことで投稿に含まれているtagを取得することができます。

これでタグの実装は完了したので、次は指定したタグを含んだ投稿だけを表示させる処理を書きます・

<h1>タグ検索(準備)</h1>
まずどうやって検索するかというと、viewで検索キーワードとなるものをuserに入力してもらい、それをparams[:keyword]で受け取り、該当するレコードを返すといった感じになります。

今回はタグで検索したいので選択肢を用意しておくほうがいいでしょう。
ここでの選択肢は、タグの名前を全て表示することです。
formにあるselectを用いて選択させる様にします。
検索窓を用意したいviewに以下を書きます。

```ruby:index.html.erb
<%= form_with url: root_path, method: :get, local: true do |f| %>
  <%= f.select :keyword, Tag.all.map{ |tag| [tag.name, tag.id]} %>
  <button type="submit", class="mt-2 mb-2 btn btn-success"><i class="fas fa-search">検索する</i></button>
<% end %>
```


こう書くことで下の画像の様なセレクトタグが表示されます。
![スクリーンショット 2021-10-23 22.11.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1541345/f5253009-e6dd-0463-ab39-88157a473428.png)

実際に表示されているのはタグの名前ですが、送信されるのはタグのidです。

```ruby:
Tag.all.map{ |tag| [tag.name, tag.id]}
```

mapの[]の中身が今はname, idの順番になっていますがこれが逆になっていれば送信されるのは`name`で表示されるのは`id`になります。
これに関しては用途で使い分けてください！

idを送信する準備が整ったので次は送られてきたidを使って検索をかけたいと思います。

#検索をかける
まずはcontrollerにparamsを使う様にかかないといけません。
適当なインスタンスを用意して実際に取得できるか確認します。

```ruby:posts_controller.rb
def index
  @posts = Post.all
  @keyword = params[:keyword]
end
```

form送られているのはidなので`binding.pry`を使うか、viewで表示させてみて選んだタグと同じ`id`が取得できていればOKです。

もしできていないのであれば、`f.select`の第一引数に設定している`:keyword`と`params[:keyword]`のスペルが違っている可能性があるので確認してください!

さて、keywordが取得できるのは確認できたので実際に処理を書いていきます。
流れとしては
・検索が行われていない。=>つまり`params[:keyword]`があるかないかで処理を分岐させる
・`keyword`があればタグが使われている投稿を探す
・`keyword`がなければ全レコードを表示する
とします。

```ruby:posts_controller.rb
def index
  @posts = params[:keyword].present? ? Tag.find(params[:keyword]).posts : Post.all
end
```
この動作は、`params[:keyword]`に値が入っているのであれば、TagモデルからIDが`params[:keyword]`のものを引っ張ってきて、そのタグが持つ投稿を表示してね。
ない場合はPostを全て表示してね。みたいな感じです！

・Tag.findではidを引数にするので、params[:keyword]で送られてくるidが使えるんです！
・タグが含まれている投稿は、Railsの関連付けのおかげでTag.postsとすることで簡単に取得できます。
1対Nの関係のもので確認できますので、やってみてください！

このif文の書き方はググれば出てくると思いますが一応

```ruby:
@posts = <  条件式  > ? <  trueの処理  > : <  falseの処理  >
みたいな感じで書きます
```
もっと詳しく調べたいなら`「rails if文 1行」`でググれば多分出てきますので見てください

以上です!
Alibaba eKYCについて

# Alibaba eKYCについて
新しい製品が出ているかメニューを眺めていた時に見つけました。
クラウドベンダーからPOCの段階ですがeKYC製品を提供していることに驚きました。
2021/10/23時点で詳細なドキュメントが無いので、内容は薄いためご了承ください。
[Alibaba eKYC](https://www.alibabacloud.com/product/ekyc)

# eKYCとは
eKYCはオンラインでの本人確認です。
**electronic Know Your Customer**の略称です。
銀行の口座開設やクレジットカードの発行手続きなどで利用される場面が増えてきました。

# 日本における本人確認方法
例えば、銀行口座開設するための本人確認は対面や、本人確認出来る公的な書類が今まで必要でした。
犯罪収益移転防止法が改正され2018年11月30日に施行されました。
それにより、書類の郵送が不要な方法が規定されました。
ここ1～2年で普及し始めた感じでしょうか。

# 追加された4つの方法
参照サイトの5に分かりやすく書いてありますので、ご一読ください。
**6条1項1号ホ**の方法(写真付き本人確認書類の画像＋本人の容貌の画像の送信)が比較的簡単なので、利用している場面が多いかと思います。
この方法以外は、少しずつセキュリティー的なハードルが高くなり利便性も低くなっています。

# Alibaba eKYCはどの方法か
[Alibaba eKYC](https://www.alibabacloud.com/product/ekyc)のVerification Processを見ると、6条1項1号ホの方法に対応していることがわかります。
(不安要素として残るのはデータが保存されるのかどうかですが、マスクされた特徴データを識別するだけで、データは保存されないとのこと。)

### 1.本人確認IDドキュメント(本人確認書類)
* サポートされているIDドキュメントを自動的に認識します
    * 事前に本人確認IDドキュメントの種類を問い合わせて確認する必要があります
* 偽造検出
* OCRで文字認識

### 2.容貌確認
* 生体判定
* ISO認定の高精度ななりすまし対策
* ランダムアクションの割り当て

### 3.一致
本人確認IDドキュメントに掲載されている写真と、容貌確認で撮影した画像から同一人物かをチェックします。
チェック結果は、Match/Raise Suspicious Alert/No Matchの3パターン。

# ZOLOZ Real ID
Alibaba CloudとZOLOZによって、[**ZOLOZ Real ID**](https://www.alibabacloud.com/product/zoloz)というeKYCのデジタルおよびリモートオンラインソリューションが提供されています。
こちらもPOCです。
ISO27001およびPCI-DSSに準拠したセキュリティ標準を備えています。
本人確認IDドキュメントと生体判定から類似点を比較します。

# まとめ
* POC段階だけどクラウドベンダーがeKYC製品提供していて驚いた
* 日本の法律にも対応した内容(精度の検証は必要かと思います)
* ZOLOZ Real IDも提供(POC)されている
* デジタル技術で本人確認の手間を軽減できるのは便利


# 参照サイト
1. [日経XTECH](https://xtech.nikkei.com/atcl/nxt/column/18/01760/082600002/)
2. [ZDNet Japan](https://japan.zdnet.com/article/35164086/)
3. [ICT Business Online](https://www.ntt.com/bizon/glossary/e-e/ekyc.html)
4. [金融庁 「犯罪による収益の移転防止に関する法律施行規則の一部を改正する命令」の公表 について](https://www.fsa.go.jp/news/30/sonota/20181130/20181130.html)
5. [TRUSTDOCK](https://biz.trustdock.io/column/ekyc)
Hasuraのリレーションシップ（多対多）

## はじめに

以下のゴールを達成するため、本日は Hasuraの リレーションシップを学んでいきます。

今回はHasuraを使って1対1のリレーションを作る方法を見ていきます。

## 最終的なゴール

以下のような構成のアプリを作ることです。

![スクリーンショット 2021-10-18 17.27.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/e8a9a2e1-2723-4fec-77ef-be3b9eefdd81.png)

### 目的

- 仕事で使っている技術のキャッチアップと復習
- 使う可能性がある技術の理解度向上

## Hasuraのリレーションシップ（1対1）

今回説明するHasuraのリレーションシップ（多対多）の概念図です。

![スクリーンショット 2021-10-23 21.35.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/f25e63cc-19e9-e21b-6cfc-62f52f68fcc3.png)

Hasuraを使って、どうやって多対多のリレーションを実現するかですが、中間テーブルを使って実現しています。

中間テーブルテーブルを使って、`users`テーブルと`profiles`テーブルそれぞれの`id`を関連づけてマッピングをしていきます。

これを実際に、テーブルや関連づけやデータを追加することで実現していきます。

### 中間テーブルの作成とデータの追加

![Add_Table_-_Data___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/6ec6d150-014b-ab65-27a3-6fa6ba06ed82.png)

👇それぞれAddします。

![Relationships_-_profile_users_-_Data___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/f878a72f-5365-a93b-1cea-af9789fbe572.png)

Nameもデフォのもので。

![Relationships_-_profile_users_-_Data___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/64378632-c4f7-b52d-aabf-7681eb128bd8.png)

これで

- `profile_users.profile_id`は`profiles.id`と多対1
- `profile_users.user_id`は`users.id`と多対1

で、関連づけられました。

づぎに、`profiles`と`users`を見ていきましょう。

👇提案されていますね。1対多で。

![Relationships_-_profiles_-_Data___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/0dab0f0e-eb3e-0d74-d35d-863b7cc56af1.png)

Nameもデフォのものでsaveします。。

これで、関連付け完了です。

続いて、データを追加します。

`profile_users`テーブルをこんな感じの関連付けにしましょう。

| id  | profile_id | user_id | 
| --- | ---------- | ------- | 
| 1   | bob        | john    | 
| 2   | bob        | lilly   | 
| 3   | john       | bob     | 
| 4   | john       | lilly   | 

いつものように、`profile_users`テーブルに対して「Insert Rows」で2つ作成して、「Browse Rows」で確認します。

![Browse_-_profile_users_-_Data___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/8381304f-e39c-1b66-04d6-ba54b0b37d12.png)

### テーブル同士の関連づけ

`profiles`テーブルと`users`テーブルを1対多の関係で関連づけます。

`users`テーブルに行って、Modifyを選んで、新しいカラムを作成します。

### クエリで確認しましょう

`profile_users`から見る

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/f76b3a18-27a5-24ff-9b29-238c6f746b62.png)

`users`から見る

![API_Explorer___Hasura.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14191/da5d2c73-558e-c4e3-65e8-cd27984f1138.png)

- lillyはbobbyやJonから参照されています
- johnはbobbyから参照されています
- bobはJonから参照されています

ということがわかります。

どうやって探索しているかというと、lillyの場合

lillyのuser.id（`5f172cd2-221c-4ea5-8b83-6420b18860ab`）に、`profile_users`テーブルをみて紐づいた `profile_id`を見ると、bobbyとJonが引っかかる。という感じですね。

本日は以上です。

これで、Hasuraの基本事項は学んだので、次で、Next.jsとapolloクライアントを使って、Hasuraとの連携を学びます。

## 参考

https://hasura.io/learn/ja/graphql/hasura/relationships/

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
共同開発でpushできない！

# 事象

共同開発に参加。招待はメールで送られてきて、joinはした。
クローンはできたのに、プッシュできない。
せっかく編集してプッシュしようとしたのに、どうしよう・・・

```console
remote: Permission to [リポジトリ名] denied to [自分のユーザー名].
fatal: unable to access '[リポジトリ名]': The requested URL returned error: 403
```


# 原因
リポジトリの権限がReadになっている。

# 対策
リポジトリ管理者に権限をWriteに変更してもらう！

# 権限の確認方法
ReadかWriteかの権限名の確認方法はないんちゃうかなと思われます。

https://teratail.com/questions/120658

上記サイト参考にし、Wikiのタブが開けるかどうかで、ReadかWriteかが判断できると思いました。

* Write権限 → Wikiのタブが開ける
* Read権限 → Wikiのタブが開けない（遷移しない）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668402/c9629881-52ae-9a55-f2bf-638bb8b2db15.png)

もしWikiのタブが開けないならリポジトリ管理者に「Writeの権限付与してください！」と土下座をする！

# 他のサイトで散見された内容

リモートURLにユーザー名とかなんとかを含めるってのがありました。

が、「共同開発やから他人のユーザー名で作られてるリポジトリやねんけど！」って思い続けて調べ続けて・・・

やっぱりただの権限やないかーいって話でした！

ちなみに、権限を付与されたタイミングでも、githubからメールでなにも通知は来ませんでしたので、SlackとかLineとかで連絡してもらう必要があるんちゃうかなと思いますm(__)m
【Swagger】Docker環境で簡易モッキング


# 【Swagger】Docker環境で簡易モッキング

`Swagger`で定義したAPI仕様を使ってスタブ（モック）サーバーを構築します。こちらのソースコードを使って説明していきます。

- https://github.com/takiguchi-yu/SwaggerMocking

## アーキテクチャ

流れは以下の通りになります。

1. 開発者は VSCode を使って swagger.yaml を記述する
1. swagger-codegen を使って yaml を json に変換する
1. 変換した json を使ってスタブサーバーのコードを生成する
1. docker-compose up をしてスタブサーバーを実行する

![architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/72100564-73d9-8e41-b69c-19feba337d17.png)

## ディレクトリ構成

```bash
.
├── Dockerfile            # Node.jsのDockerイメージ
├── docker-compose.yml    # Swagger UIとNode.jsのコンテナ起動
├── gen                   # Swagger Generatorの出力ファイル
│   └── out
├── run-in-docker.sh      # Swagger Generator実行ファイル用シェル
└── swagger               # Swaggerファイル
    └── swagger.yaml
```

## swagger.yamlを作成

swagger.yamlはVSCodeで記述していきます。以下の拡張機能をインストールすることで快適になります。

- [Swagger Viewer](https://marketplace.visualstudio.com/items?itemName=Arjun.swagger-viewer)
  - Swaggerファイルをプレビューできるようになる。
- [OpenAPI (Swagger) Editor](https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi)
  - 自動補完(IntelliSense)が効いてくれるようになる。

### サンプル

```yaml:swagger/swagger.yaml
openapi: '3.0.2'
info:
  title: 簡単なAPI
  version: '1.0.0'
servers:
- url: http://localhost:49160/v1
externalDocs:
  description: Find out more about Swagger
  url: https://swagger.io/specification/
tags:
- name: List
  description: 一覧画面で使うAPI
paths:
  /list:
    get:
      tags:
      - List
      summary: 一覧情報を取得するAPI
      operationId: getList
      parameters:
      - name: listId
        in: query
        description: 一覧ID
        schema:
          type: string
      responses:
        '200':
          description: 処理成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: '200'
```

## コード生成

スタブサーバーで使うソースコードを swagger.yaml から生成します。

```bash
./run-in-docker.sh --help   # swagger-codegen-cliに対して「help」コマンドを実行します
./run-in-docker.sh langs    # swagger-codegen-cliに対して「langs」コマンドを実行します

# yaml to json
./run-in-docker.sh generate \
  -i /swagger/swagger.yaml \
  -o /gen/out/openapi \
  -l openapi

# swagger server generate
./run-in-docker.sh generate \
  -i /gen/out/openapi/openapi.json \
  -o /gen/out/nodejs-server \
  -l nodejs-server
```

## スタブサーバー起動

```bash
docker-compose up -d
```

## 動作確認

```bash
$ curl -X 'GET' \
           'http://localhost:49160/v1/list' \
           -H 'accept: application/json'

{
  "status": "200"
}
```

## 参考資料

- [OpenAPI仕様](https://swagger.io/specification/)
- [SwaggerCodegen仕様](https://github.com/swagger-api/swagger-codegen/tree/3.0.0)
  - ブランチはmasterではなく3.0.0に最新仕様が記述されている。
- [Node.js Web アプリケーションを Docker 化する](https://nodejs.org/ja/docs/guides/nodejs-docker-webapp/)
【WSL】SSHのパーミッション問題を､シンボリックリンクで解決した話


# はじめに
* WSLの環境構築中､SSH設定で､見事にハマって３時間ほど浪費した
* 色々と気付くことがあったので､Qiitaに初投稿することにした

## 対象読者
* WSLユーザで､｢`mnt/c`にhomeを置きたい!｣と考えている方

必ずハマるので是非読んで!


# ポイント
* WSLには､Linuxのファイル領域と､Windowsのファイル領域がある
    * `mnt/c`以下の領域は､Windowsのファイル領域
* Windowsには､パーミッションの概念がない
    * Windows領域のファイルのパーミッションは､`777`のガバガバ状態になっている
    * パーミッションを変更しようとしても､うまく行かない
* `.ssh`は､Linux領域に配置する
    * SSHは､ファイル(特に秘密鍵)のパーミッションがガバガバだと､エラーが出る
    * パーミッションを変更したくても､Windowsのファイル領域に置いてあると､うまく行かない
* homeを`mnt/c`に置きたい場合
    * `.ssh`などパーミッション設定が必要なものは､Linux領域に置く
    * homeにはシンボリックリンクを貼る
    

# 経緯
* WSLの開発環境を整備する
* homeが見えない所にあるのが気に食わなかったので､`mnt/c`に作成したディレクトリにhomeを移す
    * 振り返るとこれが全てのゴタゴタの始まりだった｡｡｡ 

# 発生した問題
## 問題1 gitからSSHでCloneしようとすると､パーミッションの問題で拒絶される
```
Bad owner or permissions on /mnt/c/wsl_home/.ssh/config 
fatal: Could not read from remote repository. 
Please make sure you have the correct access rights 
and the repository exists.
```
* 最初はconfigのパーミッションだけだったが､後々秘密鍵のパーミッション問題まで出てくる...

## 問題2 パーミッションが意図通り変更できない
* WSL上からパーミッションを変えようとしても､chmodで設定したようにならない!
    * `600`設定したのに､`777`から変わらない!
    * 試しに`000`で設定すると､`555`の設定になる!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418947/c85b53d7-b1ae-e6d7-6200-a3a126991e43.png)


# 根本原因
* ｢sshの秘密鍵を､パーミッションの設定ができないWindowsのファイルシステム上に置いていたこと｣が原因だった
    * Linuxから見ると､パーミッションが777のガバガバ設定になっていたので､怒られていた
    * homeを`mnt/c`(Windows領域)から､`/home/[Username]`(Linux領域)に移動すれば解決する

とはいえ､使いやすいようにわざわざ`mnt/c`にhomeを作ったので､変えたくない!

## 解決策
* `.ssh`は､Linux領域に配置し､homeには､シンボリックリンクを置く
    * ファイル自体はLinux領域にあるので､パーミッションの設定が可能
    * homeにはシンボリックリンクがあるので､通常と変わらずに色々できる(はず)
    * 設定も散らばらないので､メンテも楽なはず


```:bash
# 新しいhomeにあった.sshを元のhomeへ移す
cd ~
mv .ssh /home/[username]/.ssh

# シンボリックリンク作成
cd ~
ln -s /home/[username]/.ssh .ssh 
```
### 結果
#### homeの状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418947/dfd7abb6-93eb-9569-d8f2-57e1ec9fd1b7.png)

git cloneも無事成功!
やったぜ!
Android 11で追加されたワイヤレスデバッグ adb

#イントロ
AQUOSの2021年に購入したAndroidスマホがPCと接続してもUSB認識せずに困った

WindowsでAndroid作成アプリケーションをwifi越しに実機にadbでインストールする
Android11からwifiからadb接続可能


#環境
Windows10(64bit)
Android11
AQUOS sense 5g(SH-M17)

#ペアリング設定
※開発者モードにしておくこと
開発者向けオプション＞ワイヤレスデバック＞ペア設定コードによるデバイスのペア設定
![device-2021-10-23-211758 - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/61f9eb54-948b-1641-763d-1d638d87f6ba.png)

ペアリング、スマホの画面に出ている数字を「Enter pairing code:」に入力する
※一度成功すればペアリングは必要なくなる

```
C:\Users\su5fi>adb pair 192.168.1.26:1234
Enter pairing code: 123456
Failed: Unable to start pairing client.

```

接続、ポート番号は<font color="ff0000">ペアリングのポート番号</font>とは別

```

C:\Users\su5fi>adb connect 192.168.1.26:11635
connected to 192.168.1.26:11635

```

デバイス確認　※offlineとでているのは一度失敗した奴

```

C:\Users\su5fi>adb devices
List of devices attached
192.168.1.26:11173      offline
192.168.1.26:11635      device

```

接続確認※　-s でデバイス選択、デバイスが一つの場合は　adb shell　でよい

```

C:\Users\su5fi>adb -s 192.168.1.26:11635 shell
Sarah:/ $

```

アプリケーションのインストール
AndroidStudioでビルドした際、プロジェクト配下のoutputフォルダ配下の拡張子がapkのファイルを探す
app-debug.apkを探す、gitbashをインストールしていると便利

adb install　＜アプリケーションAPK＞する。

```

C:\work\plog\android\2021_1023_map\ImplicitIntentSample\app\build\outputs\apk\debug>adb install app-debug.apk
Performing Streamed Install
adb: failed to install app-debug.apk: Failure [INSTALL_FAILED_TEST_ONLY: installPackageLI]


```

多分こんなエラーになり、インストールが失敗する
TestOnlyアプリで作成されると、以下のよう -tオプションを与えてインストールする必要があります。

```

C:\work\plog\android\2021_1023_map\ImplicitIntentSample\app\build\outputs\apk\debug>adb install -t app-debug.apk
Performing Streamed Install
Success

```
SuccessとでればOK




#参考URL
https://zenn.dev/ik11235/articles/android-wireless-debug
https://codechacha.com/ja/how-to-disable-testonly-in-android/
Manjaro Linux kernel build

kernelパッケージを自分でビルドする場合
linux-5.14.16に更新した時のメモ

makepkgのオプション調整

```sh
# /etc/makepkg.conf
# 並列コンパイル。数字は環境に応じて適宜調整。
MAKEFLAGS="-j3"
# ビルド時間短縮。ccacheを有効にする。複数マシンがあれば分散コンパイルdistccも活用できる。
BUILDENV=(!distcc color ccache check !sign)
```

manjaroがリリースしているkernelパッケージのPKGBUILDなどを取得

```sh
#PKGBUILDファイルやパッチファイルを取得
git clone --single-branch --depth=1 https://gitlab.manjaro.org/packages/core/linux514.git
```

パッケージのビルド。
makepkg -sでビルドに必要なパッケージのインストールも行ってくれる。

```sh
#kernelパッケージのビルド
cd linux514
makepkg -s
sudo renice -n -20 -g `ps -g -o pid,pgid,comm| grep makepkg | awk '{print $2}'`
```

自分で調整したい場合。
PKGBUILD内で、make menuconfigのオプション調整を行えそう。
私は標準設定で問題ないので試していませんが、調整するとしたら、次の箇所を修正すると良いと思います。
make configの行をmake oldconfig、make menuconfigで置き換えます。
makepkgコマンド実行中に、カーネルオプションの設定画面が表示されるので、自分でオプションを調整できるので、それが反映されると思います。

```diff
diff --git a/PKGBUILD b/PKGBUILD
index 06ba6bd..8bd1039 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -132,7 +132,8 @@ prepare() {
   make prepare
 
   msg "rewrite configuration"
-  yes "" | make config >/dev/null
+  make oldconfig
+  make menuconfig
 }
 
 build() {
```

linux514のアップグレード

```sh
#lsでファイル名補完を利用して、pacmanにファイル名を渡しています。
sudo pacman -U linux514-headers-5.14.16-1-x86_64.pkg.tar.zst
sudo pacman -U linux514-5.14.16-1-x86_64.pkg.tar.zst
```

memo
署名が必要な場合、自作パッケージのインストール用に、自分の鍵を信用できる鍵として登録しておく。

```sh
sudo pacman-key --send-key keyid
sudo pacman-key --recv-key keyid
sudo pacman-key --lsign-key keyid
```

Manjaroのカーネルパッケージを利用して、インストールする場合、Manjaro Setting Managerか、コマンドラインで導入できます。

```sh
mhwd-kernel -l
sudo mhwd-kernel -i linux514
```

Manjaroの主な特徴、概略や便利な機能は、次のサイトで確認できます。
https://wiki.manjaro.org/index.php/Manjaro:A_Different_Kind_of_Beast
ポートフォリオを作成して学び・得たこと

# 概要
未経験から転職するために、ポートフォリオを作成しました（まだまだ追加したい機能などあるので改善は進めています）。
アプリの内容はReadMeに書いているため省略し、ここでは**アプリを作成する中で、学び・得たことについて**まとめたいと思います。技術的な部分よりも精神的な部分が多いです。

github:[WORD MASTER ~あなた自身のオリジナル単語帳を作ろう~](https://github.com/kazu848/word_master)

# 学び・得たこと

## 精神的な部分

### 人の役に立ちたい気持ちを再認識
元々、人の役に立つことがしたいと思い続けており、生活を便利にしている化学が好きということも合わせて、現職である化学メーカーに就職しました(ITエンジニアを目指している理由は省略)。

ありがたいことに、今回作成したアプリは40人以上の方が体験してくださり、「既存のアプリよりも使いやすい」「サービスとしてリリースされたら使いたい」「友人にも教えたい」など、多くの意見をいただけました。

この体験を通じて、改めて**人の役に立つことをしたい**と認識できました。

### 他者を巻き込みまとめることの大変さと楽しさ
悩み事を解決し便利にすることがアプリ開発には必須のため、ポートフォリオにおいても、可能な限り**多くの方に体験してもらい、いただいた意見を基に改善することが重要**だと考えました。

そこで、SNS(ツイッター)を通じてアプリ体験の参加者を募ったところ、最終的に40人以上の方が参加してくれました。

参加者をまとめるためにTwitterのDMで1つのグループを作成しましたが、グループ内でDMすると全員に通知が飛んでしまい、①参加者にとっては必要以上の通知による負担が生じ、②私自身が貴重な意見を逃す可能性ありました。

そこで、グループでは全体連絡や取りまとめた意見のみの連絡とし、アプリに対する意見などは個別にDMをいただくことにしました。

私自身、このような形で人を巻き込み行動するのは初めてで、募集をかけるツイートをした時はとても緊張しましたし、多くの方が参加を表明してくれた時も自分にまとめられるのか、否定的な意見ばかりだったらどうしようと不安も感じました。

結果的には、まとめることに苦労しながらも多くの方とコミュニケーションを取り、ご意見・ご提案も多くいただき、**非常に貴重な経験になった**と感じています。

ITエンジニアに転職してからも今回の経験を生かして、**上手く周囲の人を巻き込みながら開発を進められる人材を目指したい**と考えています。

### プログラミングを学ぶことの楽しさ
2021年の4月にProgateを始めるまで、プログラミングに触れた経験がありませんでした。
このポートフォリオを作成し始めるまでに3ヶ月間集中してRuby, Ruby on Railsを学習し、8月の終わりからポートフォリオ作成を開始しました。

学習中もポートフォリオ作成中も分からないこと・エラーに出会いながら、**日々新しいことを学び、少しずつ成長していることが実感できて非常に楽しく学習できています**。

まずはバックエンドをしっかり身につけようと考えていますが、その後は**フロントエンド・インフラについても学習したい**と考えています。

### 様々な方と関わり価値観・知見・考え方を広げることの大切さ
プログラミング学習を始めてから、プログラミングのコミュニティやアプリの体験会を通じて、自分とはバックグラウンドが全く異なる方々と関わる機会がかなり増えました。
その中で、自分とは異なる価値観や考え方に多く出会うことができ、とても良い影響を得られました。

ITエンジニアになってからは、**勉強会などに積極的に参加し、自身の価値観・知見・考え方を広げていきたい**と思います。


## 技術的な部分

### サービスを開発することの大変さ
今回のポートフォリオは下記の技術で開発しました。

言語:Ruby(2.7.3)
フレームワーク:Ruby on Rails(6.1.4.1)
フロントエンド:HTML/Scss/Javascript
DB:PostgreSQL
インフラ:AWS(VPC | RDS | EC2 | S3 | Route53 | ACM | ALB | CloudFront)
ソースコード管理:GitHub

バックエンドエンジニアを目指しているため、Ruby, Ruby on Railsを使用していますが、UIをHTML/Scss/JSで整えて、実際の運用を意識してインフラにはAWSを利用しています。
簡単なUIしか整えてませんが苦労しましたし、インフラもなんとか実装できたという状態です。

そのため、サービスを開発・運営することがどれほど大変かを感じました(今想像しているよりも大変と思います)。

エンジニアとして、**1日でも早く戦力になること・チームの一員として上手くコミュニケーションを取り活躍することを目標に業務に取り組みたい**と思います。

### 公式ガイド・リファレンスの重要さ
徐々に公式ガイドやリファレンスを参照する割合を増やしています。
他の方が執筆したQiitaやブログ記事も参照するのですが、正確性や細部の情報が不足していることがあります。

引き続き、**分からないことは公式の情報をメインにして理解する**よう努めたいと思います。

### ググる能力の大切さ

分からないことはネットで調べて学習するしかないと日々感じています。
分からないことを言語化する重要性を認識する一方で、どのようなワードで検索すれば良いか分からない状態によく陥ります。

現在は、できる限り言語化して検索→検索結果を基に少しずつ答えに近いワードに変更という流れを繰り返して解決しています。

適切な用語を覚えて、短時間で目的の情報が得られるように努めたいと思います。
S3オブジェクトのARNから、バケット名とオブジェクトキーを抽出するコマンド

# 目的

S3オブジェクトのARN (例)`arn:aws:s3:::example-bucket/example-folder/example-subfolder/example-file.txt`から、

- バケット名:`example-bucket`
- オブジェクトキー:`example-folder/example-subfolder/example-file.txt`

を抽出する。

# コマンド

事前準備として、`S3_OBJECT_ARN`にS3オブジェクトのARNを設定する。

```bash
S3_OBJECT_ARN=arn:aws:s3:::example-bucket/example-folder/example-subfolder/example-file.txt
```

`RESULT`に、`sed`で抽出したものを配列として設定する。
`S3_BUCKET_NAME`に`RESULT`配列の0番目を設定する。
`S3_OBJECT_KEY`に`RESULT`配列の1番目を設定する。

```bash
RESULT=($(echo ${S3_OBJECT_ARN} | sed -E 's/arn:aws:s3:::([^/]+)\/(.+)/\1 \2/'))
S3_BUCKET_NAME=${RESULT[0]}
S3_OBJECT_KEY=${RESULT[1]}
```

出力して確認する。

```bash
echo ${S3_BUCKET_NAME}
# => example-bucket

echo ${S3_OBJECT_KEY}
# => example-folder/example-subfolder/example-file.txt
```
Djangoアプリをherokuにデプロイするときの注意点

![heroku_注意点.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667780/e00f304a-23ee-e85b-d378-a3dd165a53c4.jpeg)

Djangoアプリケーションをherokuにデプロイする際に注意するべきポイントを紹介します。エラーが出たときほど成長ができると感じますが、「**とにもかくにも早くエラーを解消したい！**」という方の手助けになればと思います。

:::note warn
【注意点②】と【注意点③】は、解決はしましたが、「何故解決したのか」は明確に分かっていません。お手元の環境や状況では解決しない可能性もあるかもしれません。
:::

## 注意点① 容量が500Mを超えていないか
herokuはSlug Sizeというものがあり、それを500M超えるとデプロイできません。下記のエラーが出ます。

```python
remote: -----> Compressing...
remote:  !     Compiled slug size: 700M is too large (max is 500M).
remote:  !     See: http://devcenter.heroku.com/articles/slug-size
```

私はPyTorchの容量がとても大きく、デプロイ時にエラーが出ました。PyTorchがGPUのままでは到底500Mに抑えることはできないため、CPUでインストールする方法で解決しました。

参考記事
[HerokuアプリのSlug Sizeを簡単に減らす方法](https://qiita.com/kanatano_mirai/items/b300152a315c2a2ecb10)
[PyTorchを使ったアプリをHerokuにディプロイする際の注意点](https://qiita.com/kimisyo/items/e73844cf1ff46e2f26c5)
[Herokuで機械学習モデルを利用したアプリのデプロイ時の500MB制限回避策]
(https://qiita.com/nori2711/items/615183fdc6858758d380)

## 注意点② gitignoreにdb.sqlite3が入っていないか
heroku上でログインやサインアップなどをしようとするとエラーが出てしまいましたが、gitignoreファイルに記述されているdb.sqlite3を削除したら解消されました。疑問なのは[gitignore.io](https://www.toptal.com/developers/gitignore)で「Django」と検索するとdb.sqlite3が入っていることです。まだまだherokuとDjangoについて分からないことが多いなぁと感じました。

## 注意点③ settings.pyに「import django_heroku と django_heroku.setting(locals())」が残っていないか
初回デプロイ時は確か記述したままgit pushした気がしますが、それ以降はコメントアウトか削除しておかないとgit pushできませんでした。これも注意点②と同じでセオリー通りではなく不思議なのですが、現状アプリは正常に動いています。こちらも更新の余地ありです。
***
今回は特に悩まされたエラーに対する注意点を紹介しました。
今後も手強いエラーが出た際は、解決策とともに追記していこうと思います。