OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Lightsailを使ってみた

# はじめに

AWSのコンピューティングサービスの一つであるLightsailを試しに少しだけ触ってみたので、その記録を記事としてまとめてみました。

# Lightsailの管理画面

［AWS マネジメントコンソール］にログインして、［サービス］>［コンピューティング］>［Lightsail］と進むと、Lightsailの管理画面が表示されます。
画面中央の［インスタンスの作成］をクリックすると、インスタンス作成のウィザードに入ります。

![lightsail_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/aa6e313d-0de5-4bd7-c0a6-6ea8a91f2f24.png)

# インスタンスの作成

## ロケーションの選択

* 個人で利用するのであれば、低レイテンシーな東京リージョン（ap-northeast-1）を選択するのが良いと思います。
* 東京リージョンを選択した場合、A/B/DのAZの中から1つを選ぶことが出来ますが、AZによる違いはないと思うので、どれを選んでも良いと思います。
 * 厳密にはAZによる違いがあるのかもしれませんが、特に記載されていませんでした。

![lightsail_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/1813a45b-4f57-232b-03ef-d2eacc17835c.png)

## インスタンスイメージの選択

* EC2のようにOS（プラットフォーム）の種類を選べるだけでなく、利用するアプリも含めてイメージ（設計図）を選択できます。
* 独自のSSHキーペアを使う場合は、ここでキーペアをアップロードしておきます。

||OSのみ|アプリ＋OS|
|---|---|---|
|Windows系|Windows Server 2016、<br>Windows Server 2012R2|SQL Server 2016 Expressのみ<br>※OSはWindows Server 2016のみ|
|Linux系|Amazon LinuxやCentOS、<br>Ubuntuなど8種類のOS|WordPressやNginxなど14種類のアプリから1つを選択<br>※OSは不明（選択不可）|

## インスタンスプランの選択

* 必要とするリソース（CPU、メモリ、ストレージ容量、データ転送量）に応じて、インスタンスの種類を選ぶことができます。
* ［並べ替え：］の右側にある項目名をクリックすると、リソースやコストの順にインスタンスを並べ替えて表示できます。
 * ［月次料金］をクリックすると「月額料金の安いインスタンス」の順に表示されます。
 * ［メモリ］などをクリックすると「メモリ量の多いインスタンス」の順に表示されます。
 * ［処理中］と書かれている部分は、「サーバーの処理能力（CPU）の高いインスタンス」の順に表示されるようです。

![lightsail_003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/da773d0a-11f9-e412-a8f2-c4dde741ce87.png)

## インスタンス名とタグの設定

* 一意なインスタンス名を指定する必要がありますが、どのレベルでの「一意」なのかは分かりませんでした。
 * リージョン内で一意、AWSアカウント内で一意など色々と考えられますが...
* インスタンスを識別できるように、必要に応じてタグの設定をします。
* 全て設定が完了したら、［インスタンスの作成］をクリックします。

![lightsail_004_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/c30634c9-7e9e-dbc1-86f6-264e3efcbcaf.png)


# インスタンスの利用

## サーバーコンソールで接続する

* Lightsailのトップ画面から、作成したインスタンスの名前をクリックしてインスタンスの管理画面へ遷移します。
* 所望のインスタンス名（※ここでは `Lightsail-test`）をクリックして、インスタンスの設定画面へと遷移します。
* 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/ba954ccc-c270-1165-7df8-8c58930886f4.png)


* 遷移先の設定画面で［SSHを使用して接続］をクリックすると、サーバーコンソールが起動してインスタンスに接続できます。

![lightsail_006_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/6d947e5d-912a-292b-7f20-ea09b63f3bcb.png)

## 独自のSSHクライアントで接続する

* Lightsailのトップ画面の右上にある［アカウント］ボタンをクリックして、［アカウント］画面へと遷移します。
* アカウント画面で［SSHキー］タブを開き、［デフォルトのキー］を選択して、pemファイルをダウンロードします。
 * 独自のSSHキーを利用する場合は、仮想サーバーの作成時にSSHキーをアップロードしておく必要があります。
* あとは所望のSSHクライアントに「仮想サーバーのパブリックIP」「ユーザー名（ec2-user）」「pemファイル」の3つを設定すれば、仮想サーバーにログインすることができます。 
 * インスタンスのパブリックIP（もしくは静的IP）は、インスタンスの管理画面だけでなく、Lightsailのトップ画面でも確認できます。

![lightsail_010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/37f09b49-694d-488f-63f9-e69245aebc5f.png)

![lightsail_008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/6e0d7e69-6633-dd36-c113-6a9cab3483a8.png)


# 利用上の注意点

* インスタンスを［停止］しても課金が継続されるため、課金を止めるにはインスタンスの［削除］が必要となります。
* インスタンスを削除しても、追加したストレージや静的IPは同時に削除されないため、［ストレージ］タブや［ネットワーキングタブ］から個別に削除する必要があります。
* インスタンスの設定画面で［ネットワーキング］タブを選択すると、ファイアウォールの設定を変更出来ますが、変更できるのはインバウンドのみとなります。
ジェネレーター内包表記 タプル内包表記

```py:1
def g():
    for i in range(10):
        yield i

g = g()
print(next(g))
print(next(g))
print(next(g))
```

```:1の実行結果
0
1
2
```
これを内包表記で書くと

```py:ジェネレーター内包表記
g = (i for i in range(10))

for j in range(3):
    print(next(g))
```

```:ジェネレーター内包表記の実行結果
0
1
2
```

()で囲っているので一見、
タプルの様にも見えなくはない。
タプルの内包表記は下記の様になる。

```py:タプルの内包表記
t = tuple(i for i in range(10))
print(t)
```

```:タプルの内包表記実行結果
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
```

```py:ジェネレーター内包表記2
g = (i for i in range(10))

for j in g:
    print(j)
```

```:ジェネレーター内包表記2の実行結果
0
1
2
3
4
5
6
7
8
9
```

```py:ジェネレーター内包表記3
g = (i for i in range(10) if i % 3 == 0)

for j in g:
    print(j)
```

```:ジェネレーター内包表記3の実行結果
0
3
6
9
```
Dockerを使って、phpMyAdminをいとも簡単に接続する 。

「Dockerでwebアプリケーションを作ろう！」

と思い立ち、せっせと環境構築をし、なんとか構築し終わったーと思い、phpMyAdminに接続しようとしたら、全然できない…。公式イメージ通りにやってるつもりなのにエラーの連続。


なんとか接続できたので、
Docker初学者の人のためにここに書き残します！
＊データベースの設定完了後につまずいていたので、それ以降から投稿します。

データベースがローカルで走っている状態にしてください。
そうしたら、ターミナルでコンテナを見てみましょう。
 
```terminal
$ docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             
STATUS              PORTS                               NAMES
655317389bfd        mysql:5.7           "docker-entrypoint.s…"   23 hours ago        
Up 34 minutes       33060/tcp, 0.0.0.0:4506->3306/tcp   twitter_clone_db_1

```
ぐちゃぐちゃですみません笑
これで、データベースを確認できます。

私がつまづいてしまった場所がここからです。

まず、はじめにdocker-hubから公式のimageを取ってきます。
https://hub.docker.com/r/phpmyadmin/phpmyadmin/


そしてpullしていきます。　　
pullっていうのは、特定のイメージをダウンロードしてくることです！

```terminal
＄　docker pull phpmyadmin/phpmyadmin 
```

そして、完了。よし、runだー！と思ったら…

```
$ docker run --name my-own-phpmyadmin -d --link  twitter_clone_db_1 -p 8081:80 
phpmyadmin/phpmyadmin 

f1df1be3ac876912155029470016bdbe97960e293eec543cbd0bad383269fda9
docker: Error response from daemon: Cannot link to /twitter_clone_db_1, as it 
does not belong to the default network.
```
なんかネットワークにつながっていないみたい。
とりあえずネットワークを調べてみる。

```terminal
$ docker network ls
NETWORK ID          NAME                    DRIVER              SCOPE
a05d069a01f9        bridge                  bridge              local
411a1f6ecd92        host                    host                local
5398f730cb0c        none                    null                local
8117a9fd204d        twitter_clone_default   bridge              local
```

つなぐべきは、一番下のネットワークだとわかったので、
オプションを使ってネットワークに接続させつつ、コンテナを起動させてみる。

```terminal
$ docker run --net=twitter_clone_default  --name my-own-phpmyadmin -d --link  
twitter_clone_db_1 -p 8081:80 phpmyadmin/phpmyadmin
```
すると…

```
d762f136d4c888e4d1cb715536b44b33c98aca180bc10965fb9389624e834bb
```

できたーーーーーー
自力でやった甲斐がありました。泣

確認してみます！

```
$ docker ps
CONTAINER ID        IMAGE                   COMMAND                  CREATED             
STATUS              PORTS                               NAMES
fd762f136d4c        phpmyadmin/phpmyadmin   "/docker-entrypoint.…"   43 seconds 
ago      Up 42 seconds       0.0.0.0:8081->80/tcp           my-own-phpmyadmin

655317389bfd        mysql:5.7               "docker-entrypoint.s…"   24 hours ago        
Up 41 minutes       33060/tcp, 0.0.0.0:4506->3306/tcp   twitter_clone_db_1

```

しっかりできていました。

ということで、localhost:8081　へアクセスします。

<img width="481" alt="スクリーンショット 2020-01-16 21.14.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553393/63c04cba-5e38-e332-e6cb-8867ec68d77a.png">


usernameに「root」を入れて、Passwordは自分で設定したものを入れてください。
<img width="1199" alt="スクリーンショット 2020-01-16 21.17.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553393/c567842a-922c-5f9f-ad5f-84075b8dba82.png">

これで完成です！
Dockerを使えば、効率が著しく上がりますよね！
引き続き、webアプリケーション作成に励みます！
コメント名が「作成者」に変わる現象の修正方法

## 「作成者」って誰だよ…
後輩の添削などをしている時，折角つけたコメントが，結局誰がつけたのか分からなくなるのはちょっと悲しくないですか…（実体験）

また，ググった際には2013以前の設定方法ばかりで2016以降のものの設定方法が分からなかったため，こちらに設定方法の変更方法をまとめました．
versionはoffice 2016です．

基本メモなので至らない点などあるかと思いますが，何か分からないことなどあればコメント頂けると助かります．

## 設定手順
1. ファイル > オプションを選択

2. Wordのオプション > トラストセンター > トラストセンターの設定を選択![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212454/f98b73e6-8e33-940d-d1cc-ad8b39a0eb1b.png)

3. トラストセンター > プライバシーオプションを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212454/9a0ecd8e-3cdd-b966-3c21-fd83e12006a7.png)

4. ドキュメント固有の設定「ファイルを保存するときにファイルのプロパティから個人情報を削除する」の☑を外す

設定は以上です！

また，場合によっては設定が上手く反映されない場合もあるようなので，一度ドキュメントを保存し再起動すれば反映されます．
[React]@babel/preset-env と @babel/ransform-runtime を core-js@3 で対応する

最近の勉強で学んだ事を、ノート代わりにまとめていきます。
主に自分の学習の流れを振り返りで残す形なので色々、省いてます。
Webエンジニアの諸先輩方からアドバイスやご指摘を頂けたらありがたいです！

#Babel と core-js の関係のおさらい

>Babelが提供する @babel/polyfill や @babel/preset-env などのモジュールを利用すると
>built-ins objects(Promise, WeakMap等)
static methods(Object.assign, Array.from等)
instance methods(Array.prototype.includes等)
といった新しい機能を使った実装が可能になりますよね。これらのBabelモジュールは core-js が提供するpolyfillを内部的に読み込んでいます。特に @babel/polyfill は core-js と regenerator-runtime を束ねて提供するpolyfill集です

core-jsのバージョンを指定して直接読み込むます！
古いブラウザをサポートするため、core-js を利用してポリフィルを含めた React 16 向けの環境を次のように設定

>React 16 はコレクション型 Map および Set に依存しています。これらの機能をネイティブに提供しない（IE 11 未満など）、または標準非準拠な挙動をする（IE 11 など）古いブラウザやデバイスをサポートする場合は、core-js や babel-polyfill などのような、グローバル環境のポリフィルをバンドルしたアプリケーションに含めることを検討してください。

```package.json
+    "core-js": "^3.6.4",
```

```src/index.js 
+ import 'core-js/es/set'; 
+ import 'core-js/es/weak-map'; 
```

これで完了です！

#参考記事
[JavaScript 環境の要件](https://ja.reactjs.org/docs/javascript-environment-requirements.html/)
[Babel7.4で非推奨になったbabel/polyfillの代替手段と設定方法](https://aloerina01.github.io/blog/2019-06-21-1/)
[ReferenceError: Can't find variable: WeakMap](https://github.com/sweetalert2/sweetalert2/issues/1588/)
[@babel/polyfill と core-js](http://var.blog.jp/archives/79457227.html/)
Swipe.js スライド時にイベントを発火させる

Swipe.jsでiphoneライクなTimepickerを実装したので共有します。
出来上がりイメージ図は<img width="584" alt="スクリーンショット 2020-01-16 19.50.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254495/d127ea49-76f6-a8ad-2b39-270538c1bb55.png">
こんな感じです。
コードはこちらから確認できます。
[Timepicker using Swiper.js](https://codepen.io/dogoku/pen/zNxKpd)


公式ドキュメントはあまり参考ならなかったです。(わたし的に)
[Swiper](https://swiperjs.com/)

# 補足
iphoneライクに指でスワイプできるようにすると
どうしてもイベントが発火しなかったので、
泣く泣く指スワイプは外しました。
(実装に成功した方は是非教えていただきたい)

ちなみに指スワイプを実装したコードは以下になります。


```javascript:index.js

var defaults = {
  pagination: '.swiper-pagination',
  slidesPerView: 3,
  freeMode: true,
  freeModeSticky: true,
  freeModeMomentumRatio: 0.25,
  freeModeVelocityRatio: 0.25,
  freeModeMinimumVelocity: 0.1,
  mousewheelControl: true,　<-- こいつと、
  mousewheelSensitivity: 0.5,  <-- こいつを実装する。
  loop: true,
  loopAdditionalSlides: 5,
  direction: 'vertical',
  slideToClickedSlide: true,
  centeredSlides: true
};

```
Docker Hub の Build triggers の使い方

Docker Hub の (Remote) Build triggers の使い方がよく分からなかったので調べました。

Docker Hubには外部からリクエストをPOSTすることでAutomated Buildを実行する「Build triggers」という設定がBuildタブの「Configure Automated Builds」の中にあるのですが（下記画像参照）、どうもDocker v19.03現在時点で、その使い方の詳細が消えてしまっているようです。（[現在のドキュメント](https://docs.docker.com/docker-hub/builds/)にも記載されていません。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54918/a406e24b-4c94-0c96-687e-d463c2391465.png)

昔のドキュメントをさかのぼってみると[v17.06時点のドキュメント](https://github.com/docker/docker.github.io/blob/17.06-stable/docker-hub/builds.md#remote-build-triggers)には書いてありました。（オリジナルサイズの画像はリンク先へ）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54918/0dcba588-96b9-6240-3d94-cd9ee4ec0f62.png)

よく見ると「Trigger Url」の形式も変わっています。（昔のTrigger TokenはTrigger Urlに含まれたように見えます。）どこかの時点で仕様が変わったのだと思いますがよくわかりませんでした。Trigger Urlは変わっていますが、JSONパラメータは同じものが使えるようです。~~少なくとも*Trigger by Source tag named v1.1*が~~すべて動作することを確認しました。`build`または`docker_tag`はBUILD RULESの定義にマッチするものが反応し、`source_type`は指定したブランチ/タグをpushした時と同じように反応するようです。（注意 もしかしたらJSONパラメータは将来廃止する or 廃止されたという意図なのかもしれないので注意した方がいいかもしれません。）

ちなみに現在のTrigger Urlの形式 `https://hub.docker.com/api/build/v1/source/` で検索してもBuild triggersの情報はあまり見つかりませんが、古い形式である `https://registry.hub.docker.com/` `trigger` あたりを検索キーワードとすると見つかると思います。

検索＆コピペ用に画像のExamplesの内容をテキスト化しておきます。

```
# Trigger all tags/branchs for this automated build.
$ curl -H "Content-Type: application/json" --data '{"build": true}' -X POST https://

# Trigger by docker tag name
$ curl -H "Content-Type: application/json" --data '{"docker_tag": "master"}' -X POST https://

# Trigger by Source branch named staging
$ curl -H "Content-Type: application/json" --data '{"source_type": "Branch", "source_name": "staging"}' -X POST https://

# Trigger by Source tag named v1.1
$ curl -H "Content-Type: application/json" --data '{"source_type": "Tag", "source_name": "v1.1"}' -X POST https://


curl --data build=true -X POST https://registry.hub.docker.com/u/svendowideit/testhook/trigger/be579c
82-7c0e-11e4-81c4-0242ac110020/
```

## おまけ

勢い余って、Build triggers をCLIで実行するツールを作ってみたけど、curlで十分だし使わない気がするなぁ。

https://github.com/ko1nksm/docker-build-trigger
【PHP8.0】マイナススタートの配列インデックスが使えるようになる

```php:PHP7.4
	$arr = [];
	$arr[-10] = 1;
	
	$arr[] = 1;
```

どうなるかというと`[-10=>1, 0=>1]`です。

これは[マニュアル](https://www.php.net/manual/ja/language.types.array.php)にも明記されています。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/4690c36b-844f-c90f-dd10-718a249e94e8.png)

しかしこの動作はPHP8.0で変更になります。
[Arrays starting with a negative index](https://wiki.php.net/rfc/negative_array_index)というRFCにおいて変更が決定しました。

# Arrays starting with a negative index

## Introduction

[array_fillのドキュメント](https://www.php.net/manual/function.array-fill.php)には、『start_index が負の場合は、 返される配列の最初のインデックスが start_index となり、それ以降のインデックスはゼロから始まります』とあります。

明示的に負のキーを使用し、その後キーを省略した場合は常にこのような動作になります。

## Proposal

現在の動作は、最後の数値キーがnであった場合、次の暗黙キーは`n>=0`であれば`n+1`、`n<0`であれば`0`ということになります。

このRFCでは、nの符号に関係なく常に`n+1`とすることによって、この動作を一貫させることを目指しています。

[配列のドキュメント](http://php.net/manual/en/language.types.array.php)にもわざわざ注釈として書かれているように、これは例外的な動作であり、学習コストとなります。

このプロポーザルはPHP8.0を対象としています。
この変更により問題が発生する可能性がある場合、移行を容易にするために非推奨の通知を出すことも提案します。

以下のコードは全て同じ結果になります。

```php
	$a = array_fill(-2, 3, true);
	$b = [-2 => true, true, true];
	$c = ["string" => true, -2 => true, true, true];
	unset($c["string"]);
	$d[-2] = true;
	$d[] = true;
	$d[] = true;
```

現在は全て以下のようになります。

```php:～PHP7.4
array(3) {
  [-2]=>
  bool(true)
  [0]=>
  bool(true)
  [1]=>
  bool(true)
}
```

このRFCにより、以下の動作に変更になります。

```php:PHP8.0～
array(3) {
  [-2]=>
  bool(true)
  [-1]=>
  bool(true)
  [0]=>
  bool(true)
}
```

非推奨を出力する投票が受理された場合、移行フェーズ中は以下のE_DEPRECATEDを発生させます。

`Deprecated: In the next major version of PHP the implicit keys of this array will start from -1 instead of 0 in ...`


## Backward Incompatible Changes

配列を負のインデックスから開始し、その後暗黙のキーを使い、そして明示的なキーで配列要素にアクセスした際に影響が発生します。


```php
$a[-2] = true; // 現行：キーは-2 / RFC：キーは-2
$a[] = true; // 現行：キーは0 / RFC：キーは-1
$a[] = true; // 現行：キーは1 / RFC：キーは-0
 
if ($a[1] === true) {
    echo 'Accessing key 1 explicitly';
}
```

PHP8.0以降、'Accessing key 1 explicitly'が出力されなくなります。

## Proposed PHP Version(s)

PHP8.0。


## Unaffected PHP Functionality

明示的なキー、文字列のキーには影響しません。
また、-1以上の数値インデックスを持つ配列も影響を受けません。
最初から暗黙のキーを使う配列のインデックスは0から始まります。

キーを使用しないforeachも影響を受けません。


## 投票

このRFCは賛成17反対2で可決されました。

E_DEPRECATEDを出す提案は賛成8反対14で却下されました。

すなわち、PHP8.0で前触れなく突然動作が変更になります。


# 感想

PHP4.2から長い時を経て、元の鞘に戻ることになりました。
さすがに当時のことは知らないので、どうして変更されたのかは全くわかりません。

しかし、この仕様に依存する実装をしている人なんていないでしょう。
すなわち実質的な影響はほぼゼロです。
そもそもネガティブスタートの配列って何に使うんだろうか？

ただ、MySQLの[AUTO_INCREMENT](https://dev.mysql.com/doc/refman/5.6/ja/example-auto-increment.html)も[マイナスは使えない](https://qiita.com/sakuraya/items/0dd0bb4114e56f42556d#-100%E3%81%8B%E3%82%89%E5%A7%8B%E3%81%BE%E3%82%8B%E8%87%AA%E5%8B%95%E6%8E%A1%E7%95%AA)ですし、あえて変更する必要があるのかは少し疑問です。

あと配列をコピーしたら[何かおきそう](https://qiita.com/rana_kualu/items/9d41a593f1b866b0c67a)で少し楽しみですね。
[Rails]使用中のlocalhost3000のプロセスを切る

最近の勉強で学んだ事を、ノート代わりにまとめていきます。
主に自分の学習の流れを振り返りで残す形なので色々、省いてます。
Webエンジニアの諸先輩方からアドバイスやご指摘を頂けたらありがたいです！

#localhost:3000で別のサーバーを起動したい
localhost:3000でサーバーを起動しようとしたら別のRailsのプロジェクトで使用していたのを忘れていました。

```ruby
$ rails s
/Users/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/railties-6.0.2.1/lib/rails/app_loader.rb:53: warning: Insecure world writable dir /Users in PATH, mode 040777
=> Booting Puma
=> Rails 5.2.3 application starting in development 
=> Run `rails server -h` for more startup options
A server is already running. Check /Users/Desktop/project/tmp/pids/server.pid.
Exiting
```

3000のポートを使用している物を確認！

```ruby
sudo lsof -nP -iTCP:3000 -sTCP:LISTEN
COMMAND   PID             USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node    40429 tester.user        29u  IPv4 0xbed1da96d5b6b725      0t0  TCP *:3000 (LISTEN)
ruby    70168 tester.user        12u  IPv4 0xbed1da96d2fa3425      0t0  TCP 127.0.0.1:3000 (LISTEN)
ruby    70168 tester.user        13u  IPv6 0xbed1da96b93aa9e5      0t0  TCP [::1]:3000 (LISTEN)
```

プロセス番号（PID）を指定してプロセスを切る

```ruby
kill -9 70168
```

これで完了！

#参考記事
[Rails sのプロセスが切れない時](https://qiita.com/motty93/items/d22c1eb8f5128f8cd7f8/)
[Killing MailCatcher: Something's using port 1025](https://stackoverflow.com/questions/24830534/killing-mailcatcher-somethings-using-port-1025/)
[React]axiosの処理が繰り返し、呼び出される問題

コンポーネント内で定義したstateをaxiosのresponseデータを使って書き換える処理を書きましたが、console.log()で取ってみると何度もresponseが返ってくる事象。。。

```js
        const [posts, setPosts] = useState([]);

        axios
            .get('/api/posts')
            .then(response => {
                setPosts(response.data);
                console.log(posts)   //何度も通信が走っていることを確認

            })
            .catch(() => {
                console.log('通信に失敗しました');
            });
```

下記で解決しました。

```js
    useEffect(() => {
        getPostsData();
    },[])

    function getPostsData(){
        axios
            .get('/api/posts')
            .then(response => {
                setPosts(response.data);

            })
            .catch(() => {
                console.log('通信に失敗しました');
            });
    }
```


axiosの処理を関数化し、第２引数を[]にすることで、空配列が渡ってきたときのみ、処理が走るようにします。

やはり公式、、、

https://ja.reactjs.org/docs/hooks-reference.html

空の配列 [] を渡すと、この副作用がコンポーネント内のどの値にも依存していないということを React に伝えることになります。つまり副作用はマウント時に実行されアンマウント時にクリーンアップされますが、更新時には実行されないようになります。
シェルスクリプト bash で tuple っぽくデータを扱ってみる

配列を定義します。
空白スペース区切りで tuple っぽいデータを宣言しています。
for ループ内で配列の要素を一つずつ取り出して、set コマンドで位置パラメータに代入しています。
そしてそれらを出力させているだけです。

```bash:tuple.sh
#!/bin/bash

declare -a tuples=("a 1" "b 2" "c 3")

for tuple in "${tuples[@]}"
do
  set -- $tuple
  echo $1 $2
done
```

以下のような出力が得られます。

```bash
$ ./tuple.sh 
a 1
b 2
c 3
```

もし、カンマ区切りで tuple っぽいデータを宣言したい場合は、IFS変数を変更する。

```tuple2.sh
#!/bin/bash

declare -a tuples=("a,1" "b,2" "c,3")

for tuple in "${tuples[@]}"
do
  IFS=","
  set -- $tuple
  echo $1 $2
done
IFS=
```
ethercalcでunhideできなくなったら: apiでdataをまんま書き換えてしまう

なんか最近また開発してんのかな？

# やっちまった
今回は row をたくさんhideしたら戻らなくなったので

裏側のデータを直で書き直すことで復活

# やりたいこと
auditで見える set * hide yes を全部消したい


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/6e9b7514-7543-bc0d-6432-f41a664903cd.png)



# 復活手順

画面からはできなさそうなので、apiを使った

*完全に破壊手順なので要backup。

## apiの使い方

 api endpoint: 一般的なapiが `/api` だとするなら、ethercalcのは `/_` になってる

```ruby
# 既存コンテンツをゲット
curl -s -X GET 'Content-Type: text/x-socialcalc'   http://etcalc.local:8000/_/your_doc > etcalc.save

# hideの記述行を消す
vim etcalc.save

set 5 hide yes とか書いてる行を消す。


# 既存コンテンツを新しいdataでまんま上書き
curl -X PUT -H 'Content-Type: text/x-socialcalc'  --data-binary @etcalc.save http://etcalc.local:8000/_/your_doc
```

## file構造

headとtailはこんな感じ

```ruby
socialcalc:version:1.0
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=SocialCalcSpreadsheetControlSave
--SocialCalcSpreadsheetControlSave
Content-type: text/plain; charset=UTF-8

# SocialCalc Spreadsheet Control Save
version:1.0
part:sheet

...data

Content-type: text/plain; charset=UTF-8

version:1.0
rowpane:0:1:1
colpane:0:1:1
ecell:A1
--SocialCalcSpreadsheetControlSave
Content-type: text/plain; charset=UTF-8

--SocialCalcSpreadsheetControlSave--
```



# api reference

https://github.com/audreyt/ethercalc/blob/master/API.md


これがあればcopyたくさん作れるな。
初心者　アプリ開発

初めましてプログラミング初心者です
お店の空席確認ができるアプリを作成しています
ログインして席の番号をクリック
jsで席の番号の色が変わるように実装しました

ログアウトの機能も実装してあるのですが

リロードした時に番号の色が変わらずログアウトした時のみ色が変わるような実装がしたいです

セッションを使えば実装できるのでしょうか
Codebuildのローカルキャッシュでハマった話

# 実現したいこと
[前回の記事](https://qiita.com/PedMk0/items/39362f445be66474b596) で構築したCIパイプラインの実行時間を短縮したい
具体的には，CodeBuildでDockerイメージを作成する際のgoモジュールを予めキャッシュしておき，ビルド毎に発生するダウンロード時間を短縮したい．

#環境
- Golang 1.13.5
- Docker 18
- AWS 東京リージョン

# やったこと/ハマったこと
### やったこと1

- CodeBuildの設定変更
CodeBuildのアーティファクト設定からキャッシュタイプを"ローカルキャッシュ"に変更
オプションは"CustomCache"を選択

- buildspec.yamlの編集  
前回作成したbuildspec.ymlに cache項目を追加

```yaml

version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
    commands:
    - $(aws ecr get-login --no-include-email --region ap-northeast-1)

  pre_build:
    commands:
    - make test

  build:
    commands:
    - make build

  post_build:
    commands:
    - make push-image

#キャッシュ対象にするディレクトリを指定
cache:
  paths:
  # goモジュールの保存先
  - '/go/pkg/mod/**/*'
```

### ハマったこと1
- goモジュールが `/go/pkg/mod/` に保存されていない  
go buildをDockerbuildの中で行っていたため ダウンロードしたモジュールは
CodeBuild上で作成されたDockerコンテナの `/go/pkg/mod/` に保存されていた

当然Dockerコンテナ自体をキャッシュすることは出来ないのでこの方法は破綻

go buildをCodeBuildのコンテナ上で行い，Docker build時にコピーすることに変更
これにより，goモジュールはCodeBuildコンテナの `/go/pkg/mod/` に保存される

### やったこと2
- buildspec.ymlを編集

```yaml
version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
      # goのランタイムが必要になったので追加
      golang: 1.13
    commands:
     - $(aws ecr get-login --no-include-email --region ap-northeast-1)

  pre_build:
    commands:
    - make test

  build:
    commands:
    # CodeBuildコンテナ上でbuildするため make buildから変更
    - CGO_ENABLED=0 go build -ldflags '-d -w -s' -o app
    - make build

  post_build:
    commands:
    - make push-image

cache:
  paths:
  - '/go/pkg/mod/**/*'

# go buildで必要になる環境変数の指定
env:
  variables:
    GOOS: linux
    GOARCH: amd64

```

- DockerFileを編集  
元々はgo buildもdocker build内で行っていたので
docker buildでは既に作成されたgoアプリの実行ファイルを使用してイメージを作成するようにDockerFileを編集


### ハマったこと2
- なぜかローカルキャッシュが機能していない

キャッシュの設定は上手くいっているようでログ上もローカルキャッシュを読み込んでいる(シンボリックリンクを作成している)
が，肝心のリンク先にキャッシュされているはずのファイルが存在しない．

[AWSの仕様ページ](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-caching.html#caching-local) を見るにローカルキャッシュが利用できない場合もあるとのことだが，今回の設定は該当していないように思える．

今回は原因調査まで行う余裕がなかったため　一旦ローカルキャッシュを諦め
S3にキャッシュさせることにした．

### (課題は残るものの)完成
キャッシュ設定前後ではビルド時間が 3min43sec -> 3min09sec と多少なりキャッシュの恩恵を確認できた．
ただ，S3キャッシュはS3からキャッシュデータをダウンロードし，ビルド後にS3へアップロードするため，予めコンテナ内にデータを保持しておき，シンボリックリンクを作成するのみのローカルキャッシュと比べると時間がかかってしまう．
(今回はキャッシュデータが50MBを超えていたのでダウンロード/アップロードに時間がかかっているのが実感としてあった)
macOSをCatalinaにしたらRubyとRailsが消えた時【zsh: /usr/local/bin/rails: bad interpreter: System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: no such file or directory】の対処

##Catalinaにした後Rubymineのプラグインを挿入後の再起動でRailsが消えた
エディターでRubymineを使用しているのですが、プラグインを挿入し再起動、%rails sなどのコマンドをしても、『Rails is not currently installed on this system. To get the latest version, simply type: $ sudo gem install rails』とエラーが発生。

###rbenvのパスの設定が変わったと想定
ここら辺の環境設定ではプログラミング初心者はとても頭を悩ます分野。
プログラミングスクールのDive　Into　Codeに通っていた頃、メンターの皆様によく教わりました。
「bash~が〜」とか「システムでのRubyとローカルは違う〜」「rbenvのpathは〜」
色々教わりましたが、Rubyの構文やRailsの仕組み、そもそもブラウザの仕組みやHTMLやCSSを働きながら多方面の分野を勉強する為、環境構築はとても苦手でした。

###極論：教授して頂いたコードをコピペ
ここでは一応腹落ちするまで教えて頂きましたが、３０分ググったりして悩んだ場合は素直に教えてもらい先に進んだ方が良い。ただ自分のこの調べる力は、後々のエンジニアとしての『再現性』を豊にするの実感。
エンジニアの8~9割りはエラーやバグの解決に時間を要する為、プログラミング初心者は解決できなくともそこで挫折しないで良い経験だとして、力として欲しい。

##「~/.zshrc」ファイルにrbenvのpath設定をしてあげる
話題を本題に戻します。
%which　ruby　をコマンドした場合、
/usr/bin/ruby　の表示。
このままだと、いくら%rails　sなどのRailsコマンドをしても、
【zsh: /usr/local/bin/rails: bad interpreter: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: no such file or directory
Rails is not currently installed on this system. To get the latest version, simply type:】のエラー表示が出る。
その後には、【 $ sudo gem install rails】とアドバイスされる。
###結果論： $ sudo gem install railsのコマンドは要らない
元々railsのgemはインストールされている中で、pathが違った為のエラー。
なので、pathを通す為にコマンドしてあげれば良い。
##%which rubyで【/Users/ユーザー名/.rbenv/shims/ruby】になるまで
https://teratail.com/questions/218281 このサイトを参考にしました。
ただここでは一時的な解決にしかならない為、エディターを再起動したり、違うターミナル開けた場合、同じエラーになりました。
###対処法の結論

`%echo 'export PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"' >> ~/.zshenv`
`%echo 'eval "$(rbenv init -)"' >> ~/.zshenv`
`%echo 'source $HOME/.zshenv' >> ~/.zshrc`
`exec $SHELL`
`source $HOME/.zshenv`

`%Which ruby 
/Users/ユーザー名/.rbenv/shims/ruby`
`%which rails
/Users/ユーザー名/.rbenv/shims/rails`

もうOSのアップデートの度に、びっくりしなくて済みます。
##参考にしたサイト
https://medium.com/@petehanner/getting-rails-to-work-with-catalina-zsh-84146e1d2099
備忘録としてコマンドだけをツイートしたのも残しておきます。
https://twitter.com/ARTS_papa/status/1217754991819030529
Mobile Blazor Bindings は「Xamarin.Forms アプリ生成器」でした

[BlazorでiOS/Androidネイティブアプリケーションを開発可能にする「Mobile Blazor Bindings」、マイクロソフトが発表 － Publickey](https://www.publickey1.jp/blog/20/blazoriosandroidmobile_blazor_bindings.html)

これなんですけど。「ざまりん乙」的な声が今回もチラホラ聞かれたので「マジか！それはすごい」と思って試してみました。

## サンプルアプリを動かしてみた

* [ASP.NET Blog / Announcing Experimental Mobile Blazor Bindings](https://devblogs.microsoft.com/aspnet/mobile-blazor-bindings-experiment/)

こちらの手順の通りで、簡単に試すことができます。[^1]

[^1]: 簡単に動かせたのは Xamarin.Forms アプリ開発環境は既に構築済みだったこともありｗ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8227/17ac25b9-d107-66e5-dff1-26c690acf9b9.png)

まあ、ソリューションを見てみただけで Xamarin(Xamarin.Forms アプリ) なんですけども。

## inspect してみた

続いて、Android 向けのプロジェクトをエミュレータで実行し、Android Studio 付属の Device Monitor で inspect してみました(もしかしてガワネイティブ？という可能性もあったので)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8227/1c97edc7-cdfe-dd91-bb07-e55c568d1bca.png)

FrameLayout や RelativeLayout などの Android ネイティブ部品が並んでいるので確かに "ネイティブ" でした。
また、PlatformRenderer とか ButtonRenderer、これらは Xamarin.Forms アプリを inspect した時と同じ感じです。

## Mobile Blazor Bindings のソースコードを見てみた

ソースコードはこちらです(Open by default 素晴らしい)。

* [xamarin/MobileBlazorBindings: Experimental Mobile Blazor Bindings - Build native mobile apps with Blazor](https://github.com/xamarin/MobileBlazorBindings)

[ここらへん](https://github.com/xamarin/MobileBlazorBindings/blob/master/src/Microsoft.MobileBlazorBindings/Elements/Button.cs#L11-L17) に、それっぽい記述を見つけることができます。

```csharp
using XF = Xamarin.Forms;

namespace Microsoft.MobileBlazorBindings.Elements
{
    public class Button : View
    {
        static Button()
        {
            ElementHandlerRegistry
                .RegisterElementHandler<Button>(renderer => new ButtonHandler(renderer, new XF.Button()));
        }
（以下略）
```

サンプルアプリに Razor テンプレート(``*.razor``) に記述した ``<Button>`` という要素は、上記の処理で ``Xamarin.Forms.Button`` にマップされるように見えます。

## つまり

**「Razor の仕組みを使って Xamarin.Forms アプリを作ることができるのが Mobile Blazor Bindings」**

ということのようです。 UI用DSLから Android/iOS 向けには Xamarin.Forms が使われる点は、[Uno Platform](https://qiita.com/tan-y/items/b240252870a4d7aa9d34#uno-platform-%E3%81%AE%E5%B1%95%E6%9C%9B) にも近いと思います。

## なにがおいしいの？

Blazor は「We **B** Assembly + **Razor**」の造語だっと記憶してますが、昨日の [.NET Conf Focus on Blazor](https://www.publickey1.jp/blog/20/blazor_webassembly5blazorpwa.html) のまとめを見ると、

**「WebAssembly 使う使わん関係なく、とにかく Razor 技術から様々なプラットフォーム向けアプリを生成するフレームワークが Blazor」**
という事になったようですね(Mobile Blazor Bindings に wasm 技術の欠片は見当たりませんでした)。

という事で、``.razor`` テンプレートやそれが属するプロジェクトに記述された UI や C# コードは、Webアプリ／モバイルアプリ／デスクトップ向けアプリとしても再利用できますよ、という目論見のようです。

Razor は、ASP.NET を使ってWebフロントエンドを開発するための技術として普及している(と思う)ので、その流れでカバー範囲を広げたい人には刺さるでしょう(一方 XAML を主戦場とする人には前述の Uno Platform の方が刺さるでしょうか)。

「「「ネイティブAndroid のラッパーである Xamarin.Android」、をラップした Xamarin.Forms」をさらにラップした Mobile Blazor Bindings」、、、というゴテゴテ感、個人的にはキライじゃないし、それなりに基盤がしっかりしていないとさすがに崩れ落ちるので、.NET基盤 ってすごいなあ、と思います。
AWS EC2インスタンスの複製をしてみた。その7（備忘録）

前回の続きです。https://qiita.com/Bikeiken-IT/items/e1b80cc6cf2cbced5440

EC2インスタンスのEC2-test-2にSnapshotから生成したボリュームをアタッチします。
![step41-atatch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/d9e6a108-007d-dd42-0669-840a133bc188.png)
AWSサービスのEC2の画面の左側にスクロールがあります。スクロールのなかにボリュームという項目があるので、それを選択します。
次に、先ほどSnapshotから生成したボリュームを選択します。アクションからボリュームのアタッチを選択します。
![step42-atatch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/59638e57-e3da-47db-acfc-c01514205f45.png)
ボリュームのアタッチには二つの入力項目があります。
一つは、ボリュームをアタッチするインスタンスの選択です。
もう一つは、その６でメモ帳等に保存してあるはずのEC2-test-2のボリュームを置くディレクトリです。
二つの項目の入力を確認して、アタッチのボタンを押してください。
これでEC2-test-2にSnapshotから生成したボリュームがアタッチされました。
![step43-running.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/10905d3a-1783-a488-7045-64322aa0617c.png)
最後に、アタッチされたボリュームが反映されているかをブラウザで確認します。

まず、停止してあるEC2-test-2を動作させます。
![step45-sudo-start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/06e62b4c-3fdf-c93b-0573-ccfa6ad6f542.png)
次に、TeraTermからEC2-test-2に接続します。
"sudo su -"コマンドで管理者権限に移行します。
そして、"service httpd start"コマンドでApacheサーバーを起動させます。
![step46-finish.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/240d0c8c-8cc2-947d-44c1-912223eb3de6.png)
最後に、ブラウザにEC2-test-2のパブリックIPを入力して、出力を確認します。

きちんと反映されていることが確認できました。

以上で”AWS EC2インスタンスの複製をしてみた編”を終わります。

最後まで読んでいただきまして、ありがとうございました！！！
iPadから新規にEC2サーバー立てて、Blink ShellからSSHでログインする手順

# iPadから新規にEC2サーバー立てて、Blink ShellからSSHでログインする手順

[Blink Shell](https://apps.apple.com/jp/app/blink-shell-mosh-ssh-client/id1156707581)はiOS上のターミナルソフト

このソフトとiPadだけでAWSのEC2立ててログインするところまでの手順をまとめました。
大枠の操作は一般的な手順と変わりませんが、
EC2で生成したキーペアのダウンロードがiPad上でうまくいかないので、
先にipad上でキーペアを作成しておく箇所だけがつまづきポイントです。

## 今回使用した環境

- iPad Air2
- Blink Shell
- Google Chrome

## 暗号鍵のキーペアを事前に作成する

Blink Shell上で下記のコマンドを打てばOK

```sh:暗号鍵を生成する
blink> ssh-keygen -t rsa -b 4096 -m PEM -f asw_rsa.pem -C ‘’
```

最後の`-C`はユーザー名やドメイン名といった不要な情報をつけないためのオプション

## EC2にキーペアをインポートする

まずBlink Shell上で下記のコマンドを実行し、公開鍵をテキスト表示する。
それをまるっと選択してコピーしておく。

```sh:公開鍵の表示。これをコピーする
blink> cat asw_rsa.pem.pub
```

次にWEBブラウザからAWSにログインし、
下記の手順でキーペアをインポートする。

1. EC2ダッシュボードの`キーペア`を選択
2. `キーペアのインポート`
3. `キーペア名`は任意の名前
4. パブリックキーに先にコピーしておいた公開鍵をペーストする
5. `インポート`をクリックする

## EC2のインスタンスを作成する

1. EC2ダッシュボードのインスタンスからインスタンスの作成を実行
2. ステップ7までは普通に選択していく
3. ステップ7「インスタンス作成の確認」で起動をクリック
4. 「既存のキーペアを選択するか、新しいキーペアを〜〜」のダイアログが表示される
5. 「既存のキーペアの選択」を選択、キーペアは先の手順でインポートしたものを指定
6. 「インスタンスの作成」をクリック

## 動作確認

Blink Shellから下記のコマンドでSSH接続ができることを確認する。

```sh:sshでのログイン確認
blink> ssh -i ./asw_rsa.pem ec2-user@ホストのIPアドレス
```
Next.jsのセットアップ手順

# ディレクトリ作成
```
mkdir sample_app
cd sample_app
```

# node_modules初期化
```
npm init -y
```
- これでpackage.jsonを作ってくれる

# Next.jsインストール
```
npm install --save next react react-dom
```

# package.jsonのscriptsにコマンドを追加
```
"dev": "next -p 3001",
"build": "next build",
"start": "next start"
```
- ポート番号3000だと他アプリと被りやすいので別ポートに変更

# サンプルページ作成
```
mkdir pages
vi pages/index.js
```

```
export default () => <div>Welcome to next.js!</div>
```

# 起動
```
npm run dev
```

# 参考記事
- https://nextjs.org/docs/getting-started
- https://bagelee.com/programming/next-js/setup-next-js/
初心者によるプログラミング学習ログ 212日目

#100日チャレンジの212日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

212日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>212日目<br><br>前に作成した模写サイトにjavascript・jQueryで動きをつける試み。アウトプット重視<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1217544054663069697?ref_src=twsrc%5Etfw">January 15, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
関数内で例外が発生した場合、呼び出し元へ伝わる2

```py:1
def test_exception(num):
    print(1)
    try:
        print(2)
        answer = 100 / num
        return answer
        print(3)
    except ZeroDivisionError as e:
        print(4)
        raise e
    print(5)

print('start')
try:
    test_exception(1)
    print(6)
except ZeroDivisionError as e:
    print(7)
    raise e
finally:
    print('end')
```

```:1の実行結果
start
1
2
6
end
```

print('start')を
最初に実行。

次に、
tryブロックを実行する。
tryブロック1行目のtest_exception関数に引数1で入る。
なので、
print(1)を実行し、
test_exception関数内のtryブロック内を実行する。
print(2)を実行し、
answer = 100
となり100を返す。
retrunしているので、
その下のprint(3)は実行されない点に注意。
ZeroDivisionErrorは発生していないので、
test_exception関数内のexceptブロックは実行せず、とばす。

tryブロックのtest_exception関数が終わったので、
その続きでprint(6)を実行。

ZeroDivisionErrorは発生していないので、
exceptブロックは実行せず、とばす。

最後にfinallyブロックを実行する。

test_exception関数の引数を0にすると、

```py:2
def test_exception(num):
    print(1)
    try:
        print(2)
        answer = 100 / num
        return answer
        print(3)
    except ZeroDivisionError as e:
        print(4)
        raise e
    print(5)

print('start')
try:
    test_exception(0)
    print(6)
except ZeroDivisionError as e:
    print(7)
    raise e
finally:
    print('end')
```

```:2の実行結果
start
1
2
4
7
end
```
Vue.jsの時間入力にvue2-timepickerを使ってみた

# Vue.jsの時間入力にvue2-timepickerを使ってみた

下記に全て書いてある（英語）
https://www.npmjs.com/package/vue2-timepicker

#### インストールする

```
$ yarn add vue2-timepicker
or 
$ npm install vue2-timepicker --save
```

## 利用例

```vue
<template>
  <div>
    <!-- 文字列"15:00:00"などをv-modelでバインドできる --!>
    <vue-timepicker 
      :format="format"
      :minute-interval="minInterval"
      placeholder="時間"
      hour-label="時"
      minute-label="分"
      v-model="stringTime"
    />
    <!-- オブジェクトのパターン --!>
    <vue-timepicker 
      :format="format"
      :minute-interval="minInterval"
      v-model="objectTime"
    />
  </div>
</template>
<script>
import VueTimepicker from 'vue2-timepicker'
import 'vue2-timepicker/dist/VueTimepicker.css'

const vm = new Vue({
   // 色々省略
   data: {
     format: 'HH:mm', // 形式 AMなどの指定もできる
     minInterval: 5, // 分の間隔 これは5分ごとの設定
     stringTime: "15:00",
     objectTime: {
       HH: '15',
       mm: '00'
     }
   },
   components: {
     VueTimepicker,
   }
})

export default vm
</script>
```

## 注意: 文字列形式の場合のNULL
v-modelなどでバインドさせる値をstring形式（"15:00"など）にした場合
DB側からNULLなどを貰うと正しくNULLで認識されるが、そこから入力すると

想定していた文字列形式` "15:00" `ではなく
オブジェクトの` {HH: "15", mm: "00"} `になるので注意

#### 対策1: 初期値NULLを文字列にする

初期値のNULLを空文字列 `""`にする

#### 対策2: オブジェクトを文字列に変換する

フォーマットが指定されているので文字列に戻しやすい
WebからFetch APIで取得したファイルをJavaScriptのFileオブジェクトとして扱う方法

# 概要

JavaScriptの**[Fetch API](https://developer.mozilla.org/ja/docs/Web/API/Fetch_API)**をつかってWebからファイルをダウンロードしてきて、それを**[File](https://developer.mozilla.org/ja/docs/Web/API/File)**オブジェクト として扱う方法

# やり方

```javascript
const path="https://riversun.github.io/img/riversun_144.png";

fetch(path)
    .then(res => {
        return res.blob().then(blob => ({
            contentType: res.headers.get("Content-Type"),
            blob: blob
        }));
    })
    .then(data => {
        return new File([data.blob], path, {type: data.contentType});
    })
    .then(file => {
        //ここでfileを扱うコードを書く
    });
```

## ポイント

- res.blob()メソッドでレスポンスからBlobデータとして読み込むが、このメソッドはPromiseを返す
- ついでに、ヘッダーから"Content-Type"を読み出したいが、無邪気に以下のようにするとスコープ外なのでresにアクセスできない

```javascript

 fetch(path)
     .then(res => {
         return res.blob();
     })
     .then(blob => {
         //blobは取得できたけど、resから"Content-Type"ヘッダを取り出せない・・・
     })
```

- 以下のようにresが同一スコープになるようblob()から下位になるようチェインして、Content-Typeまで取得してから次に渡す。

```javascript
return res.blob().then(blob => ({
    contentType: res.headers.get("Content-Type"),
    blob: blob
}));
```
PHPでの簡易掲示板の作成の際の考え方

# 登録画面(register.php)
- 入力欄が空の場合
    - 入力値($_POST)をチェックする
    - エラーメッセージ用の連想配列を用意
- 重複登録を防ぐ(メールアドレス)
    - SELECT文で入力されたメールアドレスでSELECT文発行
    - 値が1件以上あればエラーメッセージを出す
- 入力の手間を減らす
    - 入力値($_POST)をエスケープして出力
- 確認画面への遷移
    - エラーメッセージ用の連想配列が空だったら実行する
    - 入力値($_POST)をセッション変数に格納する
    - header関数で確認画面へ遷移する
- 書き直し
    - URLパラメータで書き直しかどうかを判断
    - セッション変数の値を$_POSTに戻す

# 確認画面(confirm.php)
- 直に確認画面へアクセスされた場合
    - セッション変数が空だったら、登録画面へリダイレクト
- 入力値を出力する
    - セッション変数から入力値を出力する(画像の場合はセッション変数から画像のパス名を出力)

# 画像のアップロード(register.php)
- **$_POSTは使わず、$_FILESを使う**
- HTML側
    - formタグのenctype属性に`multipart/form-data`を指定
    - inputタグのtype属性に`file`を指定
- 画像以外はアップロードできないようにする
    - ファイル名を取得($_FILE['image']['name'])
    - ファイル名の後ろ3文字(拡張子)を切り取って文字列チェック
- アップロード
    - ファイル名を取得($_FILE['image']['name'])
    - move_upload_file関数でアップロードされたファイルを新しい位置に移動する
        - `move_uploaded_file($_FILES['image']['tmp_name'],'保存先のファイル名含むパス);`
    - セッション変数に画像のファイル名を格納する

# 確認画面(登録処理)(confirm.php)
- prepareメソッドでSQL文の雛形を用意
- executeメソッドで実際に格納する値をセッション変数から指定する
    - (パスワードはsha1関数でハッシュ化)
- **INSERT文発行後はセッション変数をunsetメソッドで破棄する**
- 完了画面へ遷移

# ログイン機能(login.php)
- ユーザからの入力値(メールアドレスとパスワード)をSELECT文に埋め込む
- セッション変数にデータベースからの値(idや氏名など)を格納し、ページ遷移
- 入力値が空の場合とデータベースとのミスマッチとでエラーメッセージを分ける。

# 次回からは自動でログインする機能(login.php)
- セッションはブラウザを閉じた時に情報が消えてしまうのでクッキーを使用する
- プログラムを書く場所はログインのチェックをしてメンバーの情報がヒットした後に記述する
- 「次回からは自動でログインする機能」をONにした場合
    - メールアドレスの入力欄には\$_COOKIEか$_POSTのメールアドレスを出力する

# メッセージ一覧画面(index.php)
- 前提としてログインしている状態でないとアクセスできないようにする
    - セッション変数のチェック、セッションが有効期限かどうかをチェック
    - 上記の条件を満たしていない場合はログイン画面へリダイレクト
- セッションの値から名前を取り出す
- 投稿したメッセージは投稿者のidとメッセージ本体をDBに格納する
- **DBに格納した後はheader関数で同じページを呼び出す**
    - **これをしないと$_POSTに値が残ったままとなるため、入力欄が空であってもDBに値が格納されてしまう**
- メッセージ一覧を表示する
    - 必要な情報(名前、画像、メッセージ等)をSQLのSELECT文に組み込む
    - 取ってきた情報をループでHTML出力する

# 返信機能(index.php?res=メッセージID)
- **表示するファイルはメッセージ一覧画面と同一で、パラメータが付与される**
- メッセージ一覧画面のURLパラメータに、返信先メッセージのidを付与する
- 上記のパラメータがセットされていたらそのidをフィルターに、SELECT文を発行し、入力欄にそのメッセージと投稿者を入力欄に出力する
- hiddenタイプで返信先メッセージid(=URLパラメータと同じもの)を仕込んでおく
- 返信メッセージを投稿する時に、上記idもINSERT文に組み込む

# メッセージ詳細画面(view.php?id=メッセージID)
- 日付部分に詳細へのリンクを貼る(twitterでも同様)
- URLパラメータにメッセージのidを付与し、それをSELECT文のフィルターとする
- データがある場合はデータを出力、データがない場合はそれ用の文言を表示

# メッセージの削除機能(delete.php?id=メッセージID)
- $_SESSIONのidとメッセージ投稿者のidが一致したら削除のリンクを出す
- 削除するプログラムに書く内容
    - URLパラメータをフィルターにしてDBから取得した投稿者のidとセッションのidが一致していたらDELETE文を発行する
    - DELETE文発行後は一覧画面へ遷移

# ページネーション(index.php?page=ページ数)
- URLパラメータにページ数を付与
- SELECT文にLIMIT句を追記
- いくつかの制約を設ける
    - ページ数が指定されていないとき
    - ページ数が1より小さいとき
    - ページ数の上限を超えたとき
- リンクを貼る
    - 前ページ
        - href属性:現在指定されているパラメータからマイナス1
        - 条件:現在指定されているパラメータが1より大きい場合に出力する
    - 次ページ
        - href属性:現在指定されているパラメータからプラス1
        - 条件:マックスページ数に収まる場合に出力する

# ログアウト機能(logout.php)
- セッション変数を空の配列で上書き
- session_destroy関数を実行
- クッキーに保存していたメールアドレスも削除する
- **セッションで使用しているクッキーの値を空にする、有効期限を切る**

```
if (ini_set('session.use_cookies')) {
    $params = session_get_cookie_params();
    setcookie(session_name() . '',time()-3600,$params['path'],$params['domain'],$params['secure'],$params['httponly']);
}
```
git コマンド一覧(簡易版)

##  git push するまでの一連の流れ

#### ブランチ一覧
```
$ git branch
```
※ ブランチ一覧・現在自分がいるブランチを確認できる。

#### ブランチ作成
```
$ git branch { ブランチ名 }  //ブランチを作成
$ git checkout { ブランチ名 }  //作成したブランチに移動
            or
$ git checkout -b { ブランチ名 }  //ブランチ作成・移動(便利！)
```
※ master or develop ブランチ(親)から、新しいブランチを作成する

#### 作成したブランチで作業開始！
作業が終了したら....

#### 更新までの流れ
```
$ git add .  //変更を追加
$ git commit "{ コメント }"  //コミット
$ git push origin {自分のブランチ名}　//pushして更新
```
※ git commit のコメントは どのような事をしたか、コメントを記載する(1行で)
※ ローカルの変更をリモートに反映(更新)する為にpushをする

その後は...
・プルリク作成
・レビューをしてもらう
・ファイル修正　　などなど。

また、新しい作業を行う時は、
・master or develop(親)　ブランチに移動
・git pull　して最新の変更を取り込む
・新しいブランチを作成
という流れになる。
GithubをTRPGのシナリオ置き場にしてみた。

# 初めに

僕は, githubに課金しています。
つまりPrivateリポジトリがつくれるのですが…！
せっかくだしTRPGシナリオや自作コンポーネントの置き場にするのは一つ楽しい試みではないかと思いました。

というわけでgithubユーザーがプログラム以外もgithubで管理しようとするとどうなるかという話です。

# やってみた

こちらは先日行った[DX3rd](http://www.fear.co.jp/dbx3rd/)のセッションで使用する資料やらシナリオを置いた場所です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77177/744d3b71-8679-75c2-fcc9-1f98732da33d.png)

# やってみた感想

これはgithubを使い慣れている人にはかなりいいソリューションだと思いました。
メリットを説明していきます。

## markdownが使える

シナリオやハンドアウトを書くのにmarkdownは非常に有用なツールでした。
レイアウトなんかはほとんどいらないし印刷してもそれなりに見栄えするものができるのがいいですね。

## いつでもどこでも編集できる！

google docsでもいいんですけど。どこでも編集したいじゃないですか！

## バージョン管理ができる！

ここ推敲前どうなってたっけ？みたいなことを考えられます。

## ほかの場所に資料がある場合雑にREADNE.mdにかける

ディレクトリ開けると探すまでもなくほかの資料のurlはれるのは結構便利に思いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77177/dc409615-6d5e-7bf1-fb49-6d3b3cb164a3.png)


## GithubPageでハンドアウトを公開できる

こんな形でプレイヤーに見せたい部分だけgithub pageとして公開することができます。
そのためハンドアウトのみdocsフォルダに入れています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77177/f8ede440-2f14-b3eb-f382-01825002044d.png)

# 結論

結構, githubをプログラミング以外で使うのもいいなぁって思いました。
小説とかにも使えると思います。
経年劣化に耐える ReactComponent の書き方

「経年劣化に耐えるコード」というのは、だれもが目指すものでしょう。「そもそもフロントエンドのコードは、今ある技術で最良のものを書き捨てるべき」という意見も理解できますが「備えあれば憂いなし」ということもありますので、ここにメモを残します。あくまで、私なりのベストプラクティスですのでご了承ください。


# 5層に別れた SFC
私はレイヤーによる技術の分離で、ReactComponent の経年劣化に備えています。ここでいうSFCとは「Stateless Functional Component」の略称ではありません。Vue.js の文脈にある「Single File Component」を指します。

```tsx
// (1) import層
import React from 'react'
import styled from 'styled-components'
// (2) Types層
type ContainerProps = {...}
type Props = {...} & ContainerProps
// (3) DOM層
const Component: React.FC<Props> = props => (...)
// (4) Style層
const StyledComponent = styled(Component)`...`
// (5) Container層
const Container: React.FC<ContainerProps> = props => {
  return <StyledComponent {...props} />
}
```

記述順は「依存関係の上流下流」に従います。import や型定義が上流工程であることは言うまでもないので省略、重要なのは(3)〜(5)を構成するレイヤーです。


# 技術の分離
なぜこの区分になっているのか、なぜこの書式になっているのか、ひとつずつ解説していきます。

### (3) DOM層

```tsx
const Component: React.FC<Props> = props => (
  <div className={props.className}>
    <button onClick={props.handleClick}>
      {props.flag ? 'click me' : 'CLICK ME'}
    </button>
  </div>
)
```
JSX(TSX)は、React のためだけのものではなく、他ライブラリでも利用される技術です。そのため、React に依存する Hooks API などはここから取り除いています。`return` を用いない記法（`props => (...)`）にすることで、Hooks API の介入を阻みます。この純粋な TSX にはビジネスロジックが無く、`Array.map`や真偽値による出し分け程度です。「ボタンを押下された事で何が発生するのか？」という知識も存在しません。**ここは副作用のない、真に Stateless なレイヤーです。**この`const Component`だけを抜き出し（export）した場合、テストのしやすさは想像に易いでしょう。


### (4) Style層

```tsx
const StyledComponent = styled(Component)`
> button {...}
`
```
React CSS in JS のメジャーどころとして、styled-components がまず挙がると思いますが、Style層もあくまで CSS の話です。styled-components が解決している名前空間の解決は、BEM(MindBEMding)が解決したことと同じです。テンプレート文字列に記述されたCSSは、BEM にフォールバックしたり、CSS Modules に移行しても成立する記述となっています。私が styled-components の`styled.div`や`styled.button` を敬遠している理由はここにあります。`>`による、children への指定漏洩防御も忘れない様にします。

BEM へのフォールバックはまれなケースかと思いますが、部分的に React を表示している様な折衷 html では、この切り分けが生きてきます。


### (5) Container層

```tsx
const Container: React.FC<ContainerProps> = props => {
  const [flag, setFlag] = React.useState(false)
  const handleClick = React.useCallback(() => {
    setFlag(!flag)
  }, [flag])
  return (
    <StyledComponent
      {...props}
      flag={flag}
      handleClick={handleClick}
    />
  )
}
```
Redux の経験がある方なら、PresentationalComponent / ContainerComponent というワードに馴染みがあるでしょう。Redux のコードベースには、Store に connect するコンポーネントとして、ContainerComponent という区分が明確にあります。これは React Hooks 全盛期のいまでも、踏襲すべきベストプラクティスであると私は考えています。**ここは Stateful なレイヤーであり「依存の注入」を行う場所でもあります。**

- useState による状態管理が、Redux Store へ移行することになった
- Storybook の為に、モックを注入する層に差し替えたい
- テストの為に、モックを注入する層に差し替えたい

もしこのレイヤーに、`useEffect`を利用した fetch 処理が介入していたとしても、Storybook やテストにおいては、代替 Container を用意すれば良いわけです。

(1)〜(4)は、ここの都合による影響を受けることがありません。Hooks か？ Redux か？ GraphQL か？ という配慮も当然不要なものとなります。**`(3) DOM層`から知識を剥奪することが重要な理由はこれに起因します。**

この様に「賢いレイヤー」を分離することで生まれるメリットは、依存注入技術の差し替えだけではなく、ビジネスロジックの移行（純関数の切り出し・Hooks から Redux への状態移譲）も容易にします。「Hooks API が過去のものになる…」という杞憂は当分先の話かと思いますが、将来の変化への備えとしては十分でしょう。
TypeScriptでthisの型を指定する方法

さっそく結論ですが TypeScript のバージョン 2.3 から `ThisType` という組み込みの型が使えるためこれを利用します。

```ts
const obj: ThisType<{ name: string }> = {
  test() {
    return this.name; // 推論できる
  }
};
```

日常的にはあまり使われないかもしれませんが、ライブラリの型定義などであると便利な型です。

例えば Vue.js で TypeScript を用いる際、this の型が推論されるのはライブラリ内部で ThisType を用いて型定義が行われているおかげです。

ThisType が使われている箇所：[vue/options\.d\.ts at 731e4d0ebc997a6c2b1fc500b08924ff7ba091b6 · vuejs/vue](https://github.com/vuejs/vue/blob/731e4d0ebc997a6c2b1fc500b08924ff7ba091b6/types/options.d.ts#L53)

## 参考
- [TypeScript特有の組み込み型関数 \- log\.pocka\.io](https://log.pocka.io/posts/typescript-builtin-type-functions/#thistype)
S3バケットのファイルをfindコマンド風に指定日数外分のみ出力するscript


# S3バケットのファイルを指定した期間外分だけ出力

S3バケットに入れているファイルをライフサイクルルールにて改廃するときに、実際に改廃が発動しているのかどうかを確認するために、S3バケット上のログを指定した日数以前のものだけ出力したいケースがあった。標準のawscliだけだと、期間指定する方法が見当たらなかったため、Pythonスクリプトを組んでみた。タイムスタンプはデフォルトのままだとUTC時間で出てきてしまうため、JST時間で出るように手を加えている。

```ruby:S3バケット全体に対して指定した日数以前のファイルを出力(第一引数でバケット名、第二引数で日数を指定)
#!/usr/bin/python

import boto3
import sys
import datetime

args = sys.argv
bucket_name=args[1]
expired_day=int(args[2])

timestamp_now=datetime.datetime.now()
s3 = boto3.resource('s3')
bucket = s3.Bucket(bucket_name)

for obj_summary in bucket.objects.all():
        dt=obj_summary.last_modified.strftime("%Y-%m-%d %H:%M:%S")
        dp=datetime.datetime.strptime(dt,"%Y-%m-%d %H:%M:%S")
        timestamp_put=dp + datetime.timedelta(hours=9)
        timestamp_del=timestamp_now - datetime.timedelta(days=expired_day)

        if timestamp_put < timestamp_del:
            print (str(timestamp_put),"s3://" + bucket_name + "/" + obj_summary.key)
```

```ruby:S3バケットの特定のプレフィックスに対して指定した日数以前のファイルを出力(第一引数でバケット名、第二引数でプレフィックス名、第三引数で日数を指定)
#!/usr/bin/python

import boto3
import sys
import datetime

args = sys.argv
bucket_name=args[1]
prefix=args[2]
expired_day=int(args[3])

timestamp_now=datetime.datetime.now()
s3 = boto3.resource('s3')
bucket = s3.Bucket(bucket_name)

for obj_summary in bucket.objects.filter(Prefix=prefix):
        dt=obj_summary.last_modified.strftime("%Y-%m-%d %H:%M:%S")
        dp=datetime.datetime.strptime(dt,"%Y-%m-%d %H:%M:%S")
        timestamp_put=dp + datetime.timedelta(hours=9)
        timestamp_del=timestamp_now - datetime.timedelta(days=expired_day)

        if timestamp_put < timestamp_del:
            print (str(timestamp_put),"s3://" + bucket_name + "/" + obj_summary.key)
```

#S3ライフサイクルルールの発動タイミング

マニュアルによると下記のため、発動タイミングの算出基準は毎日UTC0時(日本時間9時）の模様。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/intro-lifecycle-rules.html

>ライフサイクルルール: オブジェクトの存在時間に基づく
Amazon S3 がアクションを実行できる期間を、そのオブジェクトの作成 (または変更) からの日数で指定できます。
日数をライフサイクル設定の Transition アクションおよび Expiration アクションで指定する場合は、以下の点に注意してください。
アクションが実行される、オブジェクト作成からの日数です。
Amazon S3 は、ルールに指定された日数をオブジェクトの作成時間に加算し、得られた日時を翌日の午前 00:00 UTC (協定世界時) に丸めることで、時間を算出します。たとえば、あるオブジェクトが 2014 年 1 月 15 日午前 10 時 30 分 (UTC) に作成され、移行ルールに 3 日と指定した場合、オブジェクトの移行日は 2014 年 1 月 19 日 0 時 0 分 (UTC) となります。
【Rails】特定の文字列をリンクにする

運営しているサイトの掲示板において、返信時、冒頭に`>>123`のような記述が入るようにしているのですが、この部分をその番号のコメントへのリンクにすることができたので、やり方を書き残しておきます。

##controller
```app/controllers/comments_controller.rb
def index
  @comments = Comment.all
end
```

##hepler
```app/helpers/comments_helper.rb
module CommentsHelper
  def generate_link(txt)
    reply_txt = txt.slice(/>>[0-9]+/)
    id = reply_txt.slice(/[0-9]+/)
    link = ''
    link << "<a href='" << "##{id}'>#{reply_txt}</a>"
    content = txt.sub!(/>>[0-9]+/, '')
    [link: link, content: content]
  end
end
```
テキスト内の`>>{数字}`を抜き出して、aタグに変えて、他の文章と分離させた状態で値を返す処理をしています。

##view
```erb:app/views/comments/index.html.erb
<% @comments.each do |i| %>
  <% if i.content.slice(/>>[0-9]+/) %>
    <% reply = generate_link(i.content)[0] %>
    <%= reply[:link].html_safe %><br><%= reply[:content] %>
  <% else %>
    <%= i.content %>
  <% end %>
<% end %>
```

`.html_safe`を利用しないと、`<a href="hogehoge"`等がそのまま表示されてしまいます。

##注意点
helper関数を記述するファイルの冒頭に`# frozen_string_literal: true`という記述があると、関数で文字列を操作することができずエラーになってしまうので注意です。

##参考
[文字列の一部を削除する](http://rubytips86.hatenablog.com/entry/2014/03/20/155851)
[戻り値が複数ある場合の変数代入](https://qiita.com/18sasaki/items/1f73616f13d174b1bcb2)
ブラウザをコマンドで開く【R言語】



#Rを使って自動でブラウザを起動

browseURL関数を使うとブラウザで指定のURLを開ける。



```R
browseURL("https://www.r-project.org")
```

ブラウザに使うアプリを指定したい時は、

```R
browseURL("https://www.r-project.org",
browser = "C:\\Program Files\\Mozilla Firefox\\firefox.exe"
)
```

自動で開けると連続でダウンロードができる。

例えば

```
https://www.shinko-keirin.co.jp/keirinkan/kosu/mathematics/math_index.html
```

こんな**ありがたい**勉強元サイトがあるけれど、問題のダウンロードが大変!!
一つ目と二つ目のURLを開いてみてURLを見てみると

```
https://www.shinko-keirin.co.jp/・・・/drill01.doc
https://www.shinko-keirin.co.jp/・・・/drill02.doc
```

末尾がdril〇〇になっていて、ここを変えれば自動でDLできそう。
合計で25講座あるので、

```r
for(i in 1:25){
  if(i <= 9){
    URL <- paste0("https://www.shinko-keirin.co.jp/keirinkan/kosu/mathematics/word/worddrill/drill0",i,".doc")
  }else{
    URL <- paste0("https://www.shinko-keirin.co.jp/keirinkan/kosu/mathematics/word/worddrill/drill",i,".doc")
  }
  options(browser = "C:\\Program Files\\Mozilla Firefox\\firefox.exe")
  browseURL(URL)
  Sys.sleep(5)
}
```

これで連続自動ダウンロードできる。

実行時は、規約を読んでください。もしくはサイト運営者へ問い合わせてください。
サイトに負荷がかからないようsleep関数で遅延を挟むこと。
【Rails】turbolinksを無効化する

Chart.jsでグラフの描画に失敗することが多々あり、色々調べたところturbolinksが原因でした。
無効化したので、その方法をまとめます。

###Gemを削除
```rb:Gemfile
#gem 'turbolinks', '~> 5'
```
```terminal
$ bundle update
```

###application.jsを編集
以下のコメントアウトされている記述を削除します。機能に影響する系のコメントです。

```app/assets/javascripts/application.js
//= require turbolinks #この行を削除
```

###application.html.erbを編集
以下の2行の`'data-turbolinks-track': 'reload'`部分を削除します。

```erb:app/views/layouts/application.html.erb
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```

###formを編集
`form_with`を使って作成したformがある場合、全てのformに`local: true`オプションをつけます。これがないと、フォームがうまく動作しません。

##参考
[その辺にいるWebエンジニアの備忘録](https://kossy-web-engineer.hatenablog.com/entry/2018/11/29/093958)