OmniAICreator/Qiita-1.07M huggingface dataset:
【git ssh接続】〜複数のアカウントでgit ssh接続する方法〜


#暗号鍵の生成

```bash
# sshのセッティングディレクトリに移動
$cd ~/.ssh

# 暗号鍵を生成
$ ssh-keygen -t rsa
# Generating public/private rsa key pair.
# Enter file in which to save the key (/Users/(username)/.ssh/id_rsa): id_git_rsa
# Enter passphrase (empty for no passphrase):
# Enter same passphrase again:
```


#GitHubへの公開鍵のアップロード

以下URLで公開鍵の設定
https://github.com/settings/ssh

「title」に公開鍵名、「key」に公開鍵の中身を入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/861809/c3ade4c9-52a5-df87-6192-592ff628ada3.png)


#ssh接続の設定

```~/.ssh/conifg
Host github
  HostName github.com
  IdentityFile ~/.ssh/main_rsa
  User git
  Port 22
  TCPKeepAlive yes
  IdentitiesOnly yes

Host github-sub
  HostName github.com
  IdentityFile ~/.ssh/sub_rsa
  User git
  Port 22
  TCPKeepAlive yes
  IdentitiesOnly yes
```
github-subとgithubは任意
IdentityFileのファイル名も任意


#githubへのssh接続確認

```bash
# ssh接続確認 （<HOST NAME>には「github-sub」などが入る）
$ ssh -T <HOST NAME>
# Hi ******! You've successfully authenticated, but GitHub does not provide shell access.

# git cloneを実行 （ssh用のURLをコピーし、HOST NAMEを書き換える）
$ git clone <HOST NAME>:******/******.git
```

# 参考
GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~
https://qiita.com/shizuma/items/2b2f873a0034839e47ce
複数のgitアカウントを使用する場合
https://qiita.com/yamataku29/items/4744c9c70ad793c83b82
マイグレーションのロールバックが出来ない時の対処方法（UnknownMigrationVersionError）

# はじめに
rails db:rollbackでマイグレーションファイルをロールバックしようとしたところ、下記のようにUnknownMigrationVersionErrorというエラーに悩まされたので、この解決方法について書こうと思います。

```:ターミナル
rails aborted!
ActiveRecord::UnknownMigrationVersionError: 

No migration with version number 20201230115014.
```

# UnknownMigrationVersionErrorの詳細
rails db:migrateでマイグレーションファイルの状態を確認したところ、NO FILEと書かれた身に覚えのないデータが残っていました。
これは、ステータスがupのままVSコード上でマイグレーションファイルを削除してしまったため、DB上にはデータが残っている状態でした。（おそらく、ActiveHashでモデルを作成した時に、skip-migrationを忘れて謝って作成したファイルだと思います\...）
まとめると、対応するファイルが存在しないマイグレーションデータが残ったままになっていたのが、UnknownMigrationVersionErrorの原因でした。

![D5E70B3A-1D63-479C-94FD-900F409069C4_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/829213/703a2cb0-dc9d-6e6a-771f-b9f65bf86e88.jpeg)

# 解決方法
###1. VSコード上にマイグレーションファイルを作成
まず、NO FILEとなっていたIDが20201230115014のデータに対応するファイルを、VSコード上で作成します。（今回は、「20201230115014.dummy.rb」というファイル名で作成しています。）

![99E65E07-FF88-42CC-9BC3-3C9C084D0334_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/829213/067195d6-077c-4ecd-302f-946e234d11b3.jpeg)

###2. ステータスをdownにする
マイグレーションファイルを作成しただけの状態で、ロールバックしようとすると下記のようにエラーが出ます。これは、先ほど作成したマイグレーションファイルの中身が何も記述されていないことが原因です。

```:ターミナル
rails aborted!
NameError: uninitialized constant Dummy
```

これを解消するために、マイグレーションファイル内にクラスとchangeアクションを記述します。その後、一度マイグレートを行います。

```ruby:20201230115014.dummy.rb
class Dummy < ActiveRecord::Migration[6.0]
  def change
  end
end
```
```:ターミナル
rails db:migrate
```

この状態で、ロールバックしてあげると、無事ステータスがダウンになりました。
![A5D9F5BE-30C3-4305-87D0-8AE73B397D3D_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/829213/0feaf9f0-b95c-ddbe-01b0-cb7e3cbce023.jpeg)


###3. 対象ファイルの削除
ここまで来れば、後は対象ファイルを削除するだけです。VSコードで「20201230115014.dummy.rb」のファイルを削除した後、rails db:migrate:statusで確認すると、無事対象のデータが削除できてることが確認できます。
![5C22EAFC-90C1-4B95-8F5A-AB7B82F34315_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/829213/d8f9045f-1d91-b7a9-e2f8-6ab7a8a60a58.jpeg)

#終わりに
何気なく、ステータスを確認せずにマイグレーションファイルを削除すると後々面倒だなと思いました。何か見てくださる方のヒントになれば幸いです。

#参考
https://qiita.com/ISSO33/items/33a935cb3255c269bef2
リストの処理について（Ruby学習後のPython初学）

#リスト処理
リスト処理の一部補足

```python:list.py
#split関数 与えられたデータを指定の引数で分割し、リストとして戻す。以下今回は特に使用せず。

#random.randrange関数 引数のリストの要素の中でランダムに取り出す

import sys
import random
dice = []
for line in sys.stdin.readlines():
    dice.append(line.rstrip())

#入力される値(例)
1
2
3
4
5
6
#行ごとに入力された1から6までの数字がdice変数のリストに格納される

num = len(dice)

print(dice[random.randrange(num))

#diceの中身の0番目の1から5番目の6までの間のいづれかが出力される。
```
入力時に関しての処理補足

line = input().rstrip()　#rstrip関数 文字列の末尾の改行コードを取り覗く。

import sys
line = sys.stdin.readlines()　#sys.stdin.readlines関数 ファイル・複数行の入力値を全て読み込み、1行毎に処理する
【001_フィボナッチ数列】コマ大数学科

# 【001_フィボナッチ数列】コマ大数学科

>15段の階段がある。階段を上がるのには1段ずつ上がるのと2段ずつ上がるのと2通りの上がり方がある。この上がり方を組み合わせてちょうど15段上がるのは通りの登り方があるか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017176/ea92c752-a8d8-c20f-2ba0-eea8d306025d.png)



```tex
\begin{tikzpicture}
  % ==階段，放物線，
  % 線を引く
  \draw (-1,0)--(0,0);
  \draw (-1,0)--(0,0);
  \foreach \x in {0,0.5,1,...,7.5}
  \foreach \y in {0,1,2,...,15}
{
  \draw ({\x},{\x})-|({(\x)+(0.5)},{(\x)+(0.5)});
  \coordinate (\y) at ({\y/2+0.25},{\y/2});
  \node at ({\y/2},{\y/2})[below right]{\y};
}	
\draw [->](0) parabola bend ($(0)+(0.25,0.75)$) (1);  % 1段飛ばし
\draw [->](1) parabola bend ($(1)+(0.5,1.5)$)(3);     % 2段飛ばし
\draw [->](3) parabola bend ($(3)+(0.25,0.75)$) (4);  % 1段飛ばし
\draw [->](4) parabola bend ($(4)+(0.5,1.5)$)(6);     % 2段飛ばし

\end{tikzpicture}


```
ALTER DATABASE文の実行でRMAN上でコピーとみなされる（Oracle Database 19c)

RMANで取得するバックアップにはBACKUPSETとCOPYがあります。COPYはファイルの物理コピーを示し、BACKUP AS COPYコマンドで作成します。BACKUP AS COPYコマンドの実行以外にアーカイブログがCOPYとして認識されます。下記の例ではアーカイブログがCOPYとして認識されることがわかります。

```
RMAN> ALTER SYSTEM ARCHIVE LOG CURRENT;

文が処理されました

RMAN> LIST COPY;

指定がリポジトリ内のどのデータファイル・コピーとも一致しません
指定がリポジトリ内のどの制御ファイル・コピーとも一致しません
データベースdb_unique_name O19Aのアーカイブ・ログ・コピーのリスト
=====================================================================

Key     Thrd Seq     S Low時間
------- ---- ------- - --------
18      1    11      A 21-01-12
        名前: /u01/app/oracle/admin/O19A/archive/1_11_1061126924.dbf
```

BACKUP AS COPYコマンドの実行とアーカイブログ以外にALTER DATABASE文の実行でCOPYとして認識される場合があるため検証します。ALTER DATABASE CREATE STANDBY CONTROFILE文を実行すると、制御ファイルのコピーが作成されたと認識します。

```
RMAN> ALTER DATABASE CREATE STANDBY CONTROLFILE AS '/tmp/standby01.ctl' REUSE;

文が処理されました

RMAN> LIST COPY;

指定がリポジトリ内のどのデータファイル・コピーとも一致しません
指定がリポジトリ内のどのアーカイブ・ログとも一致しません
制御ファイル・コピーのリスト
===========================

Key     S 終了時間 Ckp SCN    Ckp時間
------- - -------- ---------- --------
37      A 21-01-12 10847016   21-01-12
        名前: /tmp/standby01.ctl
             タグ: TAG20210112T140427
```

ALTER DATABASE BACKUP CONTROLFILE文の実行でも制御ファイルのコピーが作成されたと認識されます。

```
RMAN> ALTER DATABASE BACKUP CONTROLFILE TO '/tmp/backup01.ctl' REUSE;

文が処理されました

RMAN> LIST COPY;

指定がリポジトリ内のどのデータファイル・コピーとも一致しません
指定がリポジトリ内のどのアーカイブ・ログとも一致しません
制御ファイル・コピーのリスト
===========================

Key     S 終了時間 Ckp SCN    Ckp時間
------- - -------- ---------- --------
38      A 21-01-12 10847426   21-01-12
        名前: /tmp/backup01.ctl
             タグ: TAG20210112T140453

37      A 21-01-12 10847016   21-01-12
        名前: /tmp/standby01.ctl
             タグ: TAG20210112T140427
```

ただし、ALTER DATABASE BACKUP CONTROLFILE TO TRACE文を実行してトレースファイルに対して制御ファイル情報を書き込んだ場合はコピーとはみなされません。

```
RMAN> ALTER DATABASE BACKUP CONTROLFILE TO TRACE;

文が処理されました

RMAN> LIST COPY;

指定がリポジトリ内のどのデータファイル・コピーとも一致しません
指定がリポジトリ内のどのアーカイブ・ログとも一致しません
制御ファイル・コピーのリスト
===========================

Key     S 終了時間 Ckp SCN    Ckp時間
------- - -------- ---------- --------
38      A 21-01-12 10847426   21-01-12
        名前: /tmp/backup01.ctl
             タグ: TAG20210112T140453

37      A 21-01-12 10847016   21-01-12
        名前: /tmp/standby01.ctl
             タグ: TAG20210112T140427
```
pytest の導入と簡単な使い方

# pythonでテストコード実装のためにpytestを使用したので、その導入方法と最低限の使い方についてまとめます。

環境
Mac OSX
Python 3.7.7, 
pytest-6.1.2, 
py-1.9.0, 
pluggy-0.13.1

## pytestの導入方法（インストール）

```qiita:ターミナル
$ pip install pytest
```

これでインストール完了です。

ファイル構成

```
.test/
├── A
│   └── test_a.py
└── B
    └── test_b.py（後でまとめて実行する場合には、ファイル名を一意に定まるようにする。（）
```


## <注意点>
* テストファイル名は`test`で始まるようにする(例：test_integration.py, test_unit.py)
* テストファイル(.py)のファイル名は一意に定まるようにする（他のテストファイルと名前が被らないようにする）
* テスト対象の関数名は`test`で始まるようにする

<関数の記述方法>

```
import os
import sys
sys.path.append(os.getcwd())  # pytestはカレントディレクトリをsys.pathに追加しないためカレントディレクトリ上にあるファイルを読み込みたい場合はimport os, import sysと一緒に明記

def test_a():
    assert 6 == multiplication(2, 3)

def multiplication(x, y):
    return x * y
```


## テストコード実行方法
フォルダ別で実行する場合

```qiita:ターミナル
$ pytest test/A
```
上階層から複数のフォルダに対してまとめて実行することもできます。

```qiita:ターミナル
$ pytest test
```


ファイル別で実行する場合

```qiita:ターミナル
$ pytest test/A/test_a.py
```
もしくは、ディレクトリを移動して

```qiita:ターミナル
$ pytest test_a.py
```
でも大丈夫です。

実行してテストに合格するとこのようになります。(グリーン表記）
![スクリーンショット 2021-01-12 14.38.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531595/ee63727e-9973-8415-1484-2aa0305ff15e.png)
【kintone】表示上の値を変える方法

こんにちは！
kintoneの画面には

* レコード一覧画面
* レコード詳細画面
* レコード追加画面
* レコード編集画面

色々とありますが、それぞれ、開いた時に値を変えるという方法を紹介したいと思います。
レコードの値ではなくて、あくまでも表示上、見た目の値の変更です。

# アプリ準備
とりあえずフィールドを1つだけ作っておきましょう

フィールド種類：文字列(1行)
フィールドコード：A

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/aa2ab8fc-0a9d-383d-f583-7494fb8bfd62.png)


# 追加画面＆編集画面
「追加画面」と「編集画面」は`event.record.フィールドコード.value`の値を変更することにより、画面を開いたときの値を変更できます。

```js
kintone.events.on(["app.record.create.show", "app.record.edit.show"], (event) => {
  event.record.A.value = "開いた時に変更";
  return event;
});
```

![112-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/c6e84b0d-802e-563d-13fa-4bc118b67387.gif)



# 詳細画面
手入力のできない詳細画面ではDOM操作が必要です。
参考：[フィールド要素を取得する](https://developer.cybozu.io/hc/ja/articles/201942014#step3)

```js
kintone.events.on("app.record.detail.show", (event) => {
    const field_A = kintone.app.record.getFieldElement("A"); //←フィールドAの要素を取得
    field_A.innerText = "開いた時に変更"; //←innerText（見た目の値）を変更
    console.log("フィールドAの値は", event.record.A.value); //←実際にレコードに保存されている値
    return event;
  });
```


↓見た目上は「開いた時に変更」ですが、レコードはもとの値「d」を保持しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/aa4174a9-d7a2-e68f-f74f-a5a5fc70b8fa.png)


# 一覧画面
詳細画面と似たような方法で、以下のようにDOM操作で見た目だけ変更できます。

見た目だけの変更なので、編集ボタンを押すとレコードで保持している、元の値に戻ってしまいます＾＾；
良いやり方があったら教えて下さい👀🙏

```js
kintone.events.on("app.record.index.show", (event) => {
  const field_A = kintone.app.getFieldElements("A");//フィールドAの要素たちを取得
  field_A.forEach((r) => {
    r.firstChild.firstChild.innerText = "開いた時に変更"; //全フィールド変更してるけどここはお好みで
  });
  return event;
});
```

![113-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/7315b41d-1df8-5e8e-5429-ba8b797f0bb1.gif)



# まとめ
レコードに保存するではなく、例えばある日付からの経過日数などを表示したい時などに重宝するのではないでしょうか👀！？
スクラム開発で使うバーンダウンチャートの管理をGitでしたい

スクラム開発で使うバーンダウンチャートの管理をGitで行えるようにしたいと思い、リポジトリをForkしてGithub Pagesでみられるツール(https://k8shiro.github.io/GithubBurnDownChart/index.html )を作りました。

リポジトリ: https://github.com/k8shiro/GithubBurnDownChart

# 背景

スクラム開発では、バックログアイテムの消化の見通しにバーンダウンチャートが使われることが多いと思います。
このバーンダウンチャートの管理方法に悩んでいて、

- Excel
    - 使いたくない、差分管理できないしファイルの共有が面倒
- チケット管理ツールに付いているやつ(OpenProjectを使っている)
    - カスタマイズ性が悪い、微妙にツールの想定と違う使い方をしていて付属のバーンダウンチャートが使えない
- googleスプレッドシート
    - これで良いのだが、会社の都合で使えない

といった状況で、うまい管理方法を探していました。

結局、要件としては

- チームで共有しやすい
- 差分管理ができる
- カスタマイズできる
- 表示できる

なのですが、これを満たす良い方法が見つからなかったので自分でcsvをGitで管理し、これをGithub Pagesでグラフ表示できるようにしてみました。

# 作ったもの
以下のようにのようにGithub Pagesでグラフがみられるようになります。実際のページは
[こちら](https://k8shiro.github.io/GithubBurnDownChart/index.html)です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86684/d6b50553-7351-fd05-2bea-2c4d5e42cc08.png)

このグラフでは

- 理想線 : スクラム開始時のバックログアイテムがスクラム終了時点で全て消化された場合の線(リリース時の0になる)
- 計画線 : 開始時の計画通りに進んだ時のバーンダウンチャートの変化を表す線です
- 実績線 : スプリントごとに更新される実際の残りのバックログアイテムのポイント合計の線です
- 完了済み : 実績線は残りの合計ですが、こちらは完了済みのアイテムの合計ポイントです(バーンアップ)

が表示され、またcsvの内容がグラフ下のテーブルで確認できます。

# 使い方

1. [こちら](https://github.com/k8shiro/GithubBurnDownChart)のGithubのリポジトリを複製してください(cloneして自前のGithubリポジトリにpush or Fork)
2. 1で作成した自分のリポジトリでGithub Pagesの公開設定をしてください
    - リポジトリの Settings > Options > GitHub Pages でSourceをmainブランチにしてsaveするだけ
3. リポジトリ内にあるburndownchart.csvを更新してPushしてください（csvのフォーマットは後述）

※ Github Pagesの公開設定・更新後、反映まで時間がかかることがあります。
※ リポジトリ名をGithubBurnDownChart以外にした場合、csvの読み込みpathを修正する必要があります。[burndownchart.jsの下部](https://github.com/k8shiro/GithubBurnDownChart/blob/main/src/burndownchart.js#L102)のpathを修正してください。

## burndownchart.csvの更新

上記のGithub Pagesの設定を行ったら、後はスプリントごとにburndownchart.csvを更新していくだけです。

初回は開始前〜リリースまでの枠(下表の0回目〜7回目)を作り、0回目に完了アイテム合計を0、それ以外をバックログアイテムのポイント合計(下表だと200)を入れます。また、リリース(下表では7回目)に計画線にリリース時の残る予定のポイント(下表では60)と理想線に0を入れます。

以降はスプリント終了ごとに更新します。スプリント終了時点での終了したアイテムのポイント合計を完了アイテム合計に(下表1回目なら18)、バックログに残っているアイテムのポイント合計を実績線に(下表なら182)を追記します。計画線と理想線は空白で大丈夫です。

|スプリント| 完了アイテム合計| 実績線| 計画線| 理想線|
|:----|:----|:----|:----|:----|
|0回目(開始前)| 0| 200| 200| 200|
|1回目| 18| 182| | |
|2回目| 38| 162| | |
|3回目| 58| 152| | |
|4回目| 80| 130| | |
|5回目| | | | |
|6回目| | | | |
|7回目(リリース)| | | 60| 0|


# 仕組み
[src/burndownchart.js](https://github.com/k8shiro/GithubBurnDownChart/blob/main/src/burndownchart.js)で大体の処理を行っています。アップロードしたcsvをXMLHttpRequest()で取ってきてcsvテキストを配列化、[Chart.js](https://www.chartjs.org/)でグラフ描画しているだけです。

# まとめ
Gitでcsvを管理し、これをGithub Pagesでグラフ表示できるようにしました。後はGitHub Actions等でcsv生成もすれば完全自動化できそうです。
スマートロックを自作したので難所をまとめる

IoT開発初心者がスマートロックを作ってみました。詰まった箇所をまとめます。

# 作製したもの

スマートロックを作製しました。開錠・施錠の方法は２つあります。

* あるエンドポイントにリクエストを送った後、ドアノブを一回ガチャっと回す
* 指定のリズムでドアノブをガチャガチャする

![IMG_1793 (online-video-cutter.com).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227166/f39a9919-311a-b6ae-b07e-1f94e5279b69.gif)

内側はこのようになっています。ブレッドボードやジャンパワイヤを使ったままですが、この方が新しい機能をつけやすいのでこのままにします。
![IMG_1794.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227166/2862ff86-ed93-2519-8e73-385b616621cd.jpeg)


# 構成

エンドポイントを利用した開錠・施錠を実現するため、以下のような構成を作りました。

![Untitled Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227166/8bb0f265-7b03-dc9b-1d78-918d6602acd7.png)

# 使用した技術

バックエンドはサーバーレスにしています。私しか利用しないので、サーバーを借りるとコストがかさむからです。デプロイにServerless Frameworkを利用しました。

WiFiを利用したかったので[ESP32-WROOM-32](https://akizukidenshi.com/catalog/g/gM-11819/)を選択しました。初めて利用したのですが開発は非常に楽でした。Arduino IDEで開発可能です。

# 難所

今回の開発で難しかった点を書いていきます。

## 消費電力を抑えながら可用性を確保する必要があった
今回はバッテリーから給電することにしました。頻繁に電池切れを起こすとスマートロックとして大変不便ですし、**最悪家から締め出されてしまう**原因にもなります。そのため消費電力をできる限り抑える必要がありました。

対策として、**[ESP32-WROOM-32](https://akizukidenshi.com/catalog/g/gM-11819/)の選定により解決**を目指しました。[ESP32-WROOM-32](https://akizukidenshi.com/catalog/g/gM-11819/)にはDeepSleepという機能があり、スリープ状態での**消費電流を10uA~150uA**に抑えることが出来ます。

しかしながら、実際に運用してみると１週間程度でバッテリーがきれてしまいます。そのため商用のスマートロックと同等の製品にすることはできませんでした。


## モバイルバッテリーが自動停止してしまう

モバイルバッテリーはもともと携帯などを充電するために作られており、過充電を防いだり無駄な電力を消費しないように自動停止する機能がついているみたいです。**家電量販店で売られているものには基本的にこの機能がついています**。

この問題はこのモバイルバッテリーを利用するすることで解決しました。
[cheero Canvas 3200mAh IoT機器対応 モバイルバッテリー ホワイト CHE-061](https://www.amazon.co.jp/gp/product/B018KD0D82/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)

## スマートロックを設置する方法に戸惑った

当然、サーボモータをカギに取り付けると以下のようにサーボモータの方が回ってしまいます。
![IMG_1776.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227166/e3e952d2-82fd-3f4a-1941-37c2ae02cd12.gif)

これをしっかりと固定するために、L字の金具などを使いました。しかし自分にこのような金具を使う経験が乏しく見栄えは悪くなってしまいました。
![IMG_1797.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227166/a74cd113-b50b-2ba7-0b95-c330ba6a128c.jpeg)


## DynamoDBをboto3で操作するのが大変

本筋ではないのですが、Pythonのboto3のAPIを使ってDynamoDBにリクエストを送るのが大変でした。APIの仕様が複雑で、私には理解するのに非常に時間がかかりました。

途中で[PynamoDB](https://github.com/pynamodb/PynamoDB)を利用することにしました。開発が非常に楽になりました。

# 開発の感想

ドアノブをガチャガチャするだけで開錠できるので、生活は非常に楽になりました。

また友達が一時的に自分の部屋を出入りする場合、物理的な鍵を共有せずに開錠・施錠ができるため、今後も便利なシチュエーションがありそうです。

[ESP32-WROOM-32](https://akizukidenshi.com/catalog/g/gM-11819/)開発ボードを利用した開発は非常にスムーズでした。お金が少し高くても、開発の速度や快適さを求めるなら開発ボードを買うべきだと実感しました。以前はお金をケチってPICを使ったり、[ESP-WROOM-02 DIP化キット](https://akizukidenshi.com/catalog/g/gK-09758/)を使ったりしていました。

スマートロックをドアに取り付けるのに苦労しました。ネット上の先人はよく3Dプリンタを使ってこの問題に取り組んでいるので、私も3Dプリンタを購入しました。次の開発から使ってみたいと思います。
Redash on EC2の障害と復旧作業

EC２でホスティングしているRedashが停止しました。

ELBから告げられる `502 Bad Gateway` のメッセージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/0522a04d-7e28-023b-a833-341201e9ac0f.png)

原因特定から復旧までのログを残します。

# 原因特定

## ELBのログ調査

さっそく省略します。なぜなら、ALBのロギングが有効になっていなかったため。

次回以降に役立つよう、AWSの公式ドキュメントに従って、ALBのアクセスログをS3に保存するように設定しておきます。
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#enable-access-logging

## EC2インスタンスへの直接アクセス

踏み台サーバー経由で、EC2インスタンスの80番ポートにアクセスします。すると接続できない。
SecurityGroupに変更を加えた覚えはないので、EC2の中で問題が起きている可能性が高そうです。

```terminal
curl -v  ip-**-**-**-**.ap-northeast-1.compute.internal:80
...
* Failed to connect to ip-**-**-**-**.ap-northeast-1.compute.internal port 80: Connection refused
* Closing connection 0
...
```


ちなみに、成功した場合のレスポンスはこんな感じです。

```terminal
curl -v  ip-**-**-**-**.ap-northeast-1.compute.internal:80

< HTTP/1.1 302 FOUND
< Server: nginx/1.9.10
< Date: Tue, 12 Jan 2021 01:21:12 GMT
......
```

## RedashへのSSHとプロセスの死活確認

Redashの入っているEC2インスタンスにSSHし、当該プロセスの死活確認をします。
ここで、そもそもRedash on EC2ってどうやって動いているんだっけ？という疑問に突き当たりました。


[公式ドキュメント](https://redash.io/help/open-source/setup)によれば docker-compose を利用しているとのこと。

> What the script does is:

> Install Docker and Docker Compose.
Download our recommended Docker Compose configuration and create initial configuration.
Start everything.

確認してみると...あれ、Dockerプロセスが死んでますね。

```terminal
/opt/redash$ sudo docker ps
sudo: unable to resolve host ip-**-**-**-**: Resource temporarily unavailable
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```

# 原因特定と復旧作業

## 原因特定

docker-composeプロセスを再起動するため、[Redashのアップグレード手順](https://redash.io/help/open-source/admin-guide/how-to-upgrade)を参考に再起動を実行すると、エラーが発生しました。

```terminal

cd /opt/redash
docker-compose up -d

> INTERNAL ERROR: cannot create temporary directory
```

検索するとディスクの残量が少ないことが原因のよう。
https://stackoverflow.com/questions/40755494/docker-compose-internal-error-cannot-create-temporary-directory

アプリケーションレベルでは、Redashがクエリの実行結果をキャッシュしていることが原因のような気がします。
https://discuss.redash.io/t/redash-taking-high-disk-space/6777

そういえば limit句 なしでクエリを実行して、レスポンスがなかったのでブラウザのタブを閉じたような記憶が...
（PostgresDBの中を覗けば明らかになると思いますが、今回はそこまでしません）

## 復旧作業

[Qiita](https://qiita.com/mangano-ito/items/629b10ea5d1ab80f2cc6)、[AWSのドキュメント](https://aws.amazon.com/premiumsupport/knowledge-center/ebs-volume-size-increase/)に従い、EBSのボリュームの追加とデバイス・ファイルシステムへの割り当ての増加を行いました。

# 反省

EC2のディスク・メモリの逼迫はデフォルトのメトリクスに出てこないので、必ず追加設定するような仕組み作りがしたいところですね。
Ubuntu 20.4にCybozu Office 10をインストール

# 本家手順書
基本的に本家の通りやってみます。
https://jp.cybozu.help/ja/of10/intro/install/lin.html

#インストール環境

Ununtu 20.4
#Apacheのインストール

```
# apt install apache2
```

#Selinuxの無効化
は、必要なかった。(たぶん）

#サイボウズのダウンロード

下記から最新版ダウンロード

```
https://office.cybozu.co.jp/trial/download/
```

#実行
ダウンロードしたファイルのアクセス権を変更して実行

```
#chmode 777 cbof-xx.x.x-linux-k4.bin
#./cbof-xx.x.x-linux-k4.bin
```

しかし、

```
GLIBCのバージョンを検出できませんでした。
```
というメッセージでインストールが終了してしまう。

http://dotnsf.blog.jp/archives/3608124.html
と
https://qiita.com/teruo-oshida/items/49f88ce150e9f3067003
から

```
#apt install libc6-i386
```

でインストーラーが止まらずに動いた。

#表示

http://127.0.0.1/cgi-bin/cbag/ag.cgi?
を表示させようとしたら、"Page not found"が出た。

https://yukushige.com/blog/?p=166
に倣い、confファイルの

```
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
```
を

```
ScriptAlias /cgi-bin/ "/usr/lib/cgi-bin/"
AddHandler cgi-script .cgi .py
```
に追加・変更して

```
#systemctl restart apache2
```

でサイボウズの初期画面が表示できた。
Web API入門#4 〜クールなURIの設計方法について〜

## はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ クールなURIの設計・変更・テクニック・不透明さについて

■ Web API入門についての過去記事
・ [Web API入門#1 〜APIとWeb API、Webの概要〜](https://qiita.com/s79ns/items/8dd2f06145cbf9464b99)
・ [Web API入門#2 〜REST、アーキテクチャについて〜](https://qiita.com/s79ns/items/bd8b1f50c34ada016196)
・ [Web API入門#3 〜URIの基礎知識〜](https://qiita.com/s79ns/items/c4ec2db048fa3b13638e)

## クールURIとは何か

#### クールURI

良いURIやきれいなURIのことを「クールURI」（Cool URI）と呼びます。
この起源は、Webの発明者Tim Berners-Leeが1998年に発表した「Cool URIs don’t change」
（クールなURIは変わらない）というWebページです。

## クールなURIの設計方法

#### プログラミング言語に依存した設計を含めない

ファイル拡張子が含まれたURI（https://〜.com/posts.php）のような構成で、そのWebページを
phpではなく、他の言語で作り直そうとリニューアルをする時に、URIの構造のまま変えることができません。
また、プログラミング言語を変更すると、そのURIにアクセスすることができなくなります。
また、開発用ディレクトリや大文字をURIに含めません。

#### メソッド名やセッションIDを含めない

例えば、/posts?action=hogeのように、実行したいアクションをURIに含めず、HTTP用のメソッドを使います。
また、ログインする度に、セッションIDが変わってしまうので、URIが常に変わってしまいます。
基本的に、セッションIDは、Cookieであったり、JWT（JSON Web Token）に保存するのが主流のようです。

#### URIにはリソースを指し示す名詞を使う

基本的に、URIには名詞を使い、動詞は使いません。（HTTPメソッドで表現することができます)

#### なるべくシンプルかつ人間が読んで理解できる

良い例はこちらで、15回目の投稿記事だとひと目で見て分かりやすいと思います。

```terminal
https://hoge.com/posts/15
```

悪い例はこちらで、基本的に冗長で、dogは犬なのか、カテゴリーで書いているのか設計者しか分かりません。
また、articleも、postsがあるのであれば、書く必要性はあまり感じられません。
カテゴリーはURIに含めず、クエリパラメータに指定する方が良いと思います。

```terminal
https://hoge.com/dog/posts/foods/article/12
```

## URIの変更方法

URIの変更方法ですが、URIを普通に変えてしまうと、リンク切れを起こしてしまい、URIが指し示すリンクにアクセスができなくなってしまいます。その状態を避ける為に、<font color="red">301リダイレクト</font>というものを使います。

#### 301リダイレクト

URIの状態変更を知らせるもので、恒久的なURIの変更を意味します。
Webページの移転などで使い、旧Webページにアクセスをすると、新しいWebページにリダイレクトされます。

また、ユーザーフレンドリーだけでなく、SEOにも効果があります。
SEO的には、元々運営していたサイトのページランク（検索結果で上位に表示されやすくなる）も継承します。

![スクリーンショット 2021-01-12 12.45.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/e5ea5be5-3c0b-0032-657b-e7597138d364.png)

#### 302リダイレクト

302リダイレクトというものもあり、こちらは一時的なURIの変更を意味します。

## URI設計のテクニック

#### URIにバージョン番号を含める

URIにバージョンを含めてあると、APIの更新時に、URIの大元は変えずにAPIのバージョンをv2からv3に変更するだけで使えるようになります。

| API | URI |
|:----|-----|
| Google Calendar | http&#58;//googleapis.com/calendar/v3/ |
| Twitter         | http&#58;//apis.twitter/1.1/           |
| Youtube         | http&#58;//googleapis.com/youtube/v3   |

#### 拡張子を用いて多言語対応のリソースを切り替える

拡張子については、プログラミング言語に依存した設計を含めないの項目でお伝えしましたが、今回はプログラムのファイル拡張子ではなく、言語を示す拡張子を使うことによって、多言語対応することができます。

例①：http&#58;//hoge.com/<font color="red">jp</font>にアクセスすることにより、日本語に対応したページに移動します。
例②：英語対応：http&#58;//hoge.com/<font color="green">en</font>にアクセスすることにより、英語に対応したページに移動します。

## URIの不透明性を保つ

#### URIからリソースの構造を推測されないようにするべき

APIを経由せずにリソースにアクセスされてしまうと情報が漏えいしてしまいます。
対策は、API以外のアクセス経由を遮断するなど色々ありますが、URIを推測されないように不透明さを保つ必要があります。

#### URIに拡張子を含めるとその言語で操作されてしまう可能性がある

URIに拡張子が含まれていると、何を使ってサイトを構成しているのかが分かるので、スクリプトを埋め込まれたりされやすくなります。

これらのことから、API経由以外でサーバーから情報が抜き出される可能性がありますので、クライアント側でURIを構築しないなどの対策を講じることが必要です。

## 次の記事はこちら

[Web API入門#5 〜HTTPの基礎〜](https://qiita.com/s79ns/items/31a6f6affdd28bb8b026)
ubuntu のターミナルからanacondaの仮想環境を呼ぶ　備忘録

 ## 概要
普段はpyenv x virtualenv を主に使うのですが、
anacondaも使う機会があったので一応備忘録として。


## やりかた

```
echo ". /home/<user>/anaconda3/etc/profile.d/conda.sh" >> ~/.bashrc
```

として

```
source ~/.bashrc
```

をしたあとに、

```
conda activate <name>
```

とするだけ。
開発中にGoogleのOAuthでリフレッシュトークンが取れなかった

開発中、何度やってもレスポンスがこんな感じになってしまう。

```google_oauth_response.json
{'token': 'foobaafoobaafoobaa', 'expiry': datetime.datetime(2021, 1, 12, 4, 26, 32, 183822), '_quota_project_id': None, '_scopes': ['https://www.googleapis.com/auth/calendar'], '_refresh_token': None, '_id_token': None, '_token_uri': 'https://oauth2.googleapis.com/token', '_client_id': 'clientid.apps.googleusercontent.com', '_client_secret': 'thisissecret'}
```

リフレッシュトークンが取りたいのにNoneになる。

## 再現してしまうパターン
開発中に取得してはDBのレコードを削除するみたいな形で検証をしていると遭遇するはず。

## 対策
こちらのページにアクセス
https://myaccount.google.com/permissions

作成したアプリケーションの認証済み情報を削除する。
これをやるだけで、次にOAuthした時にはリフレッシュトークンの取得ができている。

こんな事に数時間ハマってしまい泣きました。
お客様の課題とか要件ってどうやって探すんだろう?

Solutions EngineerやArchitectと呼ばれる、主にお客様との商談ご成約までに発生する技術的な活動をミッションとしている人にとって、お客様の技術的な課題や要件を探り当てることは最も重要かつ困難な活動の1つかと思います。この記事は、Pre-salesフェーズでお客様の課題や要件を探り当てるためにどんなやり方が考えられるかを考察した実験記事です。


# Divergence and Convergence Cycle
Divergence and ConvergenceサイクルはSoftware開発やサービス開発に利用されるDesign Thinkingのフレームワークとして有名ですが、このフレームワークはお客様との商談にて課題・要件の掘り起こしにも使えるのではと思っています。Divergence Thinkingでは、ありとあらゆるアイデアを肯定しながら可能性のある問題や解決策を可能な限り出し切ります。Convergence Thinkingでは、出し切ったアイデアからより現実的な問題や解決策に落とし込み実世界で通用する内容にまとめていきます。

<img src="https://i.imgur.com/gzTal81.jpg" width=50%>


# No pain, no change
世に出回っている製品はお客様の問題を解決できることが証明できて初めて"Solution"になります。問題を解決できることを証明するためには、問題が何なのか?何故そんな問題があるのかを深く理解することが出発地点になります。お客様は非常に広範な領域を担当しており、ある特定の分野に十分な知見を持ち合わせていないケースがほとんどで、何が真の問題なのか把握されていないことがほとんどかと思います。個々の特定分野に専門性を持ち合わせたベンダーがお客様の立場に立ってお客様と一緒に真の問題を探り当てる、これは多くのお客様がベンダーに期待していることかと思います。

<img src="https://i.imgur.com/oIlaAj1.jpg" width=50%>


# Finding the right problems - Divergence
真の問題を探り当てるには水平思考や発散思考が効果的かと考えます。お客様とのミーティングでは、お客様から発せられる言葉に細心の注意を払いながら、発している言葉の定義・意味(What)、何故そのように考えるのか?(Why)を理解します。ミーティングの場で初めて聞いた言葉の意味や背景をその場で瞬時に100%理解することは不可能なため、ミーティングの前に可能な限りお客様のことを事前に調査します。

- 有価証券報告書に記載されている基本的な数字と対処すべき課題やリスクに記載されている内容
- 売り手側とお客様の関係(既にお取引のある既存顧客か新規見込み顧客か)
- 対象のApplication、開発言語やフレームワーク
- 開示されている事例、どんなベンダーと付き合いが深そうか
 
お客様が発している言葉のWhat/Whyを理解できたとしても、注意すべきことは返ってきた答えの分野をすぐに深堀りしないことだと考えます。このフェーズでは水平思考や発散思考でお客様ご自身が気づいていない潜在的な問題を探り当てることが目的です。"[お客様]xxxxが問題で、理由はxxxxです。"、"[売り手側]なるほど、その問題はxxxxで解決できますね。弊社のxxxxはここがすごくてここが特徴です。他社にはできません!"、といった会話は避けて、"[売り手側]了解しました。他の問題についても理解したいのでもう少し背景をお聞かせ頂けませんか?"といった会話でできるだけ発散します。


# Finding the right problems - Convergence
お客様ご自身が気づいていない潜在的な問題も含めて出し切ったら一度まとめに入ります。人は誰しも、"で結局どうなるの?(So what)"が気になると思います。ただし、このフェーズの目的はあくまで真の問題を探り当てることなので、まとめは仮で構いません。発散しきった問題を並べて、各々の関連性や重要度、その課題をほったらかしにした場合に起こりうる"不"をお客様と一緒に協議して、問題の優先順位を整理していきます。仮のまとめができたら再度発散思考に戻り、仮のまとめと関連するであろう問題を掘り起こします。ここでは、議論が仮のまとめからはみ出さないように注意しながら発散します。このように、発散->収束->発散->収束を繰り返して最も重要な真の問題を特定します。


# Finding the right solution - Divergence
真の問題が特定されたら、再び発散思考に戻り問題に対する解決策を探ります。現実の世界は学生時代に勉強した数学とは異なり、ある問いに対する答えは複数あると考えます。このフェーズでは問題に対して可能性のある解決策をできる限り出し切ります。ここで重要なのは、xxxxは出来ないんだよな。。。xxxxには制限があるんだよな。。。といった思考は一旦捨てることです。製品とはありとあらゆるお客様が恒久的に求めている解決策を予めまとめた"最大公約数"でしかなく、お客様の問題を100%解決できるための要求事項と製品が提供できる解決策には必ずギャップがあります。ギャップを明確にすることがこのフェーズの大きなゴールの1つだと考えます。


# Finding the right solution - Convergence
解決策の候補を出し切ったら、各々の候補を様々な切り口で評価してお客様にとって最適な真の解決策を特定します。評価軸はテーマによって異なるので一概に特定することは困難かと思いますが、一般的には1. 実装の難易度、2. 運用負荷、3. セキュリティ観点の安全性、4. 他社での実績が主な評価軸になるかと思います。お客様との十分な協議を経て真の解決策が特定できたら、再度発散思考に戻り、問題と解決策のギャップを洗い出します。どうしても埋められないギャップがある場合は、(製品ベンダーのビジネスにはなりませんが。。。)Consulting Firm様やSIer様が持っているであろう解決策をお客様にご紹介することも、場合によっては必要かもしれません。

# 参考
[The New Solution Selling - Chapter 7](https://www.amazon.com/New-Solution-Selling-Revolutionary-Changing/dp/0071435395)
[ギリギリまで「まとめに入らない」能力](https://chikirin.hatenablog.com/entry/20111124)
[Simon Sinek - Start With Why - TED Talk Short Edited](https://www.youtube.com/watch?v=IPYeCltXpxw)
【gulp エラー】Error: [object Object] is not a PostCSS plugin

## エラーが発生した状況

npm で autoprefixer を 9.8.6 → 10.2.1 にアップデートした

## 原因と解決法

> postcss being moved to peerDep
> [Error: [object Object] is not a PostCSS plugin · Issue #1358 · postcss/autoprefixer](https://github.com/postcss/autoprefixer/issues/1358)

`npm i --save-dev postcss` で postcss をインストールすると、エラーはなくなった
AWSのメニューと説明の一覧を手軽に取得できたから単語帳にしてみた

# はじめに
ほんとなんとなく思い立ったので、なんとなく作りました
100%自分用のメモです

# 成果物
https://ankilot.com/view/?pr=XMeFbkUKa8

# 手順

- AWSにサインインする
- AWSの上のメニューをひらく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/cf6b6121-4f80-cbca-087a-e4fa044b8b48.png)

- F12をおす
- consoleで下記を実行する

```
copy($$('._142-PMgGBA2POWI1QZQeIW').map(e=>[e.textContent,e.title].join(',')).join('\n'))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/368d7335-707a-9359-b9fe-3efc709e51a3.png)


- エディタにはりつける
- 2つめのEC2の上までは左の最近アクセスした履歴なので削除する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/96cc5429-8940-583b-ad75-effb923f4843.png)

- ファイル名をつけてCSVで保存する
- https://ankilot.com/ を開いて単語帳をつくる

おわり

# 補足

- 下記の3つは説明がありませんでした
  - Personal Health Dashboard
  - サポート
  - CloudShell

- ほんとはカテゴリも入れたかったのですが、うまい具合に手軽に取得できないのであきらめました
NoMethodError: undefined method `setup' for Devise:Module



#前提条件
- AWSなどPaaS関連の設定は完了済
- SQLも実装済
- Herokuにデプロイする

#エラー文

```ruby

rake aborted!
       NoMethodError: undefined method `setup' for Devise:Module

```

#結論
gem 'devise'をgroup develop testではなく、プロダクション環境の方に書く

#原因
リポジトリのconfig/environmentで、production、deveropment、testのrbファイルがあり、gemをgroupでくくるとproduction.rbでgemが使えなくなってしまう
【Laravel】composerインストール手順と注意点。composerコマンドを実行できるようにする。

Laravelのcomposerをインストールし、composerコマンドを実行できるようにする方法。


1. [（macの場合）homevrewとopensslのインストール](#1-macの場合homevrewとopensslのインストール)
2. [composer.pharのダウンロード](#2-composerpharのダウンロード)
3. [グローバルのパスを通す](#3-グローバルのパスを通す)
4. [composerコマンドの実行](#4-composerコマンドの実行)


<br>
##1. （macの場合）homevrewとopensslのインストール

composerをインストールするためにはopenSSLでの通信が必要だが、macOS 10.12 (Sierra) 以降の macOS では、 デフォルトで OpenSSL がインストールされていない。

opneSSLをインストールするためには、homebewというパッケージ管理ツールをインストールする必要がある。

<br>

```
#homebrewのインストール
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"


#opensslのインストール
brew install openssl
```

>[homebrew公式ページ](https://brew.sh/index_ja)



<br>
##2. composer.pharのダウンロード
composerの公式ページに沿ってcomposer.pharをローカル環境にダウンロードする。

```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
```

2行目のハッシュ値はバージョンがアップデートされるごとに変わるので、[公式ページ](https://getcomposer.org/download/)から最新版をコピー

実行が完了すると、ローカルにcomposer.pharが作成される。

```
$ ls
composer.phar
```

<br>
**▼注意点**
コードをコピーする場合は原文のページで行うこと。エラーが出てしまう場合は[こちら](https://qiita.com/yuta-38/items/7928ae719b8503bd10f1)を参照



<br>
## 3. グローバルのパスを通す
`composer`コマンドをどこからでも実行できるようにファイルをグローバルのパスが通ったディレクトリに移動する。

```
mv composer.phar /usr/local/bin/composer
```


<br>
##4. composerコマンドの実行

`composer --version`で、composerが実行できるかを確認。

```
$ composer --version
Composer version 2.0.8 2020-12-03 17:20:38
```

以上でcomposerのインストールが完了。
寿司のメニューから単品の価格とコスパを推定

近場のテイクアウトを頼むときに、どれがコスパが良いのか考えたときに面白そうだと思ってやってみました。
画像のメニューから目視で
https://docs.google.com/spreadsheets/d/1B7o0XhjEKsJZga1gsGqdMc6cFz92FreOfjuCiT-Uy58/edit?usp=sharing

にまとめ、n=14という状態なのでベイズで!
価格予測のモデル作成。カテゴライズしてないネタも多いのでほどほどで。ざっくりやるのでも
・低価格っぽいネタの個数
・中価格っぽいネタ
・高価格っぽいネタ
くらいはやったほうが良いかもしれません。
甘海老といくらは完璧に一致していたのでいくらにまとめました。土日、isテイクアウトを考慮しないと

price=342*(大トロ)+296*中トロ+189*赤身+302*いくら+40*興味がないネタ+61*その他+176

大トロ342円、中トロ296円は妥当な感じですね。

価格は本質的に指数関数だと思うけど、こういう明らかに足し算っぽい所の兼ね合いってどーなんでしょうね。
寿司みたいなのは、あきらかに和に分解できる（事が明白だから価格の指数関数性を出すとコスパの悪さがバレる）ので、
改善するにしても

log(price)=log(a1*x1+a2*x2+...)+eps

くらいでしょうか。


1-14の各メニューの残差
![c4cda7f9-8286-4f5a-a9af-66a25a2d38d7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38159/7fbd231d-6a12-56d7-8feb-860bf81b5593.png)

2000円付近未満のは、割ときれいに価格が上がるとコスパが悪くなる傾向が読み取れると思うんですけど！
２０００円付近以上も右上がりなので、もしかして価格帯ごとに、価格を上げると「まとめ買い」的にコスパが良くなるのではなく、むしろ逆で「稼ぎたい」力が働くのかもしれません。

私が買ったのはもちろん一番左の600円のテイクアウト。
順番通りにnewしないと落ちる謎コード

## 問題のコード

```php:a.php
<?php
require_once('b.php');
class A {
    public function __construct(){
        echo("A construct call\n");
    }
}

// この順番でコールしないと落ちる
$a = new A();
$b = new B();
$c = new C();

// この順番でコールすると落ちる
//$a = new A();
//$c = new C();
//$b = new B();
```

```php:b.php
<?php
class B {
    public function __construct(){
        require_once('c.php');
        echo("B construct call\n");
    }
}
```

```php:c.php
<?php
class C {
    public function __construct(){
        echo("C construct call\n");
    }
}
```

## 実行結果

```bash
$ php a.php
A construct call
B construct call
C construct call
```

```bash
$ php a.php
A construct call

Fatal error: Uncaught Error: Class 'C' not found in a.php:16
Stack trace:
#0 {main}
  thrown in a.php on line 16
```

## 解説

Bのコンストラクタにcのrequireが入っているのでBのインスタンスを立てないとCが呼び出せないようになっている。
今回の例で言うと関係のある3ファイルを見ればすぐ分かるが、実際のコードになり呼び出し関係が複雑になると状況が掴めず
「順番通りにnewしないと落ちる謎コード」
となる。

## 回避策

* オートロードを使いましょう
* 正しい位置・分かりやすい位置でrequireしましょう
https-portal productionで証明書が取得できない時 (Response Code: 403)


stagingではlet's encryptからテスト用の証明書を発行できるが
productionに変更しコンテナを立ち上げると以下の様なエラーが発生する

# エラー内容

```:https-portalコンテナのログ
Response Code: 403
Response: {u'status': 403, u'type': u'urn:ietf:params:acme:error:unauthorized', u'detail': u'An account with the provided public key exists but is deactivated'}
================================================================================
Failed to sign ドメイン名
Make sure you DNS is configured correctly and is propagated to this host
machine. Sometimes that takes a while.
================================================================================
Failed to obtain certs for ドメイン名
```

## レート制限かかっているかも？
https://crt.sh/
にてドメインでggっても証明書を発行した履歴が見つからない、、これ証明書発行できてないんじゃないか？


## ポート　DNSの設定を確認

一通りポート、DNSの設定を確認するも特にこれといったエラー項目は確認できず


# 解決方法
https-portalのリポジトリの[README.md](https://github.com/SteveLTN/https-portal)の説明を全て読んでみる

>Automatic Container Discovery
WARNING: WE STRONGLY RECOMMEND AGAINST USING THIS FEATURE UNLESS ABSOLUTELY NECESSARY as exposing Docker socket to a container (even with :ro) essentially gives the container root access to your host OS. If you insist, verify the source code carefully. Read more
HTTPS-PORTAL is capable of discovering other Docker containers running on the same host, as long as the Docker API socket is accessible within the container.


あれ、、もしかしてコンテナ検出できてない？

以下記載通りにvolumeの記述を変更してみる

```
services:
  https-portal:
    # ...
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro # DANGEROUS, see the warning above
```


コンテナを再度立ち上げログを確認しつつ数分待ってみる


証明書が取得できました！！！！
Raspberry pi4へNode.jsのインストール手順

#npm init -yでエラーが出る、、、

LINEBOTを作成してみようと思い、常時稼働させられるラズパイにNode.jsのインストールを試みた。
その中で初歩的な内容だが、インストール時にまとまってあれば嬉しかったなぁと思う気持ちで備忘録として残す。

そもそものNode.jsのインストールしようと思った流れは、
npmはインストールされていたが、npm init -yでエラーが出る、、、
Node.jsが適切にインストールされていないようだな、うん。

では、手順の説明です。

##npmのアップデート
npmが入っていないときは以下のコードをターミナルにて実行。

```
$ sudo apt-get npm
```

次に、アップデート後に変化を確認するためにnpmのバージョンを確認。
以下のようにバージョンが出力されるのを確認する。

```
$ npm -v
6.14.10
```
さいごに、npmのアップデートを行う。

```
$ sudo npm update npm
```
これでnpmのアップデートは完了する。

次にNode.jsのインストールに移る。
**Node.jsをインストールするためのバージョン管理ツールnを使った方法もあるようだが、自分はここで詰まって面倒になり諦めた。**

詰まった内容としては、

* そもそもnがなかった(入れはしました)
+ Node.js と npmに決まった対応があり、その設定がnでは死ぬほど面倒だった(決定的理由)

実際のバージョンの対応は[Node.jsとnpmの対応表](https://nodejs.org/ja/download/releases/)を参考にしてください。

なので、**Node.jsのインストールとnpmとのバージョン対応を同時に行ってくれるnodebrew**を使用する。

##nodebrewのインストール

nodebrewのインストールには以下のコードを実行してください。

```
$ curl -L git.io/nodebrew | perl – setup
```
ここで、私のラズパイではあるローカルフォルダへアクセス許可がありませんとエラーが出てしまいました。
同じような場合には、

```
#777は「所有者」「所有グループ」「その他」に読み書き実行を許可します
$ chmod 777 エラーが起きている箇所
```
で解決できます。
その他にまで読み書き実行を許可しているので気をつけてください。
権限付与に関しては[こちらの記事](https://qiita.com/shisama/items/5f4c4fa768642aad9e06)で確認できます。

次にPATHを通します。

```
#パスを通す、任意のエディタで開きます(ここではvi)
$ vi ~/.bash_profile
```

任意のエディタで開いたら
`export PATH=$HOME/.nodebrew/current/bin:$PATH`
と入力して保存してください。
viの操作コマンドは[こちら](https://prev.net-newbie.com/linux/commands/vi.html)を参考にされると良いかと思います。

ちゃんとインストールできたかを確認します。

```
nodebrew -v
```
いろいろ出ますが、nodebrew 1.0.1 のように出ればOKです。

##Node.jsインストールとnpmとのバージョン対応付け
最後に、Node.jsをインストールし、対応付けます。

```
#バージョンは偶数番目が安定しているようです。
nodebrew install 任意のバージョン

#使用するNode.jsバージョンを選択。同時にnpmの対応も行われる。
nodebrew use 任意のバージョン
```

Installed successfullyと出れば終了です。

ここまで設定することで、npm init -y もエラーなく動作しました。
非同期でコメント機能作ってみた

今回は非同期通信を用いたコメント機能を実装していきたいと思います:eyes:

##前提
・コントローラー作成済み
・モデル作成済み
・リレーション設定済み

##それでは実装していきましょう:blush:
①viewを作成

```rudy:views/comments/_comment.html.erb

  <p>コメント件数：<%= pet.comments.count %></p>
    <% pet.comments.each do |comment| %>
      <%= comment.user.full_name %>
        <%= comment.created_at.strftime('%Y/%m/%d') %><%= simple_format comment.comment %>
          <% if comment.user == current_user %>
            <div class="comment-delete">
              <%= link_to "削除", pet_comment_path(comment.pet, comment), method: :delete, remote: true %>
            </div>
          <% end %>
    <% end %>
    <div class="new-comment">
      <%= form_with(model:[pet, comment], remote: true) do |f| %>
        <%= f.text_area :comment, size:"90x5" ,placeholder: "コメントをここに" %>
          <%= f.submit "送信する" %>
      <% end %>
    </div>
```

②作成した部分テンプレートを呼び出す

```
 <div class="comments_<%= @pet.id %>">
     <%= render 'comments/comment', pet: @pet, comment: @comment %>
 </div>
```

③コントローラー編集

```
class CommentsController < ApplicationController
  def create
    @pet = Pet.find(params[:pet_id])
    comment = Comment.new(comment_params)
    comment.user_id = current_user.id
    comment.pet_id = @pet.id
    comment.save
    @comment = Comment.new
  end

  def destroy
    @pet = Pet.find(params[:pet_id])
    Comment.find_by(id: params[:id], pet_id: params[:pet_id]).destroy
    @comment = Comment.new
  end

  private

  def comment_params
    params.require(:comment).permit(:comment)
  end
end
```

④ jQueryの記述

```
rudy:comments/create.js.erb
$(".comments_<%= @pet.id %>").html("<%= j (render 'comments/comment', pet: @pet, comment: @comment) %>");
$("text_area").val("");
```

```rudy:comments/destroy.js.erb
$(".comments_<%= @pet.id %>").html("<%= j (render 'comments/comment', pet: @pet, comment: @comment) %>");
```

##注意::raising_hand:
部分テンプレートを呼び出したviewのコントローラーに

```
@comment = Comment.new
@comments = Comment.all
```
を記述するのを忘れないように！
これがないとコメントを呼び出せないよ:wink:

以上で非同期コメント完成！！
Serverless Frameworkにおける環境変数の外部ファイル化の一例

```json:/conf/dev/dev.json
{
  "Other_File": "Development environment"
}
```

```ts:serverless.ts

import type { AWS } from '@serverless/typescript';

// 関数間で共通の環境変数はこちらに定義
const commonEnvironmentVariables = {
  Other_File: "${self:custom.otherfile.${self:provider.stage}.Other_File}",
};

const serverlessConfiguration: AWS = {
  service: "create-category-collections-api",
  frameworkVersion: "2",
  custom: {
    webpack: {
      webpackConfig: "./webpack.config.js",
      includeModules: true,
    },
    otherfile: {
      dev: "${file(./conf/dev/dev.json)}",
      stg: "${file(./conf/stg/stg.json)}",
      prd: "${file(./conf/prd/prd.json)}",
    },
  },
  // Add the serverless-webpack plugin
  plugins: ["serverless-webpack", "serverless-jest-plugin"],
  provider: {
    name: "aws",
    runtime: "nodejs12.x",
    apiGateway: {
      minimumCompressionSize: 1024,
    },
    environment: {
      AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1",
      ...commonEnvironmentVariables,
    },
    region: "ap-northeast-1",
    stage: "${opt:stage, self:custom.defaultStage}",
  },
  functions: {
    hello: {
      handler: "handler.hello",
      events: [
        {
          http: {
            method: "get",
            path: "hello",
          },
        },
      ],
    },
  },
};

module.exports = serverlessConfiguration;



```

## 参考
Serverless Frameworkで環境変数を外部ファイルから読み込み、環境毎に自動で切り替えてみる
https://dev.classmethod.jp/articles/serverless-framework-conf-change/
M5Stackシリーズ製品をArduinoIDEで使う

マイコンの開発環境は日々変化するものですが、みんな大好き[M5Stack](https://m5stack.com/)シリーズも、ものすごく変化が早い製品の一つです。あまりに変化が早すぎて、販売元はおろか、公式サイトの情報が古いままだったり、公式なアナウンスがないまま知らない間に更新されているサイレントアップデートもしばしばで、また個人が公開している情報がいつの間にか本家に取り込まれたりしたり、Web上の情報も新旧入り交じって、どれを信じていいのか、わからなくなることもしばしば。また公式サイトも専門用語が満載で、それがわからないと、どこから手を付けていいかと心が折れそうになることもしばしば。
ここでは、M5StackシリーズをArduinoIDEで使うための初期設定について、2021/1/12現在の（たぶん）最新＆一番確実と思われる情報をまとめておきます。

#基本的な流れ

少なくとも2021/1/12現在は、[M5StackCore2のQuickStart](https://docs.m5stack.com/#/en/arduino/arduino_core2_development)が、一番最近で正しい情報のようですので、基本的にはこの手順でいきます。

1. ArduinoIDEを導入（すでに導入済みの場合はそれを使えばOK）
2. USBドライバのインストール（すでに導入済みの場合は何もしなくてOK）
3. ボードマネージャのURLを追加
4. ボードマネージャからM5Stack関連をインストール
5. ライブラリをインストール
6. サンプルを参考にプログラムを書く

以下、順に。

# 1.ArduinoIDEを導入

[Arduino公式](https://www.arduino.cc/)のArduinoIDEをインストールしておきます。

# 2.USBドライバのインストール

[M5Stackのダウンロードサイト](https://m5stack.com/pages/download)から、USBドライバである"CP2104 Driver"をダウンロードし、インストールしておきます。

# 3.ボードマネージャのURLを追加

ArduinoIDEを起動し、ファイル(File)→環境設定(Preferences)を開く。![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457605/ce8d70e6-6a44-cb3f-b0de-f6b807385ce2.png)

ここの「追加のボードマネージャURL」のところに、以下の文字列を追加し、OKで保存

> https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json

# 4.ボードマネージャからM5Stack関連をインストール

ArduinoIDEの、ツール(Tools)→ボード(Boards)→ボードマネージャ(Board Manager)へ進み、ボードマネージャを開く。

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457605/5e70fca1-86d0-e9e7-fbba-0a911bf787e4.png)

上の検索窓に"m5stack"と入力し、出てくる"M5Stack official"をインストールする。コンパイラ一式をダウンロード・インストールするので結構時間がかかる。終わったらボードマネージャを閉じる。

# 5.ライブラリをインストール

ArduinoIDEの、スケッチ(Sketch)→ライブラリをインクルード→ライブラリを管理、からライブラリマネージャを起動する。ライブラリマネージャの検索窓で"m5stack"を入力し、M5Stack製品にあわせて以下を選んでインストール。（非公式ライブラリがいろいろ出てくるが、"by M5Stack"など、byのところの名前に"M5"がついている公式版を選ぶのがよさそう）

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457605/e8ae0632-334d-5fa4-3358-64163a68d005.png)

- Core (Basic/Gray/Fire/GO等): "M5Stack"
- Core2: "M5Core2"
- StickC: "M5StickC"
- StickCPlus: "M5StickCPlus"
- ATOM: "M5ATOM"
- CoreInk: "M5-CoreInk"
- Paper: "M5EPD"

※CoreInkとPaperのライブラリはGitHubにもあり、shutdown()等は、そのGitHubのライブラリを別途インストールしないと使えないようです（2021/1/13時点）。正確に言うと、ライブラリマネージャから入れられるライブラリが最新でない場合があり、最新でないとビルド時にエラーが出るものがあります。そんなときは、GitHubから最新版をCode→ZIPでダウンロード、して、ArduinoIDEのライブラリマネージャで「zip形式でインストール」からインストールします。→[CoreInkライブラリ](https://github.com/m5stack/M5-CoreInk) / [Paperライブラリ](https://github.com/m5stack/M5EPD)

# 6.ボードを選び、サンプルを参考にプログラムを書く

ArduinoIDEのツール(Tools)→ボード→”M5StackArduino"から、使うM5Stackシリーズを選ぶ。

![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457605/35c09b26-cfe3-14e6-26b3-c0b90b83293e.png)

そのあとで、ファイル→スケッチ例、から、各デバイスごとのスケッチの例があるので、それを参考にプログラムを書く。例えばM5StackBasicなら、"M5Stack"（ボードマネージャで選んだ名前）内にある。
【初学者向け】Nginxって？　

#はじめに
未経験からWeb系エンジニア職へ転職活動を行っています。企業との面談中に出てきたNginxというワードに聞き馴染みがなく震えたので今回まとめました。筆者は違いを意識せずApacheを使っていたのであまり馴染みがなかったようです。。

##Nginxとは
Webサーバーの一種。Webサイトを公開する時に様々なサーバーが動いているが、その中心になるのがWebサーバーである。Webサーバー用のソフトウェアには、種類と得意分野がある。以前まではApacheが有名で多く利用されていたが、近年ではNginxも注目されており、2020年8月時点のWebサーバーのシェアは第1位Nginx(36.45%)、第2位Apache(25.87%)となっていて、目覚ましい成長がある。
参考：https://news.netcraft.com/archives/2020/08/26/august-2020-web-server-survey.html

>ミドルウェア：
コンピュータを制御するオペレーションシステム（OS）と、特定の処理を行うアプリケーションソフトウェアとの間に存在するソフトウェアのこと。

>Webサーバーソフトウェア：
ミドルウェアの一つ。HTTPリクエストを送った後に、何かしらのレスポンスを返すプログラム。


##NginxとApacheの比較
###Nginx（エンジンエックス）

- オープンソースソフトウェア(OSS)
- Apachと比較して、Nginxは高速かつ高負荷に強い
- C10K問題をはじめ、大容量のデータ配信や大量同時接続に耐えることを目的に設計された。
- ノンブロッキングI/Oと非同期のイベント駆動アーキテクチャを採用することで、Apacheと比較して同時接続数が10〜100倍くらいになる。→Nginxはworkerと呼ばれるシングルスレッドのプロセスを複数利用している

###Apache（アパッチ）

- 正式名称は「Apache HTTP Server」
- オープンソースソフトウェア（OSS）
- マルチプロセスモデル（接続毎にプロセスをフォーク）のため、メモリがいっぱいになりやすい
　→リクエストを処理するごとにリソースが枯渇してしまう
- CMS(Contents Management System)を利用する際に、比較的簡単な設定で済む
- 約20年間OSSとして公開され、バージョンアップした結果、信頼性が高い


>・オープンソース：
WordPressのようにプログラミングを無料で利用でき、自由にカスタマイズができる。

>・C10K問題:
Apache HTTP ServerなどのWebサーバソフトウェアとクライアントの通信において、クライアントが約1万台に達すると、Webサーバーのハードウェア性能に余裕があるにも関わらず、レスポンス性能が大きく下がる問題
参考：https://qiita.com/katu_/items/01c9c35d17a541014d32

>・イベント駆動型アーキテクチャ:
変化に適応できてリアルタイムで意思決定できる、柔軟なシステムを組織が達成できるよう支援します。リアルタイムで状況を把握できるので、システムの現状を表すすべての利用可能なデータを使用して、手動または自動でビジネス上の意思決定を下せます。 
参考：https://www.redhat.com/ja/topics/integration/what-is-event-driven-architecture
>・シングルスレッド
コンピュータのプログラムは、基本的に1行ずつコードが実行されながら動作する。通常、分岐やループがあっても、プログラム全体は1つの流れになっている。このような一連のプログラムの流れを「スレッド（糸）」と呼ぶ。1つのスレッドだけからなるプログラムを「シングルスレッドなプログラム」という。一方、処理効率を上げるなどの目的で1つのプログラムで複数のスレッドを同時に実行することができる。これを「マルチスレッド・プログラム」という。
参考：https://www.atmarkit.co.jp/ait/articles/0503/12/news025.html




##Nginxが向いている分野

- 一般向けのWebサービスなど多数の同時アクセスが発生する業務
- 静的コンテンツが多いWebサービスなど

>静的コンテンツ：
静的コンテンツは、index.html などのように、要求のパスに指定されたhtmlなどのデータがそのまま応答のデータとして送信される方式のWebページのことです。誰が見る場合でも常に同じ内容を提供する場合に使われます。
参考：静的コンテンツと動的コンテンツ
http://juen-cs.dl.juen.ac.jp/html/www/005/

##NginxとApacheの使い分け

###Nginxの場合

- 負荷が高く、スケーラビリティが要求される
- 静的ページに同時多数のアクセスが想定される

###Apacheの場合

- 負荷が低く、早期または簡単なセットアップが必要
- 同時アクセス数が小さく、リクエスト数が多い

参考：
・https://www.out48.com/archives/1576/
・https://qiita.com/kamihork/items/49e2a363da7d840a4149

#おわりに
Nginxを実際に触ったことがないため、あまり深くまでApacheとの比較はできませんでした。
今後の学習で、この記事に深みを出していきます。
（もしこの記事に誤りがありましたらご教授いただけると幸いです。）
Unreal Game Sync環境構築

## Unreal Game Sync(UGS)とは
[UnrealGameSync(UGS)](https://docs.unrealengine.com/ja/ProductionPipelines/DeployingTheEngine/UnrealGameSync/index.html)
Fortniteの開発チームがエディタ配布のための作ったツールのようです。

## 最低限の環境
* ソースファイルなどのバージョン管理に[Perforce](https://www.perforce.com/products/helix-core)
* UE4 Engineソースそのもの(UGSのソースはEngine\Source\Programs\UnrealGameSyncに入ってる)

## すべての機能を使うための環境(メタデータサービス)
* IIS(Internet Information Services)およびWeb Deploy
* Windows Server (IISのWeb Deploy機能を使うために必須と思われる)
* MySQL8.0
* VisualStudio2017(以上？)(UGSビルドするのに必須)

---

# Perforce環境
* Perforceサーバー環境構築やらユーザー作成は割愛
* Depotに関してはStream Depotが必須と思われる(バイナリビルドアップ用)
    * Binaries(Stream)
    * depot(ソース置き場)
* depot以下に
    * Bat
    * UnrealEngine-4.26
        * Engine自体
        * UE4自身のプロジェクト置き場(FirstPerson)
    * UnrealGameSync(UGSビルドされたのを置く場所…自動配信用)

※EngineとUE4自身のプロジェクト置き場は同一フォルダに置くのが多分必須(メタデータサービスで必須と思われる)

# UGS
* Engine\Source\Programs\UnrealGameSync\UnrealGameSync.slnがプロジェクトの場所
* DeploymentSetting.cs
    * `DefaultDepotPath`を`"//depot/UnrealGameSync"`に(PerforceのUGS置く場所のURI)
    * (メタデータサービス使うなら)`ApiUrl`を`"http://IISのURL/"`に
* ビルドしたら

```
//depot/UnrealGameSync/Release/UnrealGameSync.exe
//depot/UnrealGameSync/Release/UnrealGameSync.exe.config
//depot/UnrealGameSync/Release/UnrealGameSync.pdb
//depot/UnrealGameSync/Release/Ionic.Zip.Reduced.dll

//depot/UnrealGameSync/UnstableRelease/UnrealGameSync.exe
//depot/UnrealGameSync/UnstableRelease/UnrealGameSync.exe.config
//depot/UnrealGameSync/UnstableRelease/UnrealGameSync.pdb
//depot/UnrealGameSync/UnstableRelease/Ionic.Zip.Reduced.dll
```
こんな感じに配置(コピーやら移動させるのが面倒ならビルドされたところを指定してもいいと思う)

* P4V(Perforceクライアント)を起動させてからUGSを起動する(あとはUGSリファレンスのとおりに設定すればいい)
※ビルドする際に色々エラー出る時があるので必要なものをインストールする(.Net Frameworkとかだったはず…ぐぐったら解決する)

## MySQL8
* [MySQL Windows Installer](https://dev.mysql.com/downloads/installer/)を落としてきてServerをインストール
* UGSのメタデータサービスで使うようのアカウント作成

## IIS
* Web Deployサービスが必要なのでWindows Server必須
* IISのインストールは
    * [リモートのIISへVisual StudioからWebアプリをWeb Deployする](https://www.nuits.jp/entry/iis-web-deploy)
* Web Deployに関しては
    * [Web 配置発行の Web サーバーを構成する (Web 配置ハンドラー)](https://docs.microsoft.com/ja-jp/aspnet/web-forms/overview/deployment/configuring-server-environments-for-web-deployment/configuring-a-web-server-for-web-deploy-publishing-web-deploy-handler)
を参考にすれば良い
※IISのWeb 配置による発行の有効化のための処理である右クリックー＞展開が出ないので調べたら Web Deploy3.6ではだめで3.5だと大丈夫とかいう情報あったけど、3.5でもだめで結局上記サイトの通りにやったら3.6でも問題なく出るようになった(OS自体再起動したほうがいい)

## MetadataServer
* GSプロジェクトにMetadataServerプロジェクトがあるので
    * ビルドするとエラーが出るのでMetadataServer直下に`NotForLicensees\Web.config`を作る
    * Web.template.configの`ConnectionString`をMySQLで作ったアカウントにする＆サーバーのIPを指定する
    * ビルドする
    * MetadataServerプロジェクト右クリック->発行でWebアプリを配信する
    * MySQLに`ugs_db`というデータベースができてたら成功(配信されたらブラウザが開くのでエラー出てなかったら成功)

---

資料があまりにもなくて環境構築に手間取った…まとめたら大したこと無いので辛い…
Ruby on Rails <2021年> かんたんログイン機能の実装（form_with）

###前提条件
- gem 'devise' でログイン機能を実装していること
- 新規登録で mail: guest@guest, password: 111111で登録していること

```
 <%= form_with(model: User.new, url:new_user_session_path) do |f| %>
   <%= f.hidden_field :email, value: "guest@guest" %>
   <%= f.hidden_field :password, value: "111111" %>
   <%= f.submit "ゲストログイン", class:"btn btn-success btn-sm mb-3 btn-block guest"%>
<% end %>
```

ゲストログインがクリックされるとログイン画面へ行き、
valueの中のemailとpasswordが入り
ログインした画面へリダイレクトされます。