OmniAICreator/Qiita-1.07M huggingface dataset:
【AWS】本番環境でRailsを起動しようとした時のMysql5.7系に関するエラー

同期がハマったエラーが自分もハマった事があったので復習しながら備忘録として

##やりたい事
- EC2インスタンスからGithubへアクセスできるようにする
- Githubからコードをクローンする
- unicornをインストールし設定する
- アセットをコンパイルする
- Railsを起動する<=**ここのエラーを解決する**

##Rails起動でハマったエラー①

```html:ターミナル
[ec2-user@ip-172-31-23-189 ~]$ rails db:create RAILS_ENV=production
[ec2-user@ip-172-31-23-189 ~]$　rails db:migrate　RAILS_ENV=production
[ec2-user@ip-172-31-23-189 ~]$ unicorn_rails -c config/unicorn.rb -E production -D
[ec2-user@ip-172-31-23-189 ~]$ master failed to start, check stderr log for details
//unicorn起動できない
[ec2-user@ip-172-31-23-189 ~]$ less log/unicorn.stderr.log
//エラーログを確認する
Can't connect to local MySQL server through socket '/tmp/mysql.sock(2)'
//ソケット通信できませんと怒られる
```
###原因と解決方法
エラー文最後が(2)の場合はsocketファイルが無い。=>**作りましょう！！**

```html:ターミナル
$ cd /tmp
$ ls
//my.sockが/tmp以下に無いはず
$ touch mysql.sock
//mysql.sockを/tmp以下に作成
$ sudo service mysqld restart
$ rake db:migrate
//ソケット接続できているのでmigrate完了できるはず
[ec2-user@ip-172-31-23-189 ~]$ unicorn_rails -c config/unicorn.rb -E production -D
```
##Rails起動でハマったエラー②
/tmp以下にmysql.sockを作成してもunicornが起動してくれない。
###原因と解決方法
unicornのプロセスがストップできていない=>**ストップさせましょう！**

```html:ターミナル
[ec2-user@ip-172-31-23-189 ~]$ ps aux | grep unicorn
//unicorn関連のプロセスのみを抽出するgrepコマンド使いましょう
ec2-user 17877  0.4 18.1 588472 182840 ?       Sl   01:55   0:02 unicorn_rails master -c config/unicorn.rb -E production -D
ec2-user 17881  0.0 17.3 589088 175164 ?       Sl   01:55   0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D
ec2-user 17911  0.0  0.2 110532  2180 pts/0    S+   02:05   0:00 grep --color=auto unicorn
//unicorn_rails masterがunicornのプロセス本体です。こいつをkillします
[ec2-user@ip-172-31-23-189 ~]$ kill -9 <確認したunicorn rails masterのPID>
//これでunicornのプロセスはkillされたのでもう一度unicornを起動します
[ec2-user@ip-172-31-23-189 ~]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
//これでちゃんとunicornが起動するはず
```
##Rails起動でハマったエラー③
①と②をやってもhttp://< Elastic IP >にアクセスできない
###原因と解決方法
ちゃんとmysqlやNginxが再起動できていない。=>**もう一度mysqlとNginx（設定済みなら）を停止してunicornをkill→ec2サーバをシャットダウン→再起動します**

```html:ターミナル
$ sudo service mysqld stop
//mysqlストップさせる
$ sudo service nginx stop
//nginxストップさせる
$ sudo shutdown -r now
//ec2サーバをストップさせる。これでサーバ内がクリアになる
$ ssh -i 〜〜.pem ec2-user@〜〜
//ec2ログイン。1~2分待ってからログインします
$ sudo service mysqld start
//mysqlスタートさせる
$ sudo service nginx start
//nginxスタートさせる
$ kill -9 <確認したunicorn rails masterのPID>
//unicornもう一度killしておきましょ
$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
//これでunicornが起動
```
##まとめ
awsの自動デプロイができるまで手動でデプロイ設定している最中にmysql関連のエラー多発しました。私の経験ではmysqlをちゃんと停止=>スタートさせてからunicornをkillしてあげれば解決します。socket(mysql.sock)ファイル作れていてもサーバを再起動していなかったり、mysql再起動していなかったり、unicornをkillしていないとhttp://< Elastic IP >にアクセスできないと思うので、まずは再起動する事が一番です！！

例えるなら、
**ブラウン管テレビを斜め45度チョップすれば砂嵐が直るみたいな感じです！**（違うか）

終わり
HTTPを和訳して類推してみる

こんにちは。先日、某プログラミングスクールを卒業しました。今までプログラミングそのものについては考えていたのですが、前提の基礎知識が抜けている部分が多いと感じたため、勉強してみる次第です。
MVCモデルでもよく、リクエスト・レスポンスという言葉が使われるが実際に何をしているのかを理解するには、
基本であるHTTPの理解は不可欠と言われました。
ひとまず、HTTPの和訳をして意味を類推してみようと思います。

## HTTP　正式名称から類推してみる
HTTP（ **HyperText Transfer Protocol**）　
このままだと理解できないので少しずつ噛み砕いてみることにする

1.Google先生が直訳するとこうなる

**ハイパーテキスト転送プロトコル**
=>理解不能　何かを送信する様子

2.Weblio辞書（https://www.weblio.jp/content/HyperText+Transfer+Protocol）

**WWWでハイパーテキスト文書にリンクするためのプロトコル。先立つものとして、ウェブサイトのアドレスなど（例えば、http://marketplace.com など）**

=>少し噛み砕いた説明になった？　　

ハイパーテキスト（URL）を転送するためのプロトコル。プロトコルってなんだ？

3.プロトコル

**コンピュータ システムで、データ通信を行うための規約。情報フォーマット、交信手順を定める。**

=>ルール（約束）という意味。なるほど。

### まとめ

HTTPとは・・・　**URLに通信する時のルール**　
HTTPリクエスト　=>「このルールを**守って**、データのリクエスト・通信をするよ〜」と宣言。こう考えれば間違えてない気がする。


この前提で、HTTPを改めて調べてみて
GET / HTTP/1.1などの文章を読んで理解してみようと思う。

HTTPの解説にすらなってないですが、今回は知らない言葉の調べ方についてアウトプットしてみました。

「Class名はなるべくわかりやすい命名をする」のと一緒で、命名には意味があるので、そこから予測するのもたまには面白いのではないかと思いました
テーブル作ってみた

今回はタイトル通り、テーブルを作ってみた。

前回のフレックスレイアウトに興味を持っている人は次のリンクを見てください。
[フレックスレイアウトをやってみた](https://qiita.com/yu-chan/items/feaa8347b041e151dcc7)


#ソース


```table_practice.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>テーブル　練習</title>
	<link rel="stylesheet" href="base.css">
</head>
<body>
	<div>
		<table id="table_sample1" border="1">
			<caption>サンプルテーブル colspan</caption>

			<thead>
				<tr>
					<th colspan="3">ヘッダー</th>
				</tr>
			</thead>

			<tfoot>
				<tr>
					<td>フット1</td>
					<td>フット2</td>
					<td>フット3</td>
				</tr>
			</tfoot>

			<tbody>
				<tr>
					<td>セル1</td>
					<td>セル2</td>
					<td>セル3</td>
				</tr>
			</tbody>
		</table>
	</div>

	<div>
		<table id="table_sample2" border="1">
			<caption>サンプルテーブル rowspan</caption>

			<thead>
				<tr>
					<th colspan="3">ヘッダー</th>
				</tr>
			</thead>

			<tfoot>
				<tr>
					<td>フット1</td>
					<td>フット2</td>
					<td>フット3</td>
				</tr>
			</tfoot>

			<tbody>
				<tr>
					<td rowspan="2">セル1</td>
					<td>セル2</td>
					<td>セル3</td>
				</tr>

				<tr>
					<td>セル4</td>
					<td>セル5</td>
				</tr>
			</tbody>
		</table>
	</div>


	<div>
		<table id="table_sample3" border="1">
			<caption>サンプルテーブル rowspan colspan</caption>

			<thead>
				<tr>
					<th colspan="4">ヘッダー</th>
				</tr>
			</thead>

			<tfoot>
				<tr>
					<td>フット1</td>
					<td>フット2</td>
					<td>フット3</td>
					<td>フット4</td>
				</tr>
			</tfoot>

			<tbody>
				<tr>
					<td rowspan="2" colspan="3">セル1</td>
					<td>セル2</td>
				</tr>

				<tr>
					<td>セル3</td>
				</tr>
			</tbody>
		</table>
	</div>
</body>
</html>
```

```base.css
#table_sample1 {
	margin-left: auto;
	margin-right: auto;
	padding: 0;
	border: solid;
	width: 200px;
	text-align: center;
}

#table_sample2 {
	margin-top: 20px;
	padding: 0;
	margin-left: auto;
	margin-right: auto;
	border: solid;
	width: 200px;
	text-align: center;
}

#table_sample3 {
	margin-top: 20px;
	padding: 0;
	margin-left: auto;
	margin-right: auto;
	border: solid;
	width: 400px;
	text-align: center;
}
```

`colspan`や`rowspan`をやっただけのソースとなっています。
テーブルはこれを使いこなすのが大事だと感じた。
【Python】リストとタプルの最大値を取得

最大値と最小値を求める組み込み関数の引数の与え方が複数あるようなので、検証してみた。
リストでも、タプルでも最大値、最小値は取得できる。

# まず普通の与え方

```python
max_num = max(1, 5, 10)
min_num = min(1, 5, 10)
print(max_num) # 10
print(min_num) # 1
```


# リストを引数として与える

```python
test_list = [1, 5, 10]
max_num = max(test_list)
min_num = min(test_list)

print(max_num) # 10
print(min_num) # 1
```

# タプルを引数として与える

```python
test_tuple = (1, 5, 10)
max_num = max(test_tuple)
min_num = min(test_tuple)

print(max_num) # 10
print(min_num) # 1
```
GANによる異常検知の直感的な理解[未完成]

# GANによる異常検知の直感的な理解

この記事ではGANを用いた異常検知やAutoEncoderを用いた異常検知のを初心者でもわかる直感的な説明で紹介しようと思います。GANを用いた異常検知は、教師データが少ない場合に威力を発揮します。なので、完全に教師なし学習として使われるケースはあまり無いと思います。

ただし、ここで解説する一部の手法は異常である/ないといったラベル（教師データ）は必要ありません。これは、教師なしの異常検知と呼ばれます。(AIにデータを渡すと、勝手に異常と思われるデータを除外してくれるイメージです。もちろん、閾値は決めなければならないですし、正しい保証もありません。)詳しくは、時間があれば書き足します。

# 異常検知って
異常検知というと、AutoEncoderを私はすぐに思い浮かべます。しかし、近年GANを用いた手法なども盛んに開発されています。2018年に聞いた話なのですが、製造業の企業でGANを用いて既に異常検知をしている企業もあるという話を伺いました。


## AnoGAN

AnoGANは通常のDCGANで学習を行ったGenerator部分のネットワークを用いて、少し工夫を施すことで異常検知にも使えるようにするという手法です。アルゴリズムの流れを説明します。

- まず、テストデータ（画像など）を用意する。
- テストデータ(正常な画像と異常な画像両方含まれる）を参考にGeneratorの入力となる最適と思われる乱数zを生成し、その乱数を元にテストデータと似たような画像を出力できるようにする。(注意：GeneratorやDiscriminatorの学習は一切行いません)
- 乱数zをGeneratorに入力して、画像を出力してみる。
- 正常な画像（つまりDCGANを学習する段階で多く経験した似たような画像）はテスト画像に似たような画像を上手く出力できるのに対し、異常画像を元に乱数を生成し、それを元にGeneratorから画像を出力すると上手く出力できない。
- 評価する。テスト画像と出力された画像の類似度を、画素ごとの引き算を行い絶対値をとったものなどで求める。正確には、それに加えて、テスト画像と、出力された画像それぞれを用いてDiscriminatorに通し、出力層の一個手前の層で出現した特徴量を引き算し、絶対値をとったものも類似度を測る指標として使う。

肝心のイメージですが、AutoEncoderを用いた異常検知と似ていると思います。今まで多く見てきた画像とテスト画像が似ていれば、少ない情報に変換して（zという乱数に変換して）再び復元しようとした場合、上手く復元できますが、今までAIが見てきた画像と大きく異なる画像の場合、一旦少ない情報に変換して(zという値に変換して)元のテスト画像を復元しようとしても上手くいきません。

上手く復元できたかどうか=今までAIが見てきた画像と似ている正常な画像かどうか　です。
似ているかどうかは、類似度を測って求めます。類似度の測り方については様々な手法があります。例えば、Cos類似度、KL情報量(ヒストグラムを書いて重なっている部分の面積が大きいか、小さいか)、単純に2枚の写真の同じ位置の画素同士を引き算する　などがあります。

## 教師なしの異常検知
教師ありの異常検知は皆さんどのように実装すれば良いか簡単に想像がつくと思いますが、教師なしの異常検知はパッと考えただけでは思いつかないと思います。

教師なしの異常検知の動作の仕組みを述べると、

- データの中から、外れ値のようなもの（例えば他の写真と大きく異なる）を探す
- 閾値を決めて大きく外れていると思われるデータは除外する

といった感じになります。詳しくは時間があれば追記します。
【初心者向け】Vue.jsでコンポーネントごとにデータの永続化を行うサンプル

こんにちは、[@y_temp4](https://twitter.com/y_temp4)です。

Vue.js でコンポーネントごとにデータの永続化を行うサンプルを作りましたので、ご紹介します。

## 実装（CodePen）

<p class="codepen" data-height="420" data-theme-id="0" data-default-tab="js,result" data-user="y-temp4" data-slug-hash="EqLYda" style="height: 423px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Vue Client-Side Storage Sample">
  <span>See the Pen <a href="https://codepen.io/y-temp4/pen/EqLYda/">
  Vue Client-Side Storage Sample</a> by Yuki Terashima (<a href="https://codepen.io/y-temp4">@y-temp4</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

こちらは JS 部分のコードの抜粋です。

```js
new Vue({
  el: '#root',
  data: {
    app: {
      counter1: 0,
      counter2: 0
    }
  },
  mounted() {
    const app = localStorage.app
    if (app) this.app = JSON.parse(app)
  },
  methods: {
    addCounter1() {
      this.app.counter1++
    },
    addCounter2() {
      this.app.counter2++
    },
  },
  watch: {
    app: {
      handler: newState => {
        localStorage.app = JSON.stringify(newState)
      },
      deep: true
    }
  },
  template: `<div>
    <p>{{ app.counter1 }}</p>
    <button @click="addCounter1">addCounter1</button>
    <p>{{ app.counter2 }}</p>
    <button @click="addCounter2">addCounter2</button>
  </div>`
})
```

## 解説

データの永続化を行う際には localStorage を利用します。

コンポーネント単位とはいえ、それぞれの data のキーに対して localStorage の値をセットするのはだるいので、何らかのオブジェクトとして全体をラップして（今回は app で囲っています）、それを watch で監視するという方式を取っています。

こうすることによって、キーが増えてもこのコンポーネント内では localStorage への保存のために他に watch する対処が増えないので便利です。

Vue でオブジェクトの値の変更を検知するためには、検知したいオブジェクトに handler を指定した上で deep: true を指定する必要があります。

```js
...
  watch: {
    app: {
      handler: newState => {
        localStorage.app = JSON.stringify(newState)
      },
      deep: true
    }
  },
...
```

（localStorage は文字列しか受け取らないので、保存時には JSON.stringify、読み込み時には JSON.parse を忘れずに。）

localStorage はクライアントでしか使えないので、mounted 時に保存したデータの読み込みを行います。
addCounter1 や 2 を何度か押したあと、リロードしても値が保持されていることが確認できるかと思います。

## さいごに
Vuex のデータの永続化だと [vuex\-persistedstate](https://github.com/robinvdvleuten/vuex-persistedstate) あたりが有名かと思いますが、コンポーネントレベルでの永続化の例はあまり見当たらなかったので試しに書いてみました。

もしこの記事が参考になったら、いいねしていただけると嬉しいです😄

## 参考
- [クライアントサイドストレージ — Vue\.js](https://jp.vuejs.org/v2/cookbook/client-side-storage.html)
- [$watchでオブジェクトの変更を監視する方法 \- Qiita](https://qiita.com/_Keitaro_/items/8e3f8448d1a0fe281648)
API Gatewayを通してBasic認証を使う方法

# 課題

今回は、単純なFlaskのAPIアプリを作って、全世界に公開したくないので、単純なユーザ・パスワード認証（[BasicAuth](https://ja.wikipedia.org/wiki/Basic%E8%AA%8D%E8%A8%BC)）をかけたいなと思いました。
[Zappa](https://github.com/Miserlou/Zappa)というAWS　LambdaにDeployできるフレームワークを使って、Flaskのアプリは、AWS上にすぐにDeployとAPIの確認ができました〜。

APIには、プログラムからBasicAuthに必要なヘッダーを付けておけば無事にAPIとの通信ができました。

pythonの[requests](https://2.python-requests.org/en/master/user/authentication/#basic-authentication)を使って、API叩く例：

```python
from requests.auth import HTTPBasicAuth
requests.get('https://api.example.com/', auth=HTTPBasicAuth('user', 'pass'))
```

HTTPヘッダー例：

```
GET /private/index.html HTTP/1.1
Host: example.com
Authorization: Basic ABCEF1234567890abcdef
```


ただし、開発者が簡易にAPI参照できるように、OpenAPI（swagger）表示できるページも用意しました。
そこでブラウザから、ページをアクセスしてみると。。。ダメだ。

---
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174849/98cf6fcf-56dc-c0a4-7a34-c28c2972e583.png)
---

モダンブラウザは、BasicAuthのログインをダイアログをだしてくれるのですが、出てこない様子。
どうにか、API Gatewayから返される`401 Unauthorized`のレスポンスヘッダーには、必要な`WWW-Authenticate: Basic`がないようです。

確認すると、Flask側から正しく`WWW-Authenticate: Basic`を返しているようですが、APIGatewayがそのヘッダーを消しているっぽい。

さって、API Gatewayからは、ブラウザのログインダイアログが表示されるように、`401 Unauthorized`のレスのヘッダーに`WWW-Authenticate: Basic`を付けるようにしましょう。


```
HTTP/1.1 401 Authorization Required
Date: Wed, 11 May 2005 07:50:26 GMT
Server: Apache/1.3.33 (Unix)
WWW-Authenticate: Basic realm="SECRET AREA"
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=iso-8859-1
```

# 対策方法

もうしかして、`UnauthorizedApiGatewayResponse`だけでいくかなと思うのですが、今回は、FlaskのRequestへ流す前、CUSTOM　Authorizerを導入して、BasicAuthヘッダーを確認するようにしています。

BasicAuth用の設定と関数のリポジトリにまとめたので、既存のAPIGateway(rest-api)により楽にBasicAuthを追加することができたかと思います。ここまでくるには、色々大変だったのですが、この手順で１０分以内にほしいBasicAuth設定が終わるだろう。

1. リポジトリ取得：

    ```
    git clone https://github.com/monkut/lambda-basicauth-authorizer.git
    ```

2. 環境準備（完全にAWSCLIでの用意は可能かと思うのですが、一部はBOTO3で書いちゃいました）:

    ```
    # pipenvでpython環境を用意
    pipenv install
    ```

3. 環境変数を設定、CUSTOM　Authorizerの関数を置いて、既存ApiGatewayのrest-apiを更新：

    > RESTAPI_IDは、既存のものからこのコマンドで取得：　`aws apigateway get-rest-apis`
    > `PROJECTID` は、ユニーク性を保つためのものだけです（なんでも良い）

    ```
    export AWS_PROFILE={my profile}
    export BASIC_AUTH_USERNAME={YOUR USERNAME}
    export BASIC_AUTH_PASSWORD={YOUR PASSWORD}
    export PROJECTID={YOUR PROJECT IDENTIFIER}
    export RESTAPI_ID={既存のRESTAPI ID}
    # CUSTOM Authorizer用のBucketを用意
    make createfuncbucket

    # CUSTOM Authorizerの関数をDeployして、既存のREST-APIにインストール
    make deploy
    make install
    ```

これで、APIだけじゃなくて、ユーザ（人間）がブラウザ経由でUSER/PASSのログインできるようになりました〜

FlaskにBasicAuth処理を残すちゃいば、ちょっと重複するのですが、BasicAuthなので、残っていても大した処理時間がかからないだろう。

最近、BasicAuthを使って、[zappa](https://github.com/Miserlou/Zappa) と組み合わせて、開発用のDUMMY　APIを提供したりしています。
コーギー犬はどのくらい食パンに似ているのか（Microsoft Azure で画像認識を検証する)

###はじめに
コーギー犬のお尻が食パンに似ていると一時期話題になりましたね。
人の目と同様にAIでも食パンとコーギーが似ていると判断するのでしょうか？？
Microsoft Azureを使用して、コーギーの食パン率を検証してみます。

<食パン/コーギー>
![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417361/b10f91bf-7d09-5a54-e6dd-3c178b414ef6.jpeg)

###検証方法
コーギーと食パンの画像をそれぞれ登録後、コーギーのお尻が食パン率何%くらいになるかテストする。

###Microsoft Azure 準備
※詳細は
https://azure.microsoft.com/ja-jp/services/cognitive-services/
・新規アカウントを取得します。
クレジットカード番号を登録する箇所もありますが、試すくらいであれば無料枠で使用できます。
※使用したらすぐ削除すれば問題なし

https://portal.azure.com/
・ホーム画面
＞リソースの作成＞新規＞AI + Machine Learning＞Face


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417361/ad209ef8-09f0-ec9f-79a3-a5346580fa2a.png)

｢名前｣と｢リソースグループ｣は任意の名称をつけてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417361/54ac7540-f10c-7d48-282d-15dfffb00bca.png)

▼Microsoft Custom Vision Service を使用して画像を分類する
https://docs.microsoft.com/ja-jp/learn/modules/classify-images-with-custom-vision-service/index

https://www.customvision.ai/projects
ポータル画面を開き、｢Newプロジェクト｣を選択して設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417361/63f217db-2916-2762-fe80-77563f9ea86f.png)

画像をタグ付けしてアップロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417361/55a4d376-c595-9610-8c1d-f9d8ce8f94c2.png)

画面上部の｢Train｣ボタンを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417361/0e18e9f3-a012-e4ed-b3bd-de5fa42e8c0b.png)

結果が表示されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417361/d639c448-6afe-4ece-bb73-f8508415dbf2.png)


そしてためしにコーギーの結果を載せてみると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417361/80cba4a7-efea-594b-cd96-d90d0f687162.png)
なんと食パン率0%！さすがにAIには生き物と食べ物の違いがわかっているようなので、
今度はコーギーのお尻パンを登録してタグ付けをしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417361/1fca9dd0-b131-222b-22a2-7502e107373e.png)

###検証結果
再度コーギーの画像でテストしてみても食パン率は0%でした。
タグ付けの問題なのか、AIが見ているものは人の目と違うのか、
逆に人はなぜ、コーギーを見て美味しそうと思うのでしょうか・・・・・

###おわりに
写真をある程度自分で選定していたので、雑多な画像も含めて登録すればもっと
コーギーの食パン率が上がったかもしれません。

豆大福に見えるハムスター、おにぎりっぽい猫、からあげっぽいトイプードルなど
SNSで話題になったりしますが、人が動物を見て食べ物を連想する心理が気になりました。
画像認識は奥が深いですね。
[Postgresql] Dumpして別なDBにデータを挿入する方法

任意のテーブルのデータを、ローカルDBに挿入しなければならない機会があったのでメモ。
※DBの向き先には注意する。どのDBからデータをDumpして、どのDBにデータを流すのかを間違えないようにしよう。

## 任意のテーブルのデータをDump

```bash
$ pg_dump -t table -a db > output_file

# e.g.
pg_dump -t users -a hoge_development > users.sql
```

使用しているoptionの意味

|option|意味|
|---|---|
|-t [table]<br>--table=[table]|Dumpするテーブルを指定|
|-a<br>--data-only|データのみをDumpする（schemaはDumpしない）|

# Dumpしたデータを挿入する

```bash
$ psql db < sql

# e.g.
psql hoge_development < users.sql
```

## その他

`pg_dump` コマンドのオプションの指定方法で少しハマった。

```bash

# NG
$ pg_dump -t -a users hoge_development > users.sql

# NG
$ pg_dump -ta users hoge_development > users.sql

# OK
$ pg_dump -t users -a hoge_development > users.sql
```


## 参考
- https://www.postgresql.jp/document/9.2/html/app-pgdump.html
Vue.js の v-slot でスロットのスコープ変数をなんとか推論させる

# Vue.js の v-slot でスロットのスコープ変数をなんとか推論させる

最近の Vetur では `<template>` 配下でも変数の型を確認できるようになってきましたが
スロットのスコープ変数については `any` になりがちです。

```vue:child
<template>
  <div>
    child
    <slot :id="id" :namae="namae" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      id: 1,
      namae: 'Taro',
    };
  },
};
</script>
```

```vue:parent
<template>
  <div>
    parent
    <child>
      <template v-slot="slotProps">
        child 使用
        {{ slotProps }}
      </template>
    </child>
  </div>
</template>

<script>
import Child from './child.vue';

export default {
  components: {
    Child,
  },
};
</script>
```

![child.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/1cb883bd-cf31-67b6-fa78-10e4723bd224.jpeg)

`child` 自身では template 中の変数の型を確認可能だが・・・

![parent.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/87156beb-a983-b4f5-862d-a1389f89f916.jpeg)

`parent` 側で使用した際の変数では `any`

![browser.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/fc76c1a0-670b-0059-df66-520de55259c3.jpeg)

実際の画面表示では `slotProps` の中身は `id`, `namae` を `child` にて指定した通り

これについて `parent` 側にて `id` などの型の確認ができないかなどをやってみます。

## スロット側で変数を明確にする関数を定義して `export`

スロットを持つ `child` 側にて「何もしない」が型を明示する関数を用意してみます。

```vue:child-vs

<script>
/**
 * @typedef {Object<string, any>} SlotProps
 * @property {number} id
 * @property {string} namae
 */
/**
 * @param {SlotProps} slotProps
 * @return {SlotProps}
 */
export const vs = slotProps => slotProps;

export default {
  data() {
    return {
      id: 1,
      namae: 'Taro',
    };
  },
};
</script>
```

定義された関数 `vs` は引数に渡された値をそのまま返すだけのアロー関数です。
`@typedef` により型定義した `SlotProps` はそれぞれ `child` での `<slot>` に渡している要素と同一の構造のオブジェクトの定義となります。

## 使用側でスロット側で定義した変数用関数を適用

上記の `vs` を `parent` にて適用すると・・・

```vue:parent-vs
<template>
  <div>
    parent
    <child>
      <template v-slot="slotProps">
        child 使用
        {{ vs(slotProps) }}
        {{ vs(slotProps).id }}
        {{ vs(slotProps).namae }}
      </template>
    </child>
  </div>
</template>

<script>
import Child, { vs } from './child.vue';

export default {
  components: {
    Child,
  },
  methods: {
    vs,
  },
};
</script>
```

`child.vue` より `vs` を `import` して `parent` の `methods` に追加しています。
これをエディタ上で確認してみると以下のようになります。

![slotProps.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/c66bca50-f4cc-8f66-bb42-0a6733bf839b.jpeg)

`slotProps` は相変わらず `any`

![vs.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/2d67061d-3926-588d-3df2-8ddf7070c13a.jpeg)

`child` より `import` した `vs` は定義した通りで推論されます。

![id-inferred.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/ff745a30-aab5-e427-0faf-4d48640c1e54.jpeg)

`vs(slotProps)` の結果より生やした `id` は `JSDoc` で定義した通り `number` で確認できました。
(残念ながら `vs(slotProps)` の結果から `.id` などは候補としては取得できませんでした・・・)

![not-exist.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116435/6de7bd6a-4be8-a861-a8b9-80ff644a4f83.jpeg)

`JSDoc` にて定義していない `abababab` を指定してみたところ
`SlotProps` 型に存在しない旨のメッセージが表示され、想定しないプロパティへのアクセスであることも確認できました。
急にaxiosでURLリクエストできなくなった！？

#何が起きたのか
<img width="599" alt="スクリーンショット 2019-08-28 19.46.36.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235237/68ee0337-3356-a1fd-63a1-78d15ebae811.jpeg">

今まで普通に運用できていたシステムでaxiosを利用してURLリクエストを行なっている箇所から上記のようなエラーが。。

***
from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
***

あ〜CORSのエラーね、
ん〜
CORS周辺なんか最近いじったかなぁ？
まぁ調べてみるか

```javascript
const functions = require('firebase-functions');
const corsLib = require('cors');
const cors = corsLib();

exports.say = functions.https.onRequest((request, response) => {
    return cors(request, response, () => {
        response.send("Hello from Firebase!");
    })
});
```
もともとこんな感じで書かれていました。
これの関数の中身がしっかり書かれている感じ

ちゃんとCORS許可してるぞ〜？？

気がつけば3時間ハマってた。

#CORSの問題ではなかった
corsのバージョンを変えてみたり、
firebaseのcloud functionsが悪いのかとデプロイし直したり、
しかし原因がわからない。
簡単なログを吐くfunctionを作成して呼んでみると、
動いた…

ますますわからん、cors全然問題ないじゃん…

色々調べてやっとわかった。
今回のバグ、もともとはメールを送るcloud functionだったのだが、
メールの本文をaxiosのgetでクエリパラメータとして渡していた。
今回ユーザーが長文を送ったことでバグが発生。
どうやらaxiosのget関数は渡せるクエリパラメータの長さに限界があるみたいだ。

axiosの関数をgetからpostに変更すると解決！

ちゃんとデータを来るときはpost使おうねというお話。
【線形回帰】わかるけど、線形回帰をコードで書いてみる

# はじめに
線形回帰なんてExcel使えば一発ですよ。という声があるかもしれませんが、Pythonで書いてみます。
使うデータは前にも使ったアボカドデータです。
https://qiita.com/iwasaki_kenichi/items/ea580fd9498ad6950a75


# コード
```python:main1.py

#ライブラリインポート
%matplotlib inline
import numpy as np
from pylab import *
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats

#データ読み込み
df = pd.read_csv("hogehoge.csv")

#散布図
scatter(df["Total Volume"],df["4046"])

```

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284911/39362f34-9843-e1f8-f6fc-25af680c640f.png)


```python:main2.py

#順番に、「slope:傾き」「intercept:切片」「r_value:相関係数」「p_value:p値」「std_err:推定値の標準誤差」を求める。
slope,intercept, r_value,p_value, std_err = stats.linregress(df["Total Volume"],df["4046"])

#決定係数を算出する。
r_value **2
#(ここでは0.95という高い値がでた)

#y=ax+bのyを計算する関数
def predict(x):
    return slope * x + intercept

#yを計算
fitline = predict(df["Total Volume"])

プロット
plt.scatter(df["Total Volume"],df["4046"])
plt.plot(df["Total Volume"],fitline,c='r')
plt.show()

```

#![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284911/04faa52c-daf2-a479-6e8f-309d1e005a07.png)

# おわりに
これぐらいのレベルのものはササッと書けるようになりたい。
【CentOS】コマンドメモ

#はじめに
本記事は、CentOSで筆者が個人的によく使うコマンドをメモしたものである。

#ディスクの使用量を確認

###①/optの使用量を確認
```
# du -sh /opt
```

###②/opt/app/oracle以下、2階層までを出力範囲とし、ディスク使用量が高い順に並び変え、5行出力する
```
# du /opt/app/oracle -hd 2 | sort -h | tail -5
```

#ファイル名の曖昧検索

###/var/www/html以下で、〇〇.htmlというファイルを出力する
```
# find /var/www/html -name "*.html"
```



#最後に
今、ぱっと思いついたのだけメモしたので、今後どんどん継ぎ足しをしていきます。
まだ、完成形ではないです。
NVMe接続のSSDの型番を調べる方法

# はじめに

私がこれまで使ってきた環境では、IDE（ATA）接続やSATA（Serial ATA）接続のHDDやSSDばかりでしたが、最近はM.2と呼ばれる新しい比較的新しい規格のSSDが普及してきました。
NVMeはそれほど使ったことが無いため、まずはLinux上でどのように認識されているのかを調べてみよう...ということで、M.2（※NVMe接続）のSSDの型番を調べてみました。

# SATA接続のHDDやSSDの場合

* 従来から良く知られている方法ですが、`/cat/proc/scsi/scsi`でSATA接続のHDDやSSD、DVDドライブなどの型番を調べることができます。
* 以下の例だと、WesternDigitalのSATA接続のHDD（WD20EFRX）であることが分かります。

```shell
[nkojima@hotaka ~]$ cat /proc/scsi/scsi 
Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: PBDS     Model: DVD+-RW DH-16W1S Rev: 2D14
  Type:   CD-ROM                           ANSI  SCSI revision: 05
Host: scsi2 Channel: 00 Id: 00 Lun: 00
  Vendor: ATA      Model: WDC WD20EFRX-68E Rev: 0A82
  Type:   Direct-Access                    ANSI  SCSI revision: 05
```

# NVMe接続のSSDの場合

* NVMe接続の場合、`cat /proc/scsi/scsi`では何も表示されません。
  * SATA接続ではないため、当たり前なのですが...
* NVMe接続はPCI-Expressを介して接続されているため、もしかして...と思って`lspci`を使ってみたところ、ビンゴでした。
  * `lspci`コマンドが使えない時は、`pciutils`というパッケージをインストールしてください。
* 以下の例だと、IntelのPro 760pというSSDであることが分かります。
  * 正しい名称以外にも、7600pや6100pなど異なる名称も表示されていて、少々分かりにくいです。

```shell
[nkojima@akagi ~]$ cat /proc/scsi/scsi 
Attached devices:
[nkojima@akagi ~]$ lspci | grep SSD
01:00.0 Non-Volatile memory controller: Intel Corporation SSD Pro 7600p/760p/E 6100p Series (rev 03)
```

# おまけ：Hyper-V上の仮想マシンの場合

* Hyper-V上の仮想マシンの場合は、SATA接続のデバイスが「Virtual Disk」「Virtual DVD-ROM」となっていました。
  * 仮想環境なので正しい型番は表示されないだろうと思っていましたが、こういう表記だとは思いませんでした。

```
[nkojima@vm-ikaho ~]$ cat /proc/scsi/scsi 
Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: Msft     Model: Virtual Disk     Rev: 1.0 
  Type:   Direct-Access                    ANSI  SCSI revision: 05
Host: scsi0 Channel: 00 Id: 00 Lun: 01
  Vendor: Msft     Model: Virtual DVD-ROM  Rev: 1.0 
  Type:   CD-ROM                           ANSI  SCSI revision: 00
```

# 参考URL

* [Linux で CPU や HDD の型番情報を表示する](https://futuremix.org/2007/07/linux-cpu-hdd-info)
xampp + VScode でWebサービス開発環境構築

# はじめに
サークルでphpを使ってWebサービスを作りました。
後輩に引継ぎをする時期となったのでWebサービス環境構築方法をここに掲載しておきます。
phpを使用せずにWebサービスを開発する場合でも、ローカルで動作を確認するためのツールを導入するということで参考になるかと思います。

# 導入環境
Windows10 (64bit)

# 概要
1. Visual Studio Code (VScode) のインストール
2. xampp のインストール
3. パスを通す
4. 動作確認

# 手順

## VScode
### インストール
VScodeのインストールに際しては以下のサイトが参考になったので、ここでの説明は割愛させていただきます。
[https://www.kkaneko.jp/tools/win/vscode.html](https://www.kkaneko.jp/tools/win/vscode.html)

今回は`ダウンロードとインストール`まで済んでいればOKです。

## VScodeの拡張機能のインストール
1. メニューバーの`表示(View)`を選択し、`拡張機能(Extensions)`を押します
2. または`Ctr + Shift + X`を押します。
3. 検索で`php server`を押し、`PHP Server`を探します(画像のもの)
<img width="371" alt="php.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488154/43049c24-ce9b-de62-9ae8-28e9d25d3853.png">
4. `install`を押して完了です

## xampp
またまた他のサイトが参考になりましたのでここでの説明は割愛させていただきます。
[https://qiita.com/minuro/items/d7f2b95b922ae302577c](https://qiita.com/minuro/items/d7f2b95b922ae302577c)

xamppのコントロールパネル(以下の画像)が出てくるところまででOKです
<img width="501" alt="xampp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488154/8ddc0d4f-9f82-9d67-2fac-9affda166c24.png">

## パス
これでラストです。ちょっとややこしいので注意して見てください！
1. PCの検索等で`環境変数`と打って画像のような画面が出てきたら、下の`環境変数`を押します
<img width="340" alt="php.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488154/4ae3c8ea-0757-ffe3-e584-e5d46fd9155b.png">
2. `システム環境変数`の`Path`を選択して`編集`を押します
3. `環境変数名の編集`という画面に移るので、`新規`を押して`C:\xampp\php`と記入します(プライバシーの都合上黒塗りしています)
<img width="810" alt="無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488154/a5480c9d-6088-c729-42c5-2bb6c9749197.png">
4. あとは、OKを押してPCを再起動するだけです

## 動作確認
適当なところでいいので、
フォルダ：`test`
ファイル名：`index.php`
を作成し、`index.php`には以下のコードをコピペしてください

```php
<!-- index.php -->

<!DOCTYPE html>
<html lang="ja-JP">
<head>
    <meta charset="UTF-8">
    <title>テスト</title>
</head>
<body>
    これはテストです。以下の文章はphpで出力されています<br>
    <?php
        echo "これはphpです";
    ?>
</body>
```

次に、VScodeを起動します。
メニューバーから`ファイル`を選択して`フォルダーを開く`で今作った`test`フォルダを開きます。
`index.php`を開き、コードの上で右クリックし、`PHP Server: Serve Project`を押します。
すると、ブラウザが立ち上がり、このような画面がでるはずです。
<img width="364" alt="無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488154/0e27886c-50fb-801c-bb53-3232bc93e99b.png">

# 注意
- フォルダから開かずにファイル単体(ここだとindex.php単体)でVScodeで開くとエラーが起きるので注意してください。必ずフォルダから開くようにしてください
- また、フォルダの直下には必ず`index`と名前の付いたファイルをだた一つ作成するようにしてください。

# 最後に
ここまでできていれば、Webサービス開発環境は整っています！
正確にはローカル開発環境ですが...

今回は`index.php`で確認しましたが`index.html`であっても問題はありません。
(自身、HTML, CSS, JSのみでサービスを作る際にここで作成した開発環境を利用しました)
GitHub Actions、Travis CI、CircleCIの気になる部分の比較

GitHub Actionsのβ版が利用できるようになったので、実際にさわりながら確認してみました。

CIツールを選定する際に気にしている観点で**GitHub Actions**、**Travis CI**、**CircleCI**を比較してみました。
（主に個人開発時のCIツールとしての観点が強いかと思います）

なお、いずれのCIツールも機能や仕様は本記事作成時点のものなのでご了承ください。

間違っている部分はコメント等で指摘いただけると助かります。

## 料金
個人開発だと気になる料金です。

### GitHub Actions
publicリポジトリ：無料
privateリポジトリ：月2000分まで無料

### Travis CI
publicリポジトリ：無料
privateリポジトリ：[料金プラン](https://travis-ci.com/plans)

### CircleCI
無料プラン：2500クレジット/週 = 2000分/月 (1vCPU/2GBのスペックの場合)
[料金プラン](https://circleci.jp/pricing/usage/#compute-options-table)


## 並列ジョブ数
DependabotによりPRが量産されるので、意外と重要だと思います。

### GitHub Actions
1リポジトリ20ワークフローまで可能

### Travis CI
記述をドキュメントから見つけられず
状況次第という記述あり

### CircleCI
無料プランなら1並列まで

## OS
各サービスとも、Linux, macOS, Windowsに対応しているようです。
（個人的には最新と1個前のLinuxに対応しているなら十分ですが）

### GitHub Actions
- `ubuntu-latest`, `ubuntu-18.04`, or `ubuntu-16.04`
- `windows-latest`, `windows-2019`, or `windows-2016`
- `macOS-latest` or `macOS-10.14`

[ドキュメント](https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobsjob_idruns-on)

### Travis CI
- `Ubuntu Bionic 18.04`, `Ubuntu Xenial 16.04`, `Ubuntu Trusty 14.04`, `Ubuntu Precise 12.04`
- [macOS](https://docs.travis-ci.com/user/reference/osx/)
- [windows](https://docs.travis-ci.com/user/reference/windows/)

### CircleCI
- Linux(Docker or Machine)
- macOS
- windows: 2019/08からサポートされ始めたようです [blog](https://circleci.com/blog/windows-general-availability-announcement/)

[ドキュメント](https://circleci.com/docs/ja/2.0/executor-types/#section=configuration)


## 各言語の実行環境
プログラミング言語の実行環境のサポート状況です。
これも個人開発ならメジャーな言語の最新版がサポートされていれば十分といったところ。
設定が楽かどうかも重要です。

### GitHub Actions
下記のようにstep内で言語のセットアップを実施する。

```yaml
jobs:
  test:
    name: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - uses: actions/setup-node@v1
```

[ドキュメント](https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobsjob_idstepsuses)

### Travis CI
かなりの数に対応している。
指定方法も下記のようにシンプル。

```yaml
language: node_js
```

[ドキュメント](https://docs.travis-ci.com/user/languages/)

### CircleCI
それなりの数がサポートされている。
指定はDockerのイメージで指定する。

```yaml
jobs:
  build:
    docker:
      - image: circleci/python:3.6.2-stretch-browsers
```

[ドキュメント](https://circleci.com/docs/ja/2.0/demo-apps/)

## Slack通知
CI結果は当然Slackに通知したいですよね。
Incoming webhookのURLの管理方法が楽だと嬉しい。

### GitHub Actions
デファクトスタンダードは未だ無さそう。
公式での対応が待たれる。

いちおう、いくつか調べた範囲では下記ブログで紹介されているプラグインがよさそう。
[GitHub Actions(beta)向けにslack通知プラグインを作った](https://839.hateblo.jp/entry/2019/08/16/104624)

webhookのURLはGitHubのリポジトリにSecretを登録する機能があり、それをGitHub Actionsから参照できる。

### Travis CI
SlackにTravisCIのアプリを追加し、tokenを発行する。
travisのUI上 or CLIからtokenを暗号化し、yaml中に指定する。
下記のようにシンプルに記述できる。

```yaml
notifications:
  email: false
  slack:
    secure: <暗号化されたtoken>
```

### CircleCI
WebUIからIncoming Webhook URLを指定する。


## まとめ
- GitHub ActionsはIssueやPRといったGitHubの要素とCIを連携しないなら、いまのところそんなにメリットなさそう
- 設定ファイルのシンプルさではTravis CIが一歩リード
- publicリポジトリで個人開発する範囲ならCircleCIの並列数がちょっと弱い
- CircleCIにはorbsというレシピの共有機能があるので、これをいかに活用するか次第

ということで、個人的にはまだしばらくTravis CIメインでいいかなと思ってます。
【配送手数料1000円なんて高すぎる!!】UberEATSで安く注文する〜全てはタピオカのために〜[再掲]

# UberEATS CHEAPER
(間違って記事削除してしまったので再掲してます...)


## TL; DR
`UberEats`でタピオカミルクティーを頼みたいのに配送料が高すぎる
配送料が安くなったタイミングを通知できるようにした

[GitHub](https://github.com/nochiraaa/ubereats_cheaper)

## 背景
私はタピオカミルクティーが好きです。正しくは、タピオカ抹茶ティーが大好きです。
口が寂しい時にタピオカミルクティーは丁度良いです。
糖分は取れるし、腹持ちいいし。
オフィスから歩いてタピオカミルクティーを買えるお店はありません。
なのでいつも UberEATSを利用させて頂いております。

しかし、いつも思うのです。
頼みたい時ってだいたい昼下がりの時間なんですけど、結構な頻度で
<strong>配送料高っっっっっっっっっっっっっ!!!!!!!!!!</strong>

と。頼むにしてはギリギリを超える手数料。

なので、配送料が安くなった時に通知してくれるプログラム作りました。



## 概要
`Ruby`ツールです。
アクセス負荷がかからないくらいで5分おきにデータを取得し、安くなったかどうかを判断しています。
通知方法は`Slack`と`Mac`の通知センターの2つに対応しています
(他のサービス、`Windows`などは反響があれば作ろうかなと思います。)

![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64689/bfe98e47-5f44-27ed-e031-3250766978fe.gif)


## 技術的内容
`selenium`で操作しながら情報を取得しています。
`UberEats`では、まずブラウザにお届け先の住所のデータを`Cookie`で持つ必要があります。
その上で、お店の配送手数料や配送時間、そもそも配送可能かどうかが分かるようになります。
そのため、`selenium`を利用しました。
一度お届け先の郵便番号を入力し、住所候補が出てきます。
出てきた住所候補をクリックして`Cookie`に住所情報を保持します。
その状態でお店のページに遷移します。
そうすると、住所を元に配送手数料が表示されます。
（色々調べたら緯度・経度を元にしていました。詳しくは別記事で書こうと思います。）

html要素はcssセレクター、xpathで取得していますが、html構造が変わったらこの
ツールは使えなくなるかもしれません。ご了承くださいませ。

## 使い方

```
$ bundle exec ruby ubereats_cheaper.rb [通知方法] [郵便番号] [希望配送手数料] [UberEATSのお店のURL] [Slack webhook url オプション引数]
```

- 引数1 通知方法

`mac`（デフォルト）・・・`mac`の通知センターから通知を送ります。画面右上からぴょこっと出てきます。
`slack`・・・`Slack`の特定のチャンネルに通知を送ります。引数5にて`slack webhook url`が必要になります。

- 引数2 郵便番号

[0-9]{6}のフォーマットで入力してください。

- 引数3 希望配送手数料

数字を入力してください。ここで入力した数字よりも配送手数料が低くなったら通知がきます。

- 引数4 `UberEATS`のお店のURL

ここにはお店の個別ページのURLを入力してください。
例:https://www.ubereats.com/ja-JP/tokyo/food-delivery/%E3%82%B7-%E3%82%A2%E3%83%AC%E3%82%A4-%E6%B8%8B%E8%B0%B7246%E5%BA%97-the-alley-shibuya-246/C7X1V9lWQ5KIoPq7YYLc4A/

- 引数5 `Slack`の`webhook url`

https://www.sejuku.net/blog/74471
こちらを参考に、`webhook url`を取得してください。一応この`webhook url`は後々削除されるとのことなので、反響があれば後々新しい方に切り替えようと思います。

コマンド例

```
bundle exec ruby ubereats_cheaper.rb 'slack' 
1070062 1000 'https://www.ubereats.com/ja-JP/tokyo/food-delivery/%E3%82%B7-%E3%82%A2%E3%83%AC%E3%82%A4-%E6%B8%8B%E8%B0%B7246%E5%BA%97-the-alley-shibuya-246/C7X1V9lWQ5KIoPq7YYLc4A/' 'https://hooks.slack.com/services/hoge1/hoge2/hoge3'
```

なお、`bundle exec ruby ubereats_cheaper.rb`だけで実行すると、`mac`で、自分が最近よくいる南青山へ、大好きな渋谷のジ アレイ（有名なタピオカミルクティーのお店）の配送手数料が1000円（1000円より安くなることが割と少ない）よりも安くなった時に通知が来るようになっています。

## インストール

- このリポジトリをcloneしてください

`$ git clone git@github.com:nochiraaa/ubereats_cheaper.git`

- `$ bundle install --path vendor/bundle`を実行

- Chromeドライバをインストール。以下のURLより取得できます。
https://sites.google.com/a/chromium.org/chromedriver/downloads
もしくはHomebrewを使っている方は下記でもインストールができます。
`$ brew install chromedriver`
Homebrewが入っていない方はこちらから
http://brew.sh/index_ja.html
Chromeドライバのバージョンは最新のものであれば問題なく動くと思います。
動作確認は`ChromeDriver 76.0.3809.68 (420c9498db8ce8fcd190a954d51297672c1515d5-refs/branch-heads/3809@{#864})`で行っています。

## 今後の展開
シンプルな内容で作りましたが、下記の改善も検討中です！

- 配送時間にも対応する
- オススメのお店をレコメンド
- 他に安いお店をレコメンド
- 他に早く届くお店をレコメンド
- 他のプラットフォームにも対応する
  - LINE@
  - Twitter
- API的に動くようにする
- firefox, IE, Edge, Safariにも対応する
- アメリカでも使えるようにする
- seleniumを使わず処理する
構造化開発とオブジェクト指向開発とデータ中心開発をザクッと社会システムに投影してみた

・構造化開発
　俗にいうウォーターフォール型
　上司の言うことが絶対の階級社会
　社長から部長、課長へと指令が下ってきて気が付いたら、社長の意向が全く違う風に伝わっていたなんてことも
　稟議で数か月かかかる昔の日本のような仕組み


・オブジェクト指向開発
　俗にいう分散管理型
　地方分権型
　個々人が勝手に動き回ることで、自然に秩序が築かれて行く
　アダムスミスの神の見えざる手
　個人主義、自由主義のアメリカのような仕組み


・データ中心開発
　俗にいう中央集権型
　データを中心に周りを統制する
　一番統制がしやすい
　中国の一党独裁社会のような仕組み


・おまけ
　アスペクト指向
　分散型で統制が取りずらくなったわがままな社会へ横串的に横断して統制しようとするもの
　マトリクス型組織のように、業務ごとの枠組みに専門技能に特化した横串組織を通すような仕組み
　仕組みが複雑で統制が難しいかも


注意：ザクッととらえているので、かなり不正確なところは自覚していますので、イメージとしてとらえてください。
Vue.js：Vuexのエラー：「[vuex] Do not mutate vuex store state outside mutation handlers」の原因と対応例

# 原因

- コンポーネントの「v-model」に、stateの値を設定していたため。
- v-modelは参照と設定を同時に行うため、タイトルのエラーが発生する。

```vue:issue.vue

<template>
　<!-- v-modelにstateの値を設定 ->
　<v-test-comp v-model="theValue"></v-test-comp>
</template>

<script>
import { mapState } from "vuex";

export default {
  computed: {
    //stateの値にアクセスできるよう設定
    ...mapState(["theValue"])
  }
}
</script>

```

# 対応

- v-modelに設定する値を算出プロパティに置き換える。
- 算出プロパティのgetでstateの値を返却し、set内で、storeのactionを呼び出す。

```vue:resolve.vue

<template>
　<!-- v-modelにstateの値を設定 ->
　<v-test-comp v-model="theValue"></v-test-comp>
</template>

<script>
import { mapState } from "vuex";

export default {
  computed: {
    theValue: {
      get() {
        return this.$store.theValue
      },
      set(value) {
        this.$store.dispatch("setTheValue", value)
      }
    }
  }
}
</script>

```
サーバー、XAMPP、ルート、パスを理解してWEBサイト制作に活かそう！

サーバー、XAMPP、ルート、パスを理解してWEBサイト制作に活かそう！

XAMPPを使っていて、アパッチを通さずにファイルを読み込んでしまった。

もちろん、インクルードファイルは読み込めなかった。

そのためにサーバーなどの知識を学ぼうと思います。

 

インターネットを見るということ

アドレスの読み方

https://www.google.co.jp/

http:Hypertext Transfer Protocolの略でHTMLのルールで転送します！

　プロトコルはルールのことで、言語に置き換えて説明されます。

日本語を話す人と日本語を話す人は意思が伝わりますが、日本語を話す人と英語を話す人は意思が伝わりません。httpというルール（言語）のみ通じます、ということです。

sはパソコンとサーバ間の通信データを暗号化するSSL（Secure Sockets Layer）のことです。

www.：Word Wide Web 世界に広がる蜘蛛の巣

google.co.jp：ドメイン名と呼び、インターネット上の表札のようなものです。

 

自分の使っているPCとサーバーの違い

apache（アパッチ）などのサーバーソフトがインストールされ、起動中である

 

サーバーはユーザーからの要求を受けて何か処理を行うパソコンです。

WEBサーバーはApacheがインストールされたPCを使います。

Apacheは、そのOSの上でInternetExplorerやGoogleChromeなどのブラウザと呼ばれるアプリケーションからアクセスを受けた時にHTMLファイルを返すための応用ソフトのこと

PCとサーバーに垣根はありません。

 

XAMPPを使って自分のPCのファイル（PHPが使われている）を見るために

・アパッチを起動すること

・ブラウザのアドレスバーに「localhost:ポート番号」を入力する

又は、「127.0.0.1:ポート番号」「自分のPCのIPアドレス:ポート番号」でもOK

・XAMPPのアパッチを切る、又はインターネットの接続が切れる→サーバーが落ちる

・アドレスバーに「file:///C:/Users/・・・」表示の場合、アパッチを通さずにファイルを開いているため、PHPが動かない。

 

PC　→【要求】→　サーバー（アパッチが処理）→【返事】→　PC

 

通常、ルートのindex.htmlは１つのため、複数の開発環境を作りたい場合はバーチャルホストでルートを増やすことで対応する。

 

インターネットを見るためには「ドメイン」か「IPアドレス」を入力する必要がある。

WEBサイトを公開前はIPアドレスで環境を作り、公開直前にドメインを取得することがある。

 

ポートはマンションの郵便ポストのようなもの

ユーザーの要求はIPアドレス（住所）のポート（郵便ポスト）に入る。

ポストを常に監視しているサーバーが、ポストの要求を見つけて受け取る。

サーバーは受け取った要求に対して、ユーザーに返事をする

これがWEBサイトを見るということです。

 

サーバーのファイルをブラウザで見ることと、エクスプローラーで開くことの違い
ブラウザで見る

更にルールにしたがって整えて、ファイルの中身を送ってもらう。

エクスプローラーで見る

ファイル操作、ファイルの一覧表示、名前の変更などが出来る

 

ポートは常に開いたままのポートと、要求のあったときだけ開くポートがあります。

WEBサーバーのポートは常に開放されていますが（閉じるとサイトが見られなくなるため）、FTPなどのポートは常に閉じています。

メールサーバー、SSHのポートは常に開いています。

 

パスとは：シェルがコマンド実行ファイルを探しに行く道筋

 

パスの種類
絶対パス：URLでページを指定。最上位階層からの道筋。

相対パス：現在地からの道筋。

ルートパス：1番上のディレクトリ(フォルダ)からの道筋。

 

絶対パス
用途：外部サイトへのリンクを自分のサイトに記載したい場合

デメリット：ドメイン変更やローカル環境に対応が難しく、文字が長い。

 

相対パス
用途：一般的なWebサイト開発

メリット：ドメイン変更やローカル環境に対応可能

デメリット：インクルードファイルがコピペできない

 

ルートパス
用途：大規模案件の開発

メリット：インクルードファイルのパスがコピペでOK

デメリット：書く文字数が相対パスよりも長くなる
WEBデザイン関連の言葉の理解

WEBデザイン関連の言葉をまとめました。

・HTML：正しい文章構造をタグを使用して表現する言語。テキストをクリックすると別のサイトに飛ぶ言語。

・CSS：ページのデザインやレイアウトをする言語

・ブラウザ：インターネットを閲覧するためのソフト（IE、Crome、Firefox）
・コーダー：デザインカンプ（完成見本）をブラウザで見られるようにマークアップする人
・JavaScript：Webページに動きをつける言語
クリックやタップ時のページ上の挙動の制御やアニメーションの実行、フォームのエラーチェックなどで活躍します。このようなブラウザ上で動くものをクライアントサイド
・jQuery:JS を少ない記述で書けるJSライブラリー（便利なプログラム部品集のファイル）

・Bracketsおすすめプラグイン
Emmet、Tabs、Indent Guides、Beautify、W3CValidation

・Dreamweaver
extractでPSDカンプから直接スタイル情報や文言などを抽出できる。
画像はPSDのレイヤー構造により上手く保存出来ない場合が多々あるので使わない
レイヤーマスク、写真、テキスト
コードヒントはコーディングの邪魔になるので環境設定で非表示にする

・イラストレーター（ベクター）とフォトショップ（ラスター、ビットマップ）拡大すると違う
Ai：線や図形を使って拡大してもキレイなロゴやイラスト、
Ps:写真や素材、色味や複雑なグラフィック。ピクセルをタイル状に敷き詰めて表現


・CMS：

インクルード：他のファイルに書かれている内容を読み込む

カスタムフィールド：独自の入力項目を追加してオブジェクトを管理する機能
MT:Six Apart社が提供するCMSプラットフォーム
プラットフォーム：ソフトウェアが動作するための土台（基盤）として機能する部分
「ブログ」：インフォメーションやイベント情報、商品情報や採用情報など

「ウェブページ」：会社概要やプライバシーポリシーなど、更新頻度が少ない固定情報

「ウェブサイト」：親ウェブサイトを設定、直下にブログなどコンテンツを展開
★5～10ページくらいで安価に自由な構成で作れる

＜テンプレート＞

・自由にどこでも単一ページを出力「インデックステンプレート」
・特定のルールに従い複数ページを出力「アーカイブテンプレート」
・付属システムの出力部分を調整「システムテンプレート」
・パーツ化して様々な形で共有使用「テンプレートモジュール」
ヘッダーやフッターなどの共通部分のhtmlをこちらに保存しておき、各テンプレートでインクルードすることで、全数十ページあるサイトでも一箇所を直して再構築するだけでメンテナンスが可能になります。
各種テンプレート上でインクルードすることができるのがテンプレートモジュール
どうしてもコマンドライン上でCiscoのVPN接続をしたい

# Cisco AnyConnect Secure Mobility Clientのパスワード入力が面倒臭すぎる
とあるサーバーに接続する時に、[Cisco AnyConnect Secure Mobility Client](https://www.cisco.com/c/ja_jp/products/security/anyconnect-secure-mobility-client/index.html) を使う決まりになっているのですが、案内されているやり方はUIでいちいちパスワードを入力する方法で、非常にめんどくさい。それぐらいコマンドラインでやらせろや！と思って調べると、CLIもちゃんとCiscoインストール時に用意してあるみたいです。

というわけで、他の人のスクリプトを参考にしながら、CLIでCiscoのVPN接続をするスクリプトを書きました。

参考：このサイトが助けになりました。
[(Mac)Cisco AnyConnect Secure Mobility Clientをコマンドラインから操作する](https://qiita.com/mamohacy/items/bcd3f575a9555d2f18a4)


## Shellスクリプト
まずciscoのコマンドがどこにあるか調べましょう。LinuxあるいはMac OS Xの場合、`/opt/cisco/anyconnect/bin/vpn`にあるらしいです。たぶんあると思いますが一応チェックしといて下さい。

そしたらこんな感じのスクリプトを書きます。

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

# setting
cisco_vpn=/opt/cisco/anyconnect/bin/vpn
USER='なんとか'
PASS='かんとか'

# if not exist then exit
if [ ! -e $cisco_vpn ]; then
  echo "Not found cisco" >&2 ; exit 1
fi

# kill Cisco AnyConnect
killid=`pgrep 'Cisco AnyConnect Secure Mobility Client'`
if [ -n '$killid' ]; then
    echo "Can I kill 'Cisco AnyConnect'? [Enter] " ; ps aux $killid ; read
    sudo kill $killid
fi

# connect
printf "y\n$USER\n$PASS" | $cisco_vpn connect vpn接続先のサーバー名
```

内容としては
- ciscoコマンドのパス、ユーザー名とパスワードを設定。 (セキュリティの観点からはIDやパスワードを保存すべきじゃないんでしょうね。)
- `Cisco AnyConnect Secure Mobility Client`が動いているとコマンドの方でvpn接続してくれないので、`Cisco AnyConnect Secure Mobility Client`をkillします。
- 本来対話形式するところの答えを用意しといて、vpn接続を実行。

これができたらあとは、`~/.bashrc`とかに`alias ssh_hoge='~/vpn_hoge.sh; sleep 1; ssh hoge'`という具合に書いておけば気軽に接続できます。

## 安全にパスワードを取得するバージョン（macOSの場合）

上の例では、パスワードをベタ書きしておりセキュリティ的によくないので、よりマシなスクリプトを加筆しておきます（2023.8.4）。こちら"[Macのキーチェーンアクセスを使ってターミナルで安全にパスワードを取得する](https://qiita.com/mr91i/items/a26be4457ef0699a005e)" にパスワードの取得方法をまとめました。Mac向けなのでご了承ください。またいくつかエラー処理を追加したのでそれもご参考ください。

```vpn.sh
#!/bin/bash
# if something wrong in this shell script, stop it
set -eu

# setting
cisco_vpn=/opt/cisco/anyconnect/bin/vpn
USER='なんとか'
PASS=`security find-generic-password -a account_name -s cisco_vpn_password -w`

# If command does not exist, then exit
if [ ! -e $cisco_vpn ]; then
  echo "ciso not installed" >&2
  exit 1
fi

# Kill running Cisco
if pgrep -f Cisco > /dev/null; then
    echo -e "\nCisco process detected. Can I kill this with super-user privileges? [Enter]\n"
    read
    pkill -f Cisco
fi

# If already connected, no need to connect again 
isconnected=`/opt/cisco/anyconnect/bin/vpn state | grep "Connected" | wc -l`
if [ $isconnected -gt 0 ]; then
    echo "VPN already connected."
    exit 0
fi

# Check if vpn return an error
output=$(printf "${USER}\n${PASS}" | $cisco_vpn -s connect vpn.cfca.nao.ac.jp)
nlerror=$(echo "$output" | grep -c "error")

# If error, kill running processes and try again
if [ $nlerror -gt 0 ]; then
    echo "Errors occurred during the VPN connection process. Try again after killing vpn."
    pkill vpn
    pkill cisco
    # Wait for the process to die
    sleep 3 # or 5
    output=$(printf "${USER}\n${PASS}" | $cisco_vpn -s connect vpn.cfca.nao.ac.jp)
    exit 1
fi
```
xdebugメモ

## xdebug.remote_autostart

xdebug.remote_autostart=1 にすると、Cookieに `XDEBUG_SESSION` を付与しなくてもデバッグセッションが始まる（ブレークするようになる）。

## Linuxにxdebugを入れる時の手順

```
git clone https://github.com/xdebug/xdebug.git -b 2.7.2
cd xdebug
./rebuild
```

で、`modules` 内にビルドした`xdebug.so`が生成される。
Tomcat404エラー_xmlファイルの配置場所

##Tomcat404エラーでxmlファイルの配置場所を確認する

ツール：Eclipse Luna
Tomcatプラグインインストール済み

####【実行手順と事象】
プロジェクトのクリーン（即時ビルドにチェック）
↓
Antのnative2asciiを実行
↓
Tomcatを**プラグインから起動**
（猫のアイコンをクリック）し、URL
http://localhost:8080/PROJECT/HogeHogeAction.do
を呼ぶ
↓
404エラーになり、表示されない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180727/fd77c3ad-c836-451f-0680-289884661139.png)

####【対応メモ】
Eclipseのウィンドウタブ
→設定
→Tomcat

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180727/1ee33c30-f082-fe35-3689-575b414c7cfa.png)

→「Tomcatホーム」を見る
→「Tomcatホーム」のパスをエクスプローラで表示する


→そのパスの 
**/conf/Catalina/localhost**
に、プロジェクトに対応するxmlファイルがあるか確認する。

**設定ファイルの値は問題なくても
設定ファイルの配置場所が誤っていたらエラーになる**

※サーバビューからTomcatを起動した場合はServersプロジェクトが自動生成されるが、Tomcatプラグインから起動した場合は生成されない模様。
Pythonしか知らない自分のPHPのお勉強。

### PythonリストとPHP配列
変数の格納の仕方
Python：　`lst = ['apple','banana','cherry','daikon']`
呼び方

```
print(lst[0]) # apple
print(lst[1]) # banana
print(lst[2]) # cherry
print(lst[3]) # daikon
```


変数の格納の仕方
PHP： `$lst = ['apple','banana','cherry','daikon']`

呼び方。

```
echo $lst[0] # apple
echo $lst[1] # banana
echo $lst[2] # cherry
```
laravelのsqliteのしようについて

laravelでsqliteをdefaultのDBとして使用する場合、空の値（""とかNULL)があるとエラーになる。

解決策としては、マイグレーション処理においてからの値になることが分かっているテーブルのセミコロンの前に->nullableをつける。
例）$table->string('avatar_filename'100);
　　$table->string('avatar_filename'100)->nullable();

   

もしくはsqlite以外のDBを使用するようにする。
第一回日本最強プログラマー学生選手権-予選-参戦記

先日行われた[第一回日本最強プログラマー学生選手権-予選-](https://atcoder.jp/contests/jsc2019-qual)に参加しました。結果は以下の通りです。
結果:A+B+C 3完　55分+2ペナ
順位:472/3534
パフォーマンス:1803
レート変動:1504→1540
青パフォです、やったー。ただ残念ながら本戦には出場できなそうです(50人くらい辞退してくれないかなぁ...)。
以下問題を振り返っていきます。
#A
time 3:00
全探索して条件を満たすものを数えればいいです

```python
M, D = map(int, input().split())
ans = 0
for m in range(1, M+1):
    for d in range(1, D+1):
        d1 = d%10
        d10 = d//10
        if d1>=2 and d10>=2 and m==d1*d10:
            ans+=1
print(ans)
```
#B
time 7:00
また数え上げですね。O(N^2)が通るので、Aの中の各要素について、それより大きい数字を数え上げ、等差数列の和を求めればできます。焦っていたので結構なクソコードを錬成しました。変数名のセンスをください

```python
N, K = map(int, input().split())
A = list(map(int, input().split()))
mod = 10**9+7
ans = 0
for i in range(N):
    Sum = 0
    Sum1 = 0
    a = A[i]
    for j in range(N):
        if A[j]<a:
            Sum+=1
        if i==j:
            Sum1 = Sum
    ans+=Sum*(K-1)*K//2+(Sum-Sum1)*K
    ans%=mod
print(ans)
```
300にしては少し面倒ですね
#C
よくある反転させる系の問題です。アリ本にも同じようなのがありましたね。こう言う問題は、
1. **操作の順序は関係ない**
2. **端が返されるのは一回限りである**
ことから、端から操作を決められる事が多いです。
まず、ポイントは**操作の順序を無視して区間の左端でソートした操作の順序で考えても良い**という点です。もう一つ重要なポイントは各A[i]についてそこから区間が始まるか、終わるかのいずれかであり、実は左端から順番に見ていくと、偶奇性から各A[i]に関して、そこで区間が終わるのか、区間が始まるのかのどちらかに決まってしまうという点です。
具体的に見ていきましょう。A=BWWBを考えます。まずA[1]は区間が始まることしかありえません。次にA[2]を考えてみると、A[2]はA[1]から始まる区間に含まれるので少なくとも1回はひっくり返ります。しかし、A[2]はWなので、もう一回ひっくり返る必要があります。よってA[2]から新しい区間が始まることがわかります。次にA[3]を考えると、すでにA[1],A[2]から始まっている区間に含まれることは確定しているので、少なくとも2回はひっくり返ります。A[3]は白なのでもうひっくり返る必要はありません。そこでA[3]ではA[1]かA[2]のいずれかの区間が終わることになります。実はこのどちらを終わらせたとしても後々影響はありません（各要素が幾つの区間に含まれているかだけが問題となるため）。よって、ここまでで2通りの区間の定め方があることになります。このように、どの区間を終わらせるかの組み合わせは独立なのでその積をとることにより、答えがわかります。一つ注意しなければいけないのは数列を全て見終わった時、全ての区間が閉じていなければいけないということです(BBBWなどがダメ)。以下のコードのようにcnt==0を確認する必要があります。僕は一回これを忘れてWAをとりました...

```python
mod = 10**9+7
N = int(input())
S = input()
cnt = 0
ans = 1
for i in range(N*2):
    if S[i]=='W':
        if cnt%2 == 0:
            ans*=cnt
            ans%=mod
            cnt-=1
        else:
            cnt+=1
    else:
        if cnt%2 == 0:
            cnt+=1
        else:
            ans*=cnt
            ans%=mod
            cnt-=1
if cnt==0:
    for i in range(1, N+1):
        ans*=i
        ans%=mod
    print(ans)
else:
    print(0)
```

ところで組み合わせが莫大になるので、modをとる問題は、逐一modを取っておかないと、TLEで死にます。死にました。反省。
もう少し早く解けるべきでしたね。
#D
構成の問題なので天才すれば解けるかなぁなどと色々考えてみましたが、わからず。
以下解説を参考に書きました。
この問題で重要となるのは以下の事実です。
各レベルの通路に関して、
**「任意の閉路の長さが偶数」=「奇閉路が存在しない」＝「グラフが二部グラフである」**
二部グラフとは、**二色で、隣接する辺を塗り分けられるグラフ**のことです。
ここで、各頂点に関してその各レベルに関する色の塗り方を考えます。もし、全てのレベルに関して同じ塗り方をするような頂点が2つ存在するとするとそれらを結ぶ頂点がどのレベルであっても上の条件を満たさないので矛盾します。よって全ての頂点の塗り分け方は異なります。ここで、色を0, 1と翻訳してみると、それぞれの頂点について、その塗り分け方は**二進法表示のようにみることができる**ので、k-levelまでで塗り分けられる頂点数は2^kであることがわかります。グラフの構成についてですが、上の考察を踏まえれば、各頂点に0~2^k-1の番号を振り、任意の二頂点について、一方のみが１であるようなビットの桁をレベルとする通路を、その頂点間にはれば良いことがわかります。

```python
N = int(input())
for i in range(N-1):
    print(*[(i^j).bit_length() for j in range(i+1, N)])

```
考察さえできれば実装は簡単すぎますね。まさかの３行です。bit_length()は二進数で何桁かを意味します。
あと、解説動画はわかりやすいですね。pdf何回読んでもわからなかったのが一発で理解できました。やっぱり図は重要。
#メモ
二部グラフ、bit_length、端から決まる、逐一mod
Railsチュートリアル（第12章）

# はじめに
Railsチュートリアルの第12章が終わりました。
この章では、パスワード再設定を行います。
メールを送って再設定用のリンクにアクセスする基本的な流れは11章と同じです。
ポイントだけメモしておきます。

# 隠しフィールド
メールアドレスからユーザーを特定するために、メールで送信したリンクからアクセスした際のeditアクションと、その後のパスワード再設定フォームからの送信時のupdateアクションでそれぞれメールアドレスが必要です。
リンクからアクセスする際は、リンクのパラメータにメールアドレスを含めていますが、フォームの送信で消えてしまいます。そのために、フォーム内に隠しフィールドとして保持します。

以下のように、`hidden_field_tag`で記述します。

```erb
    <%= form_for(@user, url: password_reset_path(params[:id])) do |f| %>
      ...
      <%= hidden_field_tag :email, @user.email %>
      ...
    <% end %>
```
`f.hidden_field`を使用しないのは、以下のようにパラメータの取得の仕方が変わるからです。

```erb
hidden_field_tag :email, @user.email # params[:email] 
f.hidden_field :email, @user.email   # params[:user][:email] 
```

# 時間の比較
時間も数値等と同じように比較することができます。
以下のように記述することで、`reset_sent_at`が２時間より前かどうか判定しています。

```
reset_sent_at < 2.hours.ago
```
考え方としては、`reset_sent_at`が`2.hour.ago(2時間前の時間)`より前であればtrueです。
MAC OS Xのスリープ方式(ハイバネーション)を変更する方法（要点のみ）

[macOS High Sierraにアップデートしたらスリープから復帰しなくなることがたまに起きるので](https://swk623.com/2017/12/08/macos-high-sierra%E3%81%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%97%E3%81%9F%E3%82%89%E3%82%B9%E3%83%AA%E3%83%BC%E3%83%97%E3%81%8B%E3%82%89%E5%BE%A9%E5%B8%B0%E3%81%97%E3%81%AA/)
> うちのMacBook Pro(Mid 2015)のOSをmacOS High Sierraにしてからか？スリープから復帰が遅くなった気がしてて、TouchPadは行きてるんだけど「遅いなー」と思うことが多かった気がします。

まさにこれを感じて居たので、設定を変更しました。
僕のPCは、MacbookAir(Mid2018)です。
（本記事は、参考サイトの要点を抜粋したものでほぼ引用です）

# TL;DR

> 今回試してみたのはhibernatemodeの変更です。

# 対象読者

> ディスクメンテを検討している方や、
最近なんだか、スリープ復帰が遅いと感じている方

# スリープの種類

[ MAC OS Xのスリープ方式(ハイバネーション)を変更する方法](http://www.hachim.jp/study-by-incident/mac-sleepimage.html)
> OS Xのスリープモードは3種類ある。

>スリープ (0)
所要時間:スリープ、復帰共に1〜3秒程度
スリープ移行時：メモリ内容をHDDに待避せず、メモリの内容はバッテリーが続く限りメモリで保持
復帰時：メモリから復帰のため高速、バッテリーが無くなった場合は忘れてしまうため通常のOS起動となる

>セーフスリープ （3）
所要時間:スリープ移行まで、3〜10秒程度、復帰は1〜3秒程度
スリープ移行時：メモリの内容をHDDに退避して、メモリの内容はバッテリーが続く限り保持
復帰時：メモリから復帰のため高速、バッテリーが無くなった場合はHDDの内容を読み込む

> ディープスリープ (25)
所要時間:スリープ移行、復帰共に5〜10秒程度
スリープ移行時：メモリの内容をHDDに退避し、メモリの内容を忘れてスリープ
復帰時：HDDの内容を読み込み復帰のため低速

> MBA,MBPの標準設定は
スリープ(0)とディープスリープ(25)のいいとこどりの
ハイブリッドモードな「セーフスリープ(3)」です。
そのため、画面を閉じたあとすぐに画面を開くと、なかなか画面が表示されません。これはメモリ内容をHDD（SSD）に書き込んでいるため。


## スリープモードの変更方法・確認方法

(ここからの操作をする場合、自己責任でお願いします)

```sh
sudo pmset -a hibernatemode X
```
> Xの引数部分には設定したいスリープモードの値を入力。
今回高速起動にしたい場合は「0」。
デフォルトに戻したい場合は「3」です。

## ターミナルで現在のスリープモードを確認するには…

```sh
pmset -g
```
確認してみた。

```sh
$ pmset -g
System-wide power settings:
Currently in use:
 standbydelaylow      10800
 standby              1
 halfdim              1
 hibernatefile        /var/vm/sleepimage
 proximitywake        0
 powernap             0
 gpuswitch            2
 disksleep            10
 standbydelayhigh     86400
 sleep                1 (sleep prevented by sharingd)
 hibernatemode        3
 ttyskeepawake        1
 displaysleep         2
 tcpkeepalive         1
 highstandbythreshold 50
 acwake               0
 lidwake              1
```


> MacBook Air はスリープ状態でも30日間持つよ！
という売り文句がその昔あった関係で、
ある時間以上スリープが続くとHDD（SSD）からの復帰に移るような設定(省電力モード、もう御察しの通りデフォルト3のね)になっているのかも。


# その他参考

- [「macOS High Sierra」の不具合：一部Macがスリープから正常に復帰できない](https://gori.me/macosx/macoshighsierra/100608)

# まとめ

> MacOSのスリープモード(ハイバーネートモードの設定値)-
通常スリープ [hibernatemode 0]
スタンバイ状態でメモリデータの退避は行わない。
すぐ復帰出来る反面、バッテリ枯渇時には作業状態が全て消去される。

> ディープスリープ [hibernatemode 1]
休止状態でメモリデータの退避を行う。
復帰に時間が掛かる反面、バッテリが枯渇しても作業状態は保持されている。

> セーフスリープ [hibernatemode 3]
バッテリ容量が十分あるうちはスタンバイ状態、
バッテリの消耗が進むとディープスリープへ移行。
バッテリが十分にあるうちはすぐに復帰出来るし、
万一の場合にも作業状態を失わない。