OmniAICreator/Qiita-1.07M huggingface dataset:
MarkdownエディタとしてVisual Studio Codeを使ってみる


いままでmarkdownエディタはSublime Text 3を使用していました。試しにVSCodeを使ってみたらすごくよかったので手順をまとめておく。

## Visual Studio Code のダウンロード

ここからインストーラーをダウンロードして、インストールします。

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

## 拡張機能のインストール

markdownの記述がいろいろと便利になる拡張機能をインストールしておきます。

### Markdown All in One

markdownの記述に便利なショートカットキーを提供してくれます。
まだほとんど使いこなせてません。。。

### Markdown PDF

markdownをPDFやhtml, 画像(png,jpeg)などで出力できるようになります。

### Markdown Previw Github Styling

markdownのプレビューがGithubのようなスタイルで表示されます。
Fluentd(td-agent)のインストールからログ出力まで

#はじめに
CentOSにFluentd(td-agent)をインストールして、連携させるデータをPOSTしてログで確認するまでの手順です


#環境
CentOS 7.2.1511
※自分は、MacOS上のCentOSで動かしています
[macOS+Vagrant(CentOS)でpysparkを動かす](https://qiita.com/kihei171/items/b6f56a25a5632171640d)


#td-agentのインストール

```
$ sudo su -
# curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent3.sh | sh
```

#td-agentの起動とその確認

```
# systemctl start td-agent
# systemctl status td-agent
```

#td-agentへデータ送信とログの確認

```
# curl -X POST -d 'json={"test":"hoge"}' http://localhost:8888/debug.test
# cat /var/log/td-agent/td-agent.log
2019-09-04 02:18:36.710158181 +0100 debug.test: {"test":"sample"}
```

#ログを指定したディレクトリに書き出す
※/etc/td-agent/td-agent.confに追記

```
# vi /etc/td-agent/td-agent.conf

<filter sample.**>
  @type  grep
  <regexp>
    key       test
    pattern   hoge
  </regexp>
</filter>

<match sample.**>
  @type  file
  @id    out_file_sample
  path   /var/log/td-agent/sample
</match>
```


#td-agent再起動

```
# systemctl restart td-agent
```

#データ送信とログ確認

```
# curl -X POST -d 'json={"test":"hoge"}' http://localhost:8888/sample.test
# tail /var/log/td-agent/sample/*.log
```
phpstormで配列最後の要素をカンマ付きで統一させるフォーマット設定

phpで配列のカンマ付きの指定はどうされていますか？
PHP5.4以降では配列の短縮構文が追加されて```array()```の代わりに```[]```を使えるようになってからは
個人的には読みやすいので[]が好みですが、

最後の要素の指定で```,```（カンマ）をつけるかどうか統一されていないコードもありますが、
PhpStormのコードフォーマットで一括でリファクタリングする設定です。

## 配列最後の要素の後のカンマをつけるべきか？どうか
そもそもですが、
まずカンマをつけるべきかどうか迷うところでもあると思います。公式のDOCに記述がありました。

> 最後の要素のあとのカンマは、書いても書かなくてもかまいません。 配列を一行で定義する場合は、ふつうは最後のカンマを省略します。つまり、 array(1, 2) のほうが array(1, 2, ) よりおすすめだということです。 しかし複数行で定義する場合は、最後のカンマをつけることが一般的です。 そうしておけば、配列の最後に要素を追加するのが容易になるからです。

ということで基本どっちでもいいよと言っちゃってますが、
複数行で定義の際はカンマ付きの方がいいよねということのようです。
たしかにgithubなどのバージョン管理を使用している際は、定義などで最後の要素を追加した時にカンマありの方が差分が見やすくなるのでいいですね。

```
array(
    key  => value,
    key2 => value2,
    key3 => value3,
    ...
)
```
と

```
[
    key  => value,
    key2 => value2,
    key3 => value3,
    ...
]
```

## 配列最後の要素をカンマ付きで統一させるフォーマット設定

* 「環境設定」→「エディター」→「コード・スタイル」→「PHP」

「コード変換」タブで
「複数行配列の最後の要素の後にコンマを追加する」にチェックを入れる

![スクリーンショット 2019-09-03 11.47.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452135/dd390f21-9371-aa82-95ab-aae6fdad3acd.png)

この設定でOKとし、該当ファイルを開いてコードの再フォーマットを適用すると要素の最後に自動でカンマをつけてフォーマットしてくれます。

コードフォーマットは以下コマンドです。
```Cmd + Alt + L```（Mac）または```Ctrl + Alt + L```（Win）
※ファイル保存しただけでは再フォーマットはされません。

## 前回の関連記事
phpstormで配列のarray()を[]にフォーマットで統一させる設定
https://qiita.com/a-nishimura/items/2acfb667ea6f6c596d96

## 参照
https://www.php.net/manual/ja/language.types.array.php
execができないYAMAHAルーターへssh接続でステータス取得

YAMAHAルーターへSSH接続してコマンドを実行させるのに、小技を使ったという話。
[こちら](https://qiita.com/tomohideyo/items/d671655e9ea77944d469)の続きになります。


　共通ユーザーでtelnet接続してステータス取得をcronで回しているとしてると時々失敗していることに気がついた。失敗しているタイミングでは、他の人がネットワーク構成の変更のためにログインしているということがわかり、やはりtelnetでもユーザー名指定のほうがいいよね→それもうsshでよくね？ということでtelnet接続をやめることにした。

```yaml:tasks/main(telnet).yml
- name: ルーター情報取得
  telnet:
    password: soge
    prompts:
      - "[$|>]|Password: "
    command:
      - console character en.ascii
      - show status dhcpc
```
　⇓

```yaml:tasks/main(ssh).yml
- name: ルーター情報取得
  shell: |
      console character en.ascii
      show status dhcpc
```

動作確認用テスト環境で問題ないことと、ルーターにもSSHで入れることを確認した後、ansible-playbookを起動すると、 "Failed to connect to the host via ssh:" でunreachableとなってしまった。verboseログレベルを上げながら確認していくと、"-vvvv"まで来たところで、以下のログが吐き出されて原因が判明した。

> Received disconnect from www.xxx.yyy.zzz port 22:2: Channel request 'exec' is not supported

RTX1210 「 exec ? な　に　そ　れ 」

　ルーターのOSはLinuxじゃないので予想して然るべきだったが、execができないので対応を検討。expectモジュールを使用することにしました。

```yaml:expect(ssh).yml
- name: ルーター情報取得
  local_action:
    module: expect
    command: ssh hoge@{{ inventory_hostname }}
    responses:
      "[P|p]assword: ":
        - soge
      "[#|$|>] ":
        - console character en.ascii
        - show status dhcpc
        - exit
```
一応telnetでもステータスは取れたけど、rc=2 "Connection closed by foreign host." となってエラー扱いされてしまったので、ignore_errorsをつけないと先に進めなくなってしまった。素直にtelnetモジュール使え。

```yaml:expect(telnet).yml
- name: ルーター情報取得
  local_action:
    module: expect
    command: telnet {{ inventory_hostname }}
    responses:
      "Username: ":
        - hoge
      "[P|p]assword: ":
        - soge
      "[#|$|>] ":
        - console character en.ascii
        - show status dhcpc
        - exit
  ignore_errors: True # 嫌すぎる
```
mod_rpafというモジュールを使ってALBを利用できるようにする

# オンプレにあったプロダクトをクラウドに移行させました
移行させるのは今までも何度かやってきたので、プロダクト自体が動くところまではそこそこできましたが、今回問題となったのは、オンプレで機能していたリダイレクトの設定や、プロキシの設定などです。クライアントのリクエストがオンプレ側で使われていたプロキシサーバーだったりしていたので、その辺りの部分を、AWSのアーキテクチャに沿って整える必要がありました。具体的に言えば、オンプレでやっていたプロキシの部分をALBにやらせる設定に寄せて上げるということです。

## mod_rpaf
設定でALBに寄せて上げなくてはならないモジュールがこれでした。このモジュールの機能は、

> mod_rpafを使うと、ヘッダのIPアドレスを取得して、httpdの内部のリモートIPアドレスを保持している変数(REMOTE_ADDR)に上書きしてくれます。これにより、正しいアクセス元IPアドレスがアクセスログに記録されます。

ということだそうです。
ALBやApacheにはリクエストヘッダをいじくれるヘッダがあります。X-Forwardと名のつくヘッダがこれに当たります。こいつを使って、アクセスログに利用されたIPをログに取り、アクセスされているIPをhttpd側に取得させます。

## apacheとalbに用意されているヘッダ

- **Apacheのmod_proxy_httpのヘッダ**

```
X-Forwarded-For: {クライアントが送ってきた X-Forwarded-For リクエストヘッダ値 + クライアントのIPアドレス}
X-Forwarded-Host: {クライアントが送ってきた X-Forwarded-Host リクエストヘッダ値 + クライアントが送ってきた Host リクエストヘッダ値}
X-Forwarded-Server: {クライアントが送ってきた X-Forwarded-Server リクエストヘッダ値 + リバースプロキシサーバーのホスト名. ServerNameで指定}
```

- **ELBのヘッダ**

```
X-Forwarded-For: {クライアントが送ってきた X-Forwarded-For リクエストヘッダ値 + クライアントのIPアドレス}
X-Forwarded-Port: {クライアントが接続してきたリバースプロキシサーバーのポート番号}
X-Forwarded-Proto: {クライアントが使用したプロトコル. 典型的には http や https}
```
## mod_rpafのインストール

mod_rpafのインストールに伴い、まず、ビルドに必要なパッケージを落としてきます。

```console
# yum install gcc
# yum install httpd httpd-devel
```

wgetを使って落っことしてきます。amazon-linuxに落っことしてきます。

```console
$ mkdir mod_rpaf-0.6
$ cd mod_rpaf-0.6
$ wget https://raw.github.com/ttkzw/mod_rpaf-0.6/master/mod_rpaf-2.0.c
$ sudo /usr/sbin/apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c
```

## mod_rpafのディレクティブ

- **RPAFenable** 
　
On設定すると、このモジュールの機能が有効になる。

- **RPAFsethostname**

On設定すると、リバースプロキシが付与するヘッダX-Forwarded-HostあるいはX-Hostの値をHostヘッダの値として設定する。

 - **RPAFproxy_ips**
 
リバースプロキシのIPアドレスをスペース区切りで列挙する。オリジナルにはない付加機能として"10."や"172.16."のようなドットで終わるサブネットの記法も使える。なお、この範囲を可能な限り限定してください。リバースプロキシを経由しないアクセス経路があるときには、X-Forwarded-Hostヘッダの偽装の影響を受ける恐れがある。

- **RPAFheader**

リバースプロキシが付与するアクセス元IPアドレスを格納しているヘッダ名を記述する。デフォルトではX-Forwarded-Forが使われる。

## confへどう書いたか？

```
RPAFenable On
RPAFsethostname On
RPAFproxy_ips ここにALBのDNS名を追加
RPAFheader X-Forwarded-For
```
こんな感じでALBのドメイン名を直書きでできました。カスタムログで確認して、ALBHealthCheckerのログが残っていればOKです。

## 参考文献
[リバースプロキシ/ロードバランサとmod_rpaf](https://heartbeats.jp/hbblog/2012/03/mod-rpaf.html)

[ELB の仕様を Apache と比較](https://qiita.com/nakanishi-m/items/bbd5b62109df00f67372)

[HTTP ヘッダーおよび クラシックロードバランサー](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/classic/x-forwarded-headers.html)
Google Cloud Functionsをローカルで実行する

公式のドキュメントでは2019年9月4日現在、[cloud-functions-emulator](https://github.com/googlearchive/cloud-functions-emulator) をインストールして使うように記載されていますが、cloud-functions-emulatorは現在archiveされており、公式のgithubにて2019年5月16日に作成されたissueによると [functions-framework](https://github.com/GoogleCloudPlatform/functions-framework-nodejs) という新しいツールの利用を推奨しています。

なので、functions-frameworkをインストールして使っていきます。

## インストール

公式で案内されているのは下記です。

```
$ npm install @google-cloud/functions-framework
```

私はYarnを利用しているので下記でインストールしました。

```
$ yarn add @google-cloud/functions-framework
```

## バージョンについて

node.js v8.10.0でインストールしたところ、

```
error @google-cloud/functions-framework@1.2.1: The engine "node" is incompatible with this module. Expected version ">=10.0.0". Got "8.10.0"
```

`>=10.0.0`ですよーと怒られたのでv10.16.3で入れました。

```
yarn add v1.17.3
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...

success Saved lockfile.
success Saved 28 new dependencies.
info Direct dependencies
└─ @google-cloud/functions-framework@1.2.1
info All dependencies
├─ @google-cloud/functions-framework@1.2.1
├─ accepts@1.3.7
├─ array-flatten@1.1.1
├─ body-parser@1.19.0
├─ content-disposition@0.5.3
├─ cookie-signature@1.0.6
├─ cookie@0.4.0
├─ destroy@1.0.4
├─ ee-first@1.1.1
├─ express@4.17.1
├─ finalhandler@1.1.2
├─ forwarded@0.1.2
├─ ipaddr.js@1.9.0
├─ media-typer@0.3.0
├─ merge-descriptors@1.0.1
├─ methods@1.1.2
├─ mime-db@1.40.0
├─ minimist@1.2.0
├─ negotiator@0.6.2
├─ path-to-regexp@0.1.7
├─ proxy-addr@2.0.5
├─ raw-body@2.4.0
├─ safer-buffer@2.1.2
├─ serve-static@1.14.1
├─ type-is@1.6.18
├─ unpipe@1.0.0
├─ utils-merge@1.0.1
└─ vary@1.1.2
✨  Done in 1.06s.

```

つらつらーとログが流れて、インストール完了！

## 確認

`index.js`ファイルを作成して、nodeサーバーを立ち上げて確認します。

index.js

```
exports.helloWorld = (req, res) => {
  res.send('Hello, World');
};
```

index.jsを作ったら、コマンドを叩きます。

```
$ npx @google-cloud/functions-framework --target=helloWorld
```

```
Serving function...
Function: helloWorld
URL: http://localhost:8080/
```

こんな感じでサーバーが立ち上がったら、`http://localhost:8080/`を見てみましょう。

![screenshot-localhost_8080-2019.09.04-10_47_17 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439586/82056672-484d-e6ba-ddf0-1896040cfd7e.png)

無事、Hello Worldできました！ Congratulations!

![DSJCk8lU8AAh_78.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439586/a7664666-8689-9a0a-b477-09ccde538a5f.jpeg)

## まとめ

公式のドキュメントも時には疑ってかからなければならないことを学びました。
そして、最新の情報はgithubにあり！
もっと言うと、コードにあり！!

参考：
[functions-framework を利用したGoogle Cloud Functionsにおいてpubsubのテストをする方法](https://selmertsx.hatenablog.com/entry/2019/06/26/functions-framework_%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9FGoogle_Cloud_Functions%E3%81%AB%E3%81%8A%E3%81%84%E3%81%A6pubsub%E3%81%AE%E3%83%86%E3%82%B9%E3%83%88%E3%82%92%E3%81%99%E3%82%8B)
Powershellミニメモ

* 何か入力するまで一時停止させる
  - $host.UI.RawUI.ReadKey() 
* ディレクトリ配下のファイルに対して文字列検索し、文字コード指定でファイルに書きだす  
  - Get-ChildItem . -include xx.java -Recurse -Force | Select-String "検索文字列"  | Select Line | out-file zz.txt utf8
* ファイル内テキスト置換  
  - Get-Content zz.txt | % { $_ -replace " ", "" }  | out-file xx.txt utf8
* ファイル削除
  - rm xx.txt
Postmanテストケースの書き方



* Httpステータスコードの確認
  - `tests["レスポンスコードが200であること"] = responseCode.code === 200;`

* レスポンスデータをJSONにパースする
  - `var jsonData = JSON.parse(responseBody);`

* コンソールログ出力
  - `console.log("ログコメント");`

* Postman環境変数に格納する
  - `postman.setEnvironmentVariable("user_id", jsonData.userid);`

* レスポンスを丸ごと比較

    ```
    pm.test("レスポンス確認", function () {
        pm.expect(jsonData).to.eql(
        {
            "code": "ERROR",
            "message": "パラメータが不正です。",
            "message_detail": "user_idが未設定です。"
        }
            );
    });
    ```
packerでdockerがインストール済みのamazon linux2のAMIを作成する

```json:amazon-linux2-docker.json
{
  "min_packer_version": "1.4.2",
  "variables": {
    "aws_region": "ap-northeast-1"
  },
  "builders": [
    {
      "ami_name": "docker-amazon-linux2-{{isotime | clean_ami_name}}",
      "ami_description": "An Amazon Linux 2 AMI that has Docker installed.",
      "instance_type": "t2.micro",
      "name": "amazon-linux-ami",
      "region": "{{user `aws_region`}}",
      "type": "amazon-ebs",
      "associate_public_ip_address": true,
      "source_ami_filter": {
        "filters": {
          "virtualization-type": "hvm",
          "architecture": "x86_64",
          "name": "*amzn2-ami-hvm-*",
          "block-device-mapping.volume-type": "gp2",
          "root-device-type": "ebs"
        },
        "owners": [
          "amazon"
        ],
        "most_recent": true
      },
      "ssh_username": "ec2-user"
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "script": "{{template_dir}}/setup_amazon-linux.sh",
      "only": [
        "amazon-linux-ami"
      ]
    }
  ]
}
```


```bash:setup_amazon-linux.sh
#!/bin/sh
set -e

SCRIPT=`basename "$0"`

echo "[INFO] [${SCRIPT}] Setup git"
sudo yum install -y git

echo "[INFO] [${SCRIPT}] Setup docker"
sudo yum install -y docker
sudo service docker start
sudo usermod -a -G docker ec2-user
sudo systemctl enable docker
```

## ビルド

```
packer build amazon-linux2-docker.json
```
iOS開発メモ


## StatusBar
### 色

```swift
// 2019/9/04 Xcode10.3

// .default: 黒  .lightContent: 白
// この変数に値をいれたときにステータスバーの色が変わる
private var statusBarStyle: UIStatusBarStyle = .default {
    didSet {
        setNeedsStatusBarAppearanceUpdate()
    }
}
// ステータスバーの色を決めるトコ
override var preferredStatusBarStyle: UIStatusBarStyle {
    return statusBarStyle
}

```
### 表示非表示

```swift
// 2019/9/04 Xcode10.3

// この変数に値をいれたときにステータスバーが表示非表示される
private var statusBarIsHidden: Bool = false {
    didSet {
        setNeedsStatusBarAppearanceUpdate()
    }
}
// ステータスバーの表示非表示を決めるトコ
override var prefersStatusBarHidden: Bool {
    return statusBarIsHidden
}

```

iPhoneX系で消すためには

```swift
// 2019/9/06 Xcode10.3

// iPhoneX系でステータスバーを隠すために必要
extension UINavigationController {
    override open var childForStatusBarHidden: UIViewController? {
        return self.topViewController
    }
}
```
TypeScriptのArray.filterでタイプガードが効かない時の対処

例えば、

``` typescript
type HOGE = PIYO | undefined;
```
と言うような型があったとして、Typescriptの場合ifやcase文でPIYO型として処理を行うことが出来る。

``` typescript
//hogeはHoge型の変数とする

if(hoge){
  //この中ではhogeはpiyo型として扱える
}
```

一方で、Array.filterではそのような絞り込みは行われない

``` typescript
//hogeArrayはHoge型の配列とする
hogeArray.filter(hoge => !!hoge); //これの戻り値はPIYO[] ではなく HOGE []
```
ちょっと使い勝手が悪い。

# 対応策

## ユーザー定義TypeGuardを使う
変数名 is 型名　を戻り値に書く関数で任意の方法でTypeGuardをかけられるが、
これを使うパターンだとfilterでもTypeGuardがかかる

``` typescript
const isPIYO = (hoge:HOGE): hoge is PIYO => {
 return !!hoge;
}
```
ただし、この方法だとコンパイルは通るものの、
実質キャストをかけているだけなので、isPIYOの中身が正しいかどうか静的チェックがかかるわけではない。
isPIYOの実装を間違えていると実行時に型で防げたはずのエラーが出る可能性がある。

## flatMapを使う
他にも似たような方法はいくつかあるものの、結局どこかしらでキャストをかけることになる。
そこで、静的型チェックがかかったままfilterと同じことが出来ないか色々試した結果、flatMapで何とかなるということを発見した。

``` typescript
hogeArray.flatMap(hoge => !!hoge ? [hoge]:[]);//戻り値はPIYO配列
```
ただ、filter後につなげる処理がmapだった場合はまだしも、
純粋にfilter用途でこれをやると気持ち悪いかも知れない。

また、Array.flatMapはES2019の機能なので生TypeScriptでは使えない。
Babel辺りと組み合わせて使う必要がある。
terraformでプロジェクトを作る際のボイラープレート

terraformを始める際に最低限必要なのは`main.tf`だけです。ですが変数を記録するための`variables.tf`もあったほうが便利なので作成しておきます。

## variables.tf

```hcl:variables.tf
variable "aws_region" {
  type        = string
  description = "AWSのリージョン"
  default     = "ap-northeast-1"
}

variable "app_name" {
  type        = string
  description = "製品名"
  default     = "app"
}

variable "app_instance" {
  type        = string
  description = "インスタンスの名前"
  default     = "instance"
}

variable "app_stage" {
  type        = string
  description = "ステージ名称(例えば、dev, prod, qa, etc)"
  default     = "dev"
}

variable "global_tags" {
  type = map

  default = {
    Provisioner = "Terraform"
    Owner       = "あなたのお名前"
  }
}
```

## main.tf

```hcl:main.tf
provider "aws" {
  region = var.aws_region
}
```


## 一発で配置するスニペット

```bash
echo 'variable "aws_region" {
  type        = string
  description = "AWSのリージョン"
  default     = "ap-northeast-1"
}

variable "app_name" {
  type        = string
  description = "製品名"
  default     = "app"
}

variable "app_instance" {
  type        = string
  description = "インスタンスの名前"
  default     = "instance"
}

variable "app_stage" {
  type        = string
  description = "ステージ名称(例えば、dev, prod, qa, etc)"
  default     = "dev"
}

variable "global_tags" {
  type = map

  default = {
    Provisioner = "Terraform"
    Owner       = "あなたのお名前"
  }
}' > variables.tf

echo 'provider "aws" {
  region = var.aws_region
}' > main.tf

terraform init
```
Perlのprintf/sprintfの複数の引数の幅を変数で設定する

初記事。

##やりたいこと
2つの配列で2重ループを回して、適当な処理後に各ループで結果を出力する。
出力を整形する際、各配列で最大長の要素の幅で整形したい。わざわざ2回sprintf書いて連結するのはちょっと嫌だ。

[perldoc.jp](https://perldoc.jp/func/sprintf)によれば %*s のようにアスタリスクで埋めれば後の引数で幅を指定できるようである。ただし複数引数ある時の挙動は書いてないように見える。

##試した
```perl:perl
use strict;
my @Arr1=("AAA","BB");
my @Arr2=("X","YY","ZZZZ");

my $max1=0;
$max1=length($_)>$max1?length($_):$max1 for (@Arr1);
my $max2=0;
$max2=length($_)>$max2?length($_):$max2 for (@Arr2);

for my$i(@Arr1){
    for my$j(@Arr2){
        printf('%s %*s %s %*s %s'."\n","12",$max1,$i,"34",$max2,$j,"56");
    }
}

```

出力はこんな感じになる。

```
12 AAA 34    X 56
12 AAA 34   YY 56
12 AAA 34 ZZZZ 56
12  BB 34    X 56
12  BB 34   YY 56
12  BB 34 ZZZZ 56
```

##結論
```perl:
printf("... %*s ...", ... ,$width,$content, ... );
```

%*2$x のようにすることで参照引数の位置を固定できる。が、出力を色々追加したくなった時に事故起こしそうである、シングルクォーテーションのために改行文字の扱いが面倒になる、ので採用しなかった。
右クリックからハッシュ値（MD5）を取得してクリップボードに入れる


* md5.regというファイルを作り、中身を下記にして保存。

- Windows7の場合

   ``` 
   Windows Registry Editor Version 5.00
   
   [HKEY_CLASSES_ROOT\*\shell\MD5]
   @="MD&5を取得"
   
   [HKEY_CLASSES_ROOT\*\shell\MD5\command]
   @="cmd /c md5sum \"%1\" |clip"
   ```
- Windows10の場合

   ```
  Windows Registry Editor Version 5.00
  
  [HKEY_CLASSES_ROOT\*\shell\MD5]
  @="MD&5を取得"
  
  [HKEY_CLASSES_ROOT\*\shell\MD5\command]
  @="cmd /c certutil -hashfile \"%1\" MD5|findstr -v \":\"|clip"
   ```

* md5.regを実行。
なんか警告でるけど恐れずOK押下。

* コンテキストメニューに出てくるようになる。
ChromeExtention：新しいタブに自作HTMLを指定する


* ディレクトリ構成
NewTab
├── index.html
└── manifest.json


* manifest.json

    ```
    {
    "manifest_version": 2, 
    "name": "Newtab",
    "version": "1.0",
    "permissions": [
    ],
    "chrome_url_overrides" : {
        "newtab": "index.html"
    }
    }
    ```

* index.html

    ```
    内容はお好みで
    ```

* 設定方法
  1. Chromeでchrome://extensions/にアクセス
  2. 「デベロッパーモード」をONにする
  3. 「パッケージ化されていない拡張機能を読み込む」をクリック
  4. 作成したディレクトリを選択

* 参考：manifest.jsonの中身
  * manifest_version：現状有効なバージョンが2しかないので何も考えずに2で。
  * name：拡張機能の名称。45文字まで。
  * version：最大4つの数値を dot で区切る。各数値は0～65535の範囲。
  * permissions：ChromeAPIを使うときに設定するらしい。
    * https://developer.chrome.com/extensions/declare_permissions
  * chrome_url_overrides：chrome://newtabにアクセスした際に指定のファイルを表示する
Codeシリーズミニメモ

### CodeCommit
* フルマネージドなGitホスティング
* アカウントは IAM で管理できる
 - ユーザはIAMからhttpsのID/パスを手軽に発行
* 1ファイルあたり2Gまでいける
* いろいろ管理が楽な上に、他Codeシリーズと連携できる
* お値段
 - 5人まで、50G/月、10k処理/月無料 
 - 5人超えから +$1/月人 
 - 5人超えから +10G/月、2k処理/月のボーナス 

### CodeBuild
* フルマネージドなCI
* トリガーにCodeCommitが使える
* お値段
 - 基本無料
 - テスト時に作られるEC2の料金のみ

### CodeDeploy
* このサービスに対応しているEC2のOSイメージを使って自動デプロイできる
* Blue/Greenデプロイとか自動スケールとか全部対応済み、設定するだけ
* お値段
 - 基本無料
 - デプロイ先のEC2等の料金のみ

### CodePipeline
* ビルド > 単体テスト > ステージングテスト > デプロイ
* を、よしなにやってくれる
* お値段
 - 基本無料
 - デプロイ先のEC2等の料金のみ

### CodeStar
* 一発でこれだけ用意してくれる
 - サンプルアプリケーション
 - CodeCommitリポジトリ
 - CodeBuildビルドプロジェクト 
 - デプロイツール 
 - CodePipeline継続的デプロイメントパイプライン 
 - CloudWatchメトリクス 
 - プロジェクトダッシュボード
* お値段
 - 基本無料
 - これから設定される各サービス分の料金のみ
Virtualbox上のubuntuにssh接続する

### 環境
* ホストOS：Windows7 
* ゲストOS：Ubuntu 14.04.3
* 仮想化ソフトウェア：Oracle VM VirtualBox 5.1.22
* SSHクライアント：Tera Term 4.92

### SSHサーバをインストールする
* インストール  
`$ sudo apt-get install openssh-server`
* sshdプロセスの起動確認  
`$ ps aux | grep sshd | grep -v grep`


### Virtual Boxのネットワーク設定
* VirtualBoxのメニュー＞「ファイル」＞「環境設定」＞「ネットワーク」を選択し、
ホストオンリーネットワークが設定されていることを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161713/32ed3a3e-3a78-4db1-56b2-9e92efa3e8d6.png)



* 右側の編集アイコンを選択し、IPアドレスが設定されていることを確認する  
DHCPサーバは有効化されていないままでもOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161713/2f7c3dee-9753-b6cb-8c32-25ac2aaf8532.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161713/0c03bad6-b7cc-049b-1054-e3e8a341ae49.png)


### 仮想マシンのネットワーク設定
* VirtualBoxのメニュー＞「仮想マシン」＞「設定」＞「ネットワーク」を選択し、
アダプター1にNATが割り当てられていることを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161713/e56af3f2-4552-71d2-d889-0f5fa9152ef0.png)


* アダプター2を有効化しホストオンリーアダプターを割り当てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161713/65786d6c-38d8-bbf8-2ef5-8019fa4c70b9.png)



* ゲストOS上で「システム設定」＞「ネットワーク」より対象のネットワーク（上記で設定済みのアダプター2のMACアドレス）を選択し、「Options」ボタンより編集画面を表示  
「全般」タブで「この接続が利用可能になったときは自動的に接続する」にチェックが入っていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161713/7416fd3f-8c11-de9a-5ff7-8734148dfe9f.png)


* 「IPv4 設定」タブで手動を選択して固定のIPアドレスを設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161713/ae44d0f5-14c3-d79d-2827-92023eeab01e.png)



### ホストOSからゲストOSへ接続確認
* ホストOSのSSHクライアントからIPアドレスを指定してゲストOSへ接続し、ユーザ名とパスフレーズを入力してログイン確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161713/32013914-eb08-72e1-1af3-1c13eb2d07ac.png)
terraformのproviderってなに？

`provider`とは、IaaSやPaaSその他terraformが管理するための具体的な実装のことを指す。いわばプラグインのような概念。

例えばメジャーどころのクラウド用providerは下記のものが用意されている。

AliCloud
AWS
Azure
Azure Stack
Google Cloud Platform
Oracle Cloud Infrastructure
Oracle Cloud Platform
Oracle Public Cloud
VMware NSX-T
vCloud Director
VMware vRA7
VMware vSphere

[Providers - Terraform by HashiCorp](https://www.terraform.io/docs/providers/)
terraformのaws providerにawscliで設定したプロファイル名を指定する

```hcl
provider "aws" {
  profile = "your-profile-name"
}
```

プロファイルは次の記事の方法で追加できる。[aws cliで任意のプロファイルに認証情報を追加する - Qiita](https://qiita.com/reoring/items/6d43cf31f4e646e0dee4)
【UiPath】Excelアプリケーションスコープにホットキーが効かないときの対処法

# 現象
Excelアプリケーションスコープで開いたファイルに対して、ホットキーを使用して印刷などの操作を行うことがあるが、条件によってはExcelがアクティブにならず、ホットキーを上手く送れない場合がある。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/8f2fe471-f0bd-8583-8671-4c6dca1b858e.png)

Officeのバージョンが影響するのか、OSのバージョンが影響するのかは不明だが、環境によって現象が起きたり起きなかったりする。
・Windows7 + Office2010　→　○ (ウィンドウがアクティブになる)
・Windows10 + Office2016　→　× (ウィンドウがアクティブにならない)

2019/09/09 追記 -----
・Windows10 + Office2010 → ×
上記コメントをいただいたので、Windows10だとウィンドウがアクティブにならない可能性が高いと思われる。
追記 終わり ----------

# 解決策

1. Excelアプリケーションスコープ内で、「ウィンドウにアタッチ」アクティビティを置く。
1. 「ウィンドウにアタッチ」アクティビティのセレクタに、開いているExcelファイルを指定。
1. 「ウィンドウにアタッチ」内で、ホットキーを押下する。「ホットキーを押下」へのセレクタの指定は必要ない。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/21eb8c86-130e-f326-f4bf-85da12e22356.png)
tfenvをmacOSで使う方法

## インストール

```
brew install tfenv
```

## 特定のバージョンのterraformをインストールする

```
tfenv install 0.12.7
```

## 現在利用可能なterraformのバージョンを列挙する

```
tfenv list-remote
```

## 現在インストールされているterraformを列挙する

```
tfenv list
```

## 使うterraformのバージョンを切り替える

```
tfenv use 0.12.6
```
TypeScript: 読み取り専用の配列型を宣言する3つの方法

本稿ではTypeScriptで変更不可(immutable)な読み取り専用の配列型を宣言する方法を紹介する。

## `readonly T[]`

```ts
const numbers: readonly number[] = [1, 2, 3]
numbers.push(4) // 🚫コンパイルエラー: Property 'push' does not exist on type 'readonly number[]'.
numbers.pop() // 🚫コンパイルエラー: Property 'pop' does not exist on type 'readonly number[]'.
```

`as`で型表明(type assertion)をするのと同じ。

```ts
const numbers = [1, 2, 3] as readonly number[]
```

## `ReadonlyArray<T>`

`readonly T[]`と全く同じ。別の書き方と考えてよい。

```ts
const numbers: ReadonlyArray<number> = [1, 2, 3]
numbers.push(4) // 🚫コンパイルエラー
numbers.pop() // 🚫コンパイルエラー
```

`numbers`の型は`readonly number[]`になる。

`as`で型表明(type assertion)をするのと同じ。

```ts
const numbers = [1, 2, 3] as ReadonlyArray<number>
```
## `as const`

```ts
const numbers = [1, 2, 3] as const
numbers.push(4) // 🚫コンパイルエラー: Property 'push' does not exist on type 'readonly [1, 2, 3]'.
numbers.pop() // 🚫コンパイルエラー: Property 'pop' does not exist on type 'readonly [1, 2, 3]'.
```

`readonly T[]`と異なり、`numbers`の型は`readonly [1, 2, 3]`になる。

これと同じ型になるような型アノテーションの書き方は次のとおり:

```ts
const numbers: readonly [1, 2, 3] = [1, 2, 3]
```
Windows上でshell-command*の実行結果が文字化る対応

`coding-system-for-read`変数に値を設定する。
一覧を確認するには `M-x list-coding-systems` 関数。

```lisp
(add-hook 'bat-mode-hook
          '(lambda()
             ...
             (setq coding-system-for-read 'japanese-shift-jis))
```
decimalとlong



- decimal
(最小値)-79228162514264337593543950335
(最大値)79228162514264337593543950335

- long
(最小値)-9223372036854775808
(最大値)9223372036854775807

decimal(大)⇒long(小)
long(小)⇒decimal(大)

どちらも変換することは出来ないよ
ラズベリーパイ初心者のためのコピペでできるＬチカ(備忘録）

**はじめに**
---
この記事を閲覧されているということは、
・「ラズベリーパイ初心者で、まずはＬチカから
　始めてみたい！」
・「初心者向けのＬチカの記事を読んだ。
　うん、なるほどわからん。」
という方だと推察します。
↑私自身がそうでした（笑）

そんな方のためにコピペでできる「Ｌチカ」の仕方を説明していきます。

**使用環境**
---
Thonny Python IDE　←ラズベリーパイにデフォルトで入っています。
python ver.3.7.3　  ←同じくデフォルトです。


**使用機材**
---
私は[OSOYOO](https://www.amazon.co.jp/初心者演習用パーツセット-回路配線図とサンプルスケッチ有り-スターター学習キット-リレーモジュール制御-赤外線リモコン等IoTを実践する電子部品セット/dp/B01M6ZFNSS/ref=sr_1_1?__mk_ja_JP=カタカナ&crid=1VWL30R2D0VPY&keywords=osoyoo+オソヨー&qid=1567556531&s=gateway&sprefix=oso%2Caps%2C249&sr=8-1)のセットを利用しました。

オス端子　　　　×2
メス端子　　　　×2
ＬＥＤ　　　　　×1
ブレットボード　×1
基盤　　　　　　×1
抵抗器　　　　　×1

**配線図**
---
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457895/85f9a431-e8ec-77d3-3d8c-2f63525aa983.png)
⋆[OSOYOO](http://osoyoo.com/ja/2016/04/07/use-led-to-test-gpio-pin/)より引用

**ソースコード**
---
非常にシンプルです。

```python:Ltika.py
import RPi.GPIO as GPIO
import time

#変数pinとLEDに接続されているピン番号を接続する
pin = 40

GPIO.setmode(GPIO.BOARD)
GPIO.setup(pin, GPIO.OUT)


for i in range(10): #10回繰り返す
    GPIO.output(pin,True) #ON
    time.sleep(1) #一秒待つ
    GPIO.output(pin,False) #OFF
    time.sleep(1) #一秒待つ
GPIO.cleanup()
```
たったこれだけでLTチカが実装できます。

**Lチカの可能性**
---
人感センサーと組み合わせて、部屋に人が入ってきたら、ライトを点灯させるなんてことをしてみてもいいかもしれません。

**まとめ**
---
今回はラズベリーパイ界のスライム枠！
Lチカを紹介しました。
ラズベリーパイの記事は継続的に投稿していきたいと思います。
XAMLで他のクラスを参照したい



XAMLでは一般的に

<'Window.DataContext>
    <vm:ほにゃほにゃViewModel/>
<'/Window.DataContext>

↑で書かれているViewModelしか参照できない

でもほにゃほにゃViewModel以外のViewModelmo参照したい！っていう時

例)Asdf="{Binding Path=DataContext.クラス名.プロパティ}"

Path=DataContext.○○クラス.プロパティを参照しますに変わる
デフォルトだったらItemsSourceの中身見てるんだけど
Path=DataContext.でここ見ますよになる
Windows.Resource


AppXAMLにリソースを定義すると全ての画面から共通で使用できる。
その中で製造していくのが一般的。

リソースは、x:keyで名前つけて定義する。

App.XAMLで定義されている共通のコントロールではなく、個別で使用したい！という時、Windows.Resourceで定義すれば使えるが、その画面（コントロール）でしか使えない。

```
<Window.Resources>
 　   <!-- CollectionViewSourceでDataGrid内で参照出来るようにします-->
   　 <CollectionViewSource x:Key="Sections" Source="{Binding Sections}" />
</Window.Resources>
```
特定の項目に変更があった時のみ処理を進めたい

RaisePropertyChanged()ではこのプロパティで繋がっているすべての項目が動いてしまう。

特定の項目が動いたときのみに、処理を進めていきたい時にe.PropertyNameを使用する。



if (e.PropertyName == nameof(SearchCondition.Code1))



上記の場合ではSearchCondition（検索条件）のCode1に変更があった場合のみ動く。
Code1だけ別の処理をしたい場合に使用する
新規web ページ（view）の追加方法

メモです。

新規webページの追加方法。

①ルーティングを追加
resources :コントローラー名 do
    collection do
      メソッド名 :アクション名
id を必要とする場合はmemberを使用。

②コントローラーにアクションを定義

３　viewの設定　
新規アクションへ繋がるviewのURLを編集
Wake on Lan 出来なくなった話

外出中、家PCにあるデータを見たくなったんので、いつも通りAndroidから家へVPNをつないで、さあWakeOnLanするぞとポチっても待てど暮らせどPingが通らない。
BIOS設定は異常なさそう。じゃあWindows？ということで、デバイスマネージャーでネットワークアダプタの設定を１項目づつ追っていったところ、「グリーンイーサネット」とやらが「有効」になっている。怪しい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415756/da6c7f3a-4a03-eb5b-2ba5-ceb3bb57358c.png)

Energy Efficient Ethernetと同義の様。

Wikipediaより 
> Energy Efficient Ethernetとは、IEEE 802.3azとして規格化。データ送受信のないアイドル時間の電力を低減するなどの省電力型イーサネット（物理層）の技術。

「グリーンイーサネット」を「無効」にすることで無事にWakeOnLanできるようになりました。
いつからかグリーンイーサネットが現れた？
【XamarinForms】 XAMLのみで画像を角丸マスクする方法


## XAMLのみで画像をマスク

オッス！オラ、ザマリンF村の余助！

画像を角丸でマスクして、村のみんなを驚かせたいべ！

んだも、カスタムレンダラーとかいう難しいコードは書けんべ。

けど、こんなオラにもできただよ。

Frame様に祈りを捧げるだけで、できただよ。



## 角丸マスクにはFrameを使うだよ！　

簡単だべ。Frame様に２つの祈りを捧げるだけだべ。

・`IsClippedToBounds = True`

・`Padding = "0"`



### 完成例(XAML)

```xml
<Frame IsClippedToBounds="True" CornerRadius="50" Padding="0">
    <Image Aspect="AspectFill" Source="img-1.jpg" />
</Frame>
```






## 順を追って設定

##### 

####  手順1/3 ---「CornerRadius」のみ追加

```xml
<Frame CornerRadius="50" >
```



##### ＜結果＝☓＞

- マスクされとらん。
- Frame特有のドロップシャドウ様がおわす。
- FrameデフォルトのPadding値「２０」様がおわす。

 <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118819/bea77f8f-bd63-d9d6-34a9-b62eb94bf0fc.png" width="200px" />



### 手順2/3 ---「Padding」を追加

```xml
<Frame CornerRadius="50" Padding="0">
```

##### ＜結果＝☓＞

- 写真の角が境界をはみでとるべ。
- Frame特有のドロップシャドウ様がまだおわす。

 <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118819/a0be67cd-6f21-de0f-e5ea-8942bf845a69.png" width="200px" />




### 手順3/3 ---「IsClippedToBounds」を追加

```xml
<Frame IsClippedToBounds="True" CornerRadius="50" Padding="0">
```

##### <結果＝OK>

祈りがとどき、きれいに角丸でマスクされただよ！

（ドロップシャドウ様は天に戻られたべ）

 <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118819/bdd01d8b-ea36-1b73-beaa-49dd93a08510.png" width="200px" />





## 応用例

### 1. 丸でマスク

```xml
<Frame
    WidthRequest="200"
    HeightRequest="200"
    CornerRadius="100"
    IsClippedToBounds="True"
    Padding="0"
    VerticalOptions="Center"
    HorizontalOptions="Center" >
    <Image Aspect="AspectFill" Source="img1.jpg" />
</Frame>
```

 ![image-20190904082216438](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118819/fd0a6f25-c958-4bc6-2f6f-8de7c3cee0d7.png)


### 2. バーコードスキャン風

中でGridを使ってバーコードスキャン風に。

```xml
<Frame
    WidthRequest="300"
    HeightRequest="200"
    CornerRadius="20"
    IsClippedToBounds="True"
    Padding="0"
    VerticalOptions="Center"
    HorizontalOptions="Center" >
    <Grid>
        <Image Aspect="AspectFill" Source="img1.jpg" />
        <BoxView
            BackgroundColor="white"
            HeightRequest="5"
            VerticalOptions="Center"
            HorizontalOptions="FillAndExpand"
            Opacity="0.4" />
        <Label
            Text="Barcode"
            FontSize="20"
            HorizontalOptions="End"
            VerticalOptions="Center"
            Margin="0,0,10,25"
            TextColor="white"
            Opacity="0.5" />
    </Grid>
</Frame>
```

 ![image-20190904083306541](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118819/d7d3c95d-832b-5019-7175-72645f71bded.png)


以上だべ



| メモ：環境                      |
| ------------------------------- |
| .NET Standard 2.0               |
| Xamarin.Forms 4.2               |
| IDE: VisualStudio For Mac 8.2.4 |
(調査)Node.jsとjavascriptって何が違うの？

最近jsを始めた。
しかし、Node.jsとかいう似たような何かが出てくる。
これは何だ？

<h2>Node.jsってなんだよ</h2>

<h4>js</h4>
<strong>.Webページをプログラムで制御することができるのが特徴です。

webページ上で即時的に動かすプログラミングみたいなイメージ。
webページのスライドとかアニメーションなどに使ってるあれ・・・って感じ。
入力フォームでファンクションに飛ばしたりとか。
<strong>
<h4>Node.js</h4>
s.Googleが開発したV8エンジンと非同期処理によって高速なレスポンスを実現できる。
Web開発だけでなくスマホアプリ・IoT・機械学習などさまざまな用途に・・・

なるほどわからん。とりあえずjsでサーバーにアクセスできるみたいなもんか
チャットツールとかに使っていると。
シングルスレッドなので10ｋアクセス問題に対応できるよってか。
<strong>
うーん？便利やんけ。使ってみるか。

https://www.sejuku.net/blog/86748

<h3>１、インストール～ハロワ</h3>
https://qiita.com/akabei/items/8b226e14df0b156bcf2a

<h4>①インストール</h4>
Ａ，https://nodejs.org/ja/download/　
ここでWindows Installer (.msi)をテキトーにインストール
Ｂ,visual studio2017
あるから放置。後でリンク張ろう。

練習の命名ルールはオリジナルで「node.js-ptc-目的と日付」で設定。

起動したらプログラムをいじらず、そのままデバック実行。
あ、コマンドプロンプトが一瞬で消える。。。でも表示はされてた。
（勝手に消えないよう対応中）






<h4>関係ない話</h4>
・・・サーバーサイドというと
PHPやったこと無い。
サーバー構築みたいなの仮想サーバーをポンって感じにしたくらいだし。
あんまよくわからん。

<h4>気になった言葉</h4>
「PWA」によるアプリ開発・・・なんだそりゃ。まぁ後回しに
実行エンジン「V8」を利用・・・なるほどPOWEEEEEEEER


*調査ログ書くのに参考にした
メモ・・・https://qiita.com/hiroyuki_hon/items/f2a779bb295fd12646ab

npmとか使おうとして逃げた。
<a href="https://denor.jp/visual-studio-code%e3%81%a7node-js%e3%83%97%e3%83%ad%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e3%82%92%e3%83%87%e3%83%90%e3%83%83%e3%82%b0%e5%ae%9f%e8%a1%8c%e3%81%99%e3%82%8b%e3%81%ab%e3%81%af">https://denor.jp/visual-studio-codeでnode-jsプロジェクトをデバックするには</a>
googleappsscriptでループ処理を使ってデータ追加


```javascript
function initSheet(){
  var sheet = SpreadsheetApp.getActiveSheet();
  var names = ['aaa','bbb','ccc'];
  var points = [100,20,40]
  var i;
  for (i = 0; i <= 2; i++){
    sheet.getRange(i+1, 1).setValue(names[i]);
    sheet.getRange(i+1, 2).setValue(points[i]);
  }
}
```

* getRangeで指定してsetValueで値を入れる
* iは0からだがgetRangeで指定する際に0行目だと小さすぎるので+1する
#docker --mount オプションで ローカルとコンテナのファイルを同期させるコマンド例

Command example to synchronize local and container files with #docker --mount option


# dockerコンテナを起動して、共有ディレクトリにファイルを作る

type=bind を指定して、ホストとゲストのディレクトリは両方、絶対パスで記述する

```
docker run -it --mount type=bind,src=/tmp,dst=/tmp alpine sh

/ # echo "ABC" > /tmp/some.txt
```

# ローカルでファイルを開く

```
open /tmp/some.txt
```

![image](https://user-images.githubusercontent.com/13635059/64213093-9b035e80-cee6-11e9-8c44-607b210a45c9.png)



# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2388








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
javascript 初心者まとめ replaceと正規表現

初心者のため間違っている表現があるかもしれません。
忘備録として記載します。

文字を置換する時にうまくいかないと思ったらどうやら正規表現というのがあるらしい。

```js
replace(/\s/g,"/")

//　空白を"/"に置き換える
//  \s　空白文字
//　g グローバルマッチ(文字の最後まで)
```
javascript 初心者まとめ　for文

初心者のため間違っている表現があるかもしれません。
忘備録として記載します。


<h2>基本形</h2>

```js
for(var i=0,;i<data.length;i++){
   処理
}

//処理はi=0からはじまりdate.lengthまで1ずつ増やす。
```

<h2>for in 形</h2>

```js
for( var i in オブジェクト ) {
 　　 処理
}
```

<h2>for of 形</h2>

```js
for ( var i of 配列 ) {
　　　処理
}

//回数が決まっていない場合はwhileを使う
```
<h2>while 形</h2>

```js
while (条件式) {
　　　処理
}
```
印刷プレビューリボンにクイック印刷を入れるUSysRibbons

備忘録です。runtime版でも現れる印刷プレビューリボンにクイック印刷ボタンを入れるだけです。自分のテストでは動いているので誤りあればご指摘いただければありがたいです。
<pre>
\<mso:customUI xmlns:mso="http://schemas.microsoft.com/office/2009/07/customui">
\<mso:ribbon>
\<mso:tabs>
\<mso:tab idQ="mso:TabPrintPreviewAccess">
\<mso:group id="mso_c1.D1A069D" label="QuickPrn" autoScale="true">
\<mso:control idQ="mso:FilePrintQuick"  size="large" visible="true" /></mso:group>
\</mso:tab>
\</mso:tabs>
\</mso:ribbon>
\</mso:customUI>
</pre>
「オブジェクト指向」という言葉自体がメタボ、Fat Word。指向と手法

# オブジェクト指向の曖昧さ

　「オブジェクト指向」への記事や書籍、感想は数多あるけど、実のところ雲のような概念。別の意味で、クラウドだなと。
　
　そして、それゆえに、説明も評価もいろいろと錯綜している。ある意味、メタボでありFat Wordだなと思う。
　

# 「オブジェクト指向」という"言葉"は手法や観点を探す道標

　一ついえるのは、オブジェクト指向そのものよりは、それで検索したときに、クラス、カプセル化、ポリモーフィズムとかいろいろなプログラム設計上の手法にふれることができる。

　そういった意味で、「オブジェクト指向」という言葉そのものよりは、手法が大切で、その手法を探すための道標として「オブジェクト指向」という言葉は便利だと思う。

# オブジェクト（対象）を中心に考える

　言葉だけを読めば、「オブジェクト指向」だから、「Object：客体、対象」を中心に考えることかなと思う。逆に、「手続き指向」なら、処理を中心に考える。

　プログラムにおいて、ソースを分ける、値を分ける、処理を分けるというのは設計の中心的な事柄になる。その時、字義通り、「Object：客体、対象」を中心にグループ化していくとたしかに、分けやすく、コードリーディングしやすかったり、メタボソース、ファットクラスを避けやすいように思う。

# 設計・概念上のオブジェクト、コーディング上のオブジェクト

　前述した設計・概念ではなく、コーディング上では、オブジェクトは複数の値の集合、値と処理の集合であったりする。それをJavaやC++、C#みたいに、クラスで定義するのか、GoやRustみたいに構造体で定義するのかはいろいろあれど。

　コーディング上のオブジェクトは何にでも適用できてしまうので、概念上の「Object：客体」をどう捉えるかに拠って、いろいろ表現できる。

　たとえば、「ファイルを保存する」という処理がある。これを、「File.Saver」というクラスを作ってもいいし、「保存する機能」というところを客体にして、「Saving.File」、「Storage.File」とするのもありだと思う。

　コーディング上からすれば、値や処理を集合させればオブジェクトになるが、設計や概念とは別物で、どのようにだって表現できてしまう。

# 指向・概念と手法を分けて考える
　
　よく語られるオブジェクト指向の設計や手法は、このオブジェクトをうまく使う利用方法についてが書かれてて、それが概念と手法が混在してて、それが曖昧さを生んでいるんではないかなと思ったりする。　

# オブジェクト指向は万能ではなく得意な分野と不得な分野がある

　オブジェクト指向はだめだという意見があるけど、それは、処理の流れなど手続き指向の方が向いているような場所でつかうとそうなるかもしれない。

　設計手法は、使う場所を選ぶということで、オブジェクト指向が万能薬でもないし、逆に、だからといってオブジェクト指向が駄目だというわけでもない。
【Anaconda】Panelでダッシュボード作成

#Panelとは
Anacondaで作ったウィジェットや図、グラフを綺麗に複数並べて配置できるPython Library(PiViz 系)。
Jupyter Notebookでも使えるし、PythonアプリだけじゃなくHTML/JavaScriptアプリケーションなんかも組み込める、有望株です。

以下に書くのは、下記サイトの記述から学んだことです。
https://anaconda.org/pyviz/panel
https://panel.pyviz.org/
使用感はおいおい書いていきます。

#対応Pythonバージョン
Python2.7
Python3.x
Linux, Windows, MacのどれでもOK

#インストール方法
各自のAnacondaターミナルで

```
conda install -c pyviz panel 
```
か

```
conda install -c pyviz/label/earthsim panel 
```
か

```
conda install -c pyviz/label/dev panel
```

を実行。
Jupyter Labを使いたい場合は追加で以下を実行

```
conda install -c conda-forge jupyterlab
jupyter labextension install @pyviz/jupyterlab_pyviz
```

#起動方法
まずサンプルの読み込み(↑の公式にあるサンプルです)

```
panel examples
cd panel-examples
```
そしてJupyter NotebookかJupyter Labを起動

```
jupyter notebook
```

か

```
jupyter lab
```

#コーディングサンプル
以下サイト参考。Jupyter Lab前提。Altairも使ってる
https://towardsdatascience.com/how-to-build-a-time-series-dashboard-in-python-with-panel-altair-and-a-jupyter-notebook-c0ed40f02289

```
import panel as pn
import altair as alt
from altair import datum
import pandas as pd
from vega_datasets import data
import datetime as dt

alt.renderers.enable(‘default’)
pn.extension(‘vega’)
# 会社名リストを作る
tickers = [‘AAPL’, ‘GOOG’, ‘IBM’, ‘MSFT’]
# ドロップリストで選択できるようにする
ticker = pn.widgets.Select(name=’Company’, options=tickers)
# 日付のスライダーも作っちゃう
date_range_slider = pn.widgets.DateRangeSlider(
name=’Date Range Slider’,
start=dt.datetime(2001, 1, 1), end=dt.datetime(2010, 1, 1),
value=(dt.datetime(2001, 1, 1), dt.datetime(2010, 1, 1))
)
title = ‘### Kabuka Dashboard’
subtitle = ‘Kabuka to Kaisyamei ga deruyo’
@pn.depends(ticker.param.value, date_range_slider.param.value)


def get_plot(ticker, date_range):
     # データをロードし整形
     df = source # define df
     df[‘date’] = pd.to_datetime(df[‘date’])
     # 日付フィルタ反映
     # var中の開始終了日を保持
     start_date = date_range_slider.value[0] 
     end_date = date_range_slider.value[1] 
     # データフレームをマスキング
     mask = (df[‘date’] > start_date) & (df[‘date’] <= end_date)
     df = df.loc[mask] # filter the dataframe
     # Altairチャートを作る
     chart = alt.Chart(df).mark_line().encode(x=’date’, y=‘price’,      tooltip=alt.Tooltip([‘date’,’price’])).transform_filter(
(datum.symbol == ticker) # this ties in the filter 
)
     return chart

dashboard = pn.Row(pn.Column(title, subtitle, ticker, date_range_slider),
get_plot # 上で作った機能が動くよ
)
```

#活用サンプル
Bokehサーバ使ってインタラクティブさに拍車をかけてる方もいますね。
https://panel.pyviz.org/gallery/demos/glaciers.html#gallery-glaciers

以上
ルート認証局付きサーバー証明書をコマンド1回で作る

## abst
※ あくまで検証用

+ 検証用にIP固定でないPCでwebサーバーを立てる
+ https対応したい → IP変えて証明書作り直すのつらい
+ chromeにちゃんと信用されたい
+ dockerの勉強兼ねる

## 結論
[作った](https://github.com/irutack/cert-maker)  

webサーバーのIPアドレスをconfigに記載して、
`docker-compose up -d` とかやると

 + ルート認証局 → クライアントにインストールする用
 + サーバー証明書 → webサーバーのconfigとかに設定する用
 + サーバーの秘密鍵 →  同上

が出来上がる。

使い方詳細はgithubのREADMEに

## 説明
やっていることは単純で、

1. openssl.cnfを**適切に**変更する  
  なにが必要なのかわからなくてこれが結構大変  
  改変部分はgithubのREADMEに書いた通り
1. CA証明書及びサーバー証明書を作るコマンド群をshファイルにまとめる  
    + subjの入力がinteractiveなのでexpectで書く  
      → -subj オプションにまとめて書けることを知る
    + CA証明書の秘密鍵の暗号化部分で使う(expect使ってみたかっただけ)
1. docker上のubuntuで実行するためにdockerfile作る  
  expectのインストールが対話形式  
  → `ENV DEBIAN_FRONTEND=noninteractive`を指定することで回避
1. composeファイル作る  
  起動時に実行するスクリプト指定する + volumeマウント。  
  実行するshファイルの先頭に`#!/bin/bash`を書き忘れていると、  
  コンテナがエラーで落ちる

## まとめ
証明書関連の知識が少し深まった
【備忘録】未経験から半年で学習してきたこと（Java）（３）

###今回とりあげるテーマ
　前回は条件分岐とif文、switch文で学習してきたことを書きました。
コメントをちらほらいただけてうれしいです。

まだ入社して1年もたっていないですが、これも経験だと思います。
今回とりあげるテーマは***繰り返し文、繰り返し制御文***です。

###繰り返し文とは何か？
***繰り返し文***とは繰り返し処理を行う文です。
繰り返し文には2種類あります。
・while文
・for文

##while文
　while文とは何か、javaのプログラムで見てみましょう。
　フォーマット　while(条件式){
                処理;
              }

```java:test1.java
class test1{
  public static void main(String[] args){
    int a=0;  //int型の変数aに0を代入しました
    while(a<10){　//変数aの値が10より小さい間while文のブロックの処理を繰り返します
     System.out.println(a);　//変数aの値を出力します
     a++;  //a++は a = a+1と同じ意味です
    }
 }
}
```
それぞれ何をしているのか//以降のコメントを見てください。
whileの後ろの( )は条件式です。この条件式でTrueと判断される間、
while文のブロック内の処理をします。
今回だと、変数aの値を出力しその値に１を足しています。

##do-while文
　do-while文とは何か、javaのプログラムで見てみましょう。
   フォーマット　do{
　　　　　　　　　処理;
　　　　　　　　}while(条件式)

```java:test2.java
class test2{
  public static void main(String[] args){
    int a = 0; //int型の変数aに0を代入しました。
    do{
     System.out.println(a); //変数aの値を出力します
     a++; //変数aの値を１つ増やします
    }while(a<10)//変数aの値が10より小さいか判断します
  }
}
```

先ほどのwhile文と今回のdo-while文は何が違うのでしょうか？
違うところは(条件式)が最後にきています。条件式が後ろにきていると、
do-while文のブロックの処理を先にします。その後条件式の判断を行います。
***1度は処理を行いたい！***そういう繰り返し文を書きたいときにこのdo-while文を使います。

##for文
for文は先ほどのwhile文、do-while文と少しややこしいです。
　フォーマット　for(式1; 式2; 式3){
               処理;
              }

```java:test3.java
class test3{
  public static void main(String[] args){
    int a = 0;  //int型の変数aに0を代入します。
     for(int i = 0; i<10; i++){
     //int型の変数iが0です。変数iが10より小さい間、
　　 //for文のブロックの処理を行います。
      System.out.println(a);
      a++;
    }
 }
}
```

式1というのがint i = 0, 式2というのがi < 10,　式3というのが　i++。
式1は書籍やサイトには「初期化式」といわれ、for文のブロックを何回繰り返すか表す
式が入ります。式2は式１の上限を決めています。そして、式3はブロックの処理を
行った後、式1で定義した変数の値を変更しています。

###まとめ
最後かけあしとなりましたが、繰り返し文は繰り返し処理を行う文を書きたいときに使います。よく「ループ処理」や「無限ループ」という言葉を聞きますが、「ループ処理」は繰り返し処理を行うこと、「無限ループ」は同じ処理をずっと続けることだと思っています。無限ループの起こし方はwhileを使うとできます。（for文でもいけますね･･･）

まだ勉強しないといけませんが、これからもつづけて記事を書いていきます。
このシリーズで一番言いたいのは***未経験でも何があろうと続けているとここまでプログラムについて話せる***ことです。

がんばって続けていきましょう！！

次回は今回かけなかった繰り返し制御、また別に独学でやっているpythonについてかけたらと思います。

ここまで読んでいただきありがとうございました。
Herokuで、アップロードするファイル（画像・動画）のサイズ上限を上げる方法！

どうも、Hiroyukiです＾＾

今日は、
Herokuで、アップロードするファイル（画像・動画）のサイズ上限を上げる方法
について書きたいと思います。


#記事を書いた経緯は・・・

というのも、先日Qiitaにアップした
###[YouTube Data API を利用したオリジナルサービス](https://qiita.com/Hiroyuki-Hiroyuki/items/2b900eb6103fde021a54)<img width="1017" alt="スクリーンショット 2019-09-01 8.17.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489124/44bf76ed-7303-69a6-5042-204eea78b5cb.png">

があるのですが、お陰さまで見ていただいた方から好評を頂いたので
開発の過程で苦労したところなどを発信していこうと思い、
今回はサービス開発上で、「最後に苦しんだところ」を解説していきます！

皆さんも、Herokuにサービスをデプロイする、開発最終段階となると
####「あとはデプロイするだけの楽チン作業だわ！ヒャッホーイっ！！」
となると思いますが（実体験）、
デプロイ後、
####「あれ・・・？アップロード機能が動かない・・・。どゆこと？？？ (TT)涙目」
となって、最後の段階だけになかなか気持ちが萎えてしまいました。。。（実体験）

皆さんも、開発最終局面で萎えないように、万一同じ問題が起こったら、下記方法を実践してみて下さい〜


#ここからテクニック解説

前置きが長くなりましたが、ここから本題。

僕のサービスの場合、このサービス経由で「YouTubeへの動画アップロードができる」機能を付けているんですが
####「動画をアップロードしようとすると、なぜかバリデーションエラーが出る！」
という問題が発生しました。
自分の開発環境上でプレビューしても、上手く動くし、変なバリデーションなんか付けてないのに・・・。

UploadController.phpのstoreアクション（YouTubeへの動画投稿）のみ抜粋

```php

    public function store(Request $request)
    {
        $this->validate($request,[
                    'video' => 'required|file|mimes:mp4,qt,x-ms-wmv,mpeg,x-msvideo',
                    'title' => 'required|max:24',
                    'description' => 'required|max:191',
        ]);

        $upload_movie = Youtube::upload($request->file('video')->getPathName(),[
            'title' => $request->title,
            'description' => $request->description,
            // 'tags' => ['api','youtube'],
        ]);

    //・・・（中略）・・・

        return view('upload',['user'=>$user,'movies'=>$movies,]);
    }
```

いろいろ悩んで調べたのですが、
####「もしかして、ファイルサイズの上限がHerokuに制限されてるんじゃね？？」
という結論に行き着きました。

開発環境では、

php.ini
 
```ini
・・・（前略）・・・

upload_max_filesize=100M

・・・（中略）・・・

post_max_size=100M

・・・（後略）・・・
```
と設定していたので、１００MBまでの動画は余裕でアップロードできていたのですが、
Herokuに上げた途端上記問題が発生したので、Heroku独自の制限を疑い始めました。

###解決方法は以下の通り！
意外と、超カンタンで驚き（笑）

####1.".user.ini"というファイルを作ります（下記コードのみ記載）


.user.ini

```ini
upload_max_filesize=100M
post_max_size=100M
```

####2.(Laravleの場合)".user.ini"をpublic直下に置く

####3.Herokuへデプロイする


やってみると メチャ×２ シンプルでした＾＾；
####これで解決するかもなんだから、悩んでる人は一度トライすべし！！！！


#Heroku上での画像アップロード機能について

そもそもHerokuのファイルサイズ上限に気づくのが遅くなったのは、他の画像などのアップロード時は、
###「AWSのストレージ機能　S3」
に保存されるように設定していたから。

S3のファイルサイズ上限と、Herokuのファイルサイズ上限は異なるので、
####「S3には大きなサイズのファイルがアップできるけど、Herokuにはアップできない！？？WHY??」
となって悩み続けておりました。。。

####S3へアップロードするのも、意外と苦労したので、その方法も後日解説したいと思います！
ではまた！＾＾
「オワコン」表現に潜む "感情的な単線" 思考：並行した論理的評価の必要性

# 「新しい」にうるさい業界

　プログラミング全般かもしれないですが、特に、Web開発ではよく**新しい技術**が話題にされます。

「今、流行っている手法は何か？」
「最近は、Vue.jsとNuxt.jsが流行っている」
「AWSやDockerで環境を作るのが主流です」
「とにかく、これがモダンです」（心の声：モダンってなんや？）

　今までの技術や作業で無駄や問題があり、それを改善するために新しいツールや手法を使うのは当然のことです。
　そして、その帰結として「新しい技術」が採用されたり、高評価をされるのは当然だと思います。

　一方で、新しいものの良さを説明するときに、今までのツールや手法が引き合いに出され批判されます。そして、それは象徴的に「オワコン」という表現されることもあります。

　でも、実際、「オワコン」と言われるような技術やツールも完全になくなることはなく、使われ続けます。
　また、「古いもの」、すなわち、使われ始めてから長い年月がたっているものもあります。

　C言語をはじめそうしたものはたくさん存在します。冷静に考えてそれが一番最適解だから使っていることもあるし、しょうがなくつかっているのかもしれないし、レガシーとしてつかているのかもしれない。

　理由はいろいろあり、単純に新しいものが全て良くて、それ以外は駄目というわけではないと思います。


# 物理的な因果関係　と　時間

　プログラマーの会話を聞いていると、「古い」ものではなく、「新しい」ものを使うのが「良い」とする意識がみられたりします。会社の募集要項とかでも、「新しい技術を意欲的に取り入れる」ことが良しとされるものがあります。

　プログラムだけではないですが、何か作業や物理的にものを動かすとき、そのパーツが「新しい」か「古いか」よりも、論理的、物理的に目的を果たせるか否かが大切になります。

　機械部品において「古い」が修正されるのは、材質の劣化など処理上の問題を生むからです。逆にいえば、長年使われていても、問題を起こさないのであれば、無理にそれを変える必要はなく、変えることで新たな問題を生みかねません。

　物理・工学的な視点にたつと「古い」「新しい」という時間がそのまま物事の善し悪しを判断するわけではなく、材質・論理・因果関係において、問題を生み出す要因であるかどうか重要なのだと思います。

　プログラムの世界においても、物理原則は当然踏襲されるもので、問題を改善するかどうか、その因果関係をみることが最も大切なことだとおもます。

　結果的に、既存の問題点を改善する手段は、**順序的に後**にでてくるので、生まれた当初は「新しい」と表現されます。でも、**「新しい」は一時的な表現**にすぎないですし、そこが評価のポイントではなく、**「既存の問題を解決する」**というところが重要なわけです。

# オブジェクト指向の批判者「スタティックおじさん」、「Linuxの生みの親：リーナス」

　プログラムの設計手法に関しては、毎年毎年いろいろな手法や視点が提案されます。Javaが一般的に使われるようになったとき、同時に、「オブジェクト指向」設計も話題になり、今では、それを採用**"しよう"**とするのがよくみられます。

（※オブジェクト指向とは曖昧だし、なかなかそれをうまくつかいこなせている人は少ない。）

　そして、この「オブジェクト指向」が流行りはじめたとき、「スタティックおじさん」というのが批判のやり玉にあがったことがあります。
詳しくは「スタティックおじさん」で検索すればいくらでもでてくると思います。

　一見、流行っているものが「正しい」、今までのやり方は「間違っている」という価値観が流布されて、「新しい手法」を批判をすると逆に多くの批判を受けることがあります。

　では、「オブジェクト指向」は「正しい」もので、それを採用しない人は間違っているのでしょうか？

　Linuxの生みの親、リーナス・トーバスは、オブジェクト指向を批判しています。彼は、間違っている人ですか？

「スタティックおじさん」は無名だから、心置きなく批判をする人がいるかもしれませんが、さすがに、リーナス相手だと、「うぅ！」と二の句が継げないかもしれません。
　（「リーナス オブジェクト指向」で検索すれば記事がいくつかでます。）

　ですが、スタティックおじさんだろうとリーナスだろうと批判するのはありだと思います。リーナスにだって、それなりに自分の理屈があれば批判すればいいと思います。逆に、無名な人に対しては安易に論理も持たずに批判するのはどうかなと思います。
　
　スタティックおじさんとリーナスの例を出したのは、「新しい」かどうかが問題なのではなく、論理的にそれが正しいかどうかそれが問題であり、**流行りというのは半ば「感情的」なものを伴っているのでは**と感じています。

# 現象は、直列（シリアル）ではなく、並行（パラレル）

　「新しい、古い」という時、それは物事を直列、直線上で見ているのだと思います。
　ですが世の中の現象は、人間の思考とは違い、並行に進んでいっています。

　つまり、ある分野と別の分野が同時進行で動いています。
　「新しい」と語られるものが、論理的に正しいもので、既存の手法は使われなくなることがあります。ですが、それはある特定の分野や関心に対してだけであって、他のあらゆることがそうなるわけではないと思います。

　たとえば、オブジェクト思考が特異な領域と、そうでない領域があると思います。ある膨大な値の塊をグループにして操作するにはオブジェクト指向は得意かもしれません。ですが、システムすべてをオブジェクト指向の抽象化に拠ってつくってしまうと、流れのわかりにくいものになってしまいます。

　処理の大本の流れを作る部分は、手続き指向的な発想で作ったほうがいいかもしれません。
また、膨大な値の塊のない、単純な処理だけなら、関数型言語をつかって手続き指向的にするほうが分かりやすいし、問題を起こしにくいかもしれません。

　つまり、物事は単一ではなく、いろんな分野、関心があり、それぞれでどのようなツールや技術を使うのかは変わるわけです。


　「～が正しい」というとき、暗黙的に「～の分野では」というものがついていることを意識すると、無用な混乱は産まないのではと思います。


# 感情と単線思考を排除して、技術や意見を評価する

　人は物理的な因果関係だけではなく、感情という別のノイズが思考に入り込みます。それは仕方ないことです。
　ですが、技術を評価する時、そうした感情を排除して、論理的にそれが何を解決しているのかを評価することは大切だと思います。

　そして、物事は複合的であり、並行して動いています。一体、今語られている技術はどういった分野や関心に対して有効なのかという背景や条件も合わせて意識する必要があります。

　そうすることで、●馬の一つ覚えのように、採用すべきでない手段を選ぶことを回避できるかもしれません。また、より生産的な技術的な議論ができるかもしれません。そして、今まで使われてきたもの、使われているものの「良さ・メリット」を知ることができ、それが自分のスキルの豊かさを生むヒントになるかもしれません。
JWTは使うべきではない　〜 SPAにおける本当にセキュアな認証方式 〜

React/Redux/Spring Boot/AWSでSPAを作っているのですが
認証の方式をどうするか悩みました。

ベストと思われる認証方式をこちらに記載することにしました（随時更新します）。

# JWTは使うべきじゃない
ログイン済みであるという事実を
サーバーサイドのセッションを使わずに保存しておく場合、
ログインした後でJWTなどのトークンをサーバーで生成し、
それをクライアントサイドで何らかの形で保存しておく必要がある。

なぜなら、ReactおよびReduxのstateで管理してしまうと、
ページをリロードされたときにstateがクリアされてしまうから。

具体的な保存先はローカルストレージくらいしか無いのだが
JWTをローカルストレージに格納するのは危険。
なぜなら、ローカルストレージはJavaScriptで簡単に読み込めてしまうから。

自ドメイン以外のJavaScriptを読み込んでいる場合、
そこのドメインのJavaScriptが書き換えられて
ローカルストレージを全スキャンするようなことをされたら、
JWTは簡単に抜き取られてしまう。

もちろん、「自ドメイン以外のJavaScriptを読み込んでいない」ということを保証できれば
こういったリスクは回避できるのだが、
実際にはこれを厳密に保証するのは、いささか非現実的かと思う。

マーケティング上の必要性から
Google Analyticsなどを結局入れることになったりするからである。

もちろん、Google社が先述のような悪事をするわけはないのだが
JWTというトップレベルにセキュアなデータが抜き取られるリスクが
常に自分の（あるいは顧客の）Webサイトに存在していることを考えると、
いくら極小だとしても許容できないのではないだろうか？

こういうわけで、「自ドメイン以外のJavaScriptを読み込んでいない」ということを
ルール化したり、保証していくのはなかなか難儀なことだと思う。

なので、ローカルストレージに
JWTのようなセキュアなデータを入れておくことはNG。

それがNGということなら、JWTを使うこと自体、NGということになる。

# ではどうするのか？
結論からいうと、ログイン済みという事実だけは
サーバーサイドで保存せざるを得ない。

ログインしたらサーバーでセッションIDを生成し、
これを定石どおりセキュアcookieに入れてクライアントに送る。
（こうするとSSL/httpsのときだけ、cookieが送受信される）

これも定石だが、セッションIDを保存するcookieについては
httpOnlyを有効にすることが重要。

こうしておけば、JavaScriptからcookieを読み込めなくなるので、先述のリスクを回避できる。
（httpOnlyを有効にすると、httpリクエストを発行するときしかJavaScriptからcookieを読み込めなくなる）

こういったhttpOnlyの効能を得たいがために、サーバーサイドのセッション + cookieという従来の方式を採用せざるを得ないのである。

# サーバーでセッションを管理するとスケールしないのでは？
確かに、サーバーのメモリでセッションを管理すると、特定のサーバーのメモリに依存してしまうわけだから、スケールアウトができなくなってしまう。

そこで、セッションIDの管理はDBやキャッシュサーバー（Redisなど？）で管理するのが良い。

そうしておけば特定のサーバーの状態に依存するようなことは無くなるので、スケールできる。


# 参考文献
https://dev.to/rdegges/please-stop-using-local-storage-1i04