OmniAICreator/Qiita-1.07M huggingface dataset:
ruby DB設計　中間テーブルメモ

備忘録メモ

中間テーブル作る際のthrough（経由するという意味）

モデルに多対多を設計する時に使用する

has_many 

```ruby:qiita.rb
# app/models/photo.rb
class Photo < ActiveRecord::Base
  has_many :photos_tags
  has_many :tags, through: :photos_tags
end

# app/models/tag.rb
class Tag < ActiveRecord::Base
  has_many :photos_tags
  has_many :photos, through: :photos_tags
end

# app/models/photos_tag.rb
class PhotosTag < ActiveRecord::Base
  belongs_to :photo
  belongs_to :tag
end
```

上記の様に追記で経由するモデルをthoroughで定義する
【備忘】google apps script でslack通知


# usage

```js
sendSlack("hoge");
```

# 関数

```js

function getSlackURL(){
    return "*** slack webhook ***";
}
```

```js
function sendSlack(text){
  
    const channel = "#channel_name";
    const data = {
        'channel': channel,
        'username': 'bot',
        'text': text,
        'icon_emoji': ':ghost:'
    };
    const option = { 
        "method": "post",
        "payload": JSON.stringify(data),
        "muteHttpExceptions": true 
    };
    UrlFetchApp.fetch(getSlackURL(), option);
}
```
CDNの仕組みについて

# CDNの仕組み
### 背景
ECサイトのキャンペーンを開催する時に、アクセスが集中して、ページが表示できなくことや、海外のサイトをアクセスする時に、アクセスしにくいということやが少なくありません。

そういった問題を解決するために作られたネットワークの仕組みがCDNです。CDNではウェブコンテンツ配信用にネットワークを最適化することによって、アクセスが集中したりコンテンツが大容量化したりしても、ホームページの表示やコンテンツの配信に問題が起こらないようにすることが可能です。

### CDNの仕組み
CDNを利用しない場合、ユーザが直接にウェブコンテンツを保存されているオリジンサーバにアクセスしてダウンロードすることになります。一般的に、CDNのシステムではオリジナルのウェブコンテンツが存在するサーバを ```オリジンサーバ```と呼びます。
<img width="726" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/f3213327-e46d-0463-b0cd-230ce72758c8.png">

それに対して、CDNでは、よくアクセスするウェブコンテンツを事前に複数のCDNサーバに保存して、オリジンサーバの代理でウェブコンテンツを配信します。ユーザをアクセスす時に、ユーザの一番近いのCDNサーバからウェブコンテンツを配信します。こういうことで、効率なウェブコンテンツを実現するわけです。

### 利用シーン
- ウェブサイトアクセスの加速
- ダウンロードの加速
- 音声と動画コンテンツの配信


# Tencent Cloud CDNの仕組み

オリジンサーバーのドメイン名が```www.test.com```であるとします。ドメイン名はCDNサービスにアクセスしてアクセラレーションサービスの利用を開始した後、ユーザーがHTTPリクエストを送信した場合、実際の処理フローは下図のように示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633185/d3d0e99a-aef9-264a-c9a8-112c53ab3f86.png)

#### Tencent Cloud DNSの配信流れ：
1. ユーザーが```www.test.com```下の画像リソース（例：1.jpg）へのアクセス要求を送信する場合、先にLocal DNSへドメイン名解析リクエストを送信します。
2. ローカルDNSが```www.test.com```を解析する際に、同時にCNAME``` www.test.com.cdn.dnsv1.com```が設定されていることがわかるので、CNAME``` www.test.com.cdn.dnsv1.com```の解析リクエストをTencent DNS（GSLB）に送信されます。GSLBはTencent Cloudが独自に開発したスケジューリングシステムであり、リクエストに最適なノードIPを割り当てます。
3. Tencent DNSのCNAMEの解析結果（CDNのアクセスノードIPアドレス）をローカルDNSに返します。
4. Local DNSがユーザに解析結果（CDNのアクセスノードIPアドレス）を返します。
5. ユーザーは、取得したCDNのアクセスノードIPにアクセスリクエストを送信します。
6. アクセスするCDNノードがすでに1.jpgをキャッシュしている場合、データがユーザー（10）に直接に返し、リクエストは終了します。ノードが1.jpgをキャッシュしていない場合、ノードはオリジンサーバーに1.jpgへのリクエスト（6、7、8）を送信します。コンテンツを取得した後、CDNノードは設定されたキャッシュルールに従って、コンテンツをノード（9）にキャッシュするとともに、ユーザー（10）に返して、リクエストは終了します。
WAF(Web Application Firewall)

平成31年春期 午前問題45

WAFの説明はどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/3f305709-b30d-378a-bd9a-44049baf1bcf.png)

１、WAF(Web Application Firewall)は、
  ・通過するパケットのIPアドレスや
　・ポート番号だけでなく
　・ペイロード部(データ部分)
をチェックすることで、Webアプリケーションに対する
　・攻撃を検知し、
　・遮断すること
が可能なファイアウォールです。

チェックされる内容には
　・「URLパラメタ」や
　・「クッキーの内容」などのHTTPヘッダ情報や、
　・「POSTデータの内容」などのメッセージボディ部など
があります。

本来、Webシステムへの攻撃はWebアプリケーション側で対処すべき問題ですが、脆弱性のないWebアプリケーションを作成するためには専門的な知識や技術が必要であるため、全てのWebアプリケーションのセキュリティ対策を万全にすることは難しいのが現実です。WAFはこのようなセキュリティ対策の不十分さを補完し、Webアプリケーションの堅牢性を高める役割をもちます。
　・ペイロードPayloadとは、IT用語としては、パケット通信においてパケットに含まれるヘッダやトレーラなどの付加的情報を除いた、データ本体のことである。



２、SSLの機能
Webブラウザの通信内容を改ざんする攻撃をPC内で監視し検出する。
SSL（Secure Sockets Layer　セキュア・ソケッツ・レイヤー）は、いろいろある通信プロトコルのひとつで、インターネット上の通信を暗号化するための仕組み。
・TLS（Transport Layer Security）　SSLからTLSへと移行しました。
SSL 3.0、TLS1.0、TLS1.2、TLS1.3

３、HIDS(ホスト型IDS)　host-based intrusion detection system　※Intrusion：侵入
サーバのOSへの不正なログインを監視する。
・IDSは「コンピュータの中やネットワークを監視していて、不審者がきたら元締めに報告するシステム」です。
日本語で「侵入検知システム」と呼ばれる場合もあります。

監視する場所に目を向けると、IDSは2種類に分けられます。
それは

　１）コンピュータを見張るのが仕事のIDS　→　HIDS：ホスト型IDS
　　　※ホスト型IDSは、ネットワークを通じてコンピュータに入ってくるデータなどを監視する
　２）ネットワークを見張るのが仕事のIDS　→　NIDS：ネットワーク型IDS
　　　※ネットワークを流れるデータを監視する

４、ウイルス対策ソフト
ファイルのマルウェア感染を監視し検出する。

５、WPA2(Wi-Fi Protected Access 2)
Wi-Fiアライアンスが認定した無線LANの暗号化方式の規格であり，AES暗号に対応している。
・Advanced Encryption Standard (AES) は、DESに代わる新しい標準暗号となる共通鍵暗号アルゴリズムである。

※Alliance ライアンス　同盟

６、SIEM(Security Information and Event Management)
様々なシステムの動作ログを一元的に蓄積，管理し，セキュリティ上の脅威となる事象をいち早く検知，分析する。

７、UTM(Unified Threat Management)
ファイアウォール機能を有し，ウイルス対策，侵入検知などを連携させ，複数のセキュリティ機能を統合的に管理する。

ーーーーーーーーーーーーーーーーーーーーー
補足

図のような構成と通信サービスのシステムにおいて，Webアプリケーションの脆弱性対策のためのWAFの設置場所として最も適切な箇所はどこか。ここで，WAFには通信を暗号化したり復号したりする機能はないものとする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/0d2b3f1a-1d3e-c97b-3297-0e6f06b8ae64.png)

１、WAFは、
　・「シグネチャマッチング」や
　・「HTTPヘッダの検証」などよって不正なパケットを検知しますが、
　・HTTPS通信が行われている経路上のパケットは暗号化されているため、これらの検知手法が使えません。

また、WAFによる不正アクセスの検知・遮断は、Webアプリケーションによって処理が実行される前に行われる必要があります。


参照：
https://www.ap-siken.com/kakomon/29_aki/q45.html

https://www.fe-siken.com/kakomon/28_aki/q42.html

https://www.ap-siken.com/kakomon/29_haru/q43.html

IDS
https://wa3.i-3-i.info/word15236.html

SSL
https://wa3.i-3-i.info/word116.html

SSLとTLS
https://ssl.sakura.ad.jp/column/ssl_tls/
Vue.jsで名前の表示/非表示を切り替える

#はじめに

ボタンを押すと画面上にある名前の表示と非表示の切り替えができるプログラムを書いていきます。

##ソースコード
全体のソースコードは以下の通りになります。（headタグやvueの読み込み箇所は省きます。）

HTMLファイルに書くソースコード

```vuejs
        <div id="app">
            <button @click="toggleBtn">クリックしてね</button>
            <p v-if="show">
                {{name}}
            </p>
        </div>
```

jsファイルに書くソースコード

```javascript

var app = new Vue({
    el: "#app",
    data: {
        name: "Naoki",
        show: true,
    },
    methods: {
        toggleBtn: function () {
            this.show = !this.show;
        },
    },
});
```

##ソースコードの解説
コードを書く順番で見ていきます。

###条件分岐で名前を表示させる

```html
　　　　<!-- 条件分岐 -->
       <p v-if="show">　
           {{name}}　<!-- nameの出力 -->
       </p>
```
`show`がtrueの場合、`name`のデータが出力されます。


```javascript

//保持しているデータ
    data: {
        name: "Naoki",
        show: true,
    },
```
`name`に"Naoki"という文字データと`show`にブーリアン型の true が入っている状態です。

ここでの処理内容は`v-if="show"`で条件分岐が行われ、今の`show`のデータの中身はtrueで条件を満たしているので、`name`に入っている"Naoki"という文字データが画面上に出力されることになります。
※コメント欄に補足説明があるので、よろしければご覧ください。

###クリックで名前の表示/非表示を切り替える

```html
<!-- クリックイベントでの関数の呼び出し -->
<button @click="toggleBtn">クリックしてね</button>
```
ボタンをクリックすると`toggleBtn`の処理が呼び出されます。

```javascript
// 関数の設定
    methods: {
        toggleBtn: function () {
            this.show = !this.show;
        },
    },
```
toggleBtnが呼び出されると、反転した`show`が`show`に代入されます。
ちなみに、`this`というのは、jsファイルの`app`を指しています。

ここでの処理内容は、ボタンをクリックすると`toggleBtn`の処理が呼び出されて、`show`データの`true`と`false`が切り替わる仕組みになっています。この切り替えによって、名前の表示/非表示ができるようになるというわけです。

#おわりに
はじめてQiitaに記事を書いたのですが、こんなに簡単な処理内容でも文字にして説明するとなると全然スムーズにいかず、かなり頭を使いました。人に教えることに慣れていないので、これからもっと練習して人に教えるスキルとプログラミングスキルを向上させていきたいと思います。
コンテナ上のデバッグ環境構築 - DockerでRailsチュートリアルのローカル開発環境構築 - 

# はじめに

Dockerでローカル開発環境構築を行い、Railsチュートリアルを再走しております

- Railsチュートリアル最新版（2020.8.6現在）に対応のRails 6
- Dockerを使用し、開発環境の再現が可能
- なるべくローカル環境にインストールしない

今回はRailsチュートリアルの7章に相当する部分で、
Dockerコンテナ上で開発を行っている場合にデバッグを行う内容を紹介します



第一回
[DockerでRailsチュートリアルのローカル開発環境構築（Rails 6 + PostgreSQL + Webpack) - Qiita](https://qiita.com/daddy_hacker/items/99225bf3d8665ecfdec2)

第二回
[DockerでRailsチュートリアルのローカル開発環境構築 - RSpec導入 & CircleCIでHerokuデプロイ- - Qiita](https://qiita.com/daddy_hacker/items/7036f05c0f236be8806a)

第３回
[DockerでRailsチュートリアルのローカル開発環境構築 - WebpackでBootstrapとFont Awesomeを導入 - - Qiita](https://qiita.com/daddy_hacker/items/30bf299cb0d785f9fb2f)

個人開発アプリ
[mdClip ＜オンラインmarkdownエディタ＞](https://mdclip.xyz/)



Dockerのコンテナ上で操作する場合はターミナルのコマンドを適宜

```
$ docker-compose run app ...
```

もしくは

```
$ docker-compose exec app ...
```

で置き換えてください。





# Dockerコンテナ上の開発環境でRailsのデバッグを行う



## 方法1 Railsのコンテナにアタッチ -> デタッチ

参考サイト
[Docker と Rails 5.2 の開発環境でデバッグを行えるようにする - ココナラよもやまブログ](https://yomoyamablog.coconala.co.jp/entry/2018/12/04)



### Railsのコンテナにアタッチする

```
$ docker attach $(docker-compose ps -q app)
```



これでデバッグコンソールが使用できます



### コンテナからデタッチする

デバッグを`quit`で抜けると
コンテナが終了してしまうので`rails server`も落ちる
これではすごく使い勝手が悪いなと思ったら

コンテナからデタッチ（`Control P` -> `Control Q`）するだけなら、コンテナを終了しなくて済むとのこと

ただ、VS Codeのコンソールで操作していると
`Control P` ,  `Control Q`は他のショートカットに割り当てられない

これはコンテナでタッチキーを置き換えることで解決方法とのことです

参考記事
[docker で Ctrl-p ２回押し問題 (detach-keys の問題) を解決するには - Qiita](https://qiita.com/Yuki-Inoue/items/60ec916383025160fbb8#_reference-a2d9244a6c4496f4df05)

`~/.docker/config.json`に設定を記述します

```
vi ~/.docker/config.json
```

```
{
  # ...省略
  "detachKeys": "ctrl-e"
}
```



私は `control + e`でデタッチできるように設定しました







## 方法2 VS Codeでデバッグ用のコンテナを動かす

VS codeのデバッグ機能から、デバッグ用のコンテナを立ててデバッグする方法もあるようです

[Developing inside a Container using Visual Studio Code Remote Development](https://code.visualstudio.com/docs/remote/containers#_working-with-git)

シームレスで便利そうだと思ったのですが
ここまででちょっと時間を使ってしまったのでまた別の機会に追記します

自分用メモ

[Get started with development Containers in Visual Studio Code](https://code.visualstudio.com/docs/remote/containers-tutorial)

[VS Code - Remote Containers で Docker Compose で動いている Rails アプリに接続する - さめたコーヒー](https://www.kbaba1001.com/entry/2019/07/03/220401)





# Troubleshoot

いずれもBootstrapのバージョンが異なることに起因します
あまり時間を掛けて調べる意味もない気がするので

Bootstrapのバージョンは合わせた方がいいかもしれません



## Formが左に寄る

```
#修正前
col-md-offset-3
#修正後
offset-md-3
```



## $state-danger-textがないよ

```scss
$text-danger: #dc3545;

# ...中略...

.field_with_errors {
  @extend .has-error;
  .form-control {
    color: $text-danger;
  }
}
```



## .has-errorがないよ

`.has-error` -> `:invalid`

```scss
$text-danger: #dc3545;

# ...中略...

.field_with_errors {
  @extend :invalid;
  .form-control {
    color: $text-danger;
  }
}
```
[GoogleAppsScript(GAS) ]「Hello World」する方法

# 概要
GoogleAppsScript(GAS) で 「Hello World」する方法についてまとめる。

### GAS とは
Google スプレッドシート、ドキュメント、スライド、フォームのアドオンの作成、ワークフローの自動化、外部 API との統合などに利用できる Google が提供している JavaScript ベースの実行環境のこと。（参考：[公式サイト](https://developers.google.com/apps-script/)）

# 成果物
GASのログ画面に「Hello World」という文字列を表示する。
![スクリーンショット 2020-08-09 16.39.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/dd9795b1-fe38-7d56-51bd-fa163de025d8.png)

# 前提知識
- [関数と変数の宣言と実行](https://qiita.com/ub0t0/items/94498bab5825ed46f4b8)

# 使用するソフト
Google Drive

# 全体像
Google Drive 内に保存したスプレッドシートの [スクリプト エディタ] から .gs ファイルを起動し、「Hello World」 を呼び出す関数を実行する。
![スクリーンショット 2020-08-09 17.24.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/89168550-e2d8-b9c0-2fb1-002f2c38a6da.png)


# 手順
## [Google Drive](https://drive.google.com/?hl=ja) にアクセス
Google アカウントでログイン

## スプレッド シートを作成
左上の [新規] → [Google スプレッドシート] をクリック
![スクリーンショット 2020-08-09 17.32.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/620696c1-e0ba-d6c2-df88-c28642add11c.png)


スプレッドシートが開くので、任意のファイル名（ここでは「helloworld」）に変更する![スクリーンショット 2020-08-09 17.34.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/46446575-1e4f-4603-0476-147361ab8b01.png)



## .gs の起動
[ツール] → [スクリプト エディタ] をクリック
![スクリーンショット 2020-08-09 17.36.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/dc621ccf-869d-8c9b-a03b-b95944f02738.png)

GAS の実行環境が別ブラウザで立ち上がる
![スクリーンショット 2020-08-09 17.40.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/072fc870-853e-9b8b-7def-e707445e264b.png)


## 「Hello World」するコードを記述し、実行
スクリプトは JavaScript と同様に記述する

```.js:.gs
const helloworld = () =>{
  console.log("Hello World");
}
```


任意のファイル名（ここでは「helloworld」）で保存し、[▶︎] （実行ボタン）をクリック
![スクリーンショット 2020-08-09 17.45.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/a602fec9-1411-bb2a-d54e-dd156d572a5a.png)

実行結果は、[表示] → [ログ] から確認できる
![スクリーンショット 2020-08-09 17.45.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/2cab91d4-46aa-b48e-694b-8a4869692d2f.png)

### 注意点
#### .gs ファイルを更新後に再保存/ブラウザの再読み込みする
再保存/再読み込みしないと更新が反映されない時がある
保存は command + S

#### 複数関数を作成する場合は、実行したい関数を選択する必要がある![スクリーンショット 2020-08-09 17.56.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663833/6b3b23b9-f231-824f-a949-eae6eaaf4fab.png)
【Unity】【エディタ拡張】複数のオブジェクトをまとめてPrefab化する

Unity標準機能で出来ると思ったら出来なかった

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

/// <summary>
/// 複数のオブジェクトをまとめてprefab化するエディタ拡張
/// </summary>
public class MultiPrefabCreator : EditorWindow {

	// 出力先
	private string PATH_FOLDER = "Assets/Resources/Prefab/Temp/";

	private HashSet<GameObject> m_dropList = new HashSet<GameObject>();

	//メニューに項目追加
	[MenuItem("拡張/MultiPrefabCreator")]
	static void open()
	{
		EditorWindow.GetWindow<MultiPrefabCreator>("MultiPrefabCreator");
	}

	void OnGUI()
	{
		EditorGUILayout.LabelField("MultiPrefabCreator");
		var dropArea = GUILayoutUtility.GetRect(0.0f, 50.0f, GUILayout.ExpandWidth(true));
		GUI.Box(dropArea, "ここにPrefab化したいものをまとめてをドラッグ＆ドロップ");

		var evt = Event.current;
		switch (evt.type)
		{
			case EventType.DragPerform:
				if (!dropArea.Contains(evt.mousePosition))
				{
					break;
				}
				DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
				DragAndDrop.AcceptDrag();
				break;

			case EventType.DragExited:
				foreach (GameObject go in DragAndDrop.objectReferences)
				{
					Debug.Log(go);
					m_dropList.Add(go);
				}

				CreatePrefabs();
				Event.current.Use();
				break;
		}
	}

	
	/// <summary>
	/// Prefab化
	/// </summary>
	void CreatePrefabs()
	{
		foreach (GameObject go in m_dropList)
		{
			if (null == m_dropList)
			{
				return;
			}
			string prefab = PATH_FOLDER + go.name + ".prefab";
			PrefabUtility.SaveAsPrefabAsset(go,prefab);

		}
		m_dropList.Clear();
	}
}


```

Event.currentで処理中のEventが取れるので、

#####EventType.DragPerform: ドラッグアンドドロップ イベント中
カーソルの表示を変える

#####EventType.DragExited: ドラッグアンドドロップイベント終了
Prefab作り始める


<br>
###参考
[UnityEditor上で複数のゲームオブジェクトをプレハブ化する方法](https://doruby.jp/users/motsuka/entries/UnityEditor%E4%B8%8A%E3%81%A7%E8%A4%87%E6%95%B0%E3%81%AE%E3%82%B2%E3%83%BC%E3%83%A0%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E3%83%97%E3%83%AC%E3%83%8F%E3%83%96%E5%8C%96%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)
ファイアウォール方式　パケットフィルタリング、アプリケーション・ゲートウェイ、サーキットレベルゲートウェイ

平成31年春期 午前問題44

パケットフィルタリング型ファイアウォールが，通信パケットの通過を許可するかどうかを判断するときに用いるものはどれか。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/36266290-c3b8-38ba-655f-8ceec0a8aa64.png)


ファイアウォールには幾つかの方式がありますが、

１、パケットフィルタリング型は、
パケットのヘッダ部分に含まれる「送信元/宛先IPアドレス」「送信元/宛先ポート番号」「通信の方向」などの情報と、FW内部のフィルタリングルールを比較することでパケット通過の可否を決定する方式です。ここでいうヘッダ部分とは、IPヘッダ又はTCP/UDPヘッダを指します。

２、アプリケーション・ゲートウェイ
通信を中継するプロキシ（代理）プログラムを使い、社内ネットワークとインターネットを切り離す方式。
ゲートウェイ上で、アプリケーションレベルのフィルタリングを行い、データを中継する。例えば、FTP、POP/SMTP、telnetなどのコマンドを認識し、不正なコマンドは中継しないようにすることができる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/d484edd7-ca4e-ba21-8311-40ec1372df55.png)


３、サーキットレベルゲートウェイ型とは、
従来のパケットフィルタリング型の動作に加えて、通信を許可するポート指定や制御を行うタイプです。使用するアプリケーションごとに設定が可能なため、特定のシステムやソフトにだけ通信を制御するという使い方も出来ます。



参照：

https://www.ap-siken.com/kakomon/31_haru/q44.html

アプリケーション・ゲートウェイ
https://www.atmarkit.co.jp/ait/articles/0401/01/news059.html

ファイアウォールを徹底解説
https://www.shadan-kun.com/blog/measure/2775/
devise導入後migrateをしたらmax key length is 767 bytesエラーが。

#今回のエラー

ユーザー認証のdeviseを導入しようと

```
rails db:migrate
```

を実行したらこんなエラーが

```
== 20200809082251 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0154s
-- add_index(:users, :email, {:unique=>true})
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Specified key was too long; max key length is 767 bytes
.
.
.
.
.
```

#解決方法

###1.mysql.rbを新規作成

https://qiita.com/terufumi1122/items/9ea764618eba01144e09
こちらのQiitaの記事を参考にmysql.rbを新規作成して下記のように記述

```config/initializer/mysql.rb
require 'active_record/connection_adapters/abstract_mysql_adapter'

module ActiveRecord
  module ConnectionAdapters
    class AbstractMysqlAdapter
      NATIVE_DATABASE_TYPES[:string] = { :name => "varchar", :limit => 191 }
    end
  end
end
```


###2.データベースをリセット＆migrate実行
この状態で`rails db:migrate`を実行すると

```
== 20200809082251 DeviseCreateUsers: migrating ================================
-- create_table(:users)
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

Mysql2::Error: Table 'users' already exists
.
.
.
```

userテーブルはすでにありますよ！と言われてしまうため一度データベースをリセットして再度`rails db:migrate`を実行する必要がある。リセットをマイグレーション実行を同時に行えるのが下記のコマンド

```
rails db:migrate:reset
```

こちらを実行すると

```
Dropped database 'training_app_development'
Dropped database 'training_app_test'
Created database 'training_app_development'
Created database 'training_app_test'
== 20200809082251 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0110s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0093s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.0070s
== 20200809082251 DeviseCreateUsers: migrated (0.0274s) =======================
```

見事、deviseの設定をusersテーブルに反映する事ができた
情報セキュリティにおけるサンドボックスの説明


平成31年春期 午前問題43

情報セキュリティにおけるサンドボックスの説明はどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/e9d9b49c-44f6-4094-30f6-9089c86c6f42.png)

１、サンドボックス【Sandbox】
外部から受け取ったプログラムを保護された領域で動作させることによってシステムが不正に操作されるのを防ぎ、セキュリティを向上させる仕組みです。
JavaアプレットやAdobeFlash、Webブラウザのプラグインなどでは外部プログラムの機能を制限することで脆弱性を低減させています。最近では、仮想環境として構築したサンドボックスが、未確認ファイルや不審ファイルの動作確認に使えることから標的型攻撃への対策としても注目を集めています。

２、SIEM(Security Information and Event Management)
OS，DBMS，アプリケーションソフトウェア，ネットワーク機器など多様なソフトウェアや機器が出力する大量のログデータを分析する。


３、サニタイジングやエスケープ処理　sanitizing
Webアプリケーションの入力フォームへの入力データに含まれるHTMLタグ，JavaScript，SQL文などを他の文字列に置き換えることによって，入力データ中に含まれる悪意のあるプログラムの実行を防ぐ。

・サニタイジングとは、利用者が入力した文字データを受け取る際に、プログラムにとって特別な意味を持つ可能性のある文字や文字列を検知して、一定の規則に従って別の表記に置き換えること。「無害化」とも呼ばれ、攻撃者が入力データ中にコード断片などを混入させて誤作動を誘発する攻撃などを防ぐために行われる。

４、リバースプロキシ
Webサーバの前段に設置し，不特定多数のPCから特定のWebサーバへのリクエストに代理応答する。


参照：
https://www.ap-siken.com/kakomon/31_haru/q43.html

サンドボックス【Sandbox】
https://www.sg-siken.com/word/%E3%82%B5%E3%83%B3%E3%83%89%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9.html

サニタイジング  【 sanitizing 】
http://e-words.jp/w/%E3%82%B5%E3%83%8B%E3%82%BF%E3%82%A4%E3%82%B8%E3%83%B3%E3%82%B0.html
絶対に失敗しないDockerでLaravel6.8+Vueの実行環境（LEMP環境）を構築する方法〜後編〜

記事の内容をブラッシュアップしてブログに移設しました👇

https://yutaro-blog.net/2021/04/28/docker-laravel-vuejs-1/

https://yutaro-blog.net/2021/04/29/docker-laravel-vuejs-2/

https://yutaro-blog.net/2021/04/30/docker-laravel-vuejs-3/

https://yutaro-blog.net/2021/05/25/docker-laravel-vuejs-m1/
絶対に失敗しないDockerでLaravel+Vueの実行環境（LEMP環境）を構築する方法〜前編〜

記事の内容をブラッシュアップしてブログに移設しました👇

https://yutaro-blog.net/2021/04/28/docker-laravel-vuejs-1/

https://yutaro-blog.net/2021/04/29/docker-laravel-vuejs-2/

https://yutaro-blog.net/2021/04/30/docker-laravel-vuejs-3/

https://yutaro-blog.net/2021/05/25/docker-laravel-vuejs-m1/
deviseでusersテーブルを作成しようとした時に発生したMysql2::Error:Specified key was too long; max key length is 767 bytesのエラー対処法

基本的には何もいじらずデフォルトの設定でマイグレーションしようとしただけなのでそれでエラー出るってどうよっていう話ですが、gem入れた後に

```terminal
rails g devise user
```
でモデル作って何も触らず

```terminal
rails db:migrate
```
しようとしたら

```terminal
Mysql2::Error: Specified key was too long; max key length is 767 bytes
```

とエラーが出ました。
原因は[こちら](https://qiita.com/terufumi1122/items/9ea764618eba01144e09)の記事に実にわかりやすくまとまっていました。
emailの文字数制限を変えることで解決する方法が載っていました。

自分はめっちゃ長いメールアドレスあったらどうすんねんとか訳のわからない意見が自分の中に湧き上がってきたので別の方法で解決しました。ええ。文字コード自体変えました。

```yml:database.yml
default: &default
  adapter: mysql2
  # encodingの値をutf8mb4からutf8に変更
  encoding: utf8 
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock
  #(以下略)
```

めでたしめでたし。
それにしてもカラムの型がvarchar(255)だとエラー出るとか納得いかない

#参考にした記事
https://qiita.com/terufumi1122/items/9ea764618eba01144e09
Ubuntu 20.04 LTS に Rustを新規インストール

#Ubuntu 20.04 LTS に Rustをインストール

クリーンインストールしたUbuntu20.04 LTSに Rustコンパイラをインストールする。
Ubuntuは最小インストールで入れたので、普通にやっても色々足りなかったので備忘録。

` Rustを持ってくるのに必要。普通は普通に入っている。`

```
$ sudo apt install curl
```

`Rusu の build に必要。普通は普通に入っている。`

```
$ sudo apt-get install gcc
```

`Rustのインストール`

```
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

`PATHを反映させる。一回ログアウトしても良い。再起動でもいい。*1`

```
$ source ~/.profile
```

`バージョンの確認`

```
$ rustup -V
rustup 1.22.1 (b01adbbc3 2020-07-08)
```


## Hello World してみる

```
$ mkdir rust_test
$ cd rust_test
$ cargo new hello_rust
  Created binary (application) `hello_rust` package
$ cd hello_rust
$ cargo build
   Compiling hello_rust v0.1.0 (/home/ayu/rust_test/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.21s
$ target/debug/hello_rust
Hello, world!
$
```

`大丈夫なようです。`
---
*1)Rustの環境変数だけを反映させるなら

```
$ source $HOME/.cargo/env
```
の方がいいようですが、かえって面倒くさいので、特に問題なさそうなら.profile一括反映の方が楽かも。
Arduinoインストール Ubuntu16.04 & ROS Serial 導入メモ (2020/08/09)

# 環境の詳細
 - Ubuntu 16.04 (64bit)
 - CPU: Intel core i7 7700HQ
 - Memory: 16GB
 - Graphic Board: GTX1060
 - 2020年8月9日現在（重要）

# Arduino Install
最近は便利になってinstall.shファイルなどが充実しています。数年前はjava入れたり設定したりとArduinoをUbuntuに入れるだけでも大変だったような気がします。
それでは順番にインストール方法を述べていきます。
１，以下の公式ページ「SOFTWARE/DOWNLOADS」から自分のOSにあったArduinoをダウンロード
https://www.arduino.cc/en/Main/Software
バージョンは最新版でいいと思いますが、特殊なライブラリなど使っている場合はアーカイブ(以下ページ)から別バージョンを選んでください。
https://www.arduino.cc/en/main/OldSoftwareReleases

![Arduino_1_download1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282390/a5f0e705-a5ea-b969-ea71-aec10d3eb22d.gif)


しばらく待ちます。その後arduino-1.8.13-linux64.tar.gzがダウンロード完了します。

２，ダウンロードした圧縮ファイルをhome直下へ移動&展開し、install.shを実行
ダウンロードしたディレクトリから所望のディレクトリ（今回はhome直下）に上記のダウンロードした圧縮ファイル（arduino-1.8.13-linux64.tar.gz）を移動し、展開。
中に入っているinstall.shを実行。

```
cd ~/arduino-1.8.13
sudo ./install.sh
```

![Arduino_2_install_All.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282390/fd38116c-a726-833b-909a-6037b8f4dbef.png)


終わったら親切にArduinoのショートカットまで作ってくれます。いらないけど記念に残しておきます。

３，実行確認
デスクトップにできたショートカットをダブルクリックでもArduinoを実行できますが、以下のようなコマンドを実行してもOKです。

```
sudo ./arduino-1.8.13/arduino
```

![Arduino_3_open_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282390/63544ead-7549-a379-f399-2c39dcc66822.gif)


# ROS Serial Install
以下のコマンドを実行するだけでOKです（上記のようにhomeで展開してるなら）。

```
$ sudo apt-get install ros-kinetic-rosserial ros-kinetic-rosserial-arduino
$ cd ~/arduino-1.8.13/libraries
$ rosrun rosserial_arduino make_libraries.py .
```

最後の . をお忘れなく。
ROS Serial を使ったサンプルは次回投稿します。
iperf3のコマンドのオプション理解

# 初めに
iperf3をwirelessの性能測定で使う機会があり(32Mbpsを満たしているかどうか)指定のコマンドの意味が分からなかったので調査した。

#ipefとは
サーバとクライアントでトラフィックを受け渡しし、どれだけのトラフィックが流れたか(性能試験)を確認するツールです。

# 対象コマンド
TCP serverで確認
```
-c <HU IP ADDRESS> -p 10000 -i 0.5 -b 100M -P 1 -n 200M -J
```
UDP serverで確認
```
-c <HU IP ADDRESS> -p 10000 -i 0.5 -b 100M -P 1 -n 200M -u -J
```

# オプションの意味
|オプション|説明|
|:---|:---|
|-s|サーバとして起動するオプション|
|-c|クライアントとして起動するオプション|
|-p|サーバなら待ち受けるポート、クライアントなら接続先ポートを指定する。デフォルトは5201。|
|-i|n秒ごとにbandwidth、jitter、lossの結果を出す。デフォルトは1。0にすると終了時の統計しか出力しない。|
|-b|帯域制限を掛ける。TCPの場合デフォルト無制限、UDPの場合はデフォルト1Mbit/sec。-pオプションによって並列実行している場合、それぞれのストリームに対して制限がかかる(合計ではない)。|
|-P|n個のコネクションを同時に接続する。デフォルトは1つ。|
|-n|n(byte)のバッファを送信し終えるとiperfクライアントを終了する。-t, -kオプションと一緒に指定できない。|
|-u|TCPではなくUDPを使用する。|
|-J|JSON形式で結果を出力する。|
Pythonのpropertyについてまとめ

# 概要
- pythonのpropertyについて理解が怪しかったので例を交えて整理しておく目的で記事を書きました

# 例題
- 下記コードを例に説明していく

```python

class Dog(object):
    def __init__(self):
        self.name = 'John'

dog = Dog()
print(dog.name)
```

## 何も設定しない場合
- 例題に記載してある通りのコードを実行する
- outputは"John"となる

## class変数を下記に変更

```python

class Dog(object):
    def __init__(self):
        self.__name = 'John'

dog = Dog()
print(dog.name)
```
上記のoutputは下記となる

```
Traceback (most recent call last):
〜(省略)〜
    print(dog.name)
AttributeError: 'Dog' object has no attribute 'name'
```
- `self.name = 'John'`を`self.__name = 'John'`とする事で外部からclass変数が呼び出せなくなる

## getterを使用してclass変数を外部から参照させる
```python

class Dog(object):
    def __init__(self):
        self.__name = 'John'
    @property ##getterの設定
    def name(self):
          return self.__ name

dog = Dog()
print(dog.name)
```
- 上記のoutputはJohnとなる
- getterを使用する事によって外部からclass変数=nameが参照できるようになる


## setterを使用してclass変数を外部から変更できるようにする
```python

class Dog(object):
    def __init__(self):
        self.__name = 'John'

    @name.setter ##setterの設定
    def name(self, dogname):
        self.__name = dogname

dog.name = 'sandy'
print(dog.name)
```
- 上記のoutputはsandyとなる
- setterを使用する事によって外部からclass変数=nameの内容を変更できるようになる

## 参照
https://www.headboost.jp/python-property/#1_Python
unicornとNginxの設定

Unicorn
=

``` rb:Gemfile.rbにunicornを追加する
gem 'unicorn'
```

``` rb:gemのインストール
$ bundle install
```

・設定ファイルを手動で作成する

``` terminal:unicornの設定ファイルを作成
$ touch config/unicorn.rb
```

・設定ファイルに以下を記述する

``` config:config/unicorn.rb
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15
preload_app true

before_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
    Process.kill 'QUIT', Process.pid
  end

  defined?(ActiveRecord::Base) and
      ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  Signal.trap 'TERM' do
    puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
  end

  defined?(ActiveRecord::Base) and
      ActiveRecord::Base.establish_connection
end
```

``` terminal:unicornの実行（動作確認）
$ bundle exec unicorn_rails -c config/unicorn.rb
```

``` :unicornの実行（開発環境）
$ bundle exec unicorn_rails -c config/unicorn.rb -E development -D
```

``` 抜け方
ctrl + q
``` 

``` :こんなエラーが出る事がある
unicorn Address already in use)
```

```terminal:上記エラーの対処
$ ps aux |grep 8080   # 8080のプロセスIDを表示
$ kill [プロセスID]     # 8080のプロセスをKillする
```

Nginx
=

・Homebrewでnginxをインストールします。

``` terminal:nginxのインストール
$ brew install nginx
```

``` terminal:nginxの設定を編集する
$ vi /usr/local/etc/nginx/nginx.conf
```

``` config:（一部抜粋）ポートを8080以外に設定（バッティングするため）
    server { 
        listen       80; 
        server_name  localhost; 
```


``` terminal:formulaの設定や情報を確認(homebrewで入れたものはこれで確認)
$ brew info nginx
```

``` terminal:nginxの起動
$ sudo brew services start nginx
※どうやら brew services start nginxとコマンドを実行しておけば次回以降、Mac 再起動時に Nginx が自動起動される様子。

もしくは、起動できない場合は
$ sudo nginx
```



``` terminal:nginxの停止
$ brew services stop nginx
```

unicorn + Nginxの連携設定
=

・後程、書きます。

Webサーバの起動確認
=

・下記にアクセスしてみる
http://localhost:80
＝＞アクセスできたらOK
VPNで使用されるセキュアなプロトコルであるIPsec，L2TP，TLS


平成31年春期 午前問題42


VPNで使用されるセキュアなプロトコルであるIPsec，L2TP，TLSの，OSI基本参照モデルにおける相対的な位置関係はどれか。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/25f0e5ff-c3d5-19cc-6a64-751d7c367e9d.png)


１、IPsec (IP Security)
IP(Internet Protocol)を拡張してセキュリティを高めたプロトコルで、改ざんの検知、通信データの暗号化、送信元の認証などの機能をOSI基本参照モデルのネットワーク層レベル(TCP/IPモデルではIP層)で提供する。認証プロトコルAHや認証／暗号化プロトコルESPを含む。

２、L2TP (Layer 2 Tunneling Protocol)
PPPなどのデータリンク層のフレームをカプセル化し、UDPおよびIPデータグラムに埋め込むことで、公衆ネットワーク上で伝達可能にするトンネリングプロトコル。暗号化の機能はないため必要に応じてIPsecと併用する必要がある。その名の通りOSI基本参照モデルの第2層のデータリンク層で動作する。

３、TLS (Transport Layer Security)
通信の暗号化、ディジタル証明書を利用した改ざん検出、ノード認証を含む統合セキュアプロトコル。その名の通りOSI基本参照モデルのトランスポート層で動作する。


IPsecはIPが属するネットワーク層(第3層)、L2TPはデータリンク層(第2層)、TLSはトランスポート層(第4層)にするので、適切な並びは上層から TLS→IPsec→L2TP の順です。


OSI基本参照モデル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/90dc90f5-88b2-b8af-f78c-eabcd24e1379.png)

ーーーーーーーーーーーーーーーーーーーーーーーーーーーー
補足

暗号化や認証機能を持ち，遠隔にあるコンピュータに安全にログインするためのプロトコルはどれか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/1888ae19-5e2f-b935-2c65-a7a8841c6e92.png)

１、
・IPsec
　Security Architecture for IPの略。IP(Internet Protocol)を拡張してセキュリティを高め、「改ざんの検知」「通信データの暗号化」「送信元の認証」などの機能をOSI基本参照モデルのネットワーク層レベル(TCP/IPモデルではインターネット層)で提供するプロトコルです。

・L2TP
　Layer 2 Tunneling Protocolの略。OSI参照モデルの第2層におけるトンネリングプロトコルです。暗号化の機能はないため必要に応じてIPsecと併用する必要があります。

・RADIUS
　Remote Authentication Dial In User Serviceの略。認証情報と認証手続き、および利用ログの記録(アカウンティング)をネットワーク上のサーバに一元化することを目的としたシステムです。

・SSH
　SSH(Secure SHell)は、公開鍵暗号や認証の技術を利用して、安全にリモートコンピュータと通信するためのプロトコルです。
ネットワークを介して遠隔地のコンピュータを操作する「rlogin」や「rsh」などのUNIX系コマンドや「TELNET」などを安全に利用するための方式です。またポートフォワーディング機能を使ってFTP，POP，SMTPなどの暗号化機能をもたないプロトコルを安全に利用する手段としても使用されています。


参照：

https://www.ap-siken.com/kakomon/28_haru/q43.html

https://www.ap-siken.com/kakomon/29_haru/q45.html

OSI参照モデルまとめ
https://qiita.com/tatsuya4150/items/474b60beed0c04d5d999
Lombok Macにインストール(STS使用)

SpringToolSuite4にLombokをインストールする。
MACのSTSでLombokを利用するにあたり、メモしたいと思います。

①公式サイトからダウンロード
https://projectlombok.org/download
<img width="1197" alt="スクリーンショット 2020-08-09 16.54.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675326/46020efd-98ed-f284-c365-cde144e15265.png">

②ダウンロードファイル（lombok.jar）をSpringToolSuite4のインストール場所に設置
/Applications/SpringToolSuite4.app/Contents/MacOS/ここに配置
<img width="551" alt="スクリーンショット 2020-08-09 17.00.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675326/8b81d6b5-7a45-e5c1-8a58-9788dab5d750.png">

③lombok.jarを起動しインストール（一覧にインストール先がない場合[Specifylocation]ボタンを押して、対象を選択）
インストール先:/Applications/SpringToolSuite4.app/Contents/Eclipse/eclipse.ini
選択後:install/UpdateをクリックさらにQuit Installerクリック
 
<img width="831" alt="スクリーンショット 2020-08-09 17.03.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675326/0fda1244-703d-0dc8-2353-9372ab15396b.png">
インストールが完了すると、stsのフォルダ内にlombokが入ります。 
以上でインストール完了です。
ウイルス対策ソフトでの，フォールスネガティブ、フォールスポジティブ

平成31年春期 午前問題41


ウイルス対策ソフトでの，フォールスネガティブに該当するものはどれか。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/503b4e19-04f9-f6a3-d0f8-838eafdbc0a4.png)


フォールスネガティブは、対をなすフォールスポジティブとともにウイルス対策ソフトやIDS／IPSにおける誤検知のパターンを表す言葉です。

１、フォールスネガティブ（False Negative）
本来は検知すべき悪意のある活動を、誤って害のないものとして分類すること。いわゆる検知漏れ。多くなるほどコンピュータに影響を与え得る攻撃を通過させてしまう可能性が高くなる。

２、フォールスポジティブ（False Positive）
本来は通過させるべき害のない活動を、誤って悪意のあるものとして分類すること。いわゆる過剰検知。多くなるほど正常な操作の阻害回数や管理者の負担が増える。


多分、
・ネガティブとは、ちゃんと仕事していないとのことですね。なので、検出べきものも検出できないです。
・ポジティブとは、仕事をやるすぎですね。そもそも問題ないけれど、問題ありとの判断になってしまった。


参照：
https://www.sc-siken.com/kakomon/29_haru/am2_13.html
VRChatでワールドをつくってみる (随時更新)

#この記事は
VRChatについて詳しくないけど、ワールドを作ってみたくなった。
せっかく作業ログを書きたいので、この記事は随時更新していくつもり。

#筆者のスキルレベル
- Unityはチュートリアルをいくつかやったことがある。
- VRChatは1回だけワールドを巡ってみたことがある。正直よくわかっていない。

#環境セットアップ
##ガイド
- 日本語でわかりやすく解説してくれているチュートリアルもたくさんあるけど、環境セットアップみたいなバージョン依存のあるものは公式ガイドを読むのがトラブルに遭遇する確率が低い気がしている。

- [https://docs.vrchat.com/docs/setting-up-the-sdk](https://docs.vrchat.com/docs/setting-up-the-sdk)


## Unityの該当バージョンのインストール
- 2020-08時点で Unity 2018.4.20f1
- VRChatSDKとバージョンを対応させる必要がある。
- 過去にUnityをインストールしたことがあって、Unity Hubを使える環境なら、下記をブラウザURLにコピペするとよい。

```URL
unityhub://2018.4.20f1/008688490035
```

## VRChat SDKのインストール
- VRCSDK2とVRCSDK3があるようだ。混ぜるなキケンらしい。
- 今回は **VRCSDK2** にする。
- [https://vrchat.com/home/download](https://vrchat.com/home/download)
TensorFlow 2.3.0をCUDA11+cuDNN8向けに強制的にビルドする方法

TensorFlowでGPUを利用するためには、互換性のあるバージョンのCUDAやcuDNNを利用する必要があり、2020/8/9時点で最新のTensorFlow 2.3.0も、CUDA 11やcuDNN 8には対応していません。
そのため、ソースコードからビルドしても互換性の問題で失敗します。

…が、利用している環境が「CUDA 11 + cuDNN 8」になっていて、それでもTensorFlowでGPUを使いたい人向けに「強制的に」TensorFlow 2.3.0をCUDA 11 + cuDNN 8向けにビルドする方法を残しておきます。
なお「本来なら対応していない」バージョンの組み合わせなので、全てが正常に動作する保証はありません。簡単なCNNモデルの学習や推論を試した限りでは正常に動作していますが、実験的な扱いに留めておくことをおすすめします。（CUDA11+cuDNN8に正式対応するまでの暫定的な処置）

## 環境情報

ビルドに利用した環境です。CUDAやcuDNNのフォルダなど、事前にパスを通した状態になっています。

* Windows 10 Ver1909 (64bit)
* Visual Studio Community 2019 Ver 16.5.4
* Python 3.8.2
* MSYS2（`pacman -S git patch unzip` で必要なパッケージを導入済み）
* Bazel 3.4.1 （3.1.0以上のバージョンを使う必要あり）
* CUDA 11.0.3
* cuDNN 8.0.2

## ビルド用のフォルダ構成など

今回は`S:\build\build_tf230` フォルダ配下にTensorFlowのソースコードをダウンロードしてビルドしています。Pythonの仮想環境も、TensorFlowビルド用に用意します。

```powershell
S:/build/build_tf230  # 作業フォルダRoot
 + tensorflow  # gitで取得してくるソースコード
 + venv        # Python仮想環境
 + wheelhouse  # 作成したwhlファイルを格納するフォルダ
```

## ビルド手順

`x64 Native Tools Command Prompt for VS 2019` を起動して以下の手順でビルドを行います。

```powershell
# 仮想環境を作成して有効化する
python -m venv s:\build\build_tf230\venv
cd /d s:\build\build_tf230
.\venv\Scripts\activate.bat

# 必要なパッケージのインストール
# 注意：最新の1.19.xシリーズのNumPyを使うとビルドに失敗するので注意
python -m pip install --upgrade pip
pip install numpy==1.18.5
pip install six wheel
pip install keras_applications==1.0.8 --no-deps
pip install keras_preprocessing==1.1.2 --no-deps

# ソースコード取得（v2.3.0のタグ指定）
git clone -b v2.3.0 https://github.com/tensorflow/tensorflow.git
cd tensorflow

# 環境によってはコマンドのパラメーターが長くなりすぎてエラーになるので不要な環境変数を削除
set _OLD_VIRTUAL_PATH=

# ビルド構成の設定
# CUDA support: Y
# CUDA compute capabilities: 7.5 （利用環境に合わせて変更）
# Optimization: /arch:AVX2 （利用環境に合わせて変更）
# それ以外はデフォルト設定（Enter）
python ./configure.py

# CUDA 11を使っていると、次のconfig.hの78行目の部分でエラーになる。
# C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\include\thrust\system\cuda\config.h
# CUBバージョンの互換性チェック部分だが、このチェックは「THRUST_IGNORE_CUB_VERSION_CHECK」を定義すればスキップ可能。
# bazelのパラメーターでTHRUST_IGNORE_CUB_VERSION_CHECKを有効にしてTensorFlowをビルド。
bazel build --config=opt --config=avx2_win --config=short_logs --config=cuda --define=no_tensorflow_py_deps=true --copt=-DTHRUST_IGNORE_CUB_VERSION_CHECK --copt=-nvcc_options=disable-warnings //tensorflow/tools/pip_package:build_pip_package

# パッケージの作成（wheelhouseフォルダにパッケージを作成）
# 数分間画面が更新されないので心配になりますが、きちんと処理されているのでしばらく待ちましょう
bazel-bin\tensorflow\tools\pip_package\build_pip_package ..\wheelhouse
```

これで完了です。
ポイントとしては、bazelのビルドパラメーターに`--copt=-DTHRUST_IGNORE_CUB_VERSION_CHECK` を追加して、CUDA 11のCUB互換チェックをスキップさせることです。
ShapeableImageViewで真ん丸や角丸の画像を手軽に作ってみる

真ん丸や角丸の画像を作る方法としてPiccasoなどのライブラリを使う方法[^1]や、手軽な方法としてCardViewを用いたやり方[^2]などがありますが、Material Components 1.2.0に追加された`ShapeableImageView`を使ったやり方を紹介してみます。


下のような画像を手軽に作成できます。

![top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658739/3f96c7cc-cb2d-56fb-1da9-edaba7240d2d.png)

## 準備

Material Components 1.2.0を追加しておきます。

```
dependencies {
    implementation "com.google.android.material:material:1.2.0"
}
```

## 使い方
使い方としては、styleを定義して`ShapeableImageView`の`app:shapeAppearanceOverlay`属性に指定してやるだけでOKです。以下で詳しく見ていきます。

### 真ん丸

`styles.xml`に以下を追加。
`cornerFamily`に`rounded`、`cornerSize`に50%を指定してあります。

```xml
<style name="circleImageView" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">50%</item>
</style>
```

あとはレイアウトファイルに`ShapeableImageView`を配置して`app:shapeAppearanceOverlay`属性に上記のスタイルを指定してやります。

```xml
<com.google.android.material.imageview.ShapeableImageView
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:adjustViewBounds="true"
    android:src="@drawable/ic_droid"
    app:shapeAppearanceOverlay="@style/circleImageView" />
```

<img width="30%" alt="circle.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658739/2406e153-3d8a-acc1-0d2a-59c9b6fe3725.png">


### 角丸
`cornerSize`を調整してやれば角丸にできます。
今回は24％にしてみました。

```xml
<style name="roundedCornersImageView" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">24%</item>
</style>
```

<img width="30%" alt="cornerRounded.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658739/5eff2272-e9fb-8d0e-e47f-c9d2b9d6af54.png">



### ひし形

`cornerFamily`に`cut`を指定し、`cornerSize`を50%にすればひし形にできます。

```xml
<style name="diamondImageView" parent="">
    <item name="cornerFamily">cut</item>
    <item name="cornerSize">50%</item>
</style>
```

<img width="30%" alt="diamond.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658739/8ff913a5-6493-b504-c7f3-9b11ef0da5f4.png">



### 部分的に適応

四隅の一部のみを変えることも可能です。
例えば左上をround、右下をcutにするには以下のように指定してやります。
指定できる属性名については[https://material.io/develop/android/theming/shape](https://material.io/develop/android/theming/shape)に載ってます。

```xml
<style name="mixImageView" parent="">
    <item name="cornerFamilyTopLeft">rounded</item>
    <item name="cornerFamilyBottomRight">cut</item>
    <item name="cornerSizeTopLeft">28%</item>
    <item name="cornerSizeBottomRight">24%</item>
</style>
```

<img width="30%" alt="mix.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658739/08dc68b4-cc28-9b3f-e271-11b3b9d4e418.png">

手軽に真ん丸や角丸などの画像を作成できました！
以上です。

## 参考にしたサイト

[How to use the ShapeableImageView](https://gist.github.com/gabrielemariotti/446c63ea2aed81aafc0bdec1488e27c9)

[Material Components: ShapeableImageViewで丸く切り抜かれた画像を表示する](https://satoshun.github.io/2019/12/material-shapeable-image-view/)

[^1]: [ImageViewを丸くする](https://qiita.com/furusin_oriver/items/16222897fac2b6a1496c)

[^2]: [AndroidのCardViewを使って画像を丸くする](https://hikoleaf.hatenablog.jp/entry/2020/04/18/202715)
不要になったUserDefaultsキーの管理方法

## UserDefaultsについて
「ある画面を表示したかどうか」などの情報をアプリに保存する場合、UserDefaultsを利用する機会が多いと思います。
UserDefaultsを利用して値を保存することに目を向けがちですが、アプリ開発では機能追加だけでなく、利用しなくなった機能を削除することももちろんあります。
その際に機能を削除する際に不要となるUserDefaultsのキーを適切に扱わなければ、同一のキーを利用して意図しない動作につながってしまうケースがあります

この記事では既存の不要となったキーの管理方法についてまとめ、新しい管理方法についてまとめたものとなります。

## 既存の管理方法
### 1. キーごと削除する
不要となったキーを削除するパターンです。もし別の機能開発で全く同じキー名が利用されるケースがあった場合、未然に防ぐことができなくなるためあまりおすすめはできません。

### 2. prefix / suffix
利用していないキー名にprefixやsuffixを加えることで管理するパターンです。
利用されていないキーが明示的にはなりますが、キー名が増えてくると行数が増え見通しが悪くなります。
また、`Active Compilation Conditions`を利用して、`Release`ビルドでは含めないなどを設定しないとdeprecatedなキーが成果物に含まれてしまいます。

```swift
static let isHoge = "isHoge"

// deprecated keys
static let deprecated_isFoo = "isFoo"
.
.
.
```

### 3. コメント化
使用されなくなったキーをコメントで管理するパターンです。
筆者はこのパターン方法で管理したことはないですが、コメントで管理することで視認性が落ちるのが気になります。

```swift
static let isHoge = "isHoge"

// deprecated keys
// static let isFoo = "isFoo"
.
.
.
```

他にもこんな風に管理しているなどがあれば教えていただけるとありがたいです:bow:

## どのような管理方法が理想か
上記のような管理方法を洗い出し、以下の用件が満たせていれば理想だと考えました。

1. どのキーが使用されなくなったかがわかる状態
2. 使用されいているキーと不要なキーの管理が分離されている
3. 既に利用していないキー名を再度利用しようとした場合、ビルド時にエラー検知

## 新しい管理方法
ドットファイルとスクリプトで管理するパターンを考えてみました。

- 使用しなくなったキー名を`.unused_userdefaults_key`で管理
- buildPhaseでスクリプトを実行し、使用していないキーを利用する場合エラーを出力


### 1. ドットファイルを用意
使用しなくなったキー名をまとめた`.unused_userdefaults_key`を用意します

```.unused_userdefaults_key
is_hoge
is_foo
```

### 2. スクリプトファイルを用意
キーをまとめたswiftファイルを引数として、`.unused_userdefaults_key`と一致するものが含まれていればエラーを出力するスクリプトを用意します


```unused_userdefaults_key.sh
#!/bin/sh
file_path=$1
index_array=`cat -n ${file_path}| nl -nln | grep -f .unused_userdefaults_key | cut -d " " -f1`

if (( ${#index_array[@]} )); then
  for i in ${index_array[@]}
  do
    echo "${file_path}:${i}:0: error: It's a key name that's already in use."
  done	
  exit 1
fi
```

### 3. Build Phasesに組み込み
`unused_userdefaults_key.sh`をBuildPhasesで実行するようにします
![Screen Shot 2020-08-09 at 16.27.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116582/d9441e46-9e80-5076-e2e2-4a51b2c5ea91.png)


### 動作GIF
[SwiftyUserDefaults](https://github.com/sunshinejr/SwiftyUserDefaults)を利用した場合の動作GIFです。
![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116582/ac3b124e-8085-133b-bc16-b6e4ee29a884.gif)


GitHubにもプロジェクトを公開しているので、興味がある人は確認してみてください。
GitHub: https://github.com/funzin/UnusedUserDefaultsKeyExmaple

## まとめ
不要となったUserDefaultsキーの管理方法についてまとめてみました。
削除したキーが復活して事故を防ぐには有効だと思いますので、ぜひ参考にしてもらえるとうれしいです。
execでSQLが実行できない→半角スペースが原因だった(PHP+MySQL)

#execでSQLが実行できない

PHPの勉強をしていてデータベースには接続されているのにSQLが実行できないという不具合がありました。

###原因は半角スペース！

【間違ったソースコード】

```php
<?php
  try{
    $db = new PDO('mysql: dbname=mydb; host=127.0.0.1; charset=utf8',
      'root', '');
}catch(PDOException $e){
  print('DB接続エラー：'.$e->getMessage());
}

  $count = $db->exec('INSERT INTO .........');
  print($count.'件数のデータを挿入しました');
```

SQLが実行できたソースコード

```php
<?php
  try{
    $db = new PDO('mysql:dbname=mydb; host=127.0.0.1; charset=utf8',
      'root', '');
}catch(PDOException $e){
  print('DB接続エラー：'.$e->getMessage());
}

  $count = $db->exec('INSERT INTO .........');
  print($count.'件数のデータを挿入しました');
```


お気付きになりましたでしょうか？


mysql:の後の半角スペースが原因でした。
プログラミングを学び始めて約半年。
未だに見やすさのために半角スペースを入れても良い場所とそうではない場所との区別があやふやなことに気付きました。

半角スペースを入れても良い場所などのルールについて学べるサイトなどありましたらぜひ教えてください。
Pandas個人的注意点まとめ

##概要

自分用に使っていて注意したほうがいい点をまとめる。
順次追加予定。

###indexの型に関して

CSVの読み込み時index_colを利用するとindexの型はdtypeの指定とは別に
自動で決定されてしまうようだ。

```python
import pandas as pd

# 例) input.csv
#ID,param1,param2
#0001,01,AAA
#0002,02,BBB
#0003,10,CCC

df = pd.read_csv("input.csv", dtype=object, index_col="ID")
#型をobjectに指定しているがindexだけはint型となってしまい
#先頭の0が抜け落ちてしまう
```

型を保持するためにはindexの指定を後から行う必要があるようだ。

```python
df = pd.read_csv("input.csv", dtype=object)
df.set_index("ID", inplace=True)
#これで元のデータのまま保持できる
```
いまさら聞けない Jupyter NotebookをWindowsで開けなくなった時のメモ

WindowsでAndaconda Nabigatorを使ってJupyter Notebookを開くとき，
Version upによる影響かわからないが，開けなくなった．

Jupyter NotebookのBatファイルのディレクトリにあったerror.txtファイルの

[C 16:33:17.925 NotebookApp] Bad config encountered during initialization:
[C 16:33:17.925 NotebookApp] The 'contents_manager_class' trait of a NotebookApp instance must be a subclass of 'notebook.services.contents.manager.ContentsManager', but a value of class 'dict' (i.e. {}) was specified.

をコピペして，原因を調査したところ，全く同じエラーが２０１５年ごろ言及されていた．

解決策は
「
１．管理者としてcmdを開く
２．jupyter notebook --config=/home/john/mystuff/jupyter_notebook_config.json と入力．

注意: 上記スクリプトを実行する前に、AnacondaとJupyter Labをアンインストールし、C:/ドライブ内のすべてのファイルを削除する必要があることを確認してください。
そして、最新のPython3をインストールし直し、環境パスを正しく追加/設定し、C:/User/.../Pythonではなく、C:/PythonのメインルートフォルダにPyhonを作成することが推奨されていますが、Jupyterノートブックをインストールする必要があります。

jupyter_notebook_config.pyが見つからないことがあります。 jupyter_notebook_config.pyを作成するには、pythonの.NET Frameworkをインストールした後に、jupyter_notebook_config.pyファイルを作成します。
とすると、以下のようなコマンドラインを使用することができます。
jupyter notebook --generate-config
」

がベストアンサーとなっているっぽい．

指示に従い，Anaconda promptで(コマンドプロンプトでは jupyterなどのバッチファイルを入れていなかったため)入力したところ，改善を確認した．

この程度のerrorはさっさと直したいもの．備忘録として．．．

［参考記事］
https://github.com/jupyter/notebook/issues/274#issuecomment-522808247
【メモ】Dockerでbuildしたら名前をうっかり間違えた時の対処法

# はじめに
せ○ちゃん「カッコつけて、Docker buildしたら名前間違えてたんですよ〜」
小○「な～〜にぃ〜～！？やっちまったな！！！！」

っていう時のメモ。

# 事象
`kmori/myanalysispacks:1.0` というイメージファイルを作ろうとしたらtypoして`kmoro/myanalysispacks:1.0` というものを作ってしまった・・・誰だkmoroって・・・。

```
$ docker build . -t kmoro/myanalysispacks:1.0
（メッセージ省略）
Successfully tagged kmoro/myanalysispacks:1.0
```

# 対処

IMAGE IDをとってきてRepository名を変えた奴をタグ付けしてあげて、古いのを削除するだけ。

下記の要領でIMAGE IDを取得してコピります。

```
$ docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
kmoro/myanalysispacks:1.0    latest              ************        4 minutes ago       ***MB
（以下省略）
```

あとは正しいのを設定後、古いのを削除するだけ。

```
$ docker image tag ************ kmori/myanalysispacks:1.0
$ docker rmi kmoro/myanalysispacks:1.0
```

# 5秒で読み終えられる解説

## image tag

あるタグのイメージを参照して新しいタグを作成するコマンド。
公式リファレンス：https://docs.docker.com/engine/reference/commandline/image_tag/

## rmi
1つないしは複数のイメージを削除するコマンド。
たぶん remove images の略語っぽい。
公式リファレンス：https://docs.docker.com/engine/reference/commandline/rmi/

#  最後に

せ○ちゃん「男は黙って、」
小○「$ docker image tag」
せ○ちゃん「男は黙って、」
小○「$ docker image tag」
せ○ちゃん「あらら～rmi忘れてるじゃんかよ～。」
小○「次！」
gazebo起動時のエラー対策（libcurl: (51) SSL: no alternative certificate subject name matches target host name 'api.ignitionfuel.org'）

gazebo起動時に以下エラーが発生

```
$ gazebo
[Err] [REST.cc:205] Error in REST request
libcurl: (51) SSL: no alternative certificate subject name matches target host name 'api.ignitionfuel.org'
```

以下の通りconfigを修正して解決

```diff:~/.ignition/fuel/config.yaml
-    url: https://api.ignitionfuel.org
+    url: https://api.ignitionrobotics.org
```

# 参考
[SSL: no alternative certificate subject name matches target host name 'api.ignitionfuel.org'](https://answers.gazebosim.org//question/23475/ssl-no-alternative-certificate-subject-name-matches-target-host-name-apiignitionfuelorg/)
【Swift】deinitではwillSet/didSetが呼ばれないというお話


# 結論

init/deinit内でプロパティに代入を行っても、willSet/didSetは呼ばれないので注意しましょう。
ただし、スーパークラスのプロパティのwillSet/didSetは呼ばれるようです。

# 公式ガイドの注意書き

公式ガイド（The Swift Programming LanguageのProperties）に、以下のような注意書きがあります。

>NOTE
The willSet and didSet observers of superclass properties are called when a property is set in a subclass initializer, after the superclass initializer has been called. They are not called while a class is setting its own properties, before the superclass initializer has been called.[^1]

[^1]: [The Swift Programming Language - Properties](https://docs.swift.org/swift-book/LanguageGuide/Properties

>注意
サブクラスのイニシャライザ内で、**スーパークラスのイニシャライザが呼ばれた後に**、プロパティがセットされたとき、スーパークラスのプロパティのwillSetとdidSetのオブザーバーが呼ばれます。**スーパークラスのイニシャライザが呼ばれる以前に、自身のプロパティをセットしている間は呼ばれません。**[^2]

[^2]: 太字による強調は訳者による

なるほど。スーパークラスのプロパティのdidSet/willSetについては、サブクラス内のイニシャライザでスーパクラスのイニシャライザを呼んだ後であれば、機能するということらしいです。
クラス自身で定義したプロパティのdidSet/willSetについては、イニシャライザで呼ばれないのは当然だろということか、記述が見当たりませんでした。

# コードで確認

確かにスーパークラスのプロパティのdidSetについては呼ばれました。

```swift
class Animal {
    var age: Int {
        didSet {
            print(#function, age, oldValue)
        }
    }
    
    init(age: Int) {
        self.age = age // -> 呼ばれない
    }
}

class Tiger: Animal {
    var family: String {
        didSet {
            print(#function, family, oldValue)
        }
    }
    
    init(age: Int, family: String) {
        self.family = family  // -> 呼ばれない
        super.init(age: age) // -> 呼ばれない
        
        self.age += 0  // -> didSetが呼ばれる！！
        self.family += "" // -> 呼ばれない
    }
    
    deinit {
        print(#function)
        age = 0 // -> 呼ばれる
        family = "" // -> 呼ばれない
    }
}
```

# どういうときに注意すべき？

例えば、Timerをdeinitでinvalidateしたいときに、以下のような書き方をすると呼ばれないので注意しましょう。

```swift
class ViewController2: UIViewController {
    var timer: Timer? {
        willSet {
            timer?.invalidate()
        }
    }
    
    deinit {
        timer = nil // nilを代入してもwillSetは呼ばれない！
        // -> timer?.invalidate()
    }
    ...
}
```

# 参考

[Swiftでdeinit時にメンバ変数(property)のdidSetが呼ばれない気がした](https://tech-blog.sgr-ksmt.org/2017/03/09/deinit_didset/)
[Can I use didSet in deinit?](https://stackoverflow.com/questions/52820629/can-i-use-didset-in-deinit)
AWS EC2 Linuxにオプションモジュールをインストール

# 症状
WordPressの管理者画面のサイトヘルスに「1件の致命的な問題」が出てる＞＜
内容は、以下の通り。
> **1つ以上の必須モジュールが存在しません** 
PHP モジュールはサイトの稼働に必要なほとんどのタスクをサーバー上で実行します。変更はサーバー管理者が実施する必要があります。
- オプションのモジュール dom がインストールされていないか、無効化されています。
- オプションのモジュール mbstring がインストールされていないか、無効化されています。
- オプションのモジュール imagick がインストールされていないか、無効化されています。
- 必須モジュール gd がインストールされていないか、無効化されています。

# 環境
- AWS Amazon EC2 Linux 2
- php 7.4.7
- WordPress

# 対処法
上で「インストールされていないか、無効化されています」と言われているものをインストールして、httpd.serviceを再起動する。

```
$ sudo yum install -y php php-dom
$ sudo yum install -y php php-mbstring
$ sudo yum install -y php php-imagick
$ sudo yum install -y php php-gd
$ sudo systemctl restart httpd.service
```

wordpressのダッシュボードに行くと、致命的な問題が消えた。よかったよかった。
Big Sur (Public Beta)で動かないアプリケーションたち

クリーンインストール状態で検証して同様の報告があるもののリスト。
随時更新。

## 動かないっぽい

Karabiner-Element
https://github.com/pqrs-org/Karabiner-Elements/issues/2331
修正のIssueが進んでいるので自前でビルドすればある程度動くかも。

Box Drive (Sync)
https://community.box.com/t5/Desktop-and-Mobile-Forum/MacOS-11-Big-Sur-Beta-Box-drive-crash/td-p/84586
クラッシュする。[有志によるパッチ](https://github.com/slw07g/boxdrive-patch)あり。
[Google Driveでも同様の報告](https://support.google.com/drive/thread/55040500?hl=en)があるのでファイル同期系は怪しそう。

Norton360
https://community.norton.com/en/forums/support-macos-11-big-sur
インストール自体不可能。

## 動いているっぽい

- Edge
- Chrome
- Firefox
- Google 日本語入力
- VSCode
- Filezilla
- VirtualBox
- Docker Deskotop
- MySQL Workbench
- homebrew
- Photoshop ( & CC )
- Slack
- Kindle
- Spotify
PubSubパターンメモ

# メモ元
https://micro-frontends-japanese.org/

# Publisher

```typescript
class BlueBuy extends HTMLElement {
  [...]
  connectedCallback() {
    [...]
    this.render();
    this.firstChild.addEventListener('click', this.addToCart);
  }
  addToCart() {
    // maybe talk to an api
    this.dispatchEvent(new CustomEvent('blue:basket:changed', {
      bubbles: true,
    }));
  }
  render() {
    this.innerHTML = `<button type="button">buy</button>`;
  }
  disconnectedCallback() {
    this.firstChild.removeEventListener('click', this.addToCart);
  }
}
```

# Subscriber

```typescript
class BlueBasket extends HTMLElement {
  connectedCallback() {
    [...]
    window.addEventListener('blue:basket:changed', this.refresh);
  }
  refresh() {
    // fetch new data and render it
  }
  disconnectedCallback() {
    window.removeEventListener('blue:basket:changed', this.refresh);
  }
}

```