OmniAICreator/Qiita-1.07M huggingface dataset:
Serverless Framework で iamRoleStatements を設定する

# 概要

serverless framework のデフォルトの`serverless.yml`には、↓のようにコメントアウトされて記載されている。

```yml

# you can add statements to the Lambda function's IAM Role here
#  iamRoleStatements:
#    - Effect: "Allow"
#      Action:
#        - "s3:ListBucket"
#      Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ]  }
#    - Effect: "Allow"
#      Action:
#        - "s3:PutObject"
#      Resource:
#        Fn::Join:
#          - ""
#          - - "arn:aws:s3:::"
#            - "Ref" : "ServerlessDeploymentBucket"
#            - "/*"
```

しかしこれって何を意味していてどう書けばいいの？となって困ったので解決の流れと最終的なコードをまとめる。

# 本編

やりたかったことは、lambda から lambda を呼ぶ InvokeFunction を特定の role に対して許可すること。

調べたら、[公式に書いてあった](https://serverless.com/framework/docs/providers/aws/guide/functions#permissions)のだが、これだけだと十分にわからなかった。
しかし、[こんな質問](https://forum.serverless.com/t/how-it-works-iamrolestatements-configuration-section/467)もあったので、合わせて見てみたら理解できた。

こんな感じで書いて解決した。

```yml
provider:
  name: aws
  runtime: nodejs6.10

  #you can overwrite defaults here
  #stage: dev
  region: ap-northeast-1

# you can add statements to the Lambda function's IAM Role here
  iamRoleStatements:
   - Effect: "Allow"
     Action: "lambda:InvokeFunction"
     Resource: "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:myServiceHoge-dev-invoke_hello" # InvokeFunction を呼ぶ lambda
```
venv 上で jupyter notebookを使う

よく使うのでメモ
venv上でインストールしたモジュールも、jupyter上で使えるようになります。

# 環境
Python3.3 以降
MacOS 10.13.5

#venv

```
# venvの作成
python3 -m venv venv36

# venvのActivation
source venv36/bin/activate

# pip のアップグレード
pip install --upgrade pip

#jupyter notebook のインストール
pip install jupyter
```

# jupyter notebook上でカーネルを選択するために必要なライブラリのインストール(Optional)
```
pip install tornado==4.5.3
pip install ipykernel==4.8.2
```

# jupyterの起動
```
jupyter notebook
```
Vagrant入門

#概要
以下のサイトを参考にVagrantとは何か簡単にまとめました。
####参考サイト
- [What is Vagrant?](https://opensource.com/resources/vagrant)
- [この春エンジニアなった君に使って欲しいVagrant](http://tech.furyu.jp/blog/?p=2317)
- [【Quora】What is Vagrant (software)?](https://www.quora.com/What-is-Vagrant-software)
- [Vagrant公式](https://www.vagrantup.com/docs/)
- [仮想マシンとは？](https://eng-entrance.com/linux-vm)


#Vagrantとは？
__Vagrant__とは[Virtual Box](https://www.virtualbox.org/wiki/Downloads)のような仮想化ソフトと共に用いることで、様々な仮想環境を簡単に構築・管理し、配布することができるオープンソースソフトウェアです。
これによって、あなたのローカルPCの環境を変更せずとも、全く別の環境・設定で自由自在にテストや開発を行う事が可能です。
####仮想マシンとは？
１つのコンピュータの上に「仮想的に」もう一台全く別のコンピュータを動かすシステムの事を__仮想化__と呼びます。
そして、これによって作り出された仮想的なコンピュータが__仮想マシン__です。


#なぜVagrantを使用するのか？
__Vagrant__を利用する事で以下のような利点が挙げられます。

- ホストマシンの環境に左右されず、複数の開発者間で同様の環境を共有する事が可能。
- 仮想マシンを何度でも壊す→立ち上げるができる。（何の心配もなく様々な事を試せる）
- ホストPCのOSに関係なく別のOSを動かす事ができる。

#Vagrantの基本用語解説
|用語|概要|
|:--|:--|
| Box | 環境を構築するためのテンプレート(仮想マシンのひな形) | 
| Vagrantfile | 作成する仮想マシンの設定ファイル | 
| "vagrant"コマンド |端末で実行するためのコマンド |

#Vagrantの基本コマンド

####Vagrantの初期化

```console
vagrant init
```

####VagrantのBoxのリストの表示

```console
vagrant box list
```


####sshログイン
```console
vagrant ssh
```

####仮想マシンの稼働

```console
vagrant up
```

####仮想マシンの停止

```console
vagrant halt
```

####仮想マシンの再起動

```console
vagrant reload
```

####仮想マシンの削除

```console
vagrant destroy
```

####仮想マシンの状態確認

```console
vagrant status
```

####仮想マシンの一時停止

```console
vagrant suspend
```

####仮想マシンの一時停止からの復帰

```console
vagrant resume
```
0で揃えた連番を生成したい時

## 000、001、002、003...100と手打ちはしたくない。
時々、0で桁数を揃えて（パディング）処理を行う、という作業が必要になります。
20個くらいなら気軽に手打ちで頑張ろうとも思いますが、100個を超えるとなかなか大変です。
しかし、ディレクトリ作成やファイル処理など意外と使います。

わかっていないなりに、 `for i in {0..100}`で連番を生成したのち`printf %03d ${i}`とやっていたのですが、
もっとスマートな書き方があると教わったので書き残したいと思います。

## 連番を生成するseqコマンド
まずはエクセルでドラックして作った連番を貼り付ける、なんてことはせず、コマンドで連番生成の方法から。
大変便利なseqコマンドを紹介します。

seqコマンドは基本的に初めの数値と終わりの数値を指定するだけのシンプルなコマンドです。

```seq01.sh
seq 1 10

#出力結果
1
2
3
4
5
6
7
8
9
10
```

嬉しいのは、1行につき1つの値なので、改行処理などを行わなくていいことです。

整数だけでなく小数も可能ですし、昇順・降順も指定可能です。


## 活用例
冒頭でもお話しした通り、連番のディレクトリが必要になることがあります。
その時のコマンドは下記の通りです。

```make100dir.sh
for n in  `seq -f %03g 1 100`; do mkdir hoge${n}; done
```

これで完了です。
サクッと Go → WebAssembly を試す

Go 1.11 から正式に Go の WebAssembly(wasm) サポートが導入されるのに先立ち、Go を wasm 化しブラウザでサクッと実行する手順をご紹介します。

## 概要
- Go 1.11beta1 で Go のコードを wasm に変換
- ブラウザで wasm を読み込むための html と js を用意
- ブラウザで Go の main 関数を実行

## Go から wasm 生成するための Go コマンドを準備する

Go から wasm を生成するためには Go 1.11 のバイナリが必要ですが、今回はそのβ版である Go 1.11beta1 を利用します。
（もちろん master にも wasm サポートが取り込まれているので、そちらを使っても構いません）

https://github.com/golang/go/releases/tag/go1.11beta1

また、 Go 1.11beta1 を利用するために `go` コマンドの代わりとなるその名も `go1.11beta1` コマンドが公式のサブリポジトリとして用意されているので、 `go` コマンドのバージョンを切り替えたくないときや一時的に Go 1.11beta1 を使いたいときはこちらを使うと良いでしょう。次のコマンドラインでインストールできます。

```sh
$ go get golang.org/x/build/version/go1.11beta1
$ go1.11beta1 download
```

## Go を wasm に変換する

今回は次の Go コードを用います。これをブラウザ上で実行するとコンソールに `Hello, wasm!` と表示される予定です。

```go:main.go
package main

import "fmt"

func main() {
	fmt.Println("Hello, wasm!")
}
```

このコードを `go build` で wasm に変換します。ただしデフォルトで吐かれるバイナリは Go をインストールした環境に最適化されるので、wasm 用のバイナリを吐くための環境変数 `GOOS=js` と `GOARCH=wasm` を設定します。

```sh
$ GOOS=js GOARCH=wasm go build -o test.wasm main.go

# go1.11beta1 コマンドを使う場合
# $ GOOS=js GOARCH=wasm go1.11beta1 build -o test.wasm main.go
```

## ブラウザで wasm を読み込むための html と js を用意
公式が用意している最新のコードをそのまま引っ張ってきます。

```sh
$ curl -sO https://raw.githubusercontent.com/golang/go/master/misc/wasm/wasm_exec.html
$ curl -sO https://raw.githubusercontent.com/golang/go/master/misc/wasm/wasm_exec.js
```

## Web サーバを起動する

カレントディレクトリ配下の静的ファイルを返すだけの簡易 Web サーバーを作りましょう。ちょうどこんな感じですね。

```go:server.go
package main

import (
	"flag"
	"log"
	"net/http"
)

func main() {
	addr := flag.String("a", ":5555", "address:port")
	flag.Parse()
	log.Printf("listening on %q\n", *addr)
	log.Fatal(http.ListenAndServe(*addr, http.FileServer(http.Dir("."))))
}
```

それではさっそく起動してみましょう！

```sh
$ go run server.go

# go1.11beta1 コマンドを使う場合
# $ go1.11beta1 run server.go
```

そしてブラウザで `localhost:5555/wasm_exec.html` にアクセスしてみましょう！

ブラウザの左上に `Run` ボタンが表示されていると思いますが、wasm を読み込むまでは disabled になっています。

`Run` ボタンが押せる状態になったらコンソールを開き `Run` ボタンを押しましょう。
（コンソールの開き方は説明いりませんね？）

無事コンソールに `Hello, wasm!` と表示されれば、Go の wasm 化およびブラウザへの読み込み成功です！
（ついでに `test.wasm` のレスポンスヘッダの `Content-Type` が `application/wasm` になっていることも確認しておきましょう）

## 参考
- [Go and wasm: generating and executing wasm with Go - Gopher Academy Blog Community Contributed Go Articles and Tutorials](https://blog.gopheracademy.com/advent-2017/go-wasm/)
台湾華語まとめ

#打招呼 dǎ zhāo hu（あいさつ）

## 01.你好
|中国語|ピンイン|日本語|
|:---|:---|:---|
|早安。|zǎo ān|おはようございます。|
|午安。|Wǔ ān|こんにちは。|
|晩上好。|Wǎn shàng hǎo|こんばんは。|
|晚安。|wǎn ān|お休みなさい|

## 02.好久不見了

### 例文
A：您好，好久不見呢！
こんにちは、お久しぶりですね。

B：對啊，好久不見啊！
そうですね。お久しぶりですね！

## 03.最近好嗎？

### 基本
|中国語|ピンイン|日本語|
|:---|:---|:---|
|你好嗎？|Nǐ hǎo ma?|お元気ですか？|
|過得怎麼樣。|Guò dé zěnme yàng.|いかがですか？|
|最近怎麼樣。|Zuìjìn zěnme yàng.|最近いかがでしたか？|

### 質問例文

|中国語|ピンイン|日本語|
|:---|:---|:---|
|你今年夏天過得怎麼樣？|Nǐ jīnnián xià tiān guò dé zěnme yàng?|あなたの今年の夏はどうでしたか？|
|最近工作好嗎？|uìjìn gōngzuò hǎo ma?|最近仕事はどうですか？|
|最近身體好嗎？|Zuìjìn shēntǐ hǎo ma?|最近調子はどうですか？|
|最近家裡好嗎？|Zuìjìn jiālǐ hǎo ma?|最近ご家族はどうですか？|
|最近學業好嗎？|uìjìn xuéyè hǎo ma?|最近勉強はどうですか？|

### 回答例文

|中国語|ピンイン|日本語|
|:---|:---|:---|
|一切都順利。|Yīqiè dōu shùnlì.|順調です。|
|很好喔！|Hěn hǎo ō!|元気ですよ。|
|非常好喔！|Fēicháng hǎo ō!|とても元気です。|
|還是一樣。|Háishì yīyàng.|相変わらず。|
|就那樣囉！|Jiù nàyàng luō!|まあまあです。|

### 対話例文

`Zǎo ān, hǎojiǔ bùjiàn, zuìjìn hǎo ma?`
A：早安，好久不見，最近好嗎？
おはようございます。お久しぶりです、お元気ですか？

`Zǎo ān, wǒ hěn hǎo ō!`
B：早安，我很好喔！
おはようございます。元気ですよ。

### 返答例文

|中国語|ピンイン|日本語|
|:---|:---|:---|
|有遇到一點困擾。|Yǒu yù dào yìdiǎn kùnrǎo.|ちょっと困っています。|
|身體不太擾服。|Shēntǐ bù tài rǎo fú。|元気ではありません。|
|心情很煩呢！|Xīnqíng hěn fán ne！|悩んでいます。|
|有點累。|Yǒudiǎn lèi.|ちょっと疲れています。|
|很忙呢。|Hěn máng ne.|忙しいです。|
|生病了。|Shēng bìngle.|病気です。|

### 丁寧対話例文

`Nín hǎo, hǎojiǔ bùjiàn, qǐngwèn zuìjìn hǎo ma?`
A：您好，好久不見，請問最近好嗎？
ご無沙汰しております。最近はいかがお過ごしですか？

`Hǎojiǔ bùjiàn ne! Zuìjìn yǒudiǎn mánglù ne.`
B：好久不見呢！最近有點忙碌呢。
久しぶりですね。最近忙しいですね。

## 03.聊天氣（Liáotiān qì）天気の雑談？

|中国語|ピンイン|日本語|
|:---|:---|:---|
|今天的天氣真好。|Jīntiān de tiānqì zhēn hǎo.|今日はいい天気ですね。|
|今天的天空真晴朗。|Jīntiān de tiānkōng zhēn qínglǎng.|今日は晴れましたね。|
|天氣好糟啊！|Tiānqì hǎo zāo a!|天気が悪いですね！|
|今天的天氣不太好。|Jīntiān de tiānqì bù tài hǎo.|今日は嫌な天気ですね。|

### 対話例文

`Zǎoshang hǎo, jīntiān de tiānqì zhēn hǎo ne!`
A：早上好，今天的天氣真好呢！
おはようございます。今日はいい天気ですね。

`Zǎo ān a, duì a, jīntiān de tiānqì hěn hǎo ne!`
B：早安啊，對啊，今天的天氣很好呢！
おはよう。そうですね。いい天気ですね。

`Xīwàng jīntiān yì zhěng de tiānqì dōu zhème hǎo.`
A：希望今天一整的天氣都這麼好。
今日はずっと晴れだといいですね。

`Wǒ yě xīwàng rúcǐ.`
B：我也希望如此。
そうだといいね。

※如此＝このようである，そのようである。
DistributedLog

# 详解DL
https://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=403051208&idx=1&sn=1694ac05acbcb5ca53c88bfac8a68856&scene=2&srcid=1224xZuQ9QQ4sRmiPVdHTppL&from=timeline&isappinstalled=0

# State machine replication
https://en.wikipedia.org/wiki/State_machine_replication

# Producer–consumer problem
https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem

# Consensus Algorithm
https://en.wikipedia.org/wiki/Consensus_algorithm
https://draveness.me/consensus
HTML5のdatalist

``` html
<select>
  <option value="ja">日本語</option>
  <option value="en">英語</option>
</select>
```
DBに登録しておいた内容から選ばせたいので
セレクトタグを使い選択させる

しかし自由入力も可能にして欲しいと言われる
selectタグってそんなことできたっけ？となり調べた結果

``` html
<input list="lang"/>
<datalist id="lang">
  <option value="ja">日本語</option>
  <option value="en">英語</option>
</datalist>
```

datalistを見つけました
html5の機能でテキスト入力にオートコンプリート機能を付けてくれる
optionの中身はDBから取得すればいいので対応可能でした

safariでは動かないらしいので[datalist-polyfill](https://github.com/mfranzke/datalist-polyfill)を導入する
Javaの有償化問題、Java8のサポート終了問題について、2019年1月以降どうしたらいいか

**この記事は3分程度で読めます。**

ふわっとした情報が多いため、調べたことを備忘として残します。
(調べても結局ふわっとした感じはぬぐえていない( ﾉД`))
※2018/7/3現在の情報です。

# 何がまずい？
JDK8(java8)の商用サポート期限が2019年1月で終了する(例外はあるが、後述)。以降、致命的な脆弱性があった場合にパッチが提供されないため、2019年1月までにはJDKのバージョンを上げないとセキュリティを担保できない。

# OracleJDK(JavaJDK)を8より新しいバージョンにアップデートすればいいか？
OracleJDKは2018年9月リリース予定のJava11をもって、ライセンス契約者のみの配布となるため、有償サポート契約が必要になる。
LTS版(長期サポート版、現在はJDK8がこれにあたる。次が11)のバージョンアップは3年毎のサイクルで行う予定。
短期サポート版(JDK9,10,12,13等)のバージョンアップは半年サイクルで行う。

有償サポートのプランや価格については、月額モデル等の新たなプランが米オラクルでは発表されたため、近いうちに日本オラクルより、何かしらアナウンスがあると思われる。
**有償サポートを受けた場合の特典として、JDK8のサポートが最大2025年まで延長されるという特典がある。**

# 無償のJavaは無いの？
存在する。が、OracleJDKから他のJDKへの切り替えは、Javaをバージョンアップする様なイメージになるため
切り替えを行う場合は、動作保証のためのテストフェーズが発生すると思って下さい。

## OpenJDK
OSS開発のJDK。内部的な違いはあるが、Oracleと連携をとって開発されており、機能的な差異は無いとされている。
バージョンアップは半年ペースで、最新版のみをサポート対象とする予定。
LTS版をリリースするという話が出ていたが、公式発表は無く、あまり期待できない。
RedHat社はOSに内包するOpenJDK8のサポートを独自に2020年10月まで行うとのこと。

## AdoptOpenJDK
OpenJDKのビルドを提供するプロジェクト。IBM、マイクロソフト等がバックアップしており、OpenJDKの提供しているJDKよりも多くのプラットフォームに対応している。(AIX等)
こちらは半年ごとにアップデートする通常のバージョンに加え、**4年のサポートを行うLTS版を提供する予定である。**


# 現在考えられる選択肢は…
・Oracle社の有償サポートを受けJDK8を使い続ける。
・Oracle社の有償サポートを受け、LTS版のJDK11へ切り替えを行う。3～4年ごとにバージョンアップを行う
・OpenJDKへの切り替えを行い、半年ごとにバージョンアップを行う
・OpenJDKへの切り替えを行い、2020年10月まで様子を見る。※OSがRedHatの場合のみ
・AdoptOpenJDKへの切り替えを行い、3～4年ごとにバージョンアップを行う


# 総評
無償で使う場合、AdoptOpenJDKが現実的でしょうか。JDK8の終焉まであと半年と迫っていますがあまり情報がありませんね。
そろそろ何か発表がありそうですが、発表があれば追記したいと思います。
ReactプロジェクトにPrettier(JSのコード整形)を追加

# Prettierとは 

JSのコードをいい感じに整形してくれる。コード規約とか考えずに設定ファイルを元に強制的にコード整形してくれるいい人。

[おためし:information_desk_person:](https://prettier.io/playground/)

自動で整形してほしいので、gitでコミットしようとすると先に整形してコミットしてくれるようにします今回

導入した自分のプロジェクトはこれ
https://github.com/ksyunnnn/react-starter

# 方法

既存プロジェクトがある想定で進めますお

## プロジェクトに追加

```
yarn add prettier
# or
npm install prettier
```

## プロジェクトルートに 設定ファイル作成

設定できる項目は[ここ](http://json.schemastore.org/prettierrc)

自分は[おためし:information_desk_person:](https://prettier.io/playground/)で確認して、デフォルトから変更した部分だけを記載しました。

```json:.prettierrc
{
  "printWidth": 100,
  "parser": "babylon",
  "tabWidth": 2,
  "singleQuote": true,
  "trailingComma": "all",
}

```

## ためしてみる

```
./node_modules/.bin/prettier --write "./**/*.js"
```
※グローバルインストールしてないので？binへのパス書いてる

これで実行されれば`Prettier`の導入は完了

## `git commit`に整形する

正確には`git add`のあとかな

```
# 必要なモジュール追加
yarn add lint-staged husky
```

```json:package.json
{
  "scripts": {
    "precommit": "lint-staged"
  },
  "lint-staged": {
    "*.{js}": ["prettier --write", "git add"]
  }
}
```

## ためしてみる

適当にファイル修正してから

```
git add .
```

なにもおきない

```
git commit -m "hoge"
```

<img width="309" alt="Screen Shot 2018-07-03 at 16.46.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/117615/ee4e9589-f31f-0699-1580-e626079df257.png">

なんか動いたっぽい

完了 :muscle:
今からオブジェクト指向と戦う君たちへ

#オブジェクト指向とは犬と猫は動物、バスとトラックは自動車

---

#動物基底クラスを作り鳴く関数を実装し、動物基底クラスを継承する

---
##何を言っているんだ？
この例えは自分が新米プログラマだったころ見た入門書かなにかに書かれていた例えだ。
当時は理解したつもりで居たが現場にでてプログラミングしようとすると全く役立たなかった。

---

正確に言うとオブジェクト指向プログラミングと言う機能の説明としては的を得てる。
しかし、どうその機能を使っていく、作っていくとなるとフリーズすることになる。

---

この例え、最初に理解できんと思った人は将来有望なプログラマやシステムエンジニアの素質があるかもしれない。

>Tips「犬と猫 オブジェクト指向」で検索すると同じく異を唱える先駆者を見て回ると良い

---

理解できないポイントは人により異なるだろうが、今回重視するのは、なぜ動物でくくるのか、自動車で括る必要性がどこにあるのかと言う点だ。

---

プログラマが日常的に作っているものはメルカリに最安品が出たらツイートするプログラムだったり、商品テーブルからご希望に沿う商品を検索するシステムだ。

そこに犬と猫を動物で括り、鳴くのは共通だと求められる場面はどこにも存在しない。

---

つまり犬と猫は動物だと決まっているが
プログラマが作るソースコードには決まった正解が存在していることは稀である。
これを常に意識しなければならない。
(ベストやベターという話は出てくるが正解は無いと考える)

---

##必要なのは想像力

---

**"犬"** と聞いて吠える、嗅ぐ、調教するあるいは、動物なのか４足歩行なのか哺乳類なのかネコ目なのかと思慮する想像力が必要である。

そのうえでどうして犬と猫に **鳴く** を実装しなければならないのか考えなければならない。

「走る」は必要なのでは？とか「マーキング」はいらないのかとか「爪を研ぐ」はいらないのかなどなどあらゆる要素から必要なものを選びだすことが重要である。


---

これがオブジェクト指向の３原則「継承」「カプセル化」「ポリモーフィズム」に繋がっていく。
三原則がなぜ大切なのかは[オブジェクト指向と10年戦ってわかったこと](http://qiita.com/tutinoco/items/6952b01e5fc38914ec4e)が参考になる。

---

##意識するのは使う側

---

「ツイート」するプログラムを「犬が鳴く」に置き換え、「猫が鳴く」は
「フェイスブック投稿」するプログラムとするともうちょっとわかりやすい例えに思える。

想像力を働かせ、このプログラムに拡張性がでてくるならどんな物をそうぞうするだろうか。

---

想像力を働かせ、このプログラムに拡張性がでてくるなら、「Google+」するだったり、「LINEに送る」「はてブに追加」機能の追加の予想ができればかなりいい線を行ってる。

---

これは使う側がSNSに投稿する機能を求めていると想像できたからだ。

---

#その時点で求められた機能
この時点の想像できる粒度（抽象化カプセル化する単位）は「SNSに投稿する」とできる。

---

だが「メールでリンクを送信」する機能を追加となれば「SNSに投稿する」という粒度は崩壊する。
しかし「メールでリンクを送信」まで考えた実装をしてしまうと求められていない機能が載った過剰な実装になりがちだ。

---

多くのSNSがAPIを用意しており、さらにOAuthで認証するであろうという点で、
SNSに投稿するという粒度は**その時点でもっともベターで妥当性のある実装あると**と主張できるだろう。

しかしこれらの判断は最初から出来るかというとそれは難しい。
これらを主張するためには経験と知識に裏打ちされた自信がなければ出来ない。

---
##思考せよ

---

経験、知識、自信は悩んだ分だけ成長する。

現場に出ていくと初めのうちはテストだったり、クラス設計までされた設計書をもとにプログラミングして行くことが多く思うような経験知識がつかないかもしれない。

しかしそこで思考を止めず、想像を膨らませ、思考せよ。

---

つまりコーディング中なぜこの処理が必要なのか考えることが大切である。設計書には平気で辻褄が合わない事や常識知らずな事が書いてある。

（ログインIDを忘れたのに再発行にログインしてる必要があったり、パスワードを平分でDBに突っ込んだり）

---


それらを何も考えずあとから指摘され設計書に書いてあるからと言い訳するのは成長をするチャンスを失うことになる。

（とは言え多くの場面で設計書に書いてんだろｵﾗｱｱｧｱｱ！！！という言い訳は多用するけどね…）
（まぁ大規模PJの一翼の木っ端だと全容を掴むのは難しいところも有るが…）

---

##というわけで

先のツイートの例しかり適切な粒度は個人によって異なり正解は無い。

なので違和感を覚える人も居ると思うが少なくても**考えて作られた実装**、**どういう粒度にするか考えた作り**は仮にその粒度が変更になっても改修は少なく収まる場合が多いと考えている。


---

悲しくも大きく読みを外した場合でも早々にこのクラスは拡張できないと判断し、流用した別クラスを作ると決断するのも容易だ。

これは想像せず思考せず作られた1クラス１ファンクションで２０００行を超える超大作なソースコードには不可能なことである。

---

考えて作った実装が役立たずであってもそれは次に生かせる成長になる。
それは考えた上での結論を導き出した結果は蓄積され次に同じ失敗を犯すことが減るからだ。
残念ながら考えないで作った実装では平気で同じ失敗を繰り返すのでこのような成長は得られない。

当然他人と衝突もするだろうが、奥せず考えを伝えよう。
それらすべてが経験となり、いざという時、かならず力になる。

以上

---

#ご清聴ありがとうございました。

---

####この記事
自社で新人教育のために夜も寝ないで昼寝して作った資料を再編したもので

これは自分自身がこの業界に入った時というか
学校にいる時からずっとモヤモヤしてたオブジェクト指向の説明に使われる”動物-自動車のたとえ”に対する10年前の自分への回答のようなものです。
git aliasを活用してgitを爆速で操作する

# `git config`コマンドで`alias`を設定

```sh
git config --global alias.co checkout
```

このように`checkout`に`co`というエイリアスを設定すると、`git co master`と打つだけで`git checkout master`と同等に打つのと同等になります。
`git co -b hoge`のようにエイリアスに続けて追加で複数のオプションや値を渡すこともできます。

なお、オプション付きのエイリアスを設定する場合は下記のように`''`か`""`でクオートしてあげる必要があります。

```sh
git config --global alias.pf 'push -f'
git config --global alias.aa 'commit --amend -a --no-edit'
```

律儀に`git checkout master`とカタカタとタイプしている人を見ると、エイリアス設定しようよ！と言いたくていつもムズムズしちゃいます。

```sh
git config --global alias.cm 'checkout master'
```

このようにエイリアスを設定すれば`git cm`ターーン！！！（ドヤ顔）でオッケー。

# `~/.gitconfig`を直接編集して`alias`を設定

`git config --global`で設定した項目は、ホームディレクトリ配下の`~/.gitconfig`ファイルに保存されます。`git config`コマンドでちまちま設定しなくても、このファイルを直接編集してもオッケーです。`[alias]`の行に続く部分が文字通りエイリアスの設定です。

----

下記が僕の`alias`の設定です。
これをコピペして、思うままにカスタマイズして使っていただけると幸いです。

```ini
[alias]
	a = add
	b = branch
	c = commit
	d = diff
	f = fetch
	g = reflog
	l = log
	m = merge
	p = pull
	r = rebase
	s = stash
	t = tag
	w = show
	aa = commit --amend -a --no-edit
	bd = branch -D
	bl = branch -a
	cm = checkout master
	co = checkout
	cp = cherry-pick
	df = difftool
	du = difftool @{upstream}
	mm = merge origin/master
	pf = push -f
	re = reset --soft HEAD~
	rh = reset --hard
	ri = rebase -i
	rs = reset --soft
	sl = stash list
	st = status
	su = submodule update
	pop = stash pop
	wip = commit -a -m \"[ci skip] WIP WIP WIP WIP WIP\"
	amend = commit --amend --no-edit
	shallow = clone --depth 1
```

これらの中から僕がよく使う超絶オススメ必殺エイリアスを紹介していきます。

# お勧め`alias`

## `git aa` 直前のコミットにブッコムやーつ

```sh
git config --global alias.aa 'commit --amend -a --no-edit'
```

これは、コミットされていない状態の全て差分を、直前（最新）のコミットにぶっこむコマンドのエイリアスです。
`commit`に`--amend`オプションを付けると、新たにコミットを追加するのではなく、直前のコミットを修正するような動作になります。
`-a`オプションを付けると`git add`で`stage`に追加していない修正もコミットの対象になります。`git add .`を省略できるイメージです。
最後に`--no-edit`を付けることでコミットのタイトル・メッセージを編集するステップを省いています。
直前のコミットに修正漏れがあったような場合に、「追加の修正」のようなコミットを付け足すのは超絶イケてないので、今日からは`git aa`を使いましょう！

## `git wip` とりまコミットしとくやーつ

```sh
git config --global alias.wip 'commit -a -m "[ci skip] WIP WIP WIP WIP WIP"'
```

これは、コミットされていない状態の全て差分を、サクッと一発でコミットするコマンドのエイリアスです。
`[ci skip]`をコミットタイトルに含めることで、無駄にCIを回さないようにするオモイヤリもある奥ゆかしいエリアスです。
作業を中断しなければならない場合などに咄嗟に`git stash`を使うと、stashの闇の中で修正が迷子になってしまうので、`git stash`ではなく`git wip`しておくと良いです。

## `git re` コミットを取り消すやーつ

```sh
git config --global alias.re = 'reset --soft HEAD~'
```

これは、直前（最新）のコミットを取り消して、その差分を`stage`に戻すコマンドのエイリアスです。
一度コミットをバラして整理しながらcommitし直したい時に使います。
`git re`を連打すればどんどんcommitを取り消して行けるので便利ですが、branchを切った点より行き過ぎてしまうと困ったことになるので注意しましょう。

# TL;DR

僕は`git wip`と`git aa`でとりあえず修正を1つのコミットにまとめていって、PRを出す直前に`git re`でコミットを取り消して、整理しながらコミットをまとめ直すようにしています。

ソースコードはすごく丁寧で綺麗にコーディングされているのに、gitの履歴（コミットログ）には無頓着になされている人のPRをみると、ちょっと残念というかもったいないなーと思ってしまいます。
gitの履歴を綺麗に保つことは自分にとっても、レビューアにとっても、あとあと履歴を追ってバグの原因探しをする羽目になる人のためにも、とても大切なことだと思います。

ソースコードだけでなく、gitの履歴も綺麗にするように気を使っているエンジニアがもっと増えて欲しいなと思ってます！
ngrok で docker のローカル環境を外部公開

[ngrok](https://ngrok.com/)
これを使って自分の localhost を外部公開したい
Mac の人向けです

## インストール
```bash:インストール
$ brew cask install ngrok
```

もし `brew` が入っていなければ
[The Missing Package Manager for macOS \(or Linux\) — Homebrew](https://brew.sh/)
から設定しよう

## ngrok 起動
```bash:起動
$ ngrok http 3000
```

下記の `Forwarding` が外部公開用のURL

```bash:起動時のコンソール
ngrok by @inconshreveable                                       (Ctrl+C to quit)

Session Status                online
Session Expires               7 hours, 59 minutes
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://12491a60.ngrok.io -> http://localhost:3000
Forwarding                    https://12491a60.ngrok.io -> http://localhost:3000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
```

参考：[ngrokを使用してローカル環境を外部に公開する \- Qiita](https://qiita.com/kitaro729/items/44214f9f81d3ebda58bd)

## ただし！！！

もちのロンでローカルでは docker にてアプリを起動しているので、

```bash:起動
$ ngrok http 8888
```

だと外部公開できなかった
上のコマンドだと、 localhost を外部公開しているからみたい

## docker 🐳

こんな感じでアプリを起動させている
`host=0.0.0.0` とあるので、 `host` を指定して、ngrok を起動したい

```bash:dockerの中に侵入
root@54ec94e72bf0:/usr/src/app# npm run dev

> project@1.0.0 dev /usr/src/app
> cross-env NODE_ENV=development webpack-dev-server --open --hot --host=0.0.0.0 --port=8888

Project is running at http://0.0.0.0:8888/
webpack output is served from /dist/
404s will fallback to /index.html
Unable to open browser. If you are running in a headless environment, please do not use the open flag.
```

## 正解

```bash:正解
＄ ngrok http -host-header="0.0.0.0:8888" 8888
```

## 結論

超絶便利ー
【SQL】INNER JOIN / LEFT JOIN / RIGHT JOINの小さなサンプルメモ

# 前提

結合自体の説明は省略。↓が分かりやすかった。

SQL の基礎 – JOIN (表結合)の意味の違い|てくめも@ecoop.net https://www.ecoop.net/memo/archives/2007-11-14-1.html

SQL素人でも分かるテーブル結合(inner joinとouter join) - Qiita https://qiita.com/naoki_mochizuki/items/3fda1ad6594c11d7b43c

## テーブルとデータ
![テーブル.png](https://qiita-image-store.s3.amazonaws.com/0/50690/70c1df4d-7b60-55ed-477f-531f19065b88.png)


# サンプル

## INNER JOIN

authors.id=3のデータはbooksには無いため、結果に含まれない。

![inner.png](https://qiita-image-store.s3.amazonaws.com/0/50690/0c053d49-d065-0c4e-feb4-7cc2c765cc22.png)

## LEFT JOIN

左がbooksなので、右側にしかないauthors.id=3は結果に含まれない。

![right.png](https://qiita-image-store.s3.amazonaws.com/0/50690/2cfbacc1-139d-3687-32ef-820bd1d348ec.png)


## RIGHT JOIN

右がauthorsなので、右側にしかないauthors.id=3も結果に含まれる。

![right.png](https://qiita-image-store.s3.amazonaws.com/0/50690/fd3e80d9-ad86-0460-5727-e13c28e1d675.png)
「隠れマルコフモデルによるサッカー選手のポジショニングパタンの分析」を読んで

#はじめに
本記事では植田文也氏、誉田雅彰氏によって書かれた「隠れマルコフモデルによるサッカー選手のポジショニングパタンの分析」を読んだ私なりの解釈と、感想を述べていくものとします。
（原著論文リンク：http://jcoachings.jp/jc2016/wp-content/uploads/2017/11/01.pdf）
**※【右クリック】→【URLを開く】で確認できます。**

#論文の内容
従来のサッカーにおける戦術分析の研究を見てみると、定量的でなかったり、選手のフィールド内の座標に注目し分析しており、戦術的な面で分析ができていなかったようです。
今回取り上げた論文は、攻撃中に見られた攻撃シーンを有効な攻撃であるか、非有効な攻撃であるか分類することを目的に学習を行います。
識別精度が高いモデルを作ることができた時以下のようなことがわかると筆者は主張しています。

・どういったパラメータが有効な攻撃か否かを決定することに重要か
・有効な攻撃に影響力のあるパラメータを知ることで、戦術面での指導ができる。

**状態**：選手のとボールの位置がどのようであったか（状態数はあらかじめ決めておく）
とした時

**状態遷移率**：ある状態からある状態へ変化する確率

**生起確率**：各状態から有効な攻撃になる確率、非有効な攻撃になる確率（相手にボールを奪われる等）

が未知です。これらはBaum-Welchアルゴリズムを用いて学習されるため、学習された時系列データの尤度が最大となるよう（最もらしい）パラメータを推定します。

実験として1試合を記録し、分析を行ったところ識別精度に関しては8割ほどの精度が記録され、状態について図示をしてみると、最もらしい有効な攻撃（サイドから攻め、中央にスペースを空ける）などが含まれていました。

#読んだ後の感想と考察
隠れマルコフモデル（以下HMM）を用い行なっています。
HMMについては下記リンクの記事がとてもわかりやすかったので紹介させていただきます。
（隠れマルコフの具体例：https://satomacoto.blogspot.com/2008/07/blog-post.html）


HMMはどのように状態があり、どのような確率で遷移しているかは不明だが、状態からアウトプットされる観測データを観察することで、各状態の遷移率と生起確率を推定できるというものでした。（原則として状態がどのようなものかは推定できません。）
しかし、今回は有効な攻撃であるか否かに影響があるのは選手とボールの位置だという経験則から、状態とは選手とボールの位置だという強い予想が立てられます。
今回の論文で素晴らしいと思ったのはこの工夫でした。
また、状態が設定できないという事は、一見デメリットに感じるかもしれませんが、状態を人間の経験則などを生かさずデータで表現ができるというメリットにもなり得ます。
このように結果の推定のみに焦点を置くのではなく、パラメータに注目して機械学習を行えばより応用的なフィードバックが得られると、とても勉強になりました。
Android StudioにてAAPT2 errorが出た -> 予約語だった…

### あらまし

Android Studio(3.1)にて突然、ビルド時に下記の(ざっくりした)エラーが表示されるようになった。

~~~
AAPT2 error: check logs for details
~~~

そのlogを含めてキーワードを拾ってググったりしてみたが、

自分のミスは間抜けすぎて例が無かったようなので、ここに書いておく。

### エラーの原因

コンポーネントの名前に予約語を使ってしまっていた…。

学校関連のアプリを作っていて、TextViewの名前につい「class」を使ってしまっていた。

「classTxt」に変更したらビルドできるようになったよ！

ちなみに、assetの内部で特定の文字を使っているとAAPT2 errorが出るという情報を見て、

どこかに記述系のミスが無いかなと確認している際に気づいた。

まあこんなこともあるということで。
jsFiddle + Google Maps > 動作状況 (2018-07-03) > Ubuntu + FireFox Quantumで動作

### 関連

- [jsFiddle + Google Maps > 指定の緯度経度範囲(四角)をマーキングで表示 v0.1](https://qiita.com/7of9/items/86657cf16b1905f13664)


### 状況

```txt:動作環境
Windows 8.1 Pro (64bit)
Internet Explorer バージョン 11.0.9600.19036
```

> `Windows 8.1 pro(64bit) + IE`で「セキュリティで保護されているコンテンツのみ表示しています。全てのコンテンツを表示しますか」で「はい」にしたら地図が見えた

2018年7月3日現在、上記と同じ環境で実行したところ、「セキュリティで保護されているコンテンツのみ表示しています。全てのコンテンツを表示しますか」が表示されない。

青色の雲マークが跳ねるアニメーション画像が表示される。

### 動作環境

```txt:動作環境
Ubuntu 16.04.3 LTS desktop amd64
Firefox Quantum v60.0.2 64bit
```

Ubuntu + Firefoxで動作を確認できた。
手順は下記。

1. jsFiddleのページを開く
    - 例: https://jsfiddle.net/1q16ysrx/5/
    - この状態では右下の結果は見えない
2. URLの左側の緑の鍵アイコンをクリック
    - > 安全な接続
    - > このページの一部が安全でないためFirefoxがブロックしました
3. 手順2の右にある「>」をクリック
4. 「このセッションのみ保護を無効にする」をクリック

### 注意

***保護を無効にした実行なので、信頼のおけるサイト以外では実施しないこと***
    
### 備考

Windows環境での動作も可能かもしれないが、調査は保留。
Pythonで無限大(float値)を扱う

Rubyとかではお馴染みのinfinityをPythonでつかおう！  

```python
a = float('inf')
```

これで呼び出せる。

```python
a = float('inf')

a - 1.0
Out[3]: inf

1.0 - a
Out[4]: -inf

a - a
Out[5]: nan

```

`nan`は`None`とは異なる、不動小数点型によって定義された一つの「数」です。

ちなみに

```python
b = float(1 / 0)
Traceback (most recent call last):
  略
    float(1 / 0)
ZeroDivisionError: division by zero
```

wheel theoryにはのっとっていないようです。

　　
完
【Rails】rakeタスクでrender partialしたい人生だった

HTMLファイルを書き出すrakeタスクで、HTMLの一部を別ファイルに分けたいが、`render partial`するとエラーになるので、ちゃんとできる方法を探る。

## 環境
Rails 4.1.10/Ruby 2.2.1
Rails 5.2.0/Ruby 2.6.0-preview2

## 実装
今のところこんな感じになりそう。

```rb:lib/tasks/html.rake
namespace :html do
  desc "HTMLファイル書き出し"
  task output: :environment do
    require "erb"

    TEMPLATE_DIR = "lib/tasks/template".freeze
    OUT_FILE = "lib/tasks/out.html".freeze

    # テンプレートの変数をインスタンス変数にする必要は無いが、一応ローカル変数との区別のために@を付けている
    @title = "たいとる"
    @inner_html = "<span style='color:red;'>ほげ</span>".html_safe

    @controller = ApplicationController.new
    # 今回はrakeタスクと同じ階層にテンプレートを置いておきたかったので、このような設定になっている
    # 通常のアプリと同じく app/views 以下にテンプレートを置くなら prepend_view_path は不要
    @controller.prepend_view_path(TEMPLATE_DIR)

    erb_str = File.read("#{TEMPLATE_DIR}/base.html.erb")
    renderer = ERB.new(erb_str)
    result = renderer.result

    File.open(OUT_FILE, "w") do |f|
      f.write(result)
    end
  end
end
```

ベースになるHTMLテンプレート。

```erb:lib/tasks/template/base.html.erb
<!DOCTYPE html>
<html lang="ja">
<meta charset="utf-8">
<head>
  <title><%= @title %></title>
</head>
<body>
  <%= @controller.render_to_string template: "_body", locals: { inner_html: @inner_html }, layout: false %>
</body>
</html>
```

部分HTMLを適用するポイントは以下の通り。

- `render`ではなく`render_to_string`にする
- `locals`で変数を渡す
- `layout: false`でレイアウト適用を無効化する

部分HTML。

```erb:lib/tasks/template/_body.html.erb
<div id="wrapper">
  <%= inner_html %>
</div>
```

ファイルを揃えたら、`rake html:output`でrakeタスクを実行する。
すると以下のようなファイルが出力される。

```html:lib/tasks/out.html
<!DOCTYPE html>
<html lang="ja">
<meta charset="utf-8">
<head>
  <title>たいとる</title>
</head>
<body>
  <div id="wrapper">
  <span style='color:red;'>ほげ</span>
</div>

</body>
</html>
```

他に良さそうな方法があれば良いかも…
ローカル環境のDockerコンテナの中からAWSのMySQL(RDS)にSSH越しで接続する

所要で久しぶりにSSHポートフォワーディングやったらちょっと躓いたので簡単な作業メモを残しておく。

### 手順

1.&nbsp;ホストのループバックインタフェース `lo0` にエイリアスを当てる

```shell-session
user@docker-host:~$ sudo ifconfig lo0 alias 10.200.10.1/24 
```

2.&nbsp;ホストでローカルポートフォワーディングを張る

```shell-session
user@docker-host:~$ ssh \
    -NL 10.200.10.1:13306:xxxx.yyyy.ap-northeast-1.rds.amazonaws.com:3306 \
    ec2-user@example.com
```

3.&nbsp;コンテナのMySQLクライアントからアクセス

```shell-session
root@docker-container:~$ mysql \
    -h 10.200.10.1 \
    -P 13306 \
    -u dbuser \
    --database example \
    -p
```

もしくはPHPで

```php
$pdo = new \PDO(
    'mysql:dbname=example;host=10.200.10.1;port=13306;charset=utf8mb4',
    'dbuser',
    'dbpassword',
    [
        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
    ]
);
```


### 参考

- [Docker for Mac上のコンテナから、Mac上のアプリケーションに簡単に接続する方法 - Qiita](https://qiita.com/Asayu123/items/ccfe4ccfc417ce57f445)
- [sshのport forwarding - うまいぼうぶろぐ](https://hogem.hatenablog.com/entry/20080824/1219580977)
Vuetifyを1.0.*から1.1.*にアップグレードしたら "$attrs is readonly" で怒られたときの対処

## 利用環境

* Rails@5.2.0
* vue@2.5.16
* vue-loader@4.2.2
* vuetify@1.1.1

## 発生状況

vuetifyを1.0.19から1.1.1にアップグレードしたら発生

```
$attrs is readonly
$listeners is readonly
```
関連のエラーがコンソールに出力されました

エラー内容は下記のissueの通りでした
https://github.com/vuetifyjs/vuetify/issues/4068

## 対処法

vuetify側とのvueの参照が違ったことが悪かったようなので
(Vueのインスタンスが複数ある状況下で起きるらしい？ google翻訳より)

```javascript
import Vue from 'vue/dist/vue.esm'  <- これ
```

ランタイムビルドのaliasを追加することで回避できました

```javascript:config/webpack/environment.js
environment.config.merge({
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }
})
```

以下記載箇所すべて変更

```javascript
- import Vue from 'vue/dist/vue.esm'
+ import Vue from 'vue'
```
SymfonyとLaravelのパフォーマンス比較

先日ちょっとした機会があってSymfonyとLaravelの負荷テストを行ったことがありましたので、そのときの結果を共有させていただきたいと思います。

## テスト環境
- EC2: m4.large
- Amazon Linux: 忘れた
- Nginx: 忘れた
- php: 7.2
- Laravel: 5.6
- Symfony: 3.4

### チューニングに関して
- phpはopcacheを有効にしてvalidateしない設定にしてチューニング。
- php-fpmもプロセス管理をオートではなく、dynamicで設定。
- max_childrenとかstart_servers, min_spare_serversとかを適宜設定。

### システム要件
- Nginxサーバでリクエストを受け付けて、同サーバ内のphp-fpmにFatCGI形式で投げる(unixソケット経由)。
- Symfony/Laravelは同VPC内の別のAPIサーバにhttpリクエストしてJSON形式でデータを受け取り、パースして簡単な表示を行う。
- SymfonyもLaravelもhttp clientはguzzleを採用。


## テスト結果

### Laravel
|同時接続数|レスポンスタイム(ms)|スループット(requests/s)|
|--:|--:|--:|
| 10 | 19 | 14.85 |
| 20 | 36 | 23.22 |
| 30 | 83 | 22.3 |
| 40 | 122 | 22.58 |
| 50 | 175 | 22.17 |

![laravel.png](https://qiita-image-store.s3.amazonaws.com/0/237077/b2da7fba-d8ae-a75e-ba52-3016542b1ee3.png)

同時接続数を10ずつ刻んで上げていきました。レスポンスタイムは徐々に上がっていきます。スループットは20くらいで頭打ち（泣）

### Symfony

|同時接続数|レスポンスタイム(ms)|スループット(requests/s)|
|--:|--:|--:|
| 10 | 20 | 14.89 |
| 20 | 69 | 16.44 |
| 30 | 129 | 16.55 |
| 40 | 195 | 15.65 |
| 50 | 252 | 15.64 |

![symfony.png](https://qiita-image-store.s3.amazonaws.com/0/237077/c91e2b88-f7b1-aad9-7259-a02c8a601ca4.png)

こちらもレスポンスタイムは順調に遅くなっていきます。スループットも20くらいで頭打ち。そんなに変わんないな。

### レスポンスタイムの比較

![レスポンスタイム.png](https://qiita-image-store.s3.amazonaws.com/0/237077/07773b6b-f047-c0a6-483b-828ed57a5b60.png)

レスポンスタイムは総合的にLaravelのほうが速め。同時接続が20のときは倍くらい違う。だいたい30msくらい速い。ただし、20ですでに頭打ちなので、それ以上の実績はあまり参考にならないかも。

### スループットの比較

![スループット.png](https://qiita-image-store.s3.amazonaws.com/0/237077/7c48adae-ec42-5c78-bc7f-b022ff2b15a5.png)

スループットでもLaravelのほうがいい。これを見る限りLaravelは20もうちょっとくらい行けそうだが、Symfonyはまあ20くらいなのかなぁという程度。

## 考察・総括
まあ20くらいの同時接続でこんな感じなので正直負荷テストとしてはあまりいい結果になっていない。同時接続は5ずつくらいで刻んでも良かったかもしれない。

実はphp以外にもRubyやNodeでのパフォーマンス計測が先に行われていて、そっちは100とか200とか同時接続しても捌けていたので100くらいまではやるつもりでいたので、こんな感じになってしまいました。

以前、2コアのマシンでもphp5.6、CakePHP2系のアプリケーションががんばっても同時接続で20くらいだったので、こんなもんか。

正直どんくらべの背比べ状態なのですが、Symfonyは4系が出ているにも関わらずLTSの関係上v1で使えなさそうだったので、3系でテストをしています。一方Laravelは最新の5.6でLTSではないのですが、v1が世に出るときにはLTSになっていそうな雰囲気だったので最新版を使っています。そういう意味ではちょっとフェアではなかったかも。Symfony4だったらもっと速かったかもしれない。

ちなみにムキになってバックエンドのAPIへの接続をやめたり、Lumenやあまり余計なものが入っていないSymfonyでテストしてみましたが多少パフォーマンスは良くなるもののあまり変わらなかったです。
ubuntu16.0.4 LTS でpython3.6をインストールしたときにpip3が更新されない場合の対処法

# エラーの出力
https://www.python.jp/install/ubuntu/index.html
上の手順に則ってubuntuにpython3.6をインストールした際に最後のコマンドである

```
sudo python3.6 get-pip.py
```

を実行した際にエラーが発生する場合がある。

その際は以下のようなエラーが出力される。
※下記の例はrootで実行しています。

```bash
root@test:~# python3.6 get-pip.py
Traceback (most recent call last):
  File "get-pip.py", line 20649, in <module>
    main()
  File "get-pip.py", line 197, in main
    bootstrap(tmpdir=tmpdir)
  File "get-pip.py", line 82, in bootstrap
    import pip._internal
  File "/tmp/tmpruuzep87/pip.zip/pip/_internal/__init__.py", line 42, in <module>
  File "/tmp/tmpruuzep87/pip.zip/pip/_internal/cmdoptions.py", line 16, in <module>
  File "/tmp/tmpruuzep87/pip.zip/pip/_internal/index.py", line 25, in <module>
  File "/tmp/tmpruuzep87/pip.zip/pip/_internal/download.py", line 35, in <module>
  File "/tmp/tmpruuzep87/pip.zip/pip/_internal/locations.py", line 10, in <module>
ImportError: cannot import name 'sysconfig'
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 63, in apport_excepthook
    from apport.fileutils import likely_packaged, get_recent_crashes
  File "/usr/lib/python3/dist-packages/apport/__init__.py", line 5, in <module>
    from apport.report import Report
  File "/usr/lib/python3/dist-packages/apport/report.py", line 30, in <module>
    import apport.fileutils
  File "/usr/lib/python3/dist-packages/apport/fileutils.py", line 23, in <module>
    from apport.packaging_impl import impl as packaging
  File "/usr/lib/python3/dist-packages/apport/packaging_impl.py", line 23, in <module>
    import apt
  File "/usr/lib/python3/dist-packages/apt/__init__.py", line 23, in <module>
    import apt_pkg
ModuleNotFoundError: No module named 'apt_pkg'

Original exception was:
Traceback (most recent call last):
  File "get-pip.py", line 20649, in <module>
    main()
  File "get-pip.py", line 197, in main
    bootstrap(tmpdir=tmpdir)
  File "get-pip.py", line 82, in bootstrap
    import pip._internal
  File "/tmp/tmpruuzep87/pip.zip/pip/_internal/__init__.py", line 42, in <module>
  File "/tmp/tmpruuzep87/pip.zip/pip/_internal/cmdoptions.py", line 16, in <module>
  File "/tmp/tmpruuzep87/pip.zip/pip/_internal/index.py", line 25, in <module>
  File "/tmp/tmpruuzep87/pip.zip/pip/_internal/download.py", line 35, in <module>
  File "/tmp/tmpruuzep87/pip.zip/pip/_internal/locations.py", line 10, in <module>
ImportError: cannot import name 'sysconfig'
```

## 解決策
これは単に`python3-distutils`のインストールが不足している場合に発生する問題の様です。前述のエラーが出た場合、以下の順にコマンドを実行すると解決すると思います。

```bash
sudo apt install python3-distutils
sudo python3.6 get-pip.py
```

## 参考リンク
https://github.com/pypa/pip/issues/5356
Unity と Mac で開発する Oculus Go アプリ #9 OVRPlugin.cs error CS0103: The name `OVRP_1_15_0' does not exist in the current context

次のエラーが出ました

```
Assets/Oculus/VR/Scripts/OVRPlugin.cs(2876,18): error CS0103: The name `OVRP_1_15_0' does not exist in the current context
```

<img width="500" src="https://qiita-image-store.s3.amazonaws.com/0/33505/67a11716-f7af-1b87-bf71-fcf65edf558c.png">

Oculus のフォーラムでも取り上げられていました
https://forums.oculusvr.com/developer/discussion/comment/621440

原因はMac OSだからでしょうか


## 解決方法

`OVRP_1_15_0`を使っている該当項目に `OVRPLUGIN_UNSUPPORTED_PLATFORM` の判定を入れる

```c#
		frustum = default(Frustumf2);
#if !OVRPLUGIN_UNSUPPORTED_PLATFORM
		if (version >= OVRP_1_15_0.version)
		{
			Result result = OVRP_1_15_0.ovrp_GetNodeFrustum2(nodeId, out frustum);
			if (result != Result.Success)
			{
				return false;
			}
			else
			{
				return true;
			}
		}
		else
    #endif
		{
			return false;
		}

```

これでエラーは消えた
【Angular】ダブルクリックでinputになり、blurで元に戻るやつ

# 完成したもの
## 動画
[![完成したものの動画](http://img.youtube.com/vi/s9BlxHm30Lo/0.jpg)](http://www.youtube.com/watch?v=s9BlxHm30Lo)

## ソースコード
[GitHub](https://github.com/RyoMiyashita/ng-click-input)
（ https://github.com/RyoMiyashita/ng-click-input ）

# アプリケーションの概要
- macOS Sierra: 10.12.6
- npm: 5.7.1
- Angular CLI: 6.0.8
- Node: 8.9.4
- Angular: 6.0.7（4以上で動く??）
- rxjs: 6.2.1
- typescript: 2.7.2
- webpack: 4.8.3

# 解説
div要素でnameを表示しておく。divがダブルクリックされたら関数を動かしてフラグを反転する。
フラグを用いて表示していたdivを非表示にし、代わりにinputを表示させる。
inputのblurを使ってフォーカスが外れたタイミングで再度フラグを反転させることによってinputが非表示になり、divが表示される。
## テンプレート

```html:app.component.html
<div>
  <input #testInput type="text" [(ngModel)]="name" *ngIf="isOpen" (blur)="change()">
  <div *ngIf="!isOpen" (dblclick)="change()">{{name}}</div>
</div>
```
nameを表示するdiv要素にはダブルクリックを検知するために`(dblclick)`をつけておく。また、`isOpen`フラグを用いて表示、非表示を切り替えるために`*ngIf`をつける。
ダブルクリックされた後に表示するinputにはコンポーネントから呼び出せるように#testInputと名前をつけておく。inputの入力を変数に格納するためにngModelは入出力どちらもできるようにしておく。`isOpen`のフラグを用いて表示、非表示を切り替えれるように`*ngIf`を用いる。blurのイベント検知を取るために`(blur)`をつける。

## クラス
```typescript:app.component.ts
import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  public isOpen = false;
  public name = 'cipher';

  constructor(
  ) { }

  @ViewChild('testInput') // inputにfocusを当てる
  set myInput(_input: ElementRef | undefined) {
    if (_input !== undefined) {
      _input.nativeElement.focus();
    }
  }

  change() {
    this.isOpen = !this.isOpen;
  }
}
```

inputとdivの表示、非表示を切り替えるためのフラグを`isOpen`、表示する要素を`name`として変数を宣言する。`@ViewChild`（[@ViewChild Angular公式](https://angular.io/api/core/ViewChild)）を用いてinputにつけた名前を使ってDOM要素にアクセスする。seterを使うことによって常時監視することができる。非表示の際は`undefined`になってしまうため、条件分岐しておく。`ElementRef`の`nativeElement`を用いて`focus`関数を動かしてフォーカスを当てている。
`change`関数はフラグを反転させるための関数である。

# 最後に
今回はinputを一つだけでしたが、複数にする際は表示、非表示のフラグを変えてあげれば複数でも対応できるかと思います。
RPAD/LPAD関数の不思議な挙動を試す (Oracle Database 12c Release 2)

# RPAD/LPAD関数の仕様
RPAD関数は、指定された文字列の右側に（LPAD関数は左側に）特定の文字を繰り返して文字列を返します。関数の動作はマニュアルには以下のように記述されています。

> LPADは、expr1の左側にexpr2に指定した文字を連続的に埋め込んでn桁にして戻します。このファンクションは、問合せの出力の書式設定に役立ちます

## 通常の動作
下記の例では文字列'A'の左側に'B'を連続して埋め込み、全体を10文字にして返します。'B'が連続して出力され、10文字目が'A'になっています。

```
SQL> SELECT LPAD('A', 10, 'B') LPAD FROM DUAL;

LPAD
----------
BBBBBBBBBA

```

## マルチバイト文字を指定した場合の動作
文字コードがAL32UTF8の環境（データベース、クライアントとも）で、この関数を実行してみると想定と異なる結果が得られました。
まるでフォント幅にあわせて出力長を変えているように見えます。全角文字は半角文字の半分の文字数になり、半角カナは半角英数と同じ文字数が出力されました。

```
SQL> SELECT LPAD('あ', 10, 'か') LPAD FROM DUAL;

LPAD
---------------
かかかかあ

SQL> SELECT LPAD('あ', 10, 'B') LPAD FROM DUAL;

LPAD
-----------
BBBBBBBBあ

SQL> SELECT LPAD('ｱ', 10, 'ｲ') LPAD FROM DUAL;

LPAD
------------------------------
ｲｲｲｲｲｲｲｲｲｱ

```

## 桁数を拡大した時の動作
マニュアルには桁数に対する制限について説明がありませんので、この値を拡大してみます。32768文字を指定しましたが、実際には4000バイトまでしか生成されません。初期化パラメーターmax_string_size=EXTENDEDを指定した場合はこの値は拡大されるようです。

```
SQL> SELECT LENGTHB(LPAD('A', 32768, 'B')) LPAD_LENGTH FROM DUAL;

LPAD_LENGTH
-----------
       4000

```

## PL/SQL環境とSQL環境の動作の違い
同じ関数でも PL/SQL の文で使う場合と、SQL文内で使う場合の検証を行いました。下記のようなPL/SQLプログラムを実行します。
変数 v1 には SELECT文内で実行したRPAD関数の長さが格納されます。変数 v2 には PL/SQL文内で実行したRPAD関数の長さが格納されます。

```
DECLARE
  v1 VARCHAR2(32767);
  v2 VARCHAR2(32767);
BEGIN
  SELECT RPAD('A', 32767, 'B') INTO v1 FROM DUAL;

  DBMS_OUTPUT.PUT_LINE('SQL: ' || to_char(LENGTH(v1)));

  v2 := RPAD('A', 32767, 'B');

  DBMS_OUTPUT.PUT_LINE('PL/SQL: ' || to_char(LENGTH(v2)));

END;
/
```

実行結果は以下の通りです。同じ関数でも実行される場所により実行結果が異なる場合があることがわかります。

```
SQL: 4000
PL/SQL: 32767

PL/SQLプロシージャが正常に完了しました。
```
# （参考）データ型による制限
Oracle Databaseの文字列はデータ型によって最大バイト数が決まっています。

|データ型|最大バイト数 (11.2まで)|最大バイト数 (12.1から)|PL/SQLの最大長|
|:---|----:|---:|---:|
|CHAR|2000|2000|32767|
|NCHAR|2000|2000|32767|
|VARCHAR2|4000|32767|32767|
|NVARCHAR2|4000|32767|32767|
|RAW|2000|32757|32767|

Oracle Database 12c以降は、初期化パラメーターmax_string_sizeを変更することで拡張することができます。
rspec | 存在しないクラスを定義してモックする

たとえばload周りの関係で、実装では存在するが、テストでは存在しないクラスをモックする場合。

定数をスタブして、doubleなどを返すようにしておく。

# specでの定義例

```rb
before do
  some_class = double('Some Class', some_method: 'return')
  stub_const('Example::SomeClass', some_class)
end
```

## 結果例

```rb
Example::SomeClass.some_method
=> "return"
```

# 環境

- rspec (3.7.0)
- rspec-rails (3.7.2)









<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Capybaraで要素があるまで待つ（ページ遷移対策）

画面遷移するまで待つ系の処理で、そのページにしか存在しないテキストでマッチさせるというのがあるんだけれど、それも結構大変なので、そのページにしかないidなりclassなりで検証したいなーと思ったので定義した。

```rb:spec/support/wait_until_element_exists.rb
module WaitUntilElementExists
  def wait_until_element_exists(selector)
    Timeout.timeout(Capybara.default_max_wait_time) do
      loop until page.all(selector).present?
    end
  end
end

RSpec.configure do |config|
  config.include WaitUntilElementExists, type: :feature
end
```

いちいちそのページのテキストとマッチさせなくていいので楽〜。
Capybaraで要素にデータが入るのを待つ

よく`wait_for_ajax`とかでajax処理を待つというのはあるのだけれど、ajaxが終了した後にJSによる要素の生成が間に合わずに評価が行われてエラーになることがあったので、そもそもが、その要素が空じゃなくなるまで待てばいいんじゃないか？ということで定義してみた。

```rb:support/wait_until_content_loaded.rb
module WaitUntilContentLoaded
  def wait_until_content_loaded(selector)
    Timeout.timeout(Capybara.default_max_wait_time) do
      loop until page.find(selector)&.has_content?
    end
  end
end

RSpec.configure do |config|
  config.include WaitUntilContentLoaded, type: :feature
end
```

テストもパスしてくれたので、最初に要素が空の場合はこっちを使っていきたい。
LaravelでN+1問題

ネストされたリレーションのN+1問題を回避したいので調査した。

Laravel:5.6.26

## 例としてERとLaravelのコード

![ER](http://www.plantuml.com/plantuml/png/SoWkIImgAStDuKhDAyaigLGeBKujAbQevb80WimKCAKB1616Nc9kAbSj5qnfGNvn2GwbO6FYeO90nJd8-fBpStE1J1nQmSR2jQPMb81qGbobMvIf2x6L2qH21E36SJcavgK0VG80)


```php:UserController.php
public function index()
{
	$users = User::limit(5)->get();
	return view('user.index')->with('users', $users);
}
```

```php:index.blade.php
@foreach ($users as $user)	
<p>{{ $user->name }}</p>
<ul>
  @foreach ($user->posts as $post)
  <li>{{ $post->title }}</li>
  <li>コメント数：{{ count($post->comments) }}</li>
  @endforeach
</ul>
@endforeach
```

結果、下記の様なselect文が発行される

```sql
select * from users limit 5
select * from posts where posts.user_id = 1
select * from comments where comments.post_id = 10
select * from posts where posts.user_id = 2
select * from comments where comments.post_id = 20
select * from posts where posts.user_id = 3
select * from comments where comments.post_id = 30
select * from posts where posts.user_id = 4
select * from comments where comments.post_id = 40
select * from posts where posts.user_id = 5
select * from comments where comments.post_id = 50
```

## N+1問題を回避するために`with`を使う

```php:UserController.php
public function index()
{
	$users = User::with('posts')->limit(5)->get();
	return view('user.index')->with('users', $users);
}
```

```sql
select * from users limit 5
select * from posts where posts.user_id in (1, 2, 3, 4, 5)
select * from comments where comments.post_id = 10
select * from comments where comments.post_id = 20
select * from comments where comments.post_id = 30
select * from comments where comments.post_id = 40
select * from comments where comments.post_id = 50
```

postsは回避されたがcommentsがまだ

## withでドット指定

```php:UserController.php
public function index()
{
	$users = User::with('posts.comments')->limit(5)->get();
	return view('user.index')->with('users', $users);
}
```

```sql
select * from users limit 5
select * from posts where posts.user_id in (1, 2, 3, 4, 5)
select * from comments where comments.post_id in (10, 20, 30, 40, 50)
```

ネストされたリレーション先のcommentsまで対応できる

~~RailsのbulletみたいなやつがLaravelにあるといいんだけど無いっぽい。~~

※プロダクトのコードで試した為に上記コードは記事作成時に手で起こしてあります。コピペしても動かないかも

# 追記

N+1が発生しているか、発見できるLaravel N+1 Query Detectorってライブラリがあったようです
[LaravelでN+1を検出させる](https://qiita.com/zdjjs/items/98786583710ec0ac9873)
Hyperledger Composer お試しで使うときによく使う自作シェルとかコードスニペットとか

最初の方はチュートリアルにある手順をそのままシェル化しただけなのであしからず

# コンテナを消去して再セットアップ

fabric-dev-serversディレクトリの中で使ってください。

```bash:resetDocker.sh
docker kill $(docker ps -q)
docker rm $(docker ps -aq)
docker rmi $(docker images dev-* -q)

./downloadFabric.sh
./startFabric.sh
./createPeerAdminCard.sh
composer-playground
```

# 開発環境の再インストール

```bash:reinstallDevEnv.sh
npm uninstall -g composer-cli composer-rest-server generator-hyperledger-composer
npm install -g composer-cli composer-rest-server generator-hyperledger-composer

npm uninstall -g composer-playground
npm install -g composer-playground
```

# チェーンコードのビルドから再デプロイ

チェーンコードのプロジェクトの package.json の中に埋め込んでおきます
どうせ名前指定でbnaを出力してるからネットワークバージョンは適当にタイムスタンプとかでもいいかも。

```json:package.json
  "config":{
    "networkname":"hogehoge",
    "admincard": "/Users/myname/fabric-dev-servers/networkadmin.card"
  },
  "scripts": {
    "deploy":"npm run deploy:install && npm run deploy:start && npm run deploy:card_import && npm run ping",
    "deploy:install": "composer network install --card PeerAdmin@hlfv1 --archiveFile ./dist/projectname.bna",
    "deploy:start": "composer network start --networkName $npm_package_config_networkname --networkVersion $npm_package_version --networkAdmin admin --networkAdminEnrollSecret adminpw --card PeerAdmin@hlfv1 --file $npm_package_config_admincard",
    "deploy:card_import":"composer card import --file $npm_package_config_admincard",
    "ping":"composer network ping --card admin@$npm_package_config_networkname",
    "redeploy": "npm run prepublish && npm run deploy:install && npm run redeploy:upgrade",
    "redeploy:upgrade" : "composer network upgrade --networkName $npm_package_config_networkname --networkVersion $npm_package_version --card PeerAdmin@hlfv1"
  }

```
【Ruby】使いこなせると便利。||演算子のいろんな使い方

##はじめに
rubyを書いてると「||」という記号をよく見かけます。
条件式の時に使う、or文としか理解してませんでしたが、実は様々なところで活躍します。

今回はそんな||演算子の使い方をパターン別に説明していきたいと思います。

##条件式で使う時の||

皆さんがよくご存知なのはif文の中で使うときではないでしょうか。
左から式を順に評価し、真になった場合、実行されます。

```rb

name = "hanako"

if name == "taro" || name == "hanako" || name == "jiro"
  puts "hoge"
else
  puts "fuga"
end
```

```
=>
"hoge"
```

##連続した式で使う||

||を使って値を代入するときは、以下のように使うことがあります。
主に||演算子は、**左から右へ順に式を評価し、真だったものを返します。**

```rb
hoge = nil || false || 1 || 2
#hoge = (偽) || (偽) || (真) || (真)
```

```
hoge
=> 1
```
ここでは、偽であるnil,falseを飛ばし、真である1を返しました。
しかし、1より右にある２は代入されません。
なぜなら、左から順に評価され、**一番最初に真だったものを返すからです。**

##代入演算としての||

`||=` という記号を見たことがある人はいるのではないでしょうか。
使い方としては、左辺が存在しない(偽)の場合、右辺の値が代入されるイメージです。

```rb
hoge ||= 1
```

```
hoge
=> 1
```
hogeという変数は存在しないため、1が代入されます。
ではもう一度別の値を代入してみましょう。

```
hoge ||= 2
```

```
hoge
=> 1
```
今度は、hogeという1が入った変数が存在する(真)ため、2が代入されません。

2を代入するためには、hogeをnilにする必要があります。(rubyは、falseとnil以外は真を返す)

```rb
hoge = nil
hoge ||= 2
```

```
hoge
=> 2
```

ここでは、左辺のhogeが存在しない(偽である)ため、右辺の2が代入されました。
やっていることとしては以下の文と同じです。

```rb
##以下の2つの文は同じ

hoge = hoge || 1

hoge ||= 1
```

皆さんもよく知っている自己代入と一緒ですね。

```rb
num = num + 1
num += 1
```

##まとめ

**・||演算子は、左から順に評価し、一番最初に真になったものを返す。**

とりあえずこれを押さえておけばなんとか読めると思います。
IoTもくもく会のおさらいしたらppp0が作られなくてはまった

# 経緯
社内のデバイス開発部門でラズパイのプロジェクトが立ち上がることに。
ラズパイでごにょごにょ作れ、いわゆる組込的な奴を。
だいぶ分野の違う開発な匂いがプンプンするので面白く学ぶ為に、
会社の近くのSORACOMさん主催の[IoT もくもく会（SORACOMとラズパイ編）](https://soracom.connpass.com/event/82273/)に参加することにしました。

# もくもく会の様子
このような流れで快調に楽しく催されてます。
1. SORACOMさんの有料シム使ってねー！（ここ上手い！）
2. ラズパイやセンサーはSORACOMさんから拝借。
3. 基本は[テキスト](https://github.com/soracom/handson/blob/master/ultrasonic-sensor/seminar.md#6-0)に沿ってやってちょ。
4. 分からなかったら聞いてね
5. 終わったらTECHブログ書いてー（一ヶ月も放置していてごめんなさーい）

#初参加の感想的なもの
1. WebhookやIFTTTなど、知ってはいたけどあんまり使う機会がなかったんでリアルに使えて楽しい。
2. SORACOMさんは通信サービスというより、通信＋αのデータ処理サービスが特徴なんですね。
3. なんでドングルからSIMの抜き差しに熟練の技が必要なんですかね？もっと簡単安全なものが必要かも？

# この記事の趣旨
もくもく模様は凄くたのしくて快調だったのでイベントレポートはありませーん。
というか、テキストそのものがオープンだし、普通になぞれば誰でもできるのでそちらで充分かと。
なので、その体験をSIMが手元にあるし、もう一回復習をかねておさらいしてみよう思い立ったのがこの記事です。

# そうは甘くない現実
簡単だったんですよ、**現地では**。
setup_air.shで作られるppp0インターフェースの通信デバイスが作られなということが発生。

結論、USBドングルは[FS01BU](https://www.fsi.co.jp/mobile/plusF/products/FS01BU.html)、[AK-020](https://soracom.jp/products/ak-020/)、[MS2131](https://soracom.jp/products/ms2131i8/)しか対応しておらず、手持ちのUSB　Wifiスティックは対応していないことがわかりました。

いろいろググって勉強になりました。
まず、Linuxの場合、USBドングルはストレージの認識をするようなんです。
なので、手持ちのUSB Wifiをusb_modeswitchを使ってUSBモデムとして認識させ直す必要あるそうです。

いや、いままでLinuxサーバーでUSBや追加デバイスなど、たしかに操作したことなかったことに気が付きました。

ただ、ここで手が止まりました。
SORACOMさんから提供のsetup_air.shを見ると、この３つのドングルそれぞれ、rules.dの設定ファイルの指定が違うんです。
ここまでわかったところで、きょうはここまで。次回、設定方法を見つけるか、諦めて推奨ドングルを手に入れるかしてレポートします。
window端末からterraformを使ってGCPにインスタンス生成

# はじめに
GCPを触り始めて、Terraformの存在を知ったので使ってみました。

# Terraform
https://www.terraform.io/intro/index.html
インフラ構築の管理ツール

# Terraform インストール
今回は、windows7の自端末にインストールします。
といっても、バイナリをダウンロードするだけです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/265723/8eb42357-ab91-1ff8-0575-87cffeb74f75.png)

現在最新の 0.11.7 

![image.png](https://qiita-image-store.s3.amazonaws.com/0/265723/93fa505b-554d-95ed-c3dd-3fe0815cac4a.png)

Windows(64bit)版をダウンロード
ダウンロードしたzipを解凍

解凍後の以下の実行ファイル
terraform.exe

適当なフォルダを作成して中に格納

# GCP事前準備
1：新しいプロジェクト作成
2：サービスアカウント作成
　[IAMと管理]→[サービスアカウント]
  　[サービスアカウントを作成]
　　※新しい秘密鍵の提供にチェック
　　　キーのタイプはJSON
3：ダウンロードしたJSONファイルを先程作成したフォルダに格納

# tfファイル準備
TFファイルとは、terraformよりインフラを構築するための設定ファイル
役割ごとにファイルを分割することで汎用的に運用できる

まずは、GCPの接続情報を渡すために以下のtfファイルを作成


```gcp_provider.tf
// GCP provider
provider "google" {
  credentials = "${file("key\\XXXXXXXXXX.json")}"
  project     = "XXXXXXX-999999"
  region      = "us-east1"
}
```
・credentialsはGCP認証鍵ファイルパス
　後述しますが、keyフォルダ配下に配置したJSONを相対パスで参照
　\はエスケープする必要あります。\\\
・projectは認証鍵ファイル内に記載されている[project_id]　★要注意
　GCPコンソールで表示されているProject名では動かず、ここでハマった。。。


次に作成するインスタンス用のtfファイル
今回はTerraform検証のため、GCPにはシンプルにインスタンスを1つ作成します。

```gcp_instances.tf
resource "google_compute_instance" "terraform-test" {
  name         = "terraform-test"
  machine_type = "f1-micro"
  zone         = "us-east1-c"
  description  = "gcp-terraform-test"
  tags         = ["terraform-test"]
  boot_disk {
    initialize_params {
      image = "XXXXXXXXXXXXXXXX"
    }
  }
  network_interface {
    network = "default"
    access_config {
      // Ephemeral IP
    }
  }
  service_account {
    scopes = ["userinfo-email", "compute-ro", "storage-ro", "monitoring"]
  }
}
```
・boot_disk - initialize_params - imageはお好みで
　今回は過去に作ったcentos7のlampもどきのimageを使用しました。

# フォルダ構成

> terraform/
> 　├ terraform.exe
> 　├ key/
> 　│　└ XXXXXXXXXX.json
> 　└ gcp/
> 　 　　├ gcp_provider.tf
> 　 　　└ gcp_instances.tf

# Terraform実行
コマンドプロンプト起動
>cd 対象フォルダ
>terraform init gcp
・・・
>terraform plan gcp
・・・
>terraform apply gcp
・・・

```
Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
```
[yes]入力

・・・

```
google_compute_instance.terraform-test: Still creating... (10s elapsed)
google_compute_instance.terraform-test: Creation complete after 13s (ID: terraform-test)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```

出来上がり
GCPコンソールから確認すると作ったインスタンスが起動しています。

# さいごに
project_idでハマって3時間くらいかかったけど、出来てヨカタ
次はansible