OmniAICreator/Qiita-1.07M huggingface dataset:
PHP: CouchDB のデータを読む (Read)

```php:couch_read.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//	couch_read.php
//
//						Jul/31/2020
//
// ------------------------------------------------------------------
include('Requests/library/Requests.php');

fputs (STDERR,"*** 開始 ***\n");

Requests::register_autoloader();

$url = 'http://localhost:5984/nagano/_all_docs?include_docs=true';

$request = Requests::get($url, array('Accept' => 'application/json'));

// var_dump($request->status_code);

$json_string = $request->body;
$data_aa = json_decode ($json_string,true);
$rows = $data_aa['rows'];

foreach ($rows as $unit)
	{
	$key = $unit['key'];
	$unit_aa = $unit['doc'];
	$str_out = $key . "\t" . $unit_aa["name"];
	$str_out .= "\t" . $unit_aa["population"];
	$str_out .= "\t" . $unit_aa["date_mod"];
	print "$str_out\n";
	}

fputs (STDERR,"*** 終了 ***\n");

// ------------------------------------------------------------------
```

実行

```bash
/couch_read.php
```
PHP: CouchDB のデータを作成 (Create)

```php:couch_create.php
#! /usr/bin/php
<?php
// ------------------------------------------------------------------
//	couch_create.php
//
//						Jul/31/2020
//
// ------------------------------------------------------------------
include('Requests/library/Requests.php');

fputs (STDERR,"*** 開始 ***\n");

Requests::register_autoloader();

$headers = array('Content-Type' => 'application/json');
$url_base = 'http://localhost:5984/nagano';

$result = Requests::delete($url_base);

$result = Requests::put($url_base,$headers,"{}");

$dict_aa=data_prepare_proc ();

foreach ($dict_aa as $key => $value)
	{
	$str_json = json_encode ($value);

	print $str_json . "\n";

	$url = $url_base . "/" . $key;

	$result = Requests::put($url,$headers,$str_json);
	}

fputs (STDERR,"*** 終了 ***\n");

// ------------------------------------------------------------------
function data_prepare_proc ()
{
	$dict_aa = array ();

$dict_aa = dict_append_proc ($dict_aa,'t2021','長野',18945,'2002-3-12');
$dict_aa = dict_append_proc ($dict_aa,'t2022','松本',69537,'2002-10-7');
$dict_aa = dict_append_proc ($dict_aa,'t2023','上田',72186,'2002-9-15');
$dict_aa = dict_append_proc ($dict_aa,'t2024','小諸',49672,'2002-5-22');
$dict_aa = dict_append_proc ($dict_aa,'t2025','岡谷',82341,'2002-11-11');
$dict_aa = dict_append_proc ($dict_aa,'t2026','塩尻',32597,'2002-9-21');
$dict_aa = dict_append_proc ($dict_aa,'t2027','茅野',42519,'2002-8-24');
$dict_aa = dict_append_proc ($dict_aa,'t2028','飯田',52986,'2002-9-28');
$dict_aa = dict_append_proc ($dict_aa,'t2029','中野',72513,'2002-8-5');
$dict_aa = dict_append_proc ($dict_aa,'t2030','諏訪',58146,'2002-6-17');
$dict_aa = dict_append_proc ($dict_aa,'t2031','駒ヶ根',25371,'2002-8-15');
$dict_aa = dict_append_proc ($dict_aa,'t2032','佐久',78529,'2002-4-14');
$dict_aa = dict_append_proc ($dict_aa,'t2033','伊那',29416,'2002-7-21');
$dict_aa = dict_append_proc ($dict_aa,'t2034','千曲',81729,'2002-6-19');


	return $dict_aa;
}

// ------------------------------------------------------------------
function dict_append_proc ($dict_aa,$id,$name,$population,$date_mod)
{
	$dict_unit = array ();
	$dict_unit['name'] = $name;
	$dict_unit['population'] = $population;
	$dict_unit['date_mod'] = $date_mod;
	$dict_aa[(string)$id]= $dict_unit;

	return	$dict_aa;
}
// ------------------------------------------------------------------
```

実行

```bash
./couch_create.php
```
【ふくだ学習録】インフラエンジニア教本-ネットワーク構築技術解説- part7【57日目】

# ふくだ学習録とは？
ふくだが学習したことの備忘録。
目に見える形で残すことによってやる気を出す個人的な作戦です。
他人に見せるように書いているわけではないので、すごく読みにくいです。

### 今読んでいる本
[インフラエンジニア教本 ~ネットワーク構築技術解説](https://www.amazon.co.jp/dp/4774170348)

# 第2章 ルータの教科書

### L3スイッチとの違い
前提として「これ！」という明確な違いの基準はない。
筆者目線での違いは下記。

- **ソフトウェアベースか、ハードウェアベースか**
一般論的にルータがソフトウェアベースで、L3スイッチがハードウェアベース。
なので、ルータの方が対応している機能や、プロトコルが多く、拡張性が高い。
L3スイッチはスイッチなのでポート数が多く、ハードウェアレベルで作り込みが行われているので、処理速度に優れている。

- **ルータはネットワークとネットワークをつなぐもの**

### ルーティングとは
適切なネットワークへパケットを転送すること。
パケットの転送先を判断する情報を「ルーティングテーブル」という。

### ルーティングテーブルの構築方法
スタティックルーティングとダイナミックルーティングの２種類がある。

#### スタティックルーティング
手動でルーティング情報を設定すること。

**メリット**

- 管理者の意図するパケット転送を容易に実現できること。
- ルータへの負荷が軽い

**デメリット**

- 管理者の運用コストが高い
- ネットワーク内に障害が生じた場合、自動でルーティング情報が切り替わらない。

#### ダイナミックルーティング
ルータ同士がルーティング情報を交換し、地震のルーティングテーブルを更新する。

**メリット**

- 圧倒的に管理コストが低い。

**デメリット**

- 小規模な検証を行う時に不向き（例えば、無駄なパケットを発生させてしまったりする）

### ルーティングプロトコル
ダイナミックルーティングでは、経路情報を交換するために「ルーティングプロトコル」というプロトコルを利用している。
ルーティングプロトコルにはいくつかの種類があり、そのネットワークの種類、管理/設計コンセプトによって適切なプロトコルを選択する。

### ルーティングプロトコルの種類
ルーティングプロトコルは大別すると、**EGP**（Exterior Gateway Protocol）と**IGP**（Interior Gateway Protocol）の2つがある。

#### EGP（Exterior Gateway Protocol）
AS(Autonomous System)間の経路情報を交換するためのプロトコル。
現在はBGPの一択になっているが、昔はEGPというプロトコルが利用されていた。

[ASとは](https://www.nic.ad.jp/ja/basics/terms/as.html)

#### IGP（Interior Gateway Protocol）
IGPはAS内部で利用されるプロトコル。
種類としては、RIP,OSPF,EIGRPなどがある。

[複数のルーティング手法とルーティングプロトコルの比較](https://www.atmarkit.co.jp/ait/articles/1505/28/news012.html)

### ルータは外部境界
ルータは多種多様なネットワークをつなぐためのプロトコル変換装置として発展してきた。
しかしEthernetとIPに世界制覇された今となっては、プロトコル変換装置としての意味は廃れてしまった。
そのためルータは、現在外部との境界を担っており、機能としてもアドレス変換やNAT、セキュリティ（ファイアウォール）機能、トンネルの取り扱いなどを提供するようになっている。


# 今日の一言
もっと早よ起きなければ、、

# 読了した本

#### 技術系
[データベースエンジニア養成読本 [DBを自由自在に活用するための知識とノウハウ満載!]](https://www.amazon.co.jp/dp/4774158062/ref=cm_sw_r_tw_dp_U_x_FPphEbQFPPQRM )
[ゼロから作るDeepLearning](https://www.amazon.co.jp/dp/4873117585/ref=cm_sw_r_tw_dp_U_x_y3UiEbF3P6EG7)
[PHPフレームワーク CakePHP 3入門](https://www.amazon.co.jp/dp/4798048577/ref=cm_sw_r_tw_dp_U_x_.YIjEbS1K4JY2)
[SQLアンチパターン](https://www.amazon.co.jp/dp/4873115892/ref=cm_sw_r_tw_dp_U_x_XlokEbJQK2N7P )
[Docker入門](https://www.amazon.co.jp/dp/480071091X/ref=cm_sw_r_tw_dp_U_x_xVlmEbN8ZTHZK)
[PHPフレームワーク Laravel入門](https://www.amazon.co.jp/dp/4798052582/ref=cm_sw_r_tw_dp_U_x_zzeyEbJBSQ5Y0 )
[サーバ/インフラを支える技術](https://www.amazon.co.jp/dp/4774135666)


#### ビジネス系
[サブスクリプション](https://www.amazon.co.jp/dp/B07HY1TND9/ref=cm_sw_r_tw_dp_U_x_lp4NEb3EEGD7Y)
[Running Lean ―実践リーンスタートアップ](https://www.amazon.co.jp/dp/4873115914/ref=cm_sw_r_tw_dp_U_x_UsMREbV6Y41Y8)
[amazon 世界最先端の戦略がわかる](https://www.amazon.co.jp/dp/4478105057)
[Lean Analytics ―スタートアップのためのデータ解析と活用法](https://www.amazon.co.jp/dp/4873117119)
[ピーター・ティール 世界を手にした「反逆の起業家」の野望](https://www.amazon.co.jp/dp/4864106010)
[Airbnb Story 大胆なアイデアを生み、困難を乗り越え、超人気サービスをつくる方法](https://www.amazon.co.jp/dp/4822255190)
[ユダヤの商法](https://www.amazon.co.jp/dp/4584139008)
[How Google Works](https://www.amazon.co.jp/dp/4532198348)
[イシューからはじめよ](https://www.amazon.co.jp/dp/4862760856)
[ピクサー流　創造するちから](https://www.amazon.co.jp/dp/4478016380)
[ストーリーでわかる財務３表超入門](https://www.amazon.co.jp/dp/4478015619)
はじめてのアマゾン ウェブ サービス for Developerを受けてみて...

# はじめに
AWSには「[**はじめてのアマゾンウェブサービスforDeveloper**][link-1]」というセミナーがあります。
[link-1]:https://pages.awscloud.com/JAPAN-event-OE-Hajimete-for-Dev-20200728-reg-event-LP.html?sc_channel=em&sc_campaign=JAPAN_FIELD_NL_Seminar202007&sc_medium=em_264549&sc_content=REG_webinar_strat&sc_geo=japn&sc_country=jp&sc_outcome=reg&trk=em_webiner_hajimete-for-dev-0728_EV_202007&campaign-id=AWS_EM


「**はじめてのアマゾンウェブサービス**」という名前に釣られ、参加してみました。
そのままにしておくのはもったいないので、自分なりにアウトプットしてみようと思います。
## 大まかな流れ
- **クラウドの基本的な特徴**

- **AWS のビジネス規模および成長率**
- **主要サービスのまとめ**
- **クラウド のセキュリティ**
- **クラウドを活用した開発手法のトレンド**
 - Microservices / Serverless
 - Infrastructure as a Code / DevOps
 - 非同期型処理

## クラウドを活用した開発手法のトレンド
### Microservices

クラウドネイティブ開発の場合、取り入れると有効であると思われるアーキテクチャです。

 -  それぞれのリソースをブラックボックス化してしまい、定義されたAPIでやり取りをする。
 -  他のリソースへの影響を考えずに機能改善が行えるため、楽

ということでした。

- メリット
 - **サービスごとに小規模なチームで開発を行う為、自主的かつ迅速に仕事に取り組める。**
 
 - サービスごとにスケーリングを行えるため、効率化できる。
 
 -  デプロイが容易なため新しいアイデアを試すことや、うまくいかなかった際にロールバックすることが簡単にできる。
 
 -  一つのサービスに障害が発生してもアプリケーション全体のクラッシュは回避できる。
 

マイクロサービスの対義語には「**モノリシック**」というものがあり、全体で単一のサービスとして実行されるものを言います。

参考:[マイクロサービス][link-2]
[link-2]:https://aws.amazon.com/jp/microservices/

----
### **AWS Lambda(Serverless)**
- Serverless
システムの実行には、

1. プログラムを書き
1. 実行する

という手順が必要です。

したがって、従来のシステムではプログラムを実行するための実行環境のサーバの構築やメンテナンスをする必要があります。

実行環境であるサーバにリクエストが集中して実行環境に障害が起きてしまうと元も子もないため、リクエストが増えることがわかっている場合にはスケーリングする必要があります。

そういった煩わしさをなくしたのが、サーバレスコンピューティングを担う「**AWS Lambda**」です。

- AWS Lambdaのメリット
 - **Lambdaの実行環境設定をすれば、設定をもとにAWSが面倒を見てくれる**
 - 複数の言語サポート(アクセスがまばらの場合は初動が速いPythonなどがおすすめ)

ということでした。

料金体系は

|サービス|料金体系|
|----|----|
|Lambda|実行したリクエストと時間分だけ料金発生|

となっています。

参考:[サーバーレスって何が便利なの ? AWS でサーバーレスを構築するためのサービスをグラレコで解説][link-3]
[link-3]:https://aws.amazon.com/jp/builders-flash/202003/awsgeek-serverless/

----
### Infrastructure as Code
簡単に言うと「インフラストラクチャーをコード化する」ということみたいです。
そのまんまですね。

- リソースは API 経由でプロビジョニング
- 定義ファイルによる効率化と自動化
- エラーやセキュリティ違反の除去

といったメリットがあります。
AWSでは[AWS CloudFormation][link-4]を用いて実現することができます。

[link-4]:https://aws.amazon.com/jp/cloudformation/
----
### 非同期型処理

- Amazon SQS
    - 完全マネージド型のメッセージキューイングサービス
    - AWSで非同期型処理をやるならこれ

ECサイトを例にとった具体的な構成図は以下の通りです。
![非同期処理 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675893/c64d9aa3-5c7f-a0d2-088a-92c3d6627dba.png)



非同期処理をしない場合には、ユーザが注文をした際に在庫を確認し、発送できる状態であるかの確認をするまで待機してもらうことになるのですが、AmazonSQSを間に挟むことによってフロントエンドとバックエンドを非同期にすることができ、ユーザビリティの向上につながります。

## まとめ
ここまで「はじめてのアマゾンウェブサービス for Developer」で説明受けたクラウドを活用した開発手法のトレンドをまとめてみました。

前提知識がないとなかなかイメージしにくいなと感じることがあったので、アジェンダを確認し、知らない単語があれば事前に調べることをお勧めします。
Laravel 公式ドキュメント 目次の変化 5.5 ⇒ 6.x

##基礎
`エラーとログ ⇒ エラー処理、ログとして別ページ`

##セキュリティ
`メール確認追加`

##テスト
`コンソールテスト追加`

##公式パッケージ
`Duck追加`
`Telescope追加`
PythonでSQLite3を扱ってみる[備忘録]

#### 初めに
`sqlite`は`Python`に標準で入っているモジュール。インストールせずに`import`できる。
#### コネクトする
```Python
import sqlite3

db = "./exsample.db" # データベースまでのパス
con = sqlite3.connect(db) # コネクト
```
#### テーブルを作る
```Python
cur = con.cursor()
table = "Friend" # テーブル名
sql = f"""create table {table}(
    id integer primary key autoincrement,
    name text,
    age integer,
)"""
cur.execute(sql) # SQL実行
self.con.commit() # 保存
```
`id`は`primary key`で主キーにし、`autoincrement`で自動で振り分けるようにしている。
#### テーブルがなかったら作る。
```Python
table = "Friend" # テーブル名
sql = f"""create table if not exists {table}(
    id integer primary key autoincrement,
    name text,
    age integer,
)"""
cur.execute(sql) # SQL実行
self.con.commit() # 保存
```
`if not exists`を入れる。
#### テーブル編集
```Python
old_table = "Friend" # 古いテーブル名
new_table = "NewFriend" # 新しいテーブル名
sql = f"alter table {old_table} rename to {new_table}"
cur.execute(sql) # SQL実行
self.con.commit() # 保存
```
#### テーブル削除
```Python
table = "NewFriend" # 削除したいテーブル
sql = f"drop table {table}"
cur.execute(sql) # SQL実行
self.con.commit() # 保存
```
#### 型一覧

| 型名 | 情報 |
|:-----------------|:------------------|
| NULL | NULL値 |
| INTEGER | 符号付整数。1, 2, 3, 4, 6, or 8 バイトで格納 |
| REAL | 浮動小数点数。8バイトで格納 |
| TEXT | テキスト。UTF-8, UTF-16BE or UTF-16-LEのいずれかで格納 |
| BLOB | 入力データをそのまま格納 |
#### レコード挿入
```Python
table = "Friend" # テーブル名
sql = f"insert into {table} (name, age) values ('次郎', 20)"
cur.execute(sql) # SQL実行
self.con.commit() # 保存
```
又は、

```Python
table = "Friend" # テーブル名
sql = f"insert into {table} (name, age) values (?, ?)"
data = ("次郎", 20)
cur.execute(sql, data) # SQL実行
self.con.commit() # 保存
```
`?`にして、第２引数にタプルを入れることで挿入できる。
#### レコード編集
次郎を太郎に変換してみる

```Python
table = "Friend" # テーブル名
id = 1 # 編集したいレコードのid
sql = f"update {table} set name='太郎' where id={id}"
cur.execute(sql) # SQL実行
self.con.commit() # 保存
```
#### レコード削除
```Python
table = "Friend" # テーブル名
id = 1 # 削除するレコードのid
sql = f"delete from {table} where id={id}"
cur.execute(sql) # SQL実行
self.con.commit() # 保存
```
【正規表現】基本的なメタ文字


PHPで正規表現を扱う際の基本的なポイントは[別記事](https://qiita.com/wakky_404/items/c47a9361fb8c296c7ab4)をご参照ください。


## 主なメタ文字
メタ文字の`位置`にも注目です

### 位置を表す

#### `^` 先頭
（例）
　`'#^いちご#'` いちご から`始まる`文字がヒット

#### `$` 末尾
（例）
　`'#いちご$#'` いちご で`終わる`文字がヒット

<br>

### 任意文字

#### `.` 任意の1文字
（例）
　`'#い.ご#'` 「い（任意1文字）ご」 に一致する文字がヒット
　⭕️ いちご、いなご、いいご
　❌ いいちご（間に二文字含まれるためNG）


#### `[abc]` いずれかが含まれる
（例）
　`'#[abc]#'` abcのいずれかが`含まれていれば`ヒット
　`'#[a-c]#'` 同上
　⭕️ axy、0b00

#### `[^abc]` いずれも含まれない
（例）
　`'#[^abc]#'` abcのいずれかが`含まれていなければ`ヒット
　`'#[^a-c]#'` 同上
　⭕️ xyz、0x00

<br>


### 繰り返し

`直前の1文字`について評価される

#### `*` 0回以上

#### `+` 1回以上

#### `?` 0回か1回

#### `{n}` n回

#### `{n,m}` n回以上 m回以下

#### `{n,}` n回以上


（例）
　`'#abc+#'`
　⭕️ abcc

　`'#abc{2,}#'`
　⭕️ abcccccc
　❌ abc


## 特殊文字
`\`（`¥`）を特殊文字の前に付けると特殊文字を示せる

#### `¥¥` ¥

#### `\n` 改行

#### `\t` タブ

#### `\d` 数字

#### `\D` 数字 以外

#### `\s` 空白文字（タブ、スペース）

#### `\S` 空白文字 以外

#### `\w` 単語構成文字（アルファベット、数字、アンダースコア(`_`) ）

#### `\w` 単語構成文字以外

#### `\w` 単語の境界

などなどetc...

## 最後に

完成したパターンは「正規表現チェッカー」と呼ばれるWebツールを使うと、簡単にチェックできます!

- 正規表現チェッカー / WEB ARCH LABO Tools
    - https://weblabo.oscasierra.net/tools/regex/
PHPで正規表現を扱う際の基本的な3つのポイント


基本的なメタ文字については[別記事](https://qiita.com/wakky_404/items/7841d2ef643e56c4d1a3)をご覧ください

### 1. パターンは`文字列`として扱うため、`' '`又は`" "`で囲む
（例）

- 文字末尾をチェックしたい場合
    - ⭕️ `'#xyz$#'`
    - ❌ `#xyz$#`
        - ※`$`は~で終わる を示す

<br>

### 2. パターンの最初と最後に`区切り文字(デリミタ)`が必要
- 何でも良い
- パターンに出現しない文字を使う

（例）

- 文字末尾をチェックしたい場合
    - ⭕️ `'#xyz$#'`、`'\xyz$\'`
    - ❌ `'xyz$'`

<br>

### 3. `メタ文字`はエスケープする必要がある
- **メタ文字の前に`\`を入れエスケープする**
- **変数展開される`" "`ではなく、変数展開のされない`' '`で囲む必要がある**

（例）

- 拡張子をチェックしたい場合
    - ⭕️ `'#\.jpg$#'`
    - ❌ `"#\.jpg$#"`（ダブルクオートで展開される）
    - ❌ `'#.jpg$#'`（メタ文字の前にバックスラッシュがない）

<br>
tensorflow v2.3.0 を Raspberry Pi zero 用にビルドする

# はじめに

tensorflow v2.3.0 の python3.7 用の pip パッケージを Raspberry Pi zero 用にクロスビルドする。公式の手順ではビルドできないので、ビルド手順を記録しておく。

* [Raspberry Pi のソースからのビルド](https://www.tensorflow.org/install/source_rpi?hl=ja)

# 環境
ビルド完了までに９時間ほどかかる。

* Ubuntu 20.04
* Core i3-4030U(1.9GHz)
* Mem 16GB
* Docker 19.03.8

# ビルド

## TensorFlow のソースコードのダウンロード

```shell
$ git clone https://github.com/tensorflow/tensorflow.git
$ cd tensorflow
$ git checkout v2.3.0
```

## python3.7 用の pip パッケージを作成するための変更

python 3.7 用の Docker ファイルを使用しても、python 3.7 の pip パッケージが作成できないので、cherry-pick する。

* [Cannot build raspberry pi wheel for python 3.7](https://github.com/tensorflow/tensorflow/issues/35116)

```
$ git cherry-pick 4c886a5
```

numpy のバージョンが 1.19 だとビルドに失敗するので、バージョン指定する。

```shell
$ vim tensorflow/tools/ci_build/install/install_pip_packages_by_version.sh
```

"numpy" を "numpy<1.19.0" に書き換える。

pip パッケージのみビルドするためにターゲットを変更する。
共有ライブラリが必要な場合は以下の手順は不要。

```shell
$ vim tensorflow/tools/ci_build/pi/build_raspberry_pi.sh
```

以下を削除する。

```
  //tensorflow:libtensorflow.so \
  //tensorflow:libtensorflow_framework.so \
  //tensorflow/tools/benchmark:benchmark_model \

cp bazel-bin/tensorflow/tools/benchmark/benchmark_model "${OUTDIR}"
cp bazel-bin/tensorflow/libtensorflow.so "${OUTDIR}"
cp bazel-bin/tensorflow/libtensorflow_framework.so "${OUTDIR}"
```

## ビルド

```shell
$ CI_DOCKER_EXTRA_PARAMS="-e CI_BUILD_PYTHON=python3.7 -e CROSSTOOL_PYTHON_INCLUDE_PATH=/usr/include/python3.7" \
  tensorflow/tools/ci_build/ci_build.sh PI-PYTHON37 \
  tensorflow/tools/ci_build/pi/build_raspberry_pi.sh PI_ONE
...
...
...
Target //tensorflow/tools/pip_package:build_pip_package up-to-date:
  bazel-bin/tensorflow/tools/pip_package/build_pip_package
INFO: Elapsed time: 31682.868s, Critical Path: 485.48s
INFO: 19137 processes: 19137 local.
INFO: Build completed successfully, 24526 total actions
INFO: Build completed successfully, 24526 total actions
Final outputs will go to output-artifacts
...
Output can be found here:
output-artifacts
output-artifacts/tensorflow-2.3.0-cp37-none-linux_armv6l.whl

```
1分で読めるMSA(Micro Service Architecture)とは?

#Motivation
クラウドアーキテクチャの流行りであるMSA(Micro Service Architecture)やサービスメッシュであるIstioとSidecar-proxyでありIstioのコアコンポーネントであるEnvoyのはじめの一歩の話です．

# MSA(Micro Service Architecture)がこんなに流行っている理由は??
**すべてのサービスが疎結合だから**
- 疎結合だと何がいいの?
それぞれのサービスが独立しているのでクラウドのメリットであるスケールやレプリケーションがより容易になります．
これについては以下の論文が詳しくまとめています．
[Evaluating the monolithic and the microservice architecture pattern to deploy web applications in the cloud](https://ieeexplore.ieee.org/document/7333476)

図を引用すると
- モノリシックなサービス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171398/425b41e7-6efd-af44-ee29-76694b1f1724.png)

これをスケールしようとすると...?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171398/a6ff9583-a1d2-72aa-e9b8-d00acce8dfde.png)
こうなります．　つまりWEBサーバーごと増やす形ですね．
たとえばS1のリソースは余っているけれども，S2のリソースが足りないよ！というときにはどちらもリソースが足りるまでS1S2のセットで増えていきます．


次にMSAでの単体のデプロイを見てみましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171398/20159f9f-c8cf-5f3b-6fa7-ac5f2b20982d.png)
Internetとサービスの間に**gateway**というのが挟まっています．
すべてのアクセスはgatewayを介してサービスにアクセスされます．
そしてサービスS1とS2はそれぞれリソースが独立しています．
ではこれをスケールするとしたらどうなるでしょう？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171398/0424f7d7-821d-e3a5-4700-74c6f880a649.png)

答えはそれぞれが必要なだけ独立してレプリケーションできるということです．
そしてこれはコスト面において大きく影響があったり，大量のアクセスが有った際に適切にピンポイントで増やせるので，最近のクラウドアーキテクチャの中では流行りですね！
ほかにも耐障害性などのメリットもありますが，そちらについては後日！とさせてください！

# サービスメッシュとは...
さて，MSAのメリットを見てきたわけですが，Istioを始めとしたサービスメッシュが今トレンドです
https://istio.io/

Istioは大きく２つのパートに別れます
- Control plane
- Data plane
です．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171398/bff60ab8-18b3-6b4d-ddd5-f3ed58e9e3ff.png)

かんたんに言うとさっきのS1,S2のコンテナと抱合せでproxyをおいてあげて，proxyを通るときにControl planeに報告しようね！という感じです．

MSAは大規模になればなるほどサービスのログトラッキングが複雑かつ別のサービスのログとの関連性については宝探しのような状態になります．

なのでそれらをIstioで統一してあげて，MSA内で共有しよう！というのがサービスメッシュです.

もしLGTMがつくようなら続きを書こうかな...なんて
aws wafv2の動作確認方法



## ルール
- countモードはブロックは行わず記録のみする
- `Override rules action`は、有効化すると、そのルールのみcountモードになる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/471b1e65-08b1-5016-3e6c-c55a5a35b3e0.png)

## NoUserAgent_HEADERルールの場合の動作確認

- HEADERにUserAgentが含まれていない場合はブロックします。というルール

### ブロック

```
yuta@DESKTOP-PT34LID:~$ curl  https://test.vamdemic.black.jp  -H "User-Agent:"
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
</body>
</html>
yuta@DESKTOP-PT34LID:~$ 
```

### 許可
```
yuta@DESKTOP-PT34LID:~$ curl  https://test.vamdemic.black  -H "User-Agent:a"
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>302 Found</title>
</head><body>
<h1>Found</h1>
<p>The document has moved <a href="https://test.vamdemic.black/dist/">here</a>.</p>
</body></html>
yuta@DESKTOP-PT34LID:~$ 
```
字幕をAR空間に飛ばす SFSpeechRecognizer

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">字幕をAR空間に飛ばす <a href="https://t.co/ZNKWLu0art">pic.twitter.com/ZNKWLu0art</a></p>&mdash; MLBoy_Daisuke (@JackdeS11) <a href="https://twitter.com/JackdeS11/status/1288954964291674112?ref_src=twsrc%5Etfw">July 30, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#実装

SFSpeechRecognizerのrecognitionTaskの**結果を完了ハンドラ内でSCNTextにして、SCNActionで動かします。**

```swift

let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))
speechRecognizer?.delegate = self
let recognitionRequest = SFSpeechAudioBufferRecognitionRequest()

let recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest) { result, error in        
      //認識タスク完了時に呼ばれる
      let recognizedText = result.bestTranscription.formattedString
      let text = SCNText(string: cutText, extrusionDepth: 2)
      let textNode = SCNNode(geometry: text)
      text.firstMaterial?.diffuse.contents = UIColor.randomColor
      self.sceneView.scene.rootNode.addChildNode(textNode)
      //ランダムな位置にテキストを置いて、動かす
      let random = Float.random(in: -100...100)
      let random2 = Float.random(in: -100...100)
      let random3 = Float.random(in: -200 ... -50)
      textNode.position = SCNVector3(x: 20, y: random2, z: random3)
      textNode.runAction(SCNAction.move(to: SCNVector3(x: -100, y: random, z: random3), duration: 5),completionHandler: {
      textNode.removeFromParentNode()
      })
```


機械学習やAR関連の技術情報を発信しています。
MLBoysだいすけ　https://twitter.com/JackdeS11
MLBoysゆうじ https://twitter.com/oka_yuuji

Core MLやCreate ML、Vision、ARKitを使ったアプリを作っています。
rockyshikoku@gmail.com
FlutterFragmentのためにViewPager2を改造する

前回の記事
[FlutterFragmentとViewPagerの組み合わせはonResumeのタイミングで難しかった](https://qiita.com/tfandkusu/items/50a1c4f5d5551aa816a3)
では、[ViewPager2](https://developer.android.com/reference/androidx/viewpager2/widget/ViewPager2)はページが完全遷移するまではonResumeが呼ばれないので、初回のonResumeで描画するFlutterFragmentとは相性が悪いという説明をしました。

よってすぐにonResumeが呼ばれるようにViewPager2を書き換えてみようと思います。[setMaxLifecycleメソッドの呼び出しが問題](https://qiita.com/tfandkusu/items/50a1c4f5d5551aa816a3#onresume%E3%81%8C%E5%AE%8C%E5%85%A8%E9%81%B7%E7%A7%BB%E3%81%BE%E3%81%A7%E5%91%BC%E3%81%B0%E3%82%8C%E3%81%AA%E3%81%84%E7%90%86%E7%94%B1)なので該当部分をコメントアウトします。


# Android Jetpack ソースコードのダウンロード

[ViewPager2はAndroid Jetpackの一部分](https://developer.android.com/jetpack/androidx/releases/viewpager2)なのでAndroid Jetpackのソースコードをダウンロードします。

[公式のダウンロード方法解説](https://android.googlesource.com/platform/frameworks/support.git)(英語)

Qiitaに日本語の解説もあります。
[AndroidX をソースからビルドする](https://qiita.com/yuichi_araki/items/a8db45e5aa1daad8152e)

ダウンロードすると15GBになります。

## 注意点

多くの人はライブラリについて安定版の最新版(執筆時点ではバージョン1.0.0)を使うと思いますが、こうしてダウンロードしたバージョンはアルファ版(執筆時点ではバージョン1.1.0-alpha01)になっていると思います。バージョンを指定してダウンロードする方法は見つけられませんでした。

# ライブラリモジュールを作成する

改造したViewPager2を取り込みたいプロジェクトにライブラリモジュールを追加します。

プロジェクトのルート要素で右クリックします。

![スクリーンショット 2020-07-31 4.03.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/ea684c44-5335-3e3d-2d7a-b00ab4314cb3.png)

Android Libraryを選択します。

![スクリーンショット 2020-07-31 4.04.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/4e69518a-b292-ff39-a6d8-4f6319a63604.png)

モジュール名とパッケージ名を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/34f3f127-5159-d4c7-863c-32a2d6f3a32d.png)

# ViewPager2のソースコードをライブラリモジュールに追加する

このようなディレクトリ構成を想定します。

**~/work/androidx-master-dev**
ダウンロードしたAndroid Jetpackのソースコード

**~/work/quickecho**
改造したViewPager2を含めたいアプリプロジェクト

```sh
cd work/androidx-master-dev/frameworks/support/viewpager2
# Javaソースコードをコピーする
cp -r viewpager2/src/main/java/androidx ~/work/quickecho/myviewpager2/src/main/java/
# リソースファイルをコピーする
cp -r viewpager2/src/main/res ~/work/quickecho/myviewpager2/src/main/
```

# ViewPager2を書き換える

まず、リソースファイルのパッケージ名が違くてビルドできないので修正します。

```ViewPager2.java
// import androidx.viewpager2.R;
import com.tfandkusu.myviewpager2.R;
```

問題のsetMaxLifecycleメソッド呼び出し部分をコメントアウトします。3カ所あります。

```FragmentStateAdapter.java
                mFragmentManager.beginTransaction()
                        .add(fragment, "f" + holder.getItemId())
                        // .setMaxLifecycle(fragment, STARTED)
                        .commitNow();
```

ViewPager2を使用するモジュールからのモジュール取り込みを設定します。

```build.gradle
// 略
dependencies {
    // 今回作ったライブラリモジュール
    implementation project(':myviewpager2')
    // クラス名が一緒なので本家の取り込みはコメントアウトする
    // implementation "androidx.viewpager2:viewpager2:1.0.0"
}
```

あとは通常のViewPager2と同じように使えば良いです。

# できあがり

![https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_334798_30d1768e-ced2-4c80-174d-f8a87d2d3075.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334798/efbe785c-b488-a693-8e4a-fbbad049ae04.gif)
Vue.jsのサービスワーカーにスクリプトを追加する

Vue.jsのサービスワーカーはVue CLIのPWAを追加するか、というところで追加した時に勝手についてくるやつで、GoogleのWorkboxというスクリプトを用いて、バックグラウンドでオフライン作業できるように色々やってくれるやつです。
まあとにかく、サービスワーカーでやりたいことはもっと他にもあるわけで、そのスクリプトを書いて挿入するにはどうしたらいいか？という事です。

`vue.config.js`に以下の設定を追加します。

```javascript
module.exports = {
  pwa: {
    workboxOptions: {
      importScripts: '/swlib.js'
    }
  }
}
```
この後、`public`ディレクトリに`swlib.js`を入れることで

#キャッシュの問題
WebPackではファイル名をハッシュ値などで書き換えることでキャッシュの問題をクリアしてくれる便利な機能がありますが、`importScriptsViaChunks`で利用できるようになるのはvue.jsのプラグインの問題でまだできないようです。
Go 1.15 の reflect パッケージの変更の影響詳細について

# Go 1.15 の reflect パッケージの変更の影響詳細について

[Go 1.15 リリースノート 日本語訳](https://qiita.com/c-yan/items/dad49c9dce27e77a94e7#reflect) として、reflect パッケージの変更内容を日本語訳したものの、いまいち何を言っているのか分からなかったので確認してみた.

```go
package main

import "reflect"

type u struct{}

func (u) M() {}

type t struct {
	u
	u2 u
}

func main() {
	reflect.ValueOf(t{}).Method(0).Call(nil)          // no problem
	reflect.ValueOf(t{}).Field(0).Method(0).Call(nil) // panic on go1.15
	reflect.ValueOf(t{}).Field(1).Method(0).Call(nil) // panic on go1.14 and go1.15
}
```

要するに go1.14 ではエクスポートされていないフィールドへアクセスすると `panic: reflect: reflect.flag.mustBeExported using value obtained using unexported field` でパニックするのだが、唯一埋め込みフィールドだけが例外になっていた. これについても一貫性のため同様にパニックするようにしたようだ.

これが「パッケージ `reflect` は、以前はエクスポートされていない埋め込みフィールドへのアクセスを許可していましたが、エクスポートされていないすべてのフィールドのメソッドへのアクセスを禁止するようになりました.」(原文: Package `reflect` now disallows accessing methods of all non-exported fields, whereas previously it allowed accessing those of non-exported, embedded fields.) の意味するところだ.

で、そのアクセスを使ってしまっている場合の対応だが、埋め込みフィールドに対してメソッドを呼ばずに、埋め込みの外側の値に対してメソッドを呼べばいい. それが出来るがゆえに、継承みたいなことをしたければ埋め込みフィールドを使えと言われているわけだから.

これが「以前の動作に依存しているコードは、代わりに取り囲む変数に対応する昇格メソッドにアクセスするように更新する必要があります.」(原文: Code that relies on the previous behavior should be updated to instead access the corresponding promoted method of the enclosing variable.) の意味するところだ.

promoted method という言葉を知らなかったので意味が取れてなかったのだが、この言葉は仕様書に出ていた. [The Go Programming Language Specification - Struct types](https://golang.org/ref/spec#Struct_types) にある. これを知っていれば一発で意味が取れたなあ.

まあ、この変更で困る人はほとんどいなそうですね.
Flutterパッケージ「permission_handler」のWidget Test

Flutterにて絶賛アプリ開発をやっています。
これで２案件目なんですが、前回はめちゃくちゃIntegration Testにハマりました。
そして今回はWidget Testと格闘中です。

プロジェクトでGoogleMapやGooglePlaceを使った時に、 `Cannot enable MyLocation layer as location permissions are not granted` と言うエラーが出たのがきっかけ。
「位置情報を表示するUIがあるが、パーミッション設定してないよ」 的なエラー！

StackOverFlowで調べるとパーミッション許可のダイアログをうまいこと出してくれるパッケージがあるからそれ使ったらいいよって事でした。そして使ったのが

[「permission_handler」](https://pub.dev/packages/permission_handler)

使い方は、パッケージを読み込んで、位置表示を表示するUIへの呼び出し部分に下記を入れるだけ

```
if (await Permission.location.request().isGranted) {
　// UIの呼び出し
}
```
とっても簡単でした。
でも、Widget Testでどハマりしました。

permission_handlerのモックを作らないと画面遷移できないのでテストが通らなくなってしまいました。
permission_handlerの公式ページやリポジトリを見ても全く記載なし！！
探しに探して３日間、やっとそれっぽいのを見つけました！
そして、まぐれ(?)にもテストが通ったのでここにメモ！！

もし、間違いがあれば教えてください！よろしくお願いします。

### UI側
```
FlatButton(
  onPressed: () async {
    // permission_handler
    if (await Permission.location.request().isGranted) {
      final result =
          await showModalBottomSheet<GoolePlaceItemList>(
              context: context,
              isScrollControlled: true,
              builder: (BuildContext context) {
                return GoogleMapSelectPlace();
              });
      print(result);
    }
  },
  color: Colors.white,
  child: const Text(
    '次の画面へ',
    style: TextStyle(
      color: Color(0xffC4C4C4),
      fontSize: 12,
    ),
  ),
),
```
### Widget test
```
void main() {
  group('SampleTest', () {
    setUp(() async {
      TestWidgetsFlutterBinding.ensureInitialized();
      await AppConfigAdapter().initialize();

　　　/// permission_handlerのモック
　　　/// 
      const MethodChannel('flutter.baseflow.com/permissions/methods')
          .setMockMethodCallHandler((MethodCall methodCall) async {
        if (methodCall.method == 'requestPermissions') {
          return <dynamic, dynamic>{
            // Permission.location.request().isGranted の許可をテストの場合は 「3」
　　　　　　　// 「1」 は許可OK
            3: 1,
          };
        } // set initial values here if desired
      });
    });

    testWidgets(
      '次の画面へボタンをタップするとMap画面が表示される',
      (WidgetTester tester) async {
        await tester.pumpWidget(pumpWidgetWrapper(TestScreen(
          overdrivePresenter: GoogleMapPresenter(
              testUsecase: _MockTestUsecaseCompleted(),
        )));

　　　　　// デバッグ用画面表示確認
        find
            .byType(Text)
            .evaluate()
            .toList()
            .forEach((e) => print(e.toString()));

        expect(find.text('次の画面へ'), findsOneWidget);
        await tester.tap(find.text('次の画面へ'));
        await tester.pumpAndSettle(const Duration(seconds: 5));
        expect(find.byType(GoogleMapSelectPlace), findsWidgets);
      },
    );
  });
}
```

### 参考文献
- [Widget testing permissions? #262](https://github.com/Baseflow/flutter-permission-handler/issues/262)
- [【Flutter】Widget テストの「あれ、これどうやるんだろう？」集](https://qiita.com/chooyan_eng/items/6ffd5b07de07edafd304#packageinfo-%E3%81%AE-mock)
RaspberryPi 3Bの電源LEDとACT LEDの設定

以下の２点について解説する

1. オンボードLEDのデフォルト設定の問題点について
2. RaspberryPi 3BのPowerLEDとACT LEDの設定を変更する方法を紹介する


### 1. RaspberryPiオンボードのLEDの動作の問題点

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576081/268b5bf6-b095-c7ea-041d-d718f3fa924f.png)

起動中デフォルトの状態は以下

```　　
Power LED：常に点灯（赤色）
Act LED：データアクセス時に点滅（緑色）
```

poweroff実行後　　　　　　　　　

```
Power LED: 常に点灯（赤色）
Act LED：データアクセスしないため、消灯になる
```

※ここで肝心なのは、最後の点滅がいつのタイミングで終わっているかが予測できないため、**電源スイッチを押すタイミングがわからないこと**である。

### 2. RaspberryPi 3BのPowerLEDとACT LEDの設定を変更する

Power LEDとACT LEDは/boot/config.txtに以下を追記し、点灯状態を変更した。

```
$ sudo nano /boot/config.txt             
    
dtparam=act_led_trigger=heartbeat                             
dtparam=pwr_led_trigger=off,pwr_led_activelow=on     
```

この設定で以下のような動きになる。
起動中：

```
　　Power LED：常時消灯
　　ACT LED：　ハードビート（心臓のような一定のサイクルで点滅）
```

poweroffコマンド実行後：

```
　　Power LED：常時点灯
　　ACT LED：消灯
```
　　上記の設定では、**Power LEDは消費電力が低い時に常時点灯の合図の意味なので、この時に電源OFFしてもよい**という意味になるので、常時点灯後、ACT LEDが消灯であれば、電源OFFする。

　　人の好みもあるが、**夜間で赤色のPower LED常時点灯だとかなり眩しいので、緑点滅のLEDが人にやさしい**と感じる。

　　皆さんはどうでしょうか？
Raspberry Piをバックグラウンドミュージックに活用する方法

# ミュージックプレーヤーとしてRaspberry Piを使う方法を紹介する

###準備（以下を準備してください）

1. Raspberry Pi 3B以後
2. スピーカー
3. LANに有線or無線でつながっていること

###STEP1: 再生Playerのインストール（今回は軽量なmplayerを選定）

```
$ sudo apt install mplayer 
```

###STEP2: Playlistの作成（以下はMp3/Mp4両方検索する例）

```
$ sudo find <music folder> -type f -iname \*.mp* > playlist.txt   
```
music folderは/mnt/sambaなどを指定する

###STEP3: 以下はお好みで設定してください

（以下は自分が推奨する設定）

- ビデオ再生しない（MP4だとビデオ再生してしまう）
- 出力先：Miniジャック
- 再生順序：シャッフル

```
$ mplayer -ao alsa:device=hw=1.0 -novideo -shuffle -playlist playlist.txt     
```

以下は、TeraTermでSSHでログインし、mplayerの再生ログ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/576081/9e126aeb-cba9-8ab0-bed5-f5b47fbfe759.png)

※メインマシンでYoutubeでバックグラウンドミュージックとして再生する方はいるでしょうが、メモリが占用されてしまうので、ハイパフォーマンスの仕事をしている方へお勧めします。


[おまけ]
常に新しい音楽をSambaに入れておいて、そこにアクセス指定すると常に新しいサウンドを楽しめます。
RaspberryPi上でFlask+uWSGI+NGINXを繋げる方法

いろんなサイトを参考にしているが、どれも自分の環境で動いているサイトがないため、試行錯誤しながら、やっと繋げることができたので、記録として残す。

やっとこと。

1. uwsgi.iniファイルの設定
1. uwsgi Unitサービスの設定（**ここで苦労**）
1. nginx confファイルの設定（**ここでも苦労**）


ノウハウとして、以下が必要と感じた。

- **socketプロキシサーバーの理解が必要**
- **仮想環境の実行パスの理解**

### 1. uwsgi.iniファイルの設定

```
# uwsgi.ini

[uwsgi]

socket = /tmp/uwsgi.sock
chmod-socket = 666

# wsgiファイル
wsgi-file= <実行するPythonファイルのフルパス>
callable=app

# アクセス許可ホスト:ポート
socket=0.0.0.0:8080
```

※重要なことはアクセス許可は**socket=127.0.0.1:ポート番号または0.0.0.0:ポート番号にすること**。なお、当初はhttp=0.0.0.0:ポート番号を指定していた。nginx側でsocketを設定していたので、これだとプロキシが通らない。

### 2. uwsgi Unitサービスの設定
サービスの場所:
/etc/systemd/system/uwsgi.service
中身：
```yml
[Unit]
Description=uWSGI instance to serve flask
After=network.target

[Service]
User=<user name>
WorkingDirectory= <作業ディレクトリ>
ExecStart=　<uwsgi実行モジュールのフルパス> uwsgi.ini

[Install]
WantedBy=multi-user.target
```
- user nameはpiなどを設定する
- 作業ディレクトリはuwsgi.iniファイルが入っているディレクトリを指定する
- uwsgi実行モジュールのフルパスは、仮想環境(venv)を指定する（指定例：/home/pi/project/venv/bin/uwsgi)
 
 
※ここでExecStartのパス指定エラーが出ていて苦労していた。**venv環境だとパスがわかりにくいので、pwdでもパス確認できない。.venvなどの仮想環境と言ってもパスは実在するので、直パス指定ができることがわかった**。（ユーザ認証が必要）

※**uwsgiは仮想環境でしか呼び出せないため、ExecStart＝/usr/binだと呼び出せない**。
逆に仮想環境ではなく、通常の環境にuwsgiを入れれば、呼び出せると思われる。(試していない）

※仮想環境でない場合でも動くことは確認できた。
uwsgi.serviceをほかのアプリに切り替える場合は、下記のパスを変更すればよい。
ExecStart=　uwsgi実行モジュールのフルパス uwsgi.ini

エラーになったため、エラーログを取得するように設定を追加
```yml
[Unit]
Description=uWSGI instance to serve flask
After=network.target

[Service]
User=pi
WorkingDirectory=/home/pi/MatplotlibForFlask
ExecStart=/usr/bin/uwsgi /home/pi/MatplotlibForFlask/uwsgi.ini

# 標準出力と標準エラー出力をファイルにリダイレクトする
StandardOutput=file:/home/pi/MatplotlibForFlask/uwsgi_stdout.log
StandardError=file:/home/pi/MatplotlibForFlask/uwsgi_stderr.log

[Install]
WantedBy=multi-user.target
```
変更後はTerminalで：
```
systemctl daemon-reload
```


### 3. nginx confファイルの設定

1. 「/etc/nginx/conf.d/<任意>.conf」の内容は以下に示す
2. /etc/nginx/sites-enabled/defaultを無効にする

```
server {

    listen 8081 default_server;
    server_name _;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
    }
}
```

※ここで重要なことは二つ、
１つは、**listen ポート番号とuWSGIのポート番号を重複しないこと**。重複すると正常に動作できない。
２つは、**[uwsgi_pass unix:///tmp/uwsgi.sock;]を指定すること**
httpでも指定できるようだが、うまくできなかった。

そのほかいのパラメータは特に指定していない。
例えば、プロセス数やメモリなど

以上、いろいろ不足する点があるかもしれないが、今はこの設定で動いているので、良しとする。

後は以下のコマンドでサービスを状態を確認

```
sudo systemctl status nginx.service
sudo systemctl status nginx.service
```
正常に動いていればよい。

Nginxログを確認するには、
/etc/nginx/nginx.confを確認し、access logのパスを確認する
通常であれば、
/var/log/nginx/にある

※dotenvが動かない場合
```terminal
pip uninstall dotenv-python
pip uninstall dotenv

pip install python-dotenv
```
エンジニアがポートフォリオを作る時にQiita等の記事を参考にする事の是非

# この記事を書く事にしたきっかけ
たまたま「エンジニア ポートフォリオ」で検索して色々見ていたところ、以下のYahoo知恵袋の記事が引っかかった。

[エンジニアのポートフォリオってqiitaとかサイトの記事を参考に作ってまずいのでしょうか？ ](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11213950911?__ysp=44Ko44Oz44K444OL44KiIOODneODvOODiOODleOCqeODquOCqg%3D%3D)

これへの回答は、一人を除いて全員否定的。
これに対して「ちょっとそれどうなのよ」と思った次第。
要は「物申す」な記事。

# 質問の解釈
- 参考にするサイトとして「Qiita」を挙げている
- と言うか補足で普通にそう言っている

と言う事から、「特定のサイトのコンテンツをパクったものをポートフォリオとして仕上げる」と言う意味ではなく、例えば「実装に悩んだ時にQiitaを見る」と言う意味だと言える。
（ベストアンサーの人はその辺の話が噛み合っていないようだ。）

# 自分の見解
少なくとも自分は、
**ポートフォリオに限らずあらゆる成果物は特定の問題に取り組んだ「結果」であり、「それを解決する為の実装」と言うのはあくまでも「手段」に過ぎない。**
と考えている。

「何か作っててハマったらQiita等で参考記事を探す」と言うのは**エンジニアにとってはデファクトスタンダード**だし、そもそも

- とある問題でハマっていて、作業が滞っている
- その問題の解決策が記事として上がっており、採用する事に無理がある訳ではない

これらの条件がありながらもその解決策を採用しようとしないのは、「手段と目的を履き違えている」としか言い様が無い。
「それが原因で進捗が遅れたり、最悪結果が出せなくなったり」と言う事になるのであれば、それはエンジニアのレベル云々以前に**「社会人として」使えない人材**である事は当然として理解するべき。

ただQiita等の記事を参考にするにしても、一番下のコメントにもあるように「内容を理解した上で」と言う事が前提。
でなければ「// よく分からないがとりあえず動く」と言う事になるし、場合によってはそれが後々地雷になったりする可能性もある。
例えばQiitaの記事をソースにするなら「記事の内容はすっ飛ばしてコードだけコピペして終わり」と言うのは当然ながら論外であって、最低でも記事全文は目を通した上で採用するべき。
Reactで遷移先のページ位置を一番上にする

# 問題
Reactでリンク先に遷移した時に、ページの途中や最後の位置を表示してしまう。

# 原因
Reactは、リンク経由でページ遷移をしても画面を書き換えるだけで、ページのスクロールポジションまでは初期化してくれないらしい。

# 解決策
マウント後に `window.scrollTo(0, 0)` を実行できるようにする。

一番簡単なのは `useEffect` を使う事ではないだろうか。
`componentDidMount` でも良いが、今回はモダンな `useEffect` で実装する。

```index.js
import React, { useEffect } from 'react'

export default function Sample() {

  useEffect(() => {
      window.scrollTo(0, 0)
  }, []);

  return (
    // return something...
  )
}
```
herokuでホストしてたlaravelアプリをlightsailに移動してドメイン張り替えとかした作業ログ

1.インスタンス立ち上げ

<img width="1149" alt="スクリーンショット 2020-07-30 20.46.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/363ebb96-fde1-3aac-a4c0-f3415efdaccc.png">

2.documentroot確認

<img width="952" alt="スクリーンショット 2020-07-30 20.47.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/acb2d70e-b121-cadf-64e7-abd9453ad582.png">
<img width="476" alt="スクリーンショット 2020-07-30 20.47.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/49cf52d8-582a-9104-aeb4-070f5fc9e817.png">

3.デプロイ

https://readouble.com/laravel/7.x/ja/envoy.html

Envoyと言う公式のデプロイタスク管理ツールがあるのでコレでデプロイスクリプトを管理してみる

```Envoy.blade.php
@servers(['web' => ['-i ~/.ssh/LightsailDefaultKey-ap-northeast-1.pem bitnami@54.95.226.129']])

@task('deploy', ['on' => 'web'])
cd ~/htdocs/ta9to/
git pull origin master
composer install --optimize-autoloader --no-dev
php artisan config:cache
php artisan route:cache
php artisan view:cache
@endtask
```

4.Laravel動いてるの確認

```bash
# DocumentRoot設定
$ vim /opt/bitnami/apache2/conf/bitnami/bitnami.conf
<VirtualHost _default_:80>
  #DocumentRoot "/opt/bitnami/apache2/htdocs"
  DocumentRoot "/opt/bitnami/apache2/htdocs/ta9to/public"
# apache再起動
$ sudo /opt/bitnami/ctlscript.sh restart apache
```

<img width="612" alt="スクリーンショット 2020-07-30 21.22.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/d92469d2-9460-471a-3067-83e367a9876b.png">

5.mysql設定

```bash
# mysqlパスワード確認
$ bitnami@ip-172-26-11-51:~$ cat /home/bitnami/bitnami_application_password
```

6.表示確認

<img width="1078" alt="スクリーンショット 2020-07-30 22.09.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/4160f440-e912-58f5-351e-e5b236c96cd5.png">

7.ドメイン張り替え
<img width="1153" alt="スクリーンショット 2020-07-30 22.15.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/6b885a81-723c-3ab3-911b-1371c6d00d7b.png">

8.Aレコード追加＋レジストリのネームサーバ置き換え
<img width="952" alt="スクリーンショット 2020-07-31 1.38.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192321/52bcef64-8184-d544-f384-0b0d21ce01db.png">

9.https設定
https://aws.amazon.com/jp/premiumsupport/knowledge-center/linux-lightsail-ssl-bitnami/

```bash
$ sudo /opt/bitnami/bncert-tool
```

↑のコマンドがapacheのconfに追記してくれるのでまたdocumentroot書き換える

```/opt/bitnami/apache2/conf/bitnami/bitnami.conf
<VirtualHost _default_:443>
  #DocumentRoot "/opt/bitnami/apache2/htdocs"
  DocumentRoot "/opt/bitnami/apache2/htdocs/ta9to/public"
  SSLEngine on
```

10.完了
https://www.ta9to.com/blog/posts
Integrity constraint violation: 1452... の解決方法

## エラーメッセージ
```
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails 
```

## ざっくり理解
外部キーとの関係に矛盾があるときのエラー。

## 解決方法
リレーションしている（外部キーを設定している）カラムの値が間違っていた（指定した値がリレーション先のテーブルに存在しない）ので、それを修正したら直った。
Flutterの環境構築って難しいって話

#参考にしたサイト
公式サイト
https://flutter.dev/
Flutter環境構築 - 1（Flutter SDKインストール編）
https://qiita.com/k_naruse___/items/359fcdfb8aa092e9a44e
Flutter開発環境構築(Mac編)
https://qiita.com/akatsukaha/items/3b8a5a6d94a3cdb1e047
Flutter 開発環境構築手順 (2019年 保存版)
https://qiita.com/tomy0610/items/896dc8ec9ba95c33194f


#何に困ったのか

Macのユーザーを非管理者のユーザーでやっていたら全然ターミナルのコマンドを受け付けてくれず、試しに管理者ユーザーで試したところあっさりとうまくいった。
どうも管理者権限の有無はMacでの環境構築に大きく影響を与えるようだ。

#ターミナルの種類？
zshだとかbashだとかによって変わってくるらしい。
ざっとな理解だと日本語とフランス語みたいな感じだろうか。
結果的にbashでやるべきところがzshでできたのでなんだったんだ、となった。

#それでどうなった？
Flutter doctor で問題なく使えることを確認したので、VSCodeを使って触っています。
簡単にアプリ作りたいので、まずは適当に地図を表示するアプリを作りたいです。
freeeAPIで勤怠打刻を自動化したい！　その２

今回は、スクリプト作成編です（雑にまとめました。後で気が向いたら or 質問や指摘をもらったら、追記します。）

## 動機

人は、ルーチンワークを意識すると言うのが、苦手な生き物である！！（主語でかい）
みなさん、よく月末に勤怠を入力してくださいって、言われません？
言われない？自動化してる？

僕は割と言われます
毎回、「すみません（汗」と、言って勤怠を入れるのである。
もう、３回言われたら、自動化して対策するのが、エンジニアってものですよ。
（財布も月３回、家に忘れたから、忘れるものと割り切って対策組んだし）
ちょうど、人事労務freeeにはAPIが公開されているので、こいつで勤怠打刻を自動化しましょう！
ちなみに、言語は会社で使っているPythonです。
（PowerShell版もあります。）

Python版：https://github.com/EndoHizumi/timerecordeeer
PoiwerShell版：https://github.com/EndoHizumi/tr4ps1

## セットアップ

事前にPython 3.6以降をインストールしてください。

### スクリプトでfreee APIを叩けるようになるまで
1. timerecordeeerのリポジトリから、スクリプトを一式を持ってきます。
    1. git cloneするなり、ZIPファイルでダウンロードするなり、お好きな方法で。
2. freeeからアクセストークンを取得します。
    3. 使い方をみながら、適当なコマンドを入力すると、ブラウザが開きます。
    4. freeeのアカウントでログインすると、アクセストークンが表示されます。これをコピーします。
    5. 表示されたアクセストークンを、config.jsonのaccess_tokenの欄にペーストします。
        6. config.json_templeteからリネームしておつかください

これで、スクリプトを使ってfreeeのタイムカードAPIをアクセスする準備ができました。

### 自動でスクリプトを起動させる
1. Windowsでローカルグループポリシーエディタを起動して、[ユーザーの構成] -> [Windowsの設定] -> [スクリプト（ログオン・ログオフ）]で、ログオンとログオフ時に起動するスクリプトに、このスクリプトを登録します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83578/410b0711-57e6-1ef5-e667-61c034f88049.png)

2. スクリプト名にpythonと入力、スクリプトのパラメータにスクリプトのフルパスと引数を入力します。
    3.スクリプトのパラメータの入力例
    3. ログイン（出勤）時；timerecordeeer.py "clock_in"
    4. ログアウト（退勤）時；timerecordeeer.py "clock_out"


## 使い方

```bash
python timerecordeeer.py [emboss|find] [引数]

# サブコマンドがembossのときに、入力できる引数
[clock_in|break_begin|break_end|clock_out]
# clock_inが出勤・break_beginが休憩開始・break_end休憩終了・clock_outが退勤です

# サブコマンドがfindのときに、入力できる引数
yyyy-mm-dd -f 勤怠ファイルのパス
```

## スクリプトの仕様

- コマンドラインからスクリプトを叩いて、人事労務freeeのタイムレコーダー登録APIで、勤怠を打刻する。
- 受ける引数は、freeeAPIに準拠して、出勤・休憩開始・休憩終了・退勤の４種類を受ける。
- 時刻は、スクリプトの起動日

想定する使い方として、このスクリプトをWindowsのログイン・ログオフ時に起動して、勤怠を打刻します。
休憩については、時間がまちまちなので、大人しくfreeeのスマホアプリの方で打刻します。
固定なら、タスクスケジューラに入れて自動にするんですが。


## おまけ

### アクセストークンの再取得
config.jsonのaccess_tokenを空にする（シングルクオーテーションだけにする）と、再びアクセストークンを取得することができます。
ログインしてくださいやアクセス権限がありませんというエラーになった時は、この方法でアクセストークンを再取得してください


### 外部設計

コマンド

```bash
python timerecordeeer.py [emboss|find] [引数]

# サブコマンドがembossのときに、入力できる引数
[clock_in|break_begin|break_end|clock_out]

# サブコマンドがfindのときに、入力できる引数
yyyy-mm-dd
```

レスポンス

freeeAPIのレスポンスをそのまま返す

### 内部設計

スクリプトといいつつ、雰囲気で責務分担しておく。
逆にごりごり１ファイルで書いていくと後のモチベーションに関わるので。

### 構成
![inner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83578/4404773b-737b-c14f-5129-39442d8a11f2.png)
（Draw.io初めて使ったけど、GUIがあるのね、便利）
JavaFXのドロップボックスの更新遅延の問題


## 概要
JavaFXのChoiceBoxインスタンス（ComboBoxについても同様と予想します）
の選択肢リストを入れ替える際に生じる
遅延とメモリ使用増が問題でした。



## 環境
Win10
Java8


##ドロップボックスってなに
クリックすると選択し一覧が出現するアレ。
GUIでは定番の部品ですが、何と呼ぶのが適当でしょうか？
「ドロップダウン」とか「プルダウン」とも呼ばれてますね。
JavaFXではChoiceBoxというクラスのインスタンスが一個のドロップボックスになります。

##症状
選択肢となる、アイテムのリストをセットします。

わたしは1000個程度(！)のStringリストをchoiceBox.getItems().addAll( items );
とかで渡しました。
そしたら、
choiceBoxがすでにシーングラフ上に表示済みの場合にこの操作すると、
　・GUI全体が数10秒単位で固まる
　・使用メモリ量が500MBとか数GBの単位で増加する。

おそらく、リスト中のアイテム1個が足されるたびにリスナーが働いてシーングラフにアクセスするのだと思う。
1000個もセットするな、ということなんですかねえ。

けれどもchoiceBoxが表示される前にセットする分には1000個でも問題ないのです。

---

choiceBoxが一度でも描画されたらそれまで。
setVisible(false);にしたり親ノードから外して非表示にしても症状は変わらかった。

↑　これが納得いかないのですね。なんでグラフ更新を無効化できないの？

choiceBox.setItems();というメソッドからObservableListをセットし直すという方法も試したが
このメソッドが有効なのは最初の一回だけのようです。


## 結論
いろいろためしましたが
ChoiceBoxインスタンスを使い捨てにして「シーングラフに表示された後は、インスタンスに対するリスト更新はしない」というのが一番まともなようです。

choiceBoxをfinal にしたいのだが、当面あきらめます。

## ぼやき

Java は
こういった実験に時間を費やして進捗が止まる。
なにか間違ってるのだろうか。
Python標準ライブラリにあるデータ構造の時間計算量

## 時間計算量比較

横長の表が見にくいのでどうにかしたい...

以下のページをもとにPythonの時間計算量を並べた。
載っていないメソッドについては、一部を自分で補足し、自分が理解していない残りはTBC。
https://wiki.python.org/moin/TimeComplexity
https://docs.python.org/ja/3/library/
https://www.ics.uci.edu/~pattis/ICS-33/lectures/complexitypython.txt

* List:配列。現在の割り当てサイズを超えて拡張したり、先頭に近い場所に挿入/削除すると遅い。
* TupleはListと同じOperationと時間計算量を持つimmutableなデータ構造。
* Deque:双方向連結リスト＋双端。真ん中あたりのindexにアクセスすると遅い。
* Setはmutable、Frozensetはimmutableでハッシュ可。どちらも同じOperationと時間計算量を持つ。
* DictとDefaultdictは同じOperationと時間計算量を持つ。
* setのaddは末尾に追加するのわけではないけどappendに...
* dictはpython3.7以降順序も保存
* Operationに / がある場合 平均計算量/最悪計算量
* Exampleに / がある場合 類似形
* lstはリストやタプル
* Nは長さ

| Operation | List || Deque || Set ||Dict||
|:--|:--:|:---:|:---:|:---:|:--:|:---:|:---:|:---:|
|| Example |Big(O) | Example |Big(O) | Example |Big(O) | Example |Big(O) | 
|Index|l[i]|O(1)|d[0]/d[middle]|O(1)/O(N)|-|-|d[k]/d.get(k)|O(1)|
|Store|l[i] = 0|O(1)|-|-|-|-|d[k]=v|O(1)|
|Length|len(i)|O(1)|len(d)|O(1)|len(s)|O(1)|len(d)|O(d)|
|Append|l.append(0)|O(1)|d.append()/d.appendleft()|O(1)|s.add(5)|O(1)|-|-|
|Pop|l.pop()/l.pop(i)|O(1)/O(N-i)|d.pop()/d.popleft()|O(1)|s.pop()|O(1)|d.pop(k)/d.popitem()|O(1)|
|Clear|l.clear()|O(1)|d.clear()|TBC|s.clear()|O(1)|d.clear()|O(1)|
|Slice|l[a:b]|O(b-a)|-|-|-|-|-|-|
|Extend|l.extend(lst)|O(len(lst))|d.extend(lst)/d.extendleft(lst)|O(len(lst))|-|-|-|-|
|Construction|list(lst)|O(len(lst))|deque(lst)|O(len(lst)|set(lst)|O(len(lst)|dict(lst)|O(len(lst))|
|check == |l1 == l2| O(N)|d1 == d2|O(N)|d1 == d2|O(N)|s1 == s2|O(N)|d1 == d2|O(N)|
|Insert|l[a:b]=lst| O(N)|-|-|-|-|-|-|
|Delete|del l[i]| O(N-i)|-|-|-|-|del d[k]|O(1)|
|Contain|x in l|O(N)|x in d|O(N)|x in s|**O(1)**|x in d|**O(1)**|
|Copy|l.copy()|O(N)|d.copy()|O(N)|s.copy()|O(N)|d.copy()|O(N)|
|Remove|l.remove(lst)| O(N)|d.remove(lst)|O(N)|s.remove(lst)/s.remove(lst)|**O(1)**|-|-|
|MinMax|min(l)| O(N)|min(d)|O(N)|min(s)|O(N)|min(d.values())|O(N)|
|Reverse|l.reverse()| O(N)|list(reversed(d))|O(N)|-|-|-|-|
|Iteration|for x in l:| O(N)|for dd in d:| O(N)|for x in s:|O(N)|for k, v in d:| O(N)|
|Sort|l.sort()| O(N log N)|sorted(d)|O(N)|sorted(s)|O(N)|sorted(d)|O(N)|
|Multiply|N*K|O(NK)|-|-|-|-|-|-|
|Rotate|-|-|d.rotate(i)|O(i)|-|-|-|-|
|Union|-|-|-|-|s.union(t)|O(len(s)+len(t))|-|-|
|Intersection|-|-|-|-|s.intersection(t)|O(len(s)+len(t))|-|-|
|Difference|-|-|-|-|s.difference(t)|O(len(s)+len(t))|-|-|
|Symmetric Diff|-|-|-|-|s.symmetric_difference(t)|O(len(s)+len(t))|-|-|
[rails]modelを作成する方法

#railsでmodelを作成する方法
modelはデータベースとのやりとりを行ってくれます。
modelを作成するコマンドはこんな感じです。

```
$ rails g model モデル名
```

モデル名の命名規則は、「User」のように、英数字の単数形で指定します。
また、先頭は必ず英大文字で記述します。

実際に、modelを作成するためのコマンドを打つとこんな感じです。

```
$ rails g model User
```

成功すると、、、

```
$ rails g model User
Running via Spring preloader in process 4271
      invoke  active_record
      create    db/migrate/2020072951856_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
```

作成されるファイルは以下の4つです。

db/migrate/（作成日時）_create_lists.rb：「マイグレーションファイル」というデータベースの設計図になるファイルです。
app/models/list.rb：モデルクラスはデータベースに対応したRubyのクラスです。
test/models/list_test.rb：モデルクラスのテストコードのひな形です。
test/fixtures/lists.yml：テストデータ作成のためのひな形です。
超個人的Vimチートシート

備忘として超個人的なVimコマンドのチートシートを記します。

僕はVimmerを志してからまだ日が浅いので、「超個人的」とは書いたものの、大して癖のあるような代物でもありません。『基本的なコマンド＋α』位のレベル感かと思います。

何かの参考になりましたら幸いです。

## 移動系
「Ctrl+d」と「Ctrl+u」でカーソルを半画面分移動できることを知ってから、ページ内の移動速度がかなり向上しました。

「gg」と「G」は重宝しています。よくどっち（「gg」/「G」）がどっち（一番上/下）に移動するのかこんがらがってしまっていたのですが、僕は『「G」の方が大きくて重そうだから一番下に移動する』という風に覚えています。



| キー | 動作 |
|:-----|-----|
| h/j/k/l | 左/下/上/右 |
| w | 次の単語の先頭へ進む。 |
| e | 次の単語の末尾へ進む。 |
| b | 前の単語の先頭へ戻る。 |
| { | 段落単位で前に戻る。 |
| } | 段落単位で次へ進む。 |
| Ctrl-d | 半画面ページダウン。 |
| Ctrl-u | 半画面ページアップ。 |
| gg | ファイルの先頭に移動する。 |
| G | ファイルの末尾に移動する。 |
| gd | 同じファイル内にある変数の定義場所に移動する。 |

## 編集系
「削除＝d」のイメージだったのですが、「c」を覚えたら、削除&インサートの流れがだいぶスムーズになりました。

| キー | 動作 |
|:--|:--|
| c | changeコマンド。テキストの一部を削除し、即座にインサートモードに入ることができる |
| d | deleteコマンド。テキストの一部を削除する。（※インサートモードにはならない。） |
| cc | 行を丸ごと削除してインサートモードに入る。 |

## モード変更
「A」は覚えておくと地味によく使うので便利です。

| キー | 動作 |
|:--|:--|
| v | 文字単位のビジュアルモードに入る。 |
| V | 行単位のビジュアルモードに入る。 |
| :term | ターミナルモードに入る。 |
| a | カーソルの直後からインサートモードに入る。 |
| A | 行の末尾からインサートモードに入る。（$aと同じ。） |
| o | カーソルの１行下に新しい行を作ってからインサートモードに入る。 |
| O | カーソルの１行上に新しい行を作ってからインサートモードに入る。 |
| i | カーソルの手前からインサートモードに入る。 |
| I | 行頭からインサートモードに入る。 |


## 検索・置換系
ここら辺の細かい検索条件・正規表現は今後の課題です。（習得したらだいぶ強いんだろうなぁ…。）

| キー | 動作 |
|:--|:--|
| /hoge | hogeを検索 |
| ?hoge | hogeを後方検索 |
| :substitute | 置換を行う。 |


## ファイル操作（コマンド）
さらなるVim力を身に付けるためには「:help」コマンドを引きまくる必要がありそうです。

| キー | 動作 |
|:--|:--|
| :help | Vimマニュアルを開く。 |
| :w | ファイルを保存する。 |
| :wq | ファイルを保存して閉じる。 |
| :q! | ファイルの内容を保存せずに終了する。 |
| :e | ファイルを開く。 |
| :ls | 存在しているバッファの一覧を表示する。 |
| :b | 異なるバッファに表示を切り替える。 |
| :Ex | Netrw（ファイルマネージャー）を開く。 |


## ウィンドウ操作

「追加でこのファイルも編集しちゃいたい」みたいな時に便利になると思います。（まだそこまで多用していない。）

| キー | 動作 |
|:--|:--|
| :sp | ファイルを水平分割して開く |
| :vs | ファイルを垂直分割して開く |
| Ctrl-w + H/J/K/L | 現在のウィンドウ自体を移動する |

# 番外編
## プラグイン管理
プラグイン管理には「[vim-plug](https://github.com/junegunn/vim-plug)」を使っています。

| キー | 動作 |
|:--|:--|
| :PlugInstall | .vimrcに記載されているプラグインをインストールする。 |
| :PlugUpdate | インストールされている全てのプラグインをアップデートする。 |
| :PlugClean | .vimrcから削除したプラグインを削除する。 |

## 遅いプラグインのプロファイリング方法

起動時に下記のコマンドを実行することで、Vim起動時に各プラグイン含めた起動時間を記したログ出力ファイルが生成される。

```
$ vim --startuptime startuptime.log
```


# 参考資料
- [Ruslan Osipov著『マスタリングVim』大倉雅史訳（2020）技術評論社](https://www.amazon.co.jp/%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0Vim-Ruslan-Osipov/dp/4297111691/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0vim&qid=1596124541&sr=8-1)
- [Vim チートシート(2008.12.6 版)](https://namaraii.com/files/vim-cheatsheet.pdf)
HTTPメソッドとは？

#HTTPメソッドとは？

「HTTP」は見たことがあると思います。 URLの先頭は、「http」から始まっていますね。
この「HTTP（Hypertext Transfer Protocol）」は、通信規約（プロトコル）の1つで、
ユーザーが行いたい処理をサーバーに伝える役割をしています。

ユーザーが行いたい処理をサーバーに伝えることを、「HTTPリクエスト」といいます。
例えば、「ページを移動したい」、「ブログに投稿したい」「ユーザー登録したい」などが、HTTPリクエストです。

#HTTPメソッドの種類
「HTTPメソッド」は、HTTPリクエストをする際に、
通信のやり取りの要求を定義したものです。
代表的なHTTPメソッドは、「GET」「POST」「DELETE」の3種類です。

GET：リソースの取得
ブラウザからサーバーへURLを送信し、Webページを取得（GET）します。
単にWebサイトを閲覧する際は、GETメソッドが使われます。

POST：リソースの更新、リソースへのデータ追加 など
ブラウザからサーバーへ、URL以外のデータも送信（POST）して処理を命令します。
会員情報の登録、記事投稿など、サーバーに情報を送信する際に使用します。

DELETE：リソースの削除
ブラウザからサーバーへ、URL以外のデータ削除のための情報も送信して処理を命令します。
会員情報の削除、記事削除など、情報を削除する際に使用します。
[rails]ルーティングを設定する方法

#railsでルーティングを設定するには
routing（ルーティング）では、ユーザが特定のURLにアクセスした時に、
どのコントローラのどのアクションに処理を振り分けるかを定義します。
ルーティングは、URLとアクションを結びつける役目をしています。
例えば、「あるURLにアクセスがあった時に、homeコントローラのtopアクションの処理を振り分ける」という定義を、ルーティングに記述します。

ルーティングの設定は、configフォルダ内のroutes.rbファイルに記述します。
routes.rbファイルは、Railsアプリを作成するときに自動作成されるファイルです。
こんな感じです。

```
HTTPメソッド 'URL' => 'コントローラ#アクション'
```

※HTTPメソッドについてはこちらの記事で説明しています。
https://qiita.com/yusuke1209kitamura/items/e29787bc2920a656d505

わかりやすく、実際に書いてみます。

```
Rails.application.routes.draw do
  get 'top' => 'homes#top'
end
```

この例の場合、URL「top」にアクセスすると、
homesコントローラのtopアクションが呼び出されるように設定しています。