OmniAICreator/Qiita-1.07M huggingface dataset:
M1 MacでDockerのMySQLコンテナが起動しない

## 問題の概要

M1 Macでmysqlのコンテナを起動したところ、下記のエラーが発生しました。

```shell
$ docker-compose up -d
Pulling mysql (mysql:)...
latest: Pulling from library/mysql
ERROR: no matching manifest for linux/arm64/v8 in the manifest list entries
```

## 問題の対処

### 原因

2021/06/30現在、mysqlイメージはM1 Mac(ARM64)向けには利用できないようです。

[Docker Desktop for Apple silicon](https://matsuand.github.io/docs.docker.jp.onthefly/docker-for-mac/apple-silicon/)

> 既知の問題 
> ARM64 アーキテクチャー向けのイメージがすべて利用可能となっているわけではありません。 Intel イメージの実行には、エミュレーションのもとで--platform linux/amd64をつけて実行することが必要です。 特に mysql イメージは ARM64 向けには利用できません。 これに対する当面の対処としては mariadb イメージを利用してください。

### 解決方法

`docker-compose.yml`に`platform: linux/x86_64`を追記したところ、エラーは解消されました。

```yml:docker-compose.yml
version: '3.1'
services:
  mysql:
    image: mysql
    platform: linux/x86_64 # ← 追加する
    environment:
      MYSQL_ROOT_PASSWORD: pass
    # ...
```

## 参考

- [Docker Desktop for Apple silicon](https://matsuand.github.io/docs.docker.jp.onthefly/docker-for-mac/apple-silicon/)
CrystalでC言語のバインディングを自動生成する crystal_lib

Crystal言語には、C言語のライブラリのバインディングを自動生成するツールが存在する。

https://github.com/crystal-lang/crystal_lib

追記：これをさらにラップした libgen というものがあるそうです。この記事ではlibgenは扱いません。

https://github.com/olbat/libgen

crystal_lib の使い方は簡単で、

```
git clone https://github.com/crystal-lang/crystal_lib
cd crystal_lib
shards install
crystal build src/main.cr
```

として実行形式のファイルを作成する。

次に、examplesを参考にして作成したいライブラリのテンプレートを作る。いくつかexampleを貼ります。こんな感じ。

```crystal:lib_event.cr
@[Include("event.h", prefix: %w(event_ EVENT_ Event))]
@[Link("event")]
lib LibEvent
end
```

```crystal:lib_git2.cr
@[Include(
  "git2.h",
  prefix: %w(git_ GIT_ Git),
  import_docstrings: "brief",
)]
@[Link("git2")]
lib LibGit2
end
```

```crystal:lib_ruby.cr
@[Include(
  "ruby/st.h",
  "ruby/ruby.h",
  prefix: %w(rb_ ruby_),
  remove_prefix: false,
)]
@[Link("ruby")]
lib LibRuby
end
```

prefixの指定ができるが、それ以外に自分でfunctionを記述することもできるようだ。

```crystal:libc.cr
@[Include(
  "stdlib.h",
  "sys/types.h",
  "sys/socket.h",
  "netinet/tcp.h",
  "arpa/inet.h",
  "netdb.h",
  "string.h",
  "stdio.h",
  "unistd.h",
  "sys/file.h",
  "dirent.h",
  "sys/stat.h",
  "glob.h",
  flags: "-Dlint",
)]
lib LibC
  AF_UNSPEC = AF_UNSPEC
  AF_UNIX   = AF_UNIX
  AF_INET   = AF_INET
  AF_INET6  = AF_INET6

  SOL_SOCKET    = SOL_SOCKET
  SO_REUSEADDR  = SO_REUSEADDR
  SO_KEEPALIVE  = SO_KEEPALIVE
  SO_LINGER     = SO_LINGER
  SO_SNDBUF     = SO_SNDBUF
  SO_RCVBUF     = SO_RCVBUF
  TCP_NODELAY   = TCP_KEEPALIVE
  TCP_KEEPIDLE  = TCP_KEEPALIVE
  TCP_KEEPINTVL = TCP_KEEPINTVL
  TCP_KEEPCNT   = TCP_KEEPCNT

  # memory
  fun malloc
  fun free

  # socket
  fun freeaddrinfo
  fun gai_strerror
  fun getaddrinfo
  fun socket
  fun socketpair
  fun inet_pton
  fun inet_ntop
  fun htons
  fun bind
  fun listen
  fun accept
  fun connect
  fun gethostbyname
  fun getsockname
  fun getpeername
  fun getsockopt
  fun setsockopt
  fun shutdown

  # string
  fun atof
  fun strtof
  fun strlen
  fun snprintf

  # file
  F_OK = F_OK
  X_OK = X_OK
  W_OK = W_OK
  R_OK = R_OK

  fun access
  fun link
  fun rename
  fun symlink
  fun unlink
  fun flock

  # dir
  fun getcwd
  fun chdir
  fun opendir
  fun closedir
  fun mkdir
  fun rmdir
  fun readdir
  fun rewinddir
  fun glob
  fun globfree

  # env
  # $environ : Void
  fun getenv
  fun setenv
  fun unsetenv
end
```

テンプレートを作成し終わったら、先程生成した実行形式のファイルで読み込む。アウトプットは標準出力なので適宜保存する。

```sh
./main examples/lib_git2.cr > libgit2.cr
```

このバインディング自動生成機能だが、当然完璧ではない。
私の観測した範囲では

* bitfields はうまく変換されない
* alias と type を複数回定義する

のようなことがあった。細かい欠点はともあれ、Crystal言語製作者謹製のライブラリであり、非常に便利であることは間違いないと思います。

この記事は以上です。
ゼロトラストについて説明できるように調べた内容

###ゼロトラスト
このキーワードを聞くようになって、約1年ぐらいが過ぎたなぁと感じております。
私自身、業務をしていて耳にすることは多いのですが、この言葉が意味することを正しくは理解しておりませんでした。
今回は、自分への備忘録もかねて、ゼロトラストについて簡単に説明をしたいと思います。

<参考：IPA ゼロトラストという戦術の使い方>
https://www.ipa.go.jp/icscoe/program/core_human_resource/final_project/zero-trust.html

####基本的な考え
「全てのデバイス，ユーザ，通信，ネットワークを監視し，認証・認可を行う」
これはどういう意味か。
もう少しブレークダウンすると、

１．モバイル端末、クラウドサービス等含めたすべての資産をリソースとみなす
２．アクセス先、アクセス元がどこであろうと必ず認証、認可のステップを踏ませること
３．認証・認可の際は動的なスコアリングを行うこと
４．通信の状態、ふるまい等を検知すること

他にもポイントはありますが、まずは基本的なところのみ。
それぞれ、更に解説していきます。

###１．モバイル端末、クラウドサービス等含めたすべての資産をリソースとみなす
今や企業にとってのIT資産はオンプレミスで所有しているラップトップやサーバだけではなく、モバイルデバイスやクラウドサービスなど多岐にわたっています。それらのすべての資産を把握し、可視化、認証、認可を行っていくことが求められています。

###２．アクセス先、アクセス元がどこであろうと必ず認証、認可のステップを踏ませること
社内、社外からに関わらず、すべてのリソースに対してのアクセスを認証・認可を行います。
例えば、企業で管理する「サーバA」に対してのアクセス時に、イントラからのアクセスであっても、リモートからのアクセスであっても同様に本人認証、認可を行うことが求められます。
これにより、内部不正の防止、外部攻撃者によるリソースへの不正アクセスを防止することにつながります。

###３．認証・認可の際は動的なスコアリングを行うこと
これは２ともつながるお話なのですが、「誰が」「どこに」「どこから」「どのデバイスで」などの要素を組み合わせ、スコアリングすることで認証する・しない、あるいは認証したとしてもアクセスできるリソースを制限するなどの動的なポリシー設定が求められます。
例えば、本人認証は成功していても、アクセス元のアドレスが海外のアドレスとなっているので認証は通さない、デバイスが個人の携帯端末となっているので、ポータルサイトにアクセスはできても、最低限の事務処理しか操作ができない…など、様々な条件に応じて認証・認可を動的に行います。

###４．通信の状態、ふるまい等を検知すること
認証・認可されているから大丈夫、ではなく通信の状態を監視を行うことで、不正な通信を検知、遮断を行う。
例えば、ファイルサーバから大量のデータから持ち出された、特定のリソースに短時間で大量のアクセスが行われた、不正なファイルがダウンロードされた…など、サイバー攻撃、内部不正などにつながるような挙動を検知、防止する、という考えとなります。

###最後に
IPAの、「IPA ゼロトラストという戦術の使い方」は以下の様な文言で締めくくられている。
"ゼロトラストはこれを入れれば良いというものではなく，自社の守るべき資産に合わせリスクをどう考え，
どういった技術を組み合わせて守るのかという大前提の元，今までの「外部から攻撃を受けないために
どうすれば良いか」という考えだけでなく，「外部からの攻撃を受けた後，内部からの攻撃をどう防ぐか」
という考えを加えた言葉だと捉えるのが良い。"

上記の理念に基づくと、ゼロトラストを構成するためのソリューションは非常に多岐に渡っていると考えられます。
今後も、「ゼロトラスト」をキーワードとした技術、ソリューションが増えてくるのではないかと思います。
setter、getterを使った合格、不合格判定プログラム

setter、getterを使った合格、不合格判定プログラムです。
クラス名、変数名は命名規則に反しているのでご了承ください


```Java
//  新規作成  2021/6/30
//  作成者    乃木坂好きのITエンジニア

import java.util.Scanner;

class data_set{

	int data = 0;
	void setData(int a) {
		data = +a;
	}
	int getData() {
		return data;
	}
}

public class problem_pass {
	public static void main(String[] args) {
		data_set obj = new data_set();
		Scanner sc = new Scanner(System.in);
		int pass=0;
		System.out.println("0-100までの数値を入力してください");
		try {
			String line = sc.nextLine();
			pass = Integer.parseInt(line);
		} catch(Exception e) {
			System.out.println("整数値以外は入力しないでください");
			System.exit(1);
		}
		if ((pass <0) || (pass > 100)) {
			System.out.println("数値が範囲外です");
			System.exit(1);
		}
		obj.setData((int)(Math.random()*100));
		int num = obj.getData();
		if (num > pass) {
			System.out.println("合格");
		} else {
			System.out.println("不合格");
		}

	}

}
```
Command lineの基本


```:terminal
#ファイルの作成
∼$　touch ファイル名

#ファイルの中身を確認する(conCATenate)
∼$　cat ファイル名

#ディレクトリを作成する(make directory)
∼$　mkdir ファイル名

#ディレクトリを移動する(change directory)
∼$　cd ディレクトリ名
#一つ親のディレクトリに移動する
∼$　cd ..
#ホームディレクトリに移動する
∼$　cd

#カレントディレクトリを表示する(print working directory)
∼$　pwd
#*ルートからカレントディレクトリまでの階層が表示される

#ディレクトリの中身を表示する(list)
∼$　ls
#*一つ子の階層だけ

#ファイルを移動させる(move)
∼$　mv 移動させたいファイル名　移動先のディレクトリ名
#ファイル名を変更する
∼$　mv 現在のファイル名　新しいファイル名
#ディレクトリ名を変更する
∼$　mv 現在のディレクトリ名　新しいディレクトリ名

#ファイルのコピー(copy)
∼$　cp コピーするファイル名　新しいファイル名
#ディレクトリごとコピーする
∼$　cp -r コピーするディレクトリ名　新しいディレクトリ名

#ファイルの削除(remove)
∼$　rm 削除するファイル名
#ディレクトリごと削除する
∼$　rm -r ディレクトリ名
```

＊補完機能、Tabキーを押すことで残りのファイル名を補完してくれる
＊↑で入力したコマンドを選択できる
＊control + c で終了
＊困った時は[exit]と入力し、[enter]キーを押す
AWSの監視通知3パターン

# AWSのCloudWatchの監視通知3パターン
Cloudwatchの監視はメトリクス・ログ・イベントがあるので、それそれの監視から通知の方法を記載します。

| Cloudwatch | 概要 | 通知の仕組み |
|:-:|:-:|:--|
| メトリクス | CPUやメモリなどのメトリクスを監視することが出来る。想定メトリクスを超えた際にアラート通知をすることができる。  | Cloudwatch alarm　⇨　SNS　⇨　Chatbot  |
| ログ | アプリケーションやRDSのログを監視してエラーログを通知することができる。  | Cloudwatch logs metrics filter　⇨　SNS　⇨　Lambda |
| イベント | ECSのステータス監視から停止などのステータスをイベントとして通知することができる。  |  Cloudwatch event　⇨　SNS　⇨　Lambda |

## メトリクス
メトリクスはAWSが自動で取得してくれているメトリクスで事足りることも多いかと思いますが、ECSやEC2に対してカスタムで監視設定を行う場合もあるかと思います。

自身の備忘録ですが、
プレビューが多ければ、作り方も記載しようと思います。
unity5.2の作法 その11 zundoko

#概要

unity5.2の作法、調べてみた。
zundokoやってみた。

#makefile

- menu->file->new sceneする。
- menu->file->save sceneでtokeiとする。
- menu->gameobject->create emptyする。
- menu->assetes->creates->c# scriptでtokei.csつくる。
- ダブルクリックして、コードを書く。
- ヒエラルキーのgameobjectに、コードを重ねる。
- 三角で実行。

#サンプルコード

```
using UnityEngine;
using System.Collections;

public class zundoko : MonoBehaviour {
    string res = "";
	void Start () {
	}
	void Update () {
	}
    void OnGUI() {
        GUI.color = Color.yellow;
        GUI.Box(new Rect(10, 10, 50, 30), "zundoko");
        if (GUI.Button(new Rect(100, 10, 50, 20), "run"))
        {
            res = "";
            int a = 0;
            int b = 0;
            Random r = new Random();
            do
            {
                if (a == 0)
                {
                    b++;
                }
                else
                {
                    b = 0;
                }
                //a = r.Next(2);
                a = Random.Range(0, 2);
                if (a == 0)
                {
                    res += "ズン ";
                }
                else
                {
                    res += "ドコ ";
                }
            } while (!(a == 1 && b > 4));
            res += "キ・ヨ・シ！！";
        }
        GUI.Label(new Rect(10, 80, 400, 400), res);
        
    }
}



```

以上。
unity5.2の作法 その10 アナログ時計

#概要

unity5.2の作法、調べてみた。
時計やってみた。

#makefile

- menu->file->new sceneする。
- menu->file->save sceneでtokeiとする。
- menu->gameobject->create emptyする。
- menu->assetes->creates->c# scriptでtokei.csつくる。
- ダブルクリックして、コードを書く。
- ヒエラルキーのgameobjectに、コードを重ねる。
- 三角で実行。

#サンプルコード

```
using UnityEngine;
using System.Collections;

public class tokei1 : MonoBehaviour {
    private Transform hours,
        minutes,
        seconds;
    private const float
        hoursToDeg = -360f / 12f,
        minutesToDeg = -360f / 60f,
        secondsToDeg = -360f / 60f;
    void Start() {
        CreateCamera(0f, 0f, -5f);
        CreateLight(0f, 0f, -5f);
        var tex1 = CreateTextureByColor(Color.blue);
        var tex2 = CreateTextureByColor(Color.red);
        var tex3 = CreateTextureByColor(Color.green);
        hours = CreateHand(0f, 1.0f, 1f, 0.5f, 2.0f, tex1);
        minutes = CreateHand(0f, 1.5f, 0.9f, 0.25f, 3.0f, tex2);
        seconds = CreateHand(0f, 2.0f, 0.8f, 0.1f, 4.0f, tex3);
    }
    void Update() {
        var now = System.DateTime.Now;
        hours.localRotation = Quaternion.Euler(0f, 0f, now.Hour * hoursToDeg);
        minutes.localRotation = Quaternion.Euler(0f, 0f, now.Minute * minutesToDeg);
        seconds.localRotation = Quaternion.Euler(0f, 0f, now.Second * secondsToDeg);
    }
    private Camera CreateCamera(float x, float y, float z) {
        var cam = new GameObject().AddComponent<Camera>();
        cam.name = "Camera";
        cam.clearFlags = CameraClearFlags.SolidColor;
        cam.backgroundColor = Color.gray;
        cam.nearClipPlane = 0f;
        cam.farClipPlane = 10f;
        cam.orthographic = true;
        cam.orthographicSize = 5f;
        cam.useOcclusionCulling = true;
        return cam;
    }
    private Light CreateLight(float x, float y, float z) {
        var light = new GameObject().AddComponent<Light>();
        light.name = "Light";
        light.type = LightType.Directional;
        light.transform.position = new Vector3(x, y, z);
        return light;
    }
    private Texture2D CreateTextureByColor(Color c) {
        var tex = new Texture2D(1, 1, TextureFormat.ARGB32, false);
        tex.SetPixel(0, 0, c);
        tex.Apply();
        return tex;
    }
    private Transform CreateHand(float x, float y, float z, float w, float h, Texture2D tex) {
        var cubeTrans = GameObject.CreatePrimitive(PrimitiveType.Cube).transform;
        cubeTrans.localPosition = new Vector3(x, y, z);
        cubeTrans.localScale = new Vector3(w, h, 0.01f);
        var mr = cubeTrans.GetComponent<MeshRenderer>();
        mr.material.mainTexture = tex;
        var container = new GameObject();
        container.name = "Hand";
        cubeTrans.parent = container.transform;
        return container.transform;
    }
}




```

以上。
unity5.2の作法 その9 時計

#概要

unity5.2の作法、調べてみた。
時計やってみた。

#makefile

- menu->file->new sceneする。
- menu->file->save sceneでtokeiとする。
- menu->gameobject->create emptyする。
- menu->assetes->creates->c# scriptでtokei.csつくる。
- ダブルクリックして、コードを書く。
- ヒエラルキーのgameobjectに、コードを重ねる。
- 三角で実行。

#サンプルコード

```
using UnityEngine;
using System.Collections;

public class tokei0 : MonoBehaviour {
	void Start () {
	}
	void Update () {
	}
    void OnGUI() {
        string res = "";
        res = System.DateTime.Now.ToString("HH:mm:ss");
        GUI.color = Color.yellow;
        GUI.Label(new Rect(10, 10, 100, 200), res);
    }
}



```


以上。
[JQuery] アップロードしたときにファイルの名前を取得する

## はじめに
inputタグのファイルアップロードの見た目って一辺倒で味気ないなと思ったので自作で作ってみることにしました。
![スクリーンショット 2021-06-29 0.28.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/4e7e00d9-e646-2a07-b2a1-e75d98d1dbb1.png)

最終的にはこんな感じになります

![スクリーンショット 2021-06-29 0.31.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/991598/dd471064-05e8-59e1-064f-135b35a5a551.png)

FontAwesomeを使ってアレンジしてみました。
アイコンの部分を押すとファイルを画像を選択してアップロードします、そしてアップロードした後にファイル名を表示させます。



## 本題
結論以下のようなコードで実装できます。

```
<span id ="push-image"></span>
<input type="file" class="image" id="upload_file" style="display: none">
<label class="image" for="upload_file" >
  <i class="far fa-image mx-3" aria-hidden="true"></i>
</label>

<script>
$(document).on('change', '.image',function(){
  if ($('.image').prop("files")[0] == null){
    $('#push-image').text("")
  }else{
    $('#push-image').append($('.image').prop("files")[0].name);
  }
});
</script>
```
inputタグのstyleを`display: none`にすることで最初の画像の部分は表示されなくなります。その上でlabelタグを使ってinputと連携しつつアイコン部分を表示しています。

そしてファイルを選択したときにScriptタグの中が実行されて名前を取得して表示することができます。

以上で実装できました！
もっと効率の良い方法などがあればコメントいただければ幸いです

## 参考

http://kachibito.net/snippets/how-to-display-multiple-files-properties-using-jquery
Railsで任意の数のキーワードをOR検索したい、なおかつeachだけでまとめたい

この記事は一旦雑にアウトプットしているので、別途書き直したい

## この記事の内容
eachのみにしたいが、firstが入り込んでしまうのでうーんとなる
初期値にModel.noneを用いることで解消できるという話

## 具体例
愚直に書くとfirstが入り込んでしまう

```User.rb
# @param [Array<String>] words
# @return [ActiveRecord::Relation]
def find_by_keywords(words)
  query = User.where(name: words.first)
  words.each do |w|
    query.or(User.where(name: w))
  end
  query.merge(User.where(is_active: true)) # その他に条件がある場合はmergeすることがある
end
```

eachにすべてまとめてfirstをなくすには、以下のようにnoneを使うと解消できる
※ noneが入ってくることに違和感はある...

```User.rb
# @param [Array<String>] words
# @return [ActiveRecord::Relation]
def find_by_keywords(words)
  query = User.none
  words.each do |w|
    query.or(User.where(name: w))
  end
  query.merge(User.where(is_active: true)) # その他に条件がある場合はmergeすることがある
end
```


## なんでそんなことになるの?
あとで書く

## 備考
状態をもたないActiveRecord::Relationが生成できれば良さそうなので、他にも方法はありそう?
* `query = ActiveRecord::Relation.new` な状態が作れればよいのでは?
よく使うGitコマンドまとめてみた。

**①ローカルリポジトリの新規作成(Git管理をはじめる)**
`$ git init`

**②リモートリポジトリ(GitHub)を新規追加(GitHubと紐付ける)**
`$ git remote add origin https://〜.git`
※Githubでリポジトリを作成しておく
※originというショートカットでurlのリモートリポジトリを登録
→今後はoriginという名前でGitHubリポジトリにアップしたり取得することができる

**③変更をステージに追加する**
`$ git add .`

**④変更を記録する(コミット)**
`$ git commit -m “メッセージ”`
※変更内容を簡潔に書く

**⑤ブランチを作成する**
`$ git branch 〇〇`
※〇〇はブランチ名

**⑥ブランチを切り替える**
`$ git checkhout 〇〇`

**⑦リモートリポジトリ(GitHub)へ送信する**
`$ git push origin 〇〇`
※〇〇はpushするリポジトリ名

**⑧リモートから情報を取得してマージする(プル)**
`$ git pull origin 〇〇`
※〇〇はpullしたいリポジトリ名
※リモートがマージされたら最新の情報をローカルに取り込むこと(pull)を忘れないように。
ローカルで開発中のページをhttpsでスマホからも見る

やり方が分かったので、とりあえず忘れないうちにメモ。

## サーバの設定

laragon をインストール。下記は chocolatey を使った場合。

```ps:chocolatey
cinst -y laragon
```

Laraon を起動し、Preferences の General より`Document Root`を設定し、`Auto Virtual hosts`のチェックをオンにする。
<img width="935" alt="image.png (110.5 kB)" src="https://img.esa.io/uploads/production/attachments/16142/2021/06/30/62386/3c9e4614-664a-497c-b51e-5ec67b0ac26d.png">
Servises & Ports の https にチェックを入れる。SSL 証明書発行のために管理者権限を求めてくるので（Windows10 の場合）、随時昇格ダイアログの OK ボタンを押す。

### プロキシサーバの設定
ローカル開発環境の`hosts`に書かれた内容をスマホやタブレットからも参照するため、laragon の中にプロキシサーバも立てる。

laragon の httpd.conf を開く。
<img width="735" alt="image.png (94.8 kB)" src="https://img.esa.io/uploads/production/attachments/16142/2021/06/30/62386/42aab0e3-0732-458c-804f-e830f46ae818.png">

次の3つのモジュールのコメントアウト（先頭の`#`記号）を外す。

```conf:httpd.conf
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so
```

`httpd.conf`ファイルの最後に以下の内容を追加する。

```conf:httpd.conf
<IfModule mod_proxy.c>
  ProxyRequests On
  ProxyVia On
  Listen 8080
  <Proxy *>
    Order deny,allow
    Deny from all
    Allow from all
  </Proxy>
</IfModule>
```

httpd.conf ファイルの編集を保存し、laragon の apache を再起動する。Reload ではなく、一度停止（Stop）から起動させた方ががよさそう。

## スマホ・タブレット側のプロキシ設定
スマホ・タブレット側にプロキシ設定を行うことで、テスト用 PC の`hosts`に書かれているドメイン名で開発中ページを表示することができるようになる。

スマホやタブレットのプロキシ設定を行う。以下は iPhone の例。
サーバ欄にはプロキシサーバにしている PC の IP アドレスを入力し、ポート欄には上記設定で`Listen`にある通り`8080`と入力する。

<img width="375" alt="IMG_0043.PNG (72.5 kB)" src="https://img.esa.io/uploads/production/attachments/16142/2021/06/30/62386/6c1e7662-c27a-4691-974c-c2e7d05635f8.PNG">

以上でプロキシ設定を行ったスマホやタブレットや別 PC などからも`https://プロジェクトディレクトリ名.test/`でアクセスできるようになる。

## 注意
プロキシ設定中はインターネットやほかの PC へアクセスできなくなるかもしれない。（未検証）
また、プロキシサーバ設定はセキュリティを何も考えていないので、プロキシサーバを立てたまま公共的なネットワークに接続しないようにすること。

iPhone や iPad でアクセスするとオレオレ証明書に反応して警告画面が表示されるが、何度か「表示」や「進む」などのリンクやボタンを押せば開発中ページが表示されるようになる。
Vim patchダイジェスト [2021/05]

[Vim](http://www.vim.org/)のリリースされた[patch](https://github.com/vim/vim/commits/master)の説明です。
([8.2.2821](https://github.com/vim/vim/commit/3d0e7a956afb6f913466e96bd462eff0c92ad4c6) ～ [8.2.2918](https://github.com/vim/vim/commit/3d9c4eefe656ee8bf58c0496a48bd56bac180056))
**新機能、大幅な仕様変更には、:four_leaf_clover:が付いています。**
Vim9 scriptの実装/仕様変更/不具合修正も頻繁におこなわれています。

* [8.2.2914](https://github.com/vim/vim/commit/2fa9384ca1b600b934bec81a72c5fb7ce757503a): :four_leaf_clover:ノーマルコマンド `zp`および`zP`を追加しました。`p`および`P`と同じですが、矩形ビジュアルモードでヤンクしたテキストブロックをペーストするときに末尾のスペースを追加しません。(関連patch: [8.2.2933](https://github.com/vim/vim/commit/6e0b553fa12fc5ad5d8ee3d8457e7cb16f38b56f))
* [8.2.2912](https://github.com/vim/vim/commit/f883d9027c750967b115b82de984ee449ab17aa8): :four_leaf_clover: Windows: `'encoding'`のデフォルト値を`utf-8`にしました。(関連patch: [8.2.2915](https://github.com/vim/vim/commit/ef8706fb84cfe8bd58b1b26b0742e42caf09655b))
* [8.2.2891](https://github.com/vim/vim/commit/543467136f001708f4c63376ac5d18adde82db30): if_perl: Perl 5.34 でビルドできない件を修正しました。
* [8.2.2876](https://github.com/vim/vim/commit/23c0192166760b0d73bd39252ca72e3cfe596f6e): if_python3: configureがPython 3.10を検出できない件を修正しました。
* [runtimeファイル更新](https://github.com/vim/vim/commit/3ec3217f0491e9ba8aa8ea02f7e454cd19a287ef): [Todo](https://github.com/vim/vim/commit/3ec3217f0491e9ba8aa8ea02f7e454cd19a287ef#diff-fb7eed53e3f2993f9d82c748206eaca82fd1d054a417c6de477bb54373d85643)更新。helpファイル更新。他。
* [8.2.2854](https://github.com/vim/vim/commit/30e3de21fc36153c5f7c9cf9db90bcc60dd67fb9): :four_leaf_clover:`'statusline'`に`%{% expression %}`を追加しました。expression の結果を statuslineフォーマットの文字列として再評価する以外は`%{ expression }`と同じです。
* [8.2.2830](https://github.com/vim/vim/commit/ad431995721b2a886f789e2ea7db4c84b732eb18): :four_leaf_clover:`'background'`が設定された時に端末の色を更新するようにしました。
* [runtimeファイル更新](https://github.com/vim/vim/commit/4c295027a426986566cd7a76c47a6d3a529727e7): [Todo](https://github.com/vim/vim/commit/4c295027a426986566cd7a76c47a6d3a529727e7#diff-fb7eed53e3f2993f9d82c748206eaca82fd1d054a417c6de477bb54373d85643)更新。helpファイル更新。他。

---
#### 凡例

|表記|意味|
|:------|:------|
|:four_leaf_clover:|新機能、大幅な仕様変更|
|:alien:|Vim開発者向けの追加、変更|
|`'hoge'`|オプション (`:h options`参照)|
|`:hoge`|Exコマンド (`:h :index`参照)|
|`hoge()`|組み込み関数 (`:h functions`参照)|
|`v:hoge`|Vim定義済変数 (`:h v:`参照)|
|`+hoge`|feature (`:h +feature-list`参照)|

---
#### 方針
[こちら](http://qiita.com/h_east/items/23cd0d10932505072e6b#%E6%96%B9%E9%87%9D)を参照。
pipでFatal error in launcher: Unable to create process usingが起きた際に解決した話

# 経緯
Pythonをの環境構築をする必要に迫られた。
以前にPythonの環境構築をしたかもしれないが断念したかもしれないというようなあやふやな状況。
[この記事](https://qiita.com/kerobot/items/3f4064d5174676080585#poetry-%E3%81%AE%E5%B0%8E%E5%85%A5)に従って最新版の3.9系をインストールした。

記事に沿って以下のコマンドを実行した。

```
$>pip install tqdm
```
この時点で

```
PS C:\Users\User> pip install tqdm
Fatal error in launcher: Unable to create process using '"c:\program files\python39\python.exe"  "C:\Program Files\Python39\Scripts\pip.exe" install tqdm': ??????????????????
```
とエラーが出た。
`pip`のコマンドはことごとく同じエラーが起きる。
だけど、以下のように頭に`python -m`をつけると正しく動く。という状況。

```
$>python -m pip list
```
毎度`python -m`をつけるのは不毛なので`pip ○○`で直接実行出来るようにしたくなる。

# 解決（と紆余曲折）
以前Magic Leap Oneの開発をしていた際に、Magic Leap One関連で勝手にインストールされていたPython, pipが存在していて、そのパスがユーザーの環境変数ではなくて、システム環境変数の方に記述されていた。`python -m`なしの直の`pip`コマンドはそっちのpipを実行していたようで、システム環境変数に登録されていたPythonとpipのパスを削除してユーザー環境変数の方に登録されているパスにあるpip（とついでにpython）が実行されるようにしたら解決した。

```
$>gcm pip
```
で`pip`コマンドで実行されるpip.exeのパスが確認できるので、これがユーザー環境変数で指定したパスと違うことが分かりました。
あとはそばにいた方に「システム環境変数にも別のパスが通ってるんじゃない？」と言われ、確認すると`gcm pip`で表示されたパスと同じパスがシステム環境変数に登録されていることが分かり削除し解決に至った。めでたしめでたし。もう僕のPCに一体どれだけのpythonが散在しているのか分からない...
DockerコンテナからホストOSのPostgresにアクセス全開設定にせずにログインする方法

## 概要
[Prometheus](https://qiita.com/Esfahan/items/0feaedfd771f49ac7ee4)で、[postgres-exporter]((https://qiita.com/Esfahan/items/08d0c1ff94710603bac9))のDockerコンテナからホストOS上のpostgresにログインしたかった。

コンテナからアクセスするとlocalhostからのアクセスにならないので接続拒否される。しかし、Postgresの接続許可設定をallにはしたくない。

そこで、コンテナのIPアドレスを固定し、postgresのpg_hba.confに接続許可設定をすることで通信を可能にした。

## 関連記事
- [[目次] Prometheusで監視システムを作る with Docker](https://qiita.com/Esfahan/items/7dc780501f418a71ad9d)
- [[Prometheus] Postgres Exporter with Docker](https://qiita.com/Esfahan/items/08d0c1ff94710603bac9)

## docker-compose.yaml
postgres-exporterコンテナからホストOSのpostgresにパスワードログインさせる。

Docker networkを作り、各コンテナにipv4_addressを割り当てるころでIPアドレスを固定。
postgres-exporterコンテナで `host.docker.internal:host-gateway` を渡し、コンテナからlocalhostへのアクセスを可能にする。

exporter_proxyコンテナは今回は関係ないが、他のコンテナのIPアドレスも固定する例として記載した。

詳しく知りたい方はこちらを参照。
[[目次] Prometheusで監視システムを作る with Docker](https://qiita.com/Esfahan/items/7dc780501f418a71ad9d)

```yaml:docker-compose.yaml
version: '3'
services:
  # ホストOSのpostgresに接続するコンテナ
  postgres-exporter:
    container_name: quay.io/prometheuscommunity/postgres-exporter
    image: postgres-exporter
    hostname: postgres-exporter
    # ホストOSのlocalhostへ接続するための設定
    extra_hosts:
      - "host.docker.internal:host-gateway"
    # postgresへの接続情報（後述）
    env_file:
      - ./postgres-exporter/.env
    ports:
      - 127.0.0.1:9187:9187
    restart: always
    # IPアドレスの固定化
    networks:
      sample-network:
        ipv4_address: 192.168.200.2

  exporter_proxy:
    image: rrreeeyyy/exporter_proxy
    container_name: exporter_proxy
    volumes:
      - ./exporter_proxy/config:/config
    ports:
      - 9099:9099
    entrypoint: ['/exporter_proxy', '-config', '/config/config.yaml']
    restart: always
    networks:
      sample-network:
        ipv4_address: 192.168.200.3

# ネットワークを作成し、必要なIPアドレスの数だけサブネットを切る。
networks:
  sample-network:
    ipam:
      driver: default
      config:
        # 16個
        - subnet: 192.168.200.0/28
```

## ./postgres-exporter/.envの設定
postgres-exporterコンテナに設定した `host.docker.internal` がlocalhostの意味になるので、ホスト名はこれにする。

```ini:.env
DATA_SOURCE_NAME=postgresql://postgres_exporter:password@host.docker.internal:5432/postgres?sslmode=disable
```

## pg_hba.conf
ホストOSのpg_hba.confに以下を追記する。
192.168.200.2（postgres_exporterコンテナ）から、postgres_exporterユーザーが、postgresデータベースに接続する設定。

```conf
# TYPE  DATABASE        USER          ADDRESS               METHOD
host    postgres   postgres_exporter      192.168.200.2/32       md5
```

postgresの再起動をして反映させる。これでアクセス可能となる。

## 参考
- [[Docker / Docker Compose] コンテナのIPアドレスを固定する方法](https://zaki-hmkc.hatenablog.com/entry/2021/02/26/234357)
長い文字列を省略してレイアウト崩れを防ぐ... truncateメソッド

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111652/f89d3fe1-19d2-8882-75e2-3d8638216788.png)


## はじめに
Railsのアプリケーションでデータベースからeachメソッドを使い表で一覧表示する画面を作成しました。
通常のレイアウトはこんな感じ。

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

しかし、長い文字列になった場合に２行になってしまいレイアウトが崩れてしまいました。

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

文字を小さくしてHTMLやCSSをいじって横並びにするということも考えましたが、
それだと見づらくなってしまいます。

そういえばよく**`今日はいい天気だった。そこで...`**みたいなの見るけど出来ないのかなと調べたらありました。
その名は**`truncateメソッド`**。


## truncateメソッド
truncateメソッドはActiveSupportによって使えるメソッドです。

```ruby
"我々は地球人だ。我々は宇宙人だ。我々は未来人だ。我々は原始人だ。".truncate(20)
# => "我々は地球人だ。我々は宇宙人だ。我..."
```

```ruby:trancateメソッドの使い方（デフォルト）
"省略したい文字列".trancate(文字列の数）
#または
@インスタンス.trancate(文字列の数）
```


### オプション
|オプション|説明|
|:-------|:---|
|length:|表示させる文字数を設定|
|omission:|省略された文字列の後ろにつける文字列を設定|
|separator:|切り捨てる箇所を指定することができる|

#### ●lengthオプション
trancateの`( )`に数を入れて表示させる文字列の数を指定します。
注意しなければいけないのが上の例を見て数えてみるとわかりますが、２０と指定したはずなのに
１７しか表示されていません。
そう、**`...`も含んでの数なんです。**

なので、何文字表示させるかは`...`を考えて設定する必要があります。

#### ●omissionオプション
omissionオプションは省略された文字列の後につける`...`などの文字列を指定することができます。
デフォルトでは**`...`**が表示されます。

```ruby:omissionオプション
"我々は地球人だ。我々は宇宙人だ。我々は未来人だ。我々は原始人だ。".truncate(20, omission: "~~~")
# => "我々は地球人だ。我々は宇宙人だ。我~~~"

#ちなみにomission: "~"とした場合は

"我々は地球人だ。我々は宇宙人だ。我々は未来人だ。我々は原始人だ。".truncate(20, omission: "~")
# => "我々は地球人だ。我々は宇宙人だ。我々は~"
```

#### ●separatorオプション
separatorオプションを使うと切り捨てる箇所を指定することができます。
どういうことかというと、**`我々は未`**みたいな中途半端なところで文字列が切れるの防いでくれます。

例えば

```ruby:separatorオプション
"我々は地球人だ。我々は宇宙人だ。我々は未来人だ。我々は原始人だ。".truncate(20, separator: "我")
=> "我々は地球人だ。我々は宇宙人だ。..."

#オプションなしだと

"我々は地球人だ。我々は宇宙人だ。我々は未来人だ。我々は原始人だ。".truncate(20)
=> "我々は地球人だ。我々は宇宙人だ。我..."
```

こんな違いが出ます。
ちなみにseparatorオプションは正規表現も使えるようです。
Railsガイドより引用。

```ruby:separatorオプション正規表現
"Oh dear! Oh dear! I shall be late!".truncate(18, separator: /\s/)
# => "Oh dear! Oh..."
```

この場合は空白文字のところで区切っていますね。


今回解説したのはActiveSupportのtruncateメソッド。
似たような感じのTextHelperとしてのtruncateがあるらしいです。

よく使いそうなのはActiveSupportの方かなあ。
使ってみたらまとめてみます。

それでは良いRailsライフを。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111652/292a1e90-43fc-0c66-7a9d-e6e163cf1686.png)


> 参考サイト

- [Qiita　Rails - 長い文字列を省略して表示する](https://qiita.com/ishidamakot/items/2e74d980b3a338e4c784)
- [TechTechMedia　文字列を省略して表示することができるtruncateメソッドについて](https://techtechmedia.com/truncate-rails/)
- [Railsガイド ActiveSupport](https://railsguides.jp/active_support_core_extensions.html#truncate)
ベトナムオフショア会社の選び方 2021

## ベトナムを取り巻く現状

ベトナムオフショアは、中国・インドオフショアの価格高騰に伴い栄えてきた。しかしながら、コロナ禍でもGDPプラス成長に見られるように、ベトナム経済は成長し続け、価格も上がってきている。ベトナムの経済成長は、2050年まで続くと言われている。ベトナムから見ても、利益率の低い海外からの受託案件よりは、急速に成長する国内市場に目を向けた方がリターンが高いことは明白であり、ビジネスとして旨味がない。ベトナムはいままさに転換期を迎えている。ように感じる。

これまで安さとのトレードオフであった品質・技術力に関して、いままで以上にきちんと評価しなければならなくなっている。

実際に仕事をしてみるのが一番だが、そんな事しなくても、ある程度は評価できる。割と正確に。

## 評価を見誤る典型的パターン

初めに、アンチパターンから。

### 実績による評価

稟議を通す際に、会社の実績というのは強力な判断軸となるが、実際問題として、実績は技術力の評価にはならない。それどころか、特定技術・特定サービス特化型の会社は、ビジネスモデルの融通が効きづらく、むしろ技術力が低いことが多い。その上、ベンダーロックインされやすい。最悪である。

例えばある特定分野や技術に実績があることは、ないよりは信頼がおけるが、過信するのは危険である。理由は単純で、人の入れ替わりが激しいから。ベトナムでは1.5〜3年程度で人は辞める。実績を見るのであれば、直近の実績を評価するのが良い。また CI/CD など、どのように実績を会社に蓄積しているのかを併せて評価すべきである。

### Manager による Manager の評価

発注する場合や買収する場合の事前ヒアリングは、現場の人間を抜きに行われることが多い。出す側の Manager が受ける側の Manager をヒアリングして分かった気になる。経営企画部長と事業部長、CTO が社長、役員、Tech Manager 等にヒアリングする。これで分かるのは、会社の Attitude や方向性だけであると言って過言でない。もちろん、それは大事なことだが、技術力評価にはならない。

どちらの評価も不要とは言わないが、これらだけで評価してしまうと失敗することが多い。そして残念ながら、これらだけで評価してしまう会社は極めて多い。評価に失敗した責任は、現場に降り注ぐ。いますぐ転職すべき。

では、どのように評価するか？

## SE の提供単価

2021年時点では、一般的なアウトソーシングの会社において、SE は 4,000 USD/月、BSE, LSE は 6,000 USD/月程度がまともな Pricing である。これは SE の給与相場、オフィス賃料相場、税率等から計算できる。前述の通り、受託開発は利益率が低い。この単価で出せる利益は SE 一人あたり月々 200〜300 USD 程度。これより提供単価が低い場合、何らかのからくりがあるか、SE の給与が低い（=スキルが低い or/and モチベーションが低い）のいずれかで、概ね後者。

この単価より高い会社は技術力が高いという評価には必ずしもならないが、著しく安い会社は技術力が低いと考えて間違いない。掘り出し物はない。会社規模等にもよるが、プラスマイナス200USDくらいが限度だろうか。なお、会社規模が100人未満の会社は、配賦効率が悪い。

詳細は、財務諸表を確認しチェックすべきだが、現場の人間にその機会があることは稀で、また、意思決定者がキックバック等で抱き込まれている可能性もある。しかし、財務諸表などなくとも、何か怪しいぞ、くらいまでは分かるし、その感覚はだいたい正しい。


## 信頼できる PM がいるか

現場に立つ PM が信頼できるのであれば、大きな問題は起こらない。ことが多い。品質・技術力に関しては、その PM がエンジニアとして信頼できる場合、それだけで高評価をしてしまって差し支えない。結局のところ、現場で責任を持つ人次第なのである。

ここでポイントとなるのは、その人が現場にいることと、エンジニアか否かではなくエンジニアとしての経験が豊富かという点。エンジニア以外の PM を否定したりはしないが、問題への対応に PM が技術的アプローチを取れるか？というのは、会社・チームとしての技術力に大きく貢献する。

知り合いがいない、という場合、人材紹介会社に聞くのが早い。現地人材紹介会社に知り合いなどいないことが多いと思うが、日系の人材紹介会社はたくさんある。日本でお世話になっている人材紹介会社の現地法人とアポを取るのは、やろうと思えばそんなに難しくない。人材紹介会社が他社に悪評を流すことはまずないが、信頼に足る人財がいるかどうかについては、教えてくれるだろう。


## Comtor

案件に関わる日本語人材は大きく分けて2種類いる。ブリッジSE（BSE）とコミュニケーター（Comtor）。BSE は日本語が喋れるSEで、Comtor は、SE ではないが日本語が喋れる通訳だ。BSE や Comtor の評価は、日本語能力はもちろんのこと、どちらかと言えば文化理解力や間違いなく伝えるための技術などが重要な評価軸となるが、会社の技術力評価ではその点は見ない。

BSE は技術知識があるが、Comtor には（基本的には）ない。Comtor の理解する技術用語は、普段案件で触れている技術に限定される。つまり、Comtor を介してエンジニアと話をすると、普段どんな技術に触れているか、何ができて何ができないのか、一目瞭然。一耳瞭然か。エンジニアからの話を通訳してもらう必要はない。こちらから技術的な話をし、それを翻訳してもらうだけで良い。スムーズさ、空気感、それでだいたい分かる。多くの場合、これを Comtor の能力の問題としてしまうが、それは完全な誤りである。Comtor は、会社を映し出す鏡なのである。

協力してもらう Comtor は、なるべく長くその会社にいる、できれば女性の Comtor が良い。

## まとめ

という訳で、提供単価でフィルター、PM と Comtor を見ることで、おおよその品質・技術力の評価をすることができる。そのうえで、直近の実績、経営層の評価などを併せ決断するのが良い。提供単価は2年周期くらいで上がることが多いが、必ず上がるため、4,000USDというのは2021年の単価。4,000USDを大きく超える場合、品質や技術力以外の Value があるものと思われるため、それが見合うかどうかを考える必要がある。

最初に書いた通り、ベトナムはいま転換期にあり、非常に面白い。来るなら今。
Flutter for WebでURLの＃を消す方法

くどい導入は、めんどくさいので書きません笑

使うのは url_strategy というパッケージ
https://pub.dev/packages/url_strategy

サンプルコード

```dart:main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '＃消すサンプル',
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: Text('🧸', style: TextStyle(fontSize: 30),),),
    );
  }
}

```

ではこれを、Chromeでデバッグ表示しましょう

```terminal
flutter run -d chrome --web-renderer html
```
![スクリーンショット 2021-06-30 1.30.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130358/61afd1ba-19d1-f211-5138-ace60c326d59.png)

ちゃんと表示されましたね！嬉しいっ！
でも、、、検索窓を見てください↓
![スクリーンショット 2021-06-30 1.31.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130358/b0c80208-9c20-edea-2def-f00facf598f2.png)
URIに余計な＃がついていますね
これは、Flutter web のデフォルトの設定のようです

では、このハッシュタグちゃんを消しちゃいましょう！
方法は簡単
こちらのパッケージを読み込んで…↓
https://pub.dev/packages/url_strategy

```yaml:pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  
  #to delete hash
  url_strategy: 任意のバージョン

```

メイン関数のrunAppの前に、追加するだけ↓

```dart:main.dart
import 'package:flutter/material.dart';
import 'package:url_strategy/url_strategy.dart';

void main() {
  // ここに追加
  setPathUrlStrategy();
  runApp(MyApp());
}

// 以下同じ
class MyApp extends 
```


コンソールで r　ホットリスタートすると…↓

```terminal
🔥  To hot restart changes while running, press "r" or "R".
For a more detailed help message, press "h". To quit, press "q".

Performing hot restart...                                           3.1s
Restarted application in 3,137ms.
```

ちゃんと消えましたね！↓

![スクリーンショット 2021-06-30 1.39.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130358/fa7afacb-5f9c-3a9b-82f4-9f99b31a73cf.png)


Flutter Web はまだまだ発展途上なので、今後も注視したいです…！

今回のコードはこちら↓
https://github.com/ReiyaMori/flutter_web_delete_hash
Tailwind CSSのpurgeを開発環境でも適用する


## 起きたこと

- Next.js のプロジェクトに Tailwind CSS をインストールした
- 開発環境で Tailwind CSS が適用されていることを確認したので、試しにvercel にデプロイしてみた
- 下の画像のように、見え方に差異が生じていた

| 開発環境 | 本番環境 |
| --- | --- |
| ![スクリーンショット 2021-06-30 0.54.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166596/f1870e97-27cb-82cf-ab8a-e4aa405b6c16.png) | ![スクリーンショット 2021-06-30 0.54.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166596/66a47af8-2dfb-37b3-98d6-04231ef7d352.png) |

## 何が起きていたか

`tailwind.config.js` に記載していた、`purge` の設定が良くない様子。
`purge` は未使用の Tailwind CSS のスタイルを build 時に削除してくれるものです。

```js:tailwind.config.js
module.exports = {
  purge: {
    './components/**/*.jsx',
    './pages/**/*.jsx'
  },
  darkMode: false,
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}
```

[ドキュメント](https://v2.tailwindcss.com/docs/optimizing-for-production)を読んでみたところ、下記のように記載されていた。

`Now whenever you compile your CSS with NODE_ENV set to production, Tailwind will automatically purge unused styles from your CSS.`

要はプロダクション環境時に、`purge` されるよ、とのこと、なるほど。

試しに開発環境で、build して、本番環境のように、Next.js を実行してみる。

```bash
yarn run next build
yarn run next start
```

下記のような画面が立ち上がりました、Vercel にデプロイした画面と同じですね。

![開発環境でNext.jsをプロダクションビルドして起動した画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166596/7ae80a6a-1244-5f05-40c0-907053c6ed27.png)

## 解決

再び[ドキュメント](https://v2.tailwindcss.com/docs/optimizing-for-production)を読む

`If you want to manually control whether unused styles should be removed (instead of depending implicitly on the environment variable), you can use an object syntax and provide the enabled option, specifying your templates using the content option:`

`enabled` というオプションを利用することで、解決できそうです。

```js:tailwind.config.js
module.exports = {
  purge: {
    enabled: true,
    content: ['./components/**/*.jsx', './pages/**/*.jsx']
  },
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}
```

開発環境で立ち上げて確認してみましょう。

```bash
yarn run next dev
```

![開発環境の画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166596/df9422e7-9bad-3ef4-d744-c9bf55405a43.png)

本番に合わせることができました。
ファイルを変更してホットリロード時のコンパイルが若干遅くなってしまっているようにも感じましたが、開発で見ていたものと、本番に上げた時に見え方が違うのは少々困るので仕方無しなのかな。。。

また調べてみます。
Unityで生成したボタンにキーボードのキーを自動で割り振りたい！

# この記事について
Unity１Weekで以前作成していたゲームで悩んだ内容について書こうと思います。
個人的な取り組みで会社でゲーム開発していないけど問題ないよね！

# どんなゲームか
表示される数値を二進数に変換して答えるというゲームを作った。
面白くなかったので封印した。

![スクリーンショット 2021-06-30 1.16.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296240/4fccbcad-629d-79d2-e49a-30f0a9b069a9.png)

選択する難易度によってビット数が変わるというもの。
この時にPCでやるならキーボード入力ができるようにしたいと思い、ビット数の指定時（難易度選択時）に自動でボタンとキー入力を紐付けできないかと考えました。

# ソースコード
Buttonを入れる範囲指定にからのオブジェクトを置いて、そこにHorizontal Layout Groupを追加します。
![スクリーンショット 2021-06-30 1.15.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296240/370e82db-a262-c9d2-57f8-87feff60bbeb.png)

```C#:CreateButton.cs
public string[] keyString = { "q", "w", "e", "r", "t", "y", "u", "i", "o", "p" };

private void OnEnable()
{
    for (int i = 0; i < 10; i++)
    {
        var obj = Instantiate(ButtonPrefab, this.transform);
        var bitNumber = (int) Math.Pow(2, i);
        var keyCode = keyString[i]; 
        obj.GetComponent<BitChanger>().InitSetProperty(bitNumber, keyCode);
    }

    _gameManager.CreateQuestions();
}
```

```C#:BitChanger
void Update()
{
    if (Input.GetKeyDown(keyString))
    {
        PushBitButton();
    }
}

public void InitSetProperty(int setBitNumber, string setKeyString)
{
    this.thisBitNumber = setBitNumber;
    this.keyString = setKeyString;
}
```
【オブジェクト指向 / ざっくり】委譲とは？

##どんな記事？
* 新人エンジニアのサクッとアウトプット記事
* 具体的な内容(コード)というよりは図解で"ざっくり"理解するのが目的

##オブジェクト指向とは
閲覧されている方は既知の内容だとは思いますが一応おさらい

* プログラミングに**オブジェクト**という概念を持ち込んだ考え方。
* オブジェクトは一般的に**クラス**で定義。
* クラス内でそのオブジェクト関する変数やメソッドを定義する。
* クラスはオブジェクトの設計図。それを元に実体化させたものが**インスタンス**
* クラスの定義を引き継いでさらに機能を拡張することを継承という。

##委譲とは
* あるクラスの**一部**のふるまいを別のオブジェクトに代替させること。
* 既存のクラスのふるまいを他のクラスで使いたいときに使う
* 委譲先のクラスで委譲元のクラスを**インスタンス**として定義する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288580/20603789-9b0a-78c0-e9b3-e4518310f727.png)

##継承との違い
継承は親クラスの内容を**すべて**引き継ぎ、委譲は委譲元の振る舞いを**一部**引き継ぐ
### 継承
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288580/b1237b49-605a-5bc9-f258-1cc4e9804449.png)
**定義の拡張**という意味合いが強い
### 使い分け
* 継承はふるまいを**拡張**したい時
    * 例：”クルマ”クラスを親として”電気自動車”クラスを作って"充電"というふるまいを拡張する
* 委譲は**役割を分けて委ねたい**時
    * 単一責任の原則(一つのクラスに二つ以上の役割があってはならない)を満たして保守性を上げる
        * 例：ユーザーを**表現する**"User"クラスにその情報をDBに**保存する**ビジネスロジックはあってはならない
    * 元クラスと同じ分類だが役割が違う場合に使う。
        * (同じユーザーを扱うクラスでも値の表現するクラスと保存するクラスは違うロジック)
VSCode + Dockerで開発環境構築

# この記事について
DockerとVSCodeを組み合わせて簡単にPythonの開発環境を構築します。

今まで「pyenv使ってPythonのバージョン指定をして、venvで仮想環境を作って〜」みたいなことをしていました。
私の注意力が散漫なせいで環境構築に失敗したりしてローカル環境を汚してしまうということが多々ありました。

この原因は、pyenvだろうとvenvだろうとローカル環境にインストールしているから発生するんだと思います。
そこで、Dockerを利用することでそもそもローカル環境にPythonを入れない環境構築を実践してみることにしました。

# 必要となるソフトウェア
[Docker](https://www.docker.com/)

# Dockerコマンド
### 最初のコマンド

```cmd:cmd
docker run --name=docker_test -v=/Users/xxxx/dev:/mout -d python /bin/bash
```
xxxxは任意の文字列です。
「docker run」コマンドは以下のコマンドを同時にやったのと同じことです

* docker pull（ローカルにイメージがなければ）
* docker create
* docker start

オプションは以下のように指定しています。
詳細は[公式ページ](http://docs.docker.jp/v17.06/engine/reference/commandline/run.html)を参照。

| オプション | 説明 | 使用例 |
|:--|:--|:--|
|  name=xxxx | 作成するコンテナの名称 | name=python_38 |
|  -v=xxxx:/mout/ | マウントするリポジトリを指定 | -v={ローカルのパス}:{コンテナのパス} |
| -d | コンテナをバックグラウンドで実行するオプション |  バックグラウンドで実行しない場合には「-it」がよく使用される |
| python | 使用するイメージを指定する。ローカル上に無い場合にはDockerHubから取得してきます | 今回はPythonですが、バージョン指定をしたい場合には「python:3.7」のように記述します |
| /bin/bash | 実行時に使用するコマンドを指定しています。今回はBash。 |  指定しないとPython3がそのまま実行されます。 |

次にコンテナがちゃんと動いているかどうかを確認しましょう。

```cmd:cmd
docker ps
CONTAINER ID   IMAGE        COMMAND       CREATED          STATUS                      PORTS     NAMES
853cdc3a6251   python       "/bin/bash"   4 seconds ago    Exited (0) 2 seconds ago              docker_test
```

# VSCodeの設定
今回はRemote-Containersという拡張機能を使用します。
![スクリーンショット 2021-06-30 0.50.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296240/97f55c67-3c5a-5871-3650-64ad54d98240.png)

Remote-ContainersをインストールするとVSCodeの左の一覧にリモートエクスプローラーが追加されていると思います。
これをクリックすると現在Dockerに存在しているコンテナの一覧が表示されます。
![スクリーンショット 2021-06-30 0.51.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296240/d8976931-57b4-883e-1c9b-48ac7e5882a5.png)

この中から自分が使いたいコンテナを選択します。
青くなると右側に+マークのついたアイコンが表示されるのでそれをクリックします。
![スクリーンショット 2021-06-30 0.53.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296240/2a5632fc-003e-7d3c-d43f-bfb10686dc62.png)

すると新しくVSCodeが開いてフォルダーを選択できるようになります。
フォルダーを開くボタンを押して、先ほどマウントしたフォルダかあるいはここで新しくフォルダを作成して開発を進めていきましょう。
![スクリーンショット 2021-06-30 0.54.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296240/e2f5a6d2-03a3-761b-3c30-2090caca7064.png)
Unityでゲームを一時停止させたい

# この記事について
この記事は自分の備忘録的な内容です。


# やりたい事
Unityで一時停止ができるようになりたい。
その中で、TimeScale=0;というやり方についてまとめておきます。

# 結論
* TimeScale=0にすることでゲーム進行を止めることができる
* 止めたくない処理はUpdate関数に、止めたい処理はFixedUpdate関数に入れる
* Update関数の処理を止めたい場合にはdeltaTimeを掛ける

# TimeScaleとは
[Unity公式](https://docs.unity3d.com/ja/2018.4/ScriptReference/Time-timeScale.html)

Time.timeScaleは時間の経過速度です。
1が基準となって、１よりも小さいと時間経過が遅くなり、１よりも大きいと時間経過が早くなります。

試しに左右の壁にぶつかり続けるボールを用意してその速度を変えるボタンを用意してみました。
![スクリーンショット 2021-06-29 22.30.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296240/e3d13236-6042-ce5c-7bcf-c5d600d3b20c.png)

実際に動かしてみた動画です。
![ezgif-7-84d251278534.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296240/5d81ceaa-b236-97be-a585-ea5b18c201a8.gif)


### なるほどこれで一時停止が作れるね！！！
とはいきませんでした。

# 不完全な点
まず、この時間を停止させる方法ですがUpdate関数は生きています。
全てが動作不可になると何もできなくなりますからね（メニュー画面を開くとか元に戻すとかができなくなると意味がない）。

これにより動かなくなるのは時間が関係する処理です。
* FixedUpdate関数内の処理（決められた時間間隔で実行されるUpdate関数）
* Rigidbodyを利用した処理全般
* アニメーション（回避方法あり）

なのでUpdate関数内でpositionを操作することで移動している場合、timeScale=0にしても動くことが可能な状態になってしまします。

```C#:CubeMoveManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeMoveManager : MonoBehaviour
{
    public float speed;
    // Update is called once per frame
    void Update()
    {
        var pos = transform.position;
        if (Input.GetKey("right"))
        {
            pos = new Vector3(pos.x + speed,pos.y,pos.z);
        }
        if (Input.GetKey("left"))
        {
            pos = new Vector3(pos.x - speed,pos.y,pos.z);
        }
        transform.position = pos;
    }
}

```

動画
![ezgif-7-664b2fdc1740.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296240/ea91cc9d-6f52-ceae-2ee8-adb1fd342d92.gif)

この状態を避ける方法はとりあえず二つ挙げておく。
* FixedUpdateに変更する
* 移動スピードにdeltaTimeをかける


# 注意点
timeScaleの設定はシーンをロードしてもそのままの状態になるので、シーンを遷移する際には必ずtimeScale=1に設定し直すこと。
Debian系のLinuxからWindowsの共有フォルダを使えるようにする

# はじめに

Debian系のLinuxからWindowsの共有フォルダを使えるようにする方法です。
逆の場合は、`apt install samba`とかで検索すると良さげです。

# 前提条件

プレースホルダとか書くのが面倒なので、仮の設定を用意します。

### Windows側

- 共有フォルダ：`C:\share\`
- 共有フォルダ用のユーザー名：`shareuser`
- `shareuser`のパスワード：`sharepasss`
- ファイアウォールでport445を許可するか「ファイルとプリンターの共有」ルールを有効にする
- ipアドレス：`192.168.0.123`
- `shareuser`はMicrosoftアカウントと連携していないローカルアカウントである必要あり
- 本記事のための検証では`net user /add shareuser sharepasss`でユーザー作成を行った
- `C:\share\`では`shareuser`には、お好みに応じて「フルコントロール・変更・読み取り」を許可します


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/8af7ccd3-f066-2e7c-54c0-e25d2663d6a3.png)


### Linux側

- マウント用フォルダ：`/mnt/win/share/`
- 共有フォルダ用のユーザー名：`kali`
- `kali`が所属するグループ名：`root`

# インストールするもの

Linuxに`cifs-utils`と`smbclient`をインストールします。

```shell:bash
apt install cifs-utils smbclient
```

# マウント

Linuxで`mount`を実行します。

```shell:bash
mount -t cifs -o "username=shareuser,password=sharepass,uid=kali,gid=root" //192.168.0.123/share /mnt/win/share
```

# アンマウント

マウントした後に設定ミスが発覚した場合、上書きしようとしても`busy`と表示されます。
そこで、一度`umount`を使って設定を消します。**un**mountではなく**u**mountという綴りなのは要注意です。

```shell:bash
umount /mnt/win/share
```

# うまくいかないときに頼るもの

Linux側では`dmesg` エラーログが見れるので、`tail`を利用して、リアルタイムで確認しながら、別ウィンドウでbashを開き`mount`コマンドを実行してみます。

```shell:bash
dmesg -H | tail
```

また、Linux側から`nmap`を実行してみて、445ポートがオープンかどうか確認します。

```shell:bash
nmap 192.168.0.123
```

などとやってみて、

```shell:bash
PORT     STATE SERVICE
445/tcp  open  microsoft-ds
```

445/tcpがopenなことが見れます。

ちなみに、Windows側のFireWall設定はこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/8bb3d471-5d95-cf11-062b-63dfe87d1c18.png)

うまく接続できているときに、Linux側で`mount`コマンドを下記のように実行すると、

```shell:bash
mount
```

最後のほうに上記でマウントしたものが追記されていることが分かります。

```shell:bash
//192.168.0.123/share on /mnt/win/share type cifs (rw,relatime,vers=3.1.1,cache=strict,username=share,uid=1000,forceuid,gid=0,forcegid,addr=192.168.0.123,file_mode=0755,dir_mode=0755,soft,nounix,serverino,mapposix,rsize=4194304,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1)
```

# まとめ

mountコマンド実行がうまくいけば、Linux側から`/mnt/win/share`にアクセスすると、`C:\share`の内容を書き換えることが出来ます。

**Excelsior!**
【Laravel】Auth機能を使って、ユーザーを識別する方法


#概要

Authの機能でユーザーを識別する方法を、例を使って紹介します。

例として、掲示板機能で自分が作成した記事にだけ、更新ボタンや削除ボタンをつけたいとします。

その場合、ログインしているユーザーと記事に紐づいているユーザーIDを一致させる必要があるかと思います。

そこで、Auth機能を使ってあげるといいかと思います。

下記に実装した方法を記載します。


#使用環境
Laravel 6.2
MySQL 8.0

#前提条件
・投稿テーブルのカラムに外部キーが設定してある。

#実装
例えば、Viewを出力するControllerがあります。
こんなふうなものです。

```php:Controller 
public function index()
{
    $hoges = DB::all();
    return view('hoge.index',compact('hoges'));
  
}
```

出力されるファイルは、以下で中身を表示するのはだいたいこんなふうになるでしょうか。

```php:view
@foreach($hoges as $hoge)
{{ $hoge->name }}
{{ $hoge->body }} 

@endforeach

```

ここで自身の投稿にだけ更新ボタンや削除ボタンなどを実装するものは以下です。

```php:view
@foreach($hoges as $hoge)
{{ $hoge->name }}
{{ $hoge->body }} 

@if(Auth:id() === $hoge->user_id)
<button type="button">
削除
</button>
<button type="button">
更新
</button>
@endforeach

```

こんな感じで実装が簡単にできます。

ぜひお試しください。
Dockerで一生ボリュームがマウントされない問題

# 問題
つい昨日まで動いていたDockerが突然動かなくなった。
具体的には、ホスト上のファイルがDockerコンテナ上にマウントされなくなった。
コンテナを起動することはできるが、ls等を叩いても何のフォルダもファイルも存在しない。
当然ホスト側にはフォルダやファイルが存在し、docker-compose.ymlも何も変更してない。

コンテナを何回再起動しても解決せず。
環境はWindows 10でBootCampを使用。

# 解決策
コンテナではなく、Dockerを再起動したら治った。

# 原因
ファイルはDドライブ（外付HDD）に置いていたのだが、PC起動時にDockerが走る際、まだDドライブ自体がマウントされていない状態だったっぽい。
Docker（NOTコンテナ）起動の時点で、作成したコンテナが参照しているドライブがマウントされてないといけない模様。
LaravelのマイグレーションでIndexが長いとエラーになる時の対処法

# はじめに
Laravelでマイグレーションをいつものように実行していると、

```bash
Syntax error or access violation: 1059 Identifier name ...以下略
```

という問題が発生したことがありました。
どういった理由で発生するのかを調べたので記事としてまとめたいと思います。
 

# 動作確認環境
- PHP 8.0
- Laravel 8.0
- MySQL 8.0

※下位環境でも動作する場合がございます

# Laravelのマイグレーション

```php
/**
 * Run the migrations.
 *
 * @return void
 */
public function up()
{
    Schema::create('dummy_users', function (Blueprint $table) {
        $table->id();
        $table->string('name')->comment('name');
        $table->string('session_token')->comment('session_token');
        $table->string('user_token')->comment('user_token');
        $table->string('sub_name')->comment('sub_name');
        $table->integer('ios_gold')->unsigned()->comment('ios_gold');
        $table->integer('android_gold')->unsigned()->comment('android_gold');
        $table->timestamp('last_login_datetime')->nullable()->comment('last_login_datetime');
        $table->integer('updated_at_timestamp')->unsigned()->comment('updated_at_timestamp');
        $table->integer('updated_at_timestamp2')->unsigned()->comment('updated_at_timestamp2');
        $table->timestamp('created_at')->nullable()->comment('created_at');
        $table->timestamp('updated_at')->nullable()->comment('updated_at')->index();

        $table->index(['android_gold', 'session_token', 'user_token', 'name']);
    });
}
```

Laravelでは上記のように

```php
$table->index(['android_gold', 'session_token', 'user_token', 'name']);
```

と書くことでIndexキーを貼ることができますが、このIndexが一定文字数以上になるとエラーが発生してしまいます。


# 文字数上限

MySQLは、Indexキーの文字数が<font color="Red">65文字以上</font>になるとエラーが発生します。


# LaravelのIndexキーの仕組み


```php
$table->index(['android_gold', 'session_token', 'user_token', 'name']);
```

Laravelは上記のように記述すると、

```
dummy_ussers_android_gold_session_token_user_token_name_index
```

というキー名が自動的に付けられます。

```php
/**
 * Create a default index name for the table.
 *
 * @param  string  $type
 * @param  array  $columns
 * @return string
 */
protected function createIndexName($type, array $columns)
{
    $index = strtolower($this->prefix.$this->table.'_'.implode('_', $columns).'_'.$type);

    return str_replace(['-', '.'], '_', $index);
}
```

LaravelのIlluminate\Database\Schema\Blueprintの上記メソッドで定義されている通り、
テーブル名などが自動的にキー名に付くようになります。
その影響でテーブル名が長かったりすると、Indexとして使える文字数が少なくなり、エラーになる可能性も高くなります。


# 対処法

Laravelの自動名付けを使うと↑のロジックが使われ、結果的に長めのキー名になってしまいます。
これを避けるためには、第2引数を付けることで任意のIndex名を付けることができます。

```php
$table->index(['android_gold', 'session_token', 'user_token', 'name'], 'aiueo');
```



# 関連
https://laracasts.com/discuss/channels/general-discussion/sqlstate42000-syntax-error-or-access-violation-1059-identifier-name-is-too-long

https://readouble.com/laravel/8.x/ja/migrations.html
Servletの勉強で学んだことまとめ

##  フォームの使い方


```jsp:jsp
<form action ="/servlet/FormSampleServlet" method="post">
名前:<input type="text" name="name"><br>
<input type="submit" value="登録">
</form>
```


```java:servlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");//文字コードのセット
		String name = request.getParameter("name");//"name"という名前のパラメータの値を取得する
}
```

## フォワード

・フォワード先には同じWebアプリケーションのJSPファイルやServletクラスを指定する。
・アドレスバーに表示されるURLはリクエスト時のまま変わらない

```java:forward
RequestDispatcher dispatcher = request.getRequestDispatcher("フォワード先");
dispatcher.forward(request,response);
```

## リダイレクト

・リダイレクト先にはブラウザがリクエストできる先であればどこでも指定できる。
・アドレスバーに表示されるURLはリダイレクト先のものに代わる

```java:redirect
response.sendRedirect("リダイレクト先のURL");

```


## リクエストスコープの使い方
```java:requestScope
// リクエストスコープに保存するインスタンス
Cat cat = new Cat();

// リクエストスコープにインスタンスを保存
request.setAttribute("cat",cat); // 第一引数:属性名(String),第二引数:インスタンス(Object)

//　リクエストスコープからインスタンスを取得
Cat neko = (Cat) request.getAttribute("cat"); //第一引数:属性名(String) 
// ↑　※戻り値はObject型なのでキャストが必要
```

## セッションスコープの使い方
```java:sessionScope
// セッションスコープの取得
HttpSession session = request.getSession();

// セッションスコープに保存する
session.setAttribute("cat",cat); // 第一引数:属性名(String),第二引数:インスタンス(Object)

// セッションスコープからインスタンスを取得する
Cat neko = (Cat) session.getAttribute("cat"); //第一引数:属性名(String) 
// ↑　※戻り値はObject型なのでキャストが必要

//　セッションスコープからインスタンスを削除する
sessin.removeAttribute("cat"); //第一引数:属性名(String) 

// セッションを破棄する
session.invalidate();

```

## アプリケーションスコープの使い方
```java:applicationScope
//　アプリケーションスコープの取得
ServletContext application = this.getServletContext();

// アプリケーションスコープに保存する
application.setAttribute("cat",cat); // 第一引数:属性名(String),第二引数:インスタンス(Object)

// アプリケーションスコープからインスタンスを取得する
Cat neko = (Cat) application.getAttribute("cat"); //第一引数:属性名(String) 

//　セッションスコープからインスタンスを削除する
application.removeAttribute("cat"); //第一引数:属性名(String) 

```