OmniAICreator/Qiita-1.07M huggingface dataset:
DNS勉強まとめ


###DNSサーバ

#####/etc/named.conf　設定ファイル
#####named.confのステートメント
zone　　ドメインの範囲
options　動作の詳細
include　外部ファイルの読み込み
acl　アクセスを制御するアドレス
controls　rndcコマンドの使用者
#####optionsステートメント
directory　　作業ディレクトリ
forwarders　　転送先DNSサーバ
forward　　　問合せ失敗時の動作　　　
allow-query　　問合せの受付ホスト
allow-transfer　ゾーン転送を許可するホスト
allow-recursion　　再帰問合せを受け付けるホスト
blackhole　　受け付けないホスト
#####その他記述
recursion no;   再帰問合せを禁止
version　　　バージョンの問合せに返す任意の文字列(バージョン隠ぺい)
#####コマンド
BIND の /etc/named.conf とゾーンファイルの変更内容を反映させるコマンド３つ
/etc/init.d/named restart
kill -HUP プロセスID
rndc reload

named-checkconf　　named.confの構文チェックをする

rndc    namedの管理をローカルとリモートから行う
rndc status   namedの状態を表示
rndc reload   ゾーンファイルの再読み込み
rndc halt　　　直ちにnamedを停止する
rndc stop　　　更新を保存してnamedを停止する

DNSを利用し、ホスト名をIPアドレスに変換するコマンド３つ
 dig   DNSに対してクエリを発行、詳細な情報が得られる
 host
 nslookup


#####DNSソフトウェアの種類
dnsmasq  キャッシュサーバとDHCPサーバの機能を持つ
djbdns   キャッシュサーバとコンテンツサーバの機能が分かれている、RDBは使用できない。
PowerDNS   RDBをデータベースとして使用できる

#####DNSに必要な設定ファイル２つ
/etc/nsswitch.conf 　名前解決を行うように設定する
/etc/resolv.conf 　　DNS サーバを設定する

#####ポート番号
DNSサーバが使用するポート番号：53

・ゾーンファイルのホスト名に「.（ピリオド）」を付け忘れると名前解決コマンドの実行結果に「56.168.192.in-addr.arpa」が表示される。

#####ゾーンファイルのディレクティブ
$ORIGIN	      FQDNでない場合にドメイン名を補完する
$TTL	      キャッシュの有効時間(秒)

#####ゾーンファイルのレコード (リソースタイプ)
SOAレコード     DNSサーバ名と管理者のメールアドレス
NSレコード	DNSサーバ名
Aレコード	各種サーバのIPアドレス(正引き)
MXレコード	メールサーバ名
CNAMEレコード	別名
PTR		 逆引きをするホスト名

#####ゾーンファイル記述におけるサーバの優先順位
リソースタイプの右側の数字は優先順位を表し、低いほど優先順位が高い。

named-compilezone コマンド  スレーブサーバのゾーンファイルをテキスト形式に変換する

masterfile-format text; ゾーンデータをテキスト形式に変換する記述
named.conf の zoneステートメントに記述する

NXDOMAIN
 DNSサーバは、名前解決ができない場合に「存在しない（NXDOMAIN）」というエラー表示


dnssec-keygen -n ZONE  DNSSECで公開鍵と秘密鍵を作成するコマンド
dnssec-keygen -n HOST   TSIGで共通の秘密鍵を作成するコマンド

dnssec-signzone    　DNSSECでゾーンファイルへ署名するコマンド

named -t /chroot -u uhoge -g ghoge     named を chroot環境で起動するコマンド

DNSSEC 
公開鍵暗号方式により、正当なDNSサーバである事を認証し、ゾーン情報が改竄されていないことを保証する技術

TSIG
マスターDNSサーバとスレーブDNSサーバに共通の秘密鍵を設定して、ゾーン転送、rndcコマンドの操作のなりすましを防ぎ、更新データの完全性を保証する技術

TSIGを使用する為、マスターDNSサーバとスレーブDNSサーバに共通の秘密鍵を設定する場合の /etc/named.conf のステートメントの書式
なお、設定するドメインを zzzzz.com 秘密鍵を xxxxx とする。
key "zzzzz.com" {
algorithm hmac-md5;
secret secret "xxxxx"
}; 

-TSIGで使用する共通鍵を作成するコマンド
dnssec-keygen -n HOST

-dnssec-keygenで、暗号化アルゴリズム、鍵ビット長、タイプ、鍵の名前を指定してTSIG用の鍵を作成するコマンド
dnssec-keygen -a 暗号化アルゴリズム -b 鍵ビット長 -n タイプ 鍵の名前
 
-TSIG
共通の秘密鍵 でDNSメッセージ全体の署名を行う
クライアントとサーバの時刻が合っていなければならない

-マスターDNSサーバとスレーブDNSサーバ間のゾーン転送にTSIGを使用する場合に両サーバの「/etc/named.conf」に必要な設定
keyステートメントに共通鍵を設定する
serverステートメントにお互いのIPアドレスと共通鍵を設定する

-DANE
DNS-based Authentication of Named Entitiesの略で、DNSを使った認証の仕組み
X509の証明書とDNSを紐づける
Bootstrap[column]についての気付き

# Columnについて勘違いしていたこと
offsetで調整したものは左右に均等に配分されるわけではない。
例）col-10 offset-1は左に空のカラムを追加するだけ。結果的には１、１０、１になって1列に合計12カラムで中央よせみたいになるだけ。

rowは１列にしたいときに外をこれで囲う。あとrowにjustify-content-aroundをつけると中央よせとなる。

## 新たに知ったこと
col-es(extra small)は指定できないのでcolー？で指定する。なので他のサイズを指定しておく必要がある。

## なんかおかしいこと
marginがleftにかかってることが多いなんか毎回margin:0にしてる気がする。
【nxut.js, heroku】ローカルで修正後、再デプロイしても反映されない場合の解決方法

#herokuへの再デプロイで詰まったこと
nuxt.jsでSPAアプリを作りデプロイした後、ローカルで修正してデプロイしても変更が反映されないことがあったので解決した方法を記します。

##背景
・フロントエンドをnxut.jsを使って作成
・バックエンドをRailsで作成
・両方herokuへデプロイ
・nuxtをローカルで修正、再デプロイ
・問題発生

##問題
両アプリの通信確認ができた後、nuxtをローカルで修正し再デプロイしたら変更点が反映されていなかった。

##解決した方法
ローカルでnuxt修正後、再デプロイする前に下記コマンドを実行した。

`$ yarn generate`

その後herokuへ再デプロイしました。
`$ git push heroku master`

これで解決できました。

##その他試して、効果がなかった方法
①Procfileに下記を追記
` web: yarn generate`

②ブラウザのスーパーリロード
下記サイトを参照ください
https://us-key-tech.hatenablog.com/entry/2016/12/26/190000

③herokuからアプリを削除後再度デプロイ
herokuへのnuxtアプリのデプロイ方法
https://qiita.com/saima88/items/bfab82202ccbf58c4a63

④herokuデプロイ時のURLを変更してデプロイ
`$ heroku create (ここを変更)`

⑤heroku再デプロイ
下記コードの再デプロイだけでは、どうも更新されないようです。
`$ git push heroku master`

↓再デプロイで苦労したアプリ
https://amaimon-decision.herokuapp.com/
Gateway Load Balancer とは

## 勉強前イメージ

ALB作る時に新しいの見つけた。
なんのやつなんだろう

## 調査

### gateway load balancer とは

AWS Gateway Load Balancer 、略して GWLB は
元々サードパーティのセキュリティ製品などをAWSで利用する場合はNLBやVPC Peering、NATして連携したりしていました。
GWLBとGateway Load Balancer Endpoint(GWLBE) を利用することで
スケーラブルで可用性の向上を図ります。

下記はロードバランサー作成時の画面です。
新しくGateway Load Balancerが追加されているのが確認できると思います。

![1ロードバランサーの作成 _ EC2 Management Console - Google Chro.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/4fba5b43-4bff-b21c-c010-51715178acef.png)

### 構築のイメージ

左側がアプリケーションサーバが設置されてるVPC、右側がセキュリティ製品が設置されているVPCになります。
2つのVPCをGWLBとGWLBE(Gateway Load Balancer Endpoint)でつなぎます。
PrivateLinkなので、CIDRが重複しても問題ないです。

![1# gateway load balancer とは - diagrams.net - Google.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/9995fcc5-8e39-8dff-a479-d258196a96fa.png)

### 特徴

- LBなのでスケールを行うことができ、可用性を実現
- 異なるVPCやAWSアカウント間で共有が可能

## 勉強後イメージ

新しいの出来てるなーって思ってた。
サードパーティのセキュリティ製品入れるときとかによいのね。

## 参考

- [AWS Gateway Load Balancerが東京リージョンに対応しました](https://aws.amazon.com/jp/blogs/news/aws-gateway-load-balancer-tokyo/)
- [[新サービス]セキュリティ製品等の新しい展開方法が可能なAWS Gateway Load Balancerが発表されたので調査してみた](https://dev.classmethod.jp/articles/introducing-aws-gateway-load-balancer/)
- [[AWS Black Belt Online Seminar]AWS Gateway Load Balancer](https://d1.awsstatic.com/webinars/jp/pdf/services/20210331_AWS-Blackbelt_GatewayLoadBalancer.pdf)
pi picoでmicropython その24

#概要

picoでmicropythonやってみた。
sha256やってみた。

#サンプルコード

```

import uhashlib
import ubinascii
text = b'\x61\x62\x63'
print("in: abc")
hash = uhashlib.sha256(text).digest()
print(ubinascii.hexlify(hash))
text = b''
print("in: ")
hash = uhashlib.sha256(text).digest()
print(ubinascii.hexlify(hash))
text = b'\xd3'
print("in: d3")
hash = uhashlib.sha256(text).digest()
print(ubinascii.hexlify(hash))
text = b'\x11\xaf'
print("in: 11af")
hash = uhashlib.sha256(text).digest()
print(ubinascii.hexlify(hash))


```

#結果

```
in: abc
b'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'
in:
b'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
in: d3
b'28969cdfa74a12c82f3bad960b0b000aca2ac329deea5c2328ebc6f2ba9802c1'
in: 11af
b'5ca7133fa735326081558ac312c620eeca9970d1e70a4b95533d956f072d1f98'



```

#実行手順

cd csc
pico3
プログラムをコピー
ctrl+e
ctrl+v
ctrl+d

以上。
iOSにてFCMを用いたPUSH通知受信サンプル実行録

謎にハマる部分がいくつかあったため、備忘録として残しておく。

## 1. プロジェクトのコピー

https://github.com/firebase/quickstart-ios/tree/d5132bde0b9098f464c7ab10fa9f022979a9cfa4/messaging

こちらのリポジトリをとりあえずコピー、pod installまでしておきましょう。

## 2. アプリの情報をFirebaseのコンソールに登録
1. Firebaseのコンソール画面にいく
1. プロジェクトの概要右の歯車→プロジェクトの設定
1. マイアプリよりアプリを追加を選択
1. 1.にてコピーしたプロジェクトのbundleIDがそのままだと```com.google.firebase.quickstart.MessagingExample```だったはず。このままだとビルドできないので```com.google.firebase.quickstart.MessagingExample.abc```のように変更してビルドできることを確認する。（確か同じbundleIDのアプリはこの世に存在してはいけないからとか、そんな理由かと）
1. （このタイミングでは```GoogleService-Info.plist```を入れていないので、ビルド後すぐクラッシュすると思われるがOK）
1. とりあえずビルドできることを確認したら設定したbundleIDをアプリの追加の「iOSバンドルID」のところに入力する。![スクリーンショット 2021-05-16 9.56.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262470/62308c2b-a377-b359-9d34-d52cae573dfa.png)
1. アプリ登録完了

## 2. Firebaseの情報をアプリに登録
1. プロジェクトの概要右の歯車→プロジェクトの設定
1. マイアプリに登録したアプリが追加されているか確認
1. その中に```GoogleService-Info.plist```なるボタンがあると思うので、それをダウンロード
1. ダウンロードしたらXCode上にぶち込む![スクリーンショット 2021-05-16 9.59.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262470/ca1b77b6-58c2-3230-1f27-45c4fd85fd1b.png)
1. ビルドが普通に通ることを確認する。（さっきクラッシュしてたところが通るはず）

## 3. APNsの認証キーを作成する

1. Apple Developer Programに登録する（12980円！）
1. メンバー画面に飛び、Certificates, Identifiers & Profiles→Keysを選択
1. Keyの名前を適当につける。（pushFirebaseExampleみたいな）
1. Apple Push Notifications service (APNs)にチェック入れてContinue,Registerする
1. 認証キーをダウンロードする。（二度とダウンロードできないらしいので注意）
1. このとき画面に書いてあるKeyIDをメモ ※1


## 4. Firebase上にAPNs情報を登録する
1. プロジェクトの概要右の歯車→プロジェクトの設定
1. Cloud Messaginを選択
1. マイアプリから先ほど作成したアプリのAPNs認証キーというものが空白のはずなので選択
1. ここに先ほどの認証キーをアップロード。
1. キーIDには※1にてメモしておいたKeyIDを入力
1. チームIDにはApple DeveloperのMembershipページ→Team IDとあるところを入力
1. アップロードする

## 5. テストする

1. FirebaseにてCloud Messagingを選択
1. 通知を作成
1. アプリの選択は作成したサンプルアプリを選択
1. 送信!![IMG_2337.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262470/7c4b6242-883a-cc21-65f2-a6c35b85dffc.jpeg)

できた！


実際にアプリに導入する際にはこのサンプルアプリでの動作を確認&[公式ドキュメント](https://firebase.google.com/docs/cloud-messaging/ios/first-message?authuser=0)を確認しつつやると少しはやりやすいかな、と思います。

本来であれば公式ドキュメントのみですらすら終えるつもりが・・中々時間がかかってしまった。

あまりに初心者だったため、「チームID？　何設定してもええやろ」と思って設定したので困ってました。

引き続き開発に勤しみます。
OpenShift OKDでOperatorHubの追加

# OpenShift (OKD) で、OperatorHubの追加
OpenShift (OKD) で OperatorHubを開くと、Communityのものしか表示されておらず、
RedHatが提供しているものや、Certificateされているものが表示されておりません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/7e43bd8a-4f94-7e42-96c0-bbcaec04ef13.png)

## 原因
この原因は、以下のいずれかの場合と想定されます。

- 1. OKDのインストール時にpull-secretを`fake`にした
- 2. yamlで`disable`されている
- 上記の両方

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/5d35cfe1-6ccf-14a2-587b-5a5644041bec.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/18d66b97-be94-4cdc-51b8-9ca2b987cc1a.png)

## 1. pull-secretのアップデート
RedHat提供のものや、CertificateされているOperatorを利用する場合は、RedHatが提供する`pull-secret`を利用する必要があります。

### 1.1 pull-secretの入手
以下のURLにアクセスし、pull-secretを入手します。
https://cloud.redhat.com/openshift/install/pull-secret

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/c204fb37-d47b-c44e-25c9-d116b200bf39.png)

### 1.2 pull-secretの更新
以下のコマンドで、openshift-configのpull-secretを1.1で入手したpull-secretに置き換えます

```shell
oc set data secret/pull-secret -n openshift-config --from-file=.dockerconfigjson=./pull-secret.txt
```

## 2.OperatorHubの設定変更
### 2.1. グローバル設定
左のメニューから`管理`->`クラスター設定`を開き、`グローバル設定`のタブを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/61ec2fd7-4439-865b-f071-543044f8c28a.png)

### 2.2. yamlの編集
2つめの`yaml`タブを表示し、`.spec.disableAllDefaultSources`の`true`をコメント化し、
`.spec.disableAllDefaultSources : false`を追加します。(段落注意)
次に`.spec.source`の一覧もコメント化し、`保存`を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/28abf140-30e6-7503-1771-9015841eb78b.png)

## 3. OperatorHubの反映
数分で、OperatorHubが更新され、RedHatやCerificateのOperatorが登場します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658425/92f5e670-3356-8277-7db8-4301be456c69.png)
クラスの定義


クラスを使用して以下の表示結果を出力するコードを記述します。

表示結果
-
```rb
ワンワン
わたしは犬です
わたしの名前はポチで種類はトイプードルです
```

仕様
-
|クラス変数|値|
|--|--|
|type|犬|

|インスタンス変数|値|
|--|--|
|name|ポチ|
|dog_type|トイプードル|

クラスメソッド

|メソッド名|処理|
|--|--|
|say|ワンワン|

インスタンスメソッド

|メソッド名|処理|
|--|--|
|say_type|"私は{クラス変数type}です"|
|self_introduction|わたしの名前は{インスタンス変数name}で種類は{インスタンス変数dog_type}です|


```rb:雛形
  class Dog
    @@type = "犬"

    def initialize
      @name = "マロン"
      @dog_type = "トイプードル"
    end

    def self.say
      puts "ワンワン"
    end

    def say_type
      puts "わたしは#{@@type}です"
    end

    def self_introduction
      puts "わたしの名前は#{@name}で種類は#{@dog_type}です"
    end
  end

 dog = Dog.new
 Dog.say
 dog.say_type
 dog.self_introduction
```


1)クラスの定義はclass クラス名 〜 endでした。まずはクラス変数であるtypeを定義します。
2)クラス変数は変数名の始めに@@(アットマーク2つ)をつけます。
3)インスタンス変数です。インスタンス変数は変数名の始めに@(アットマーク1つ)をつけます。
4)インスタンスごとに定義する必要があるのでインスタンスメソッド内で定義します。
5)クラスメソッドsayの定義をします。クラスメソッドはメソッドの前に自身のメソッドであることを示すself.をつけます。
6)インスタンスメソッドであるsay_typeとself_introductionを定義します。インスタンスメソッドの中ではクラス変数とインスタンス変数の両方が使えます。インスタンスメソッドの書き方は通常のメソッドと同じです。
7)定義したメソッドをクラスの外から呼び出します。
ＡＩシステムトレード開発　RSI_BREAKOUT

http://1969681.blog66.fc2.com/

#5/16　 RSI_BREAKOUTのPYTHON版

以下、ブログ掲載記事の転記です。
http://1969681.blog66.fc2.com/blog-entry-611.html

リポジトリ
https://github.com/chanmoto/rsi_breakout

#ポイント

あえてポイントだけ書くとすると・・・

* チャートは　mplfinance を使用。　
参考資料：https://saturday-in-the-park.netlify.app/tradingtools/06_plotdailychart/

* ＲＳＩはHI,LO,CLOSEの各RSIの平均値を使用した。　
参考資料：https://www.mql5.com/ja/code/21823

#MT4→Js/Pythonへの移植に関して

　今回、検討した内容に関しては、特段言及する必要もないが、Pythonを使うことで、ずいぶんとMT4をいじくりまわすよりも、やりやすかった。特にデバッグなどが、慣れたVSCODE+PDBの環境なので、サクサクと進めることができた。

　ざくっとかかった工数を書くが・・・

* JS　：　約３日
* MT5　：　５日　→　結局、断念した。
* Python　：　約１日

　もちろんではあるが、RSIの計算や移動平均計算は、ＪＳで調べたことを展開しているので、Pythonが一番、早いというわけではない。
しかしながら、JSで苦しんだ配列内のスライスループなど、Pythonならではで、やり易かったのは事実である。
　またチャート表示は、JSのライブラリを探すのに、GITHUBを調べまくったが
直ぐにキャンドルとインジケータが表示できたのも、優れたライブラリ環境のあるPythonならではのものである。

## オリジナルコード

```MT4
　　　Hi_stack[ll] = ArrayMaximum(RSI, ii[1+ll*2]-ii[0+ll*2]+1, ii[0+ll*2]+1);
```

## 移植版
```
a1 = ii[0 + linel * 2] + 1;
a2 = ii[1 + linel * 2] + 1;
b1 = ii[1 + linel * 2] + 1;
b2 = ii[2 + linel * 2] + 1;

(JS)
     HiStack[linel] = RSI.indexOf(RSI.slice(a1, a2).reduce((a, b) => a > b ? a : b), a1);

(Python)
     HiStack.append(RSI.index(max(RSI[a1:a2])))
```

###JSの場合
 リストのスライスの書き方が難しい。
 Reduceの後のアロー関数とか・・・　なんでやねんという感じ

###PYTHONの場合
 そもそもスライスは超簡単・・・
それと、配列でネストしてアウトオブレンジを気にするよりも、
リストでAppendした方が圧倒的に低ストレスのプログラミングが可能
（JSも同じことが出来るのかもしれない。MT4/MT5はダメ言語だ。）

#RSI平滑化に関して

これは副二次的なものではあるが、この1週間に調べまくった成果で
ＲＳＩのダマシを回避するのに、ＲＳＩ平滑化を取り入れてみた。

若干ながら線の交錯が少なくなっているように思える。
このような小手先の検討というのは、まだまだ取り組む余地がありそうである。

* 平滑化前　→　RSI計算に、CLOSEを使用
![9432_JP_eq.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212914/76972b78-20e1-21bd-f01d-86bd31c9ded8.png)

* 平滑化後 →　ＨＩ，ＬＯＷ，ＣＬＯＳＥのＲＳＩで平均化
![9432_JP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212914/f1411ef1-945e-ee6a-15fe-eb93a0c5306b.png)

#今後の予定
* Pythonへの移植が完了したため、今後はＡＩシステム化を検討する。
* 現時点では、ＪＳはブログ宣伝用（ＡＰＩパーツ化して、CSVデータを毎日、ダウンロード更新）
* MT4　→　最強ＥＡの再稼働　→　ただしＥＡで使えるのは、OANDA東京サーバーのみ

→  最低単位は0.1ロットからなので、資金が一万しかないので、当面はバーチャル口座でテスト運用のみとする

リポジトリ
https://github.com/chanmoto/chanmoto.github.io/tree/master/rsibreakout
Windows Terminal で Anaconda を使うメモ

今回は、Windows TerminalでAnacondaを使う方法をメモしておきます。
Windows Terminal は Microsoft Store からインストールできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32580/134ecf28-d9eb-2326-9e4c-89c3b194e05d.png)

#Windows Terminalの設定
Windows Terminalの「V」からSettingsを選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32580/74145fc4-4a92-0a04-9836-65b51f06b25c.png)

左メニューのプロファイル欄一番下に「Add new」があるので、プロファイルを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32580/cf37b7d6-81dd-b969-1c4c-e775d13f6449.png)

Command lineを以下を参考に入力します。その他の項目はお好きなように設定しても大丈夫です。

```
cmd.exe "/K" %HOMEPATH%\anaconda3\Scripts\activate.bat
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32580/138ea8ca-6e06-955f-b605-055e6efb54e2.png)

最後に「Save」をクリックします。

#Anaconda Promptを起動

Windows Terminalの「V」から追加したプロファイルを選択するとAnaconda Promptを起動できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32580/a460da56-fb9d-5c16-ab46-68a962e0f01b.png)
改善：OpenAPIをS3ホスティングにベーシック認証追加

# やりたいこと

- [前回の記事](https://qiita.com/icck/items/b3b3d8a24aa2508a5ea2)で未解決だった課題を解決したい
- **Before**
    - s3を直接参照している、閲覧制御が出来ていない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/6254869a-73a4-a780-79fd-91525016bc7d.png)

- **After**
    - CloudFront + Lambda@Edge 経由に変更し、ベーシック認証を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/f53af173-2a80-de95-31f6-b05f87179a8d.png)


# CloudFrontの設定

- [AWS S3で公開している静的サイトにBasic認証をかける](https://qiita.com/itouuuuuuuuu/items/c69eca22a5325b5a15dd)というサイトを参考に設定していきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/92665aa0-65c4-c941-b245-d856b3a10415.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/0ac76fd1-3e56-102e-f232-a1222b2a7486.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/7a22e224-26f1-c72a-e933-971dfd2a226c.png)

# ベーシック認証（Cloudfront Function）
続いてベーシック認証するためのLambdaを作っていきます。`CloudFront Function`を選択します
Lambda@Edgeの設定は省略します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/780994ee-f79c-19d4-4ff1-79d6d9f893c3.png)

# 動作確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/8d556abc-276d-d806-129a-b6a2e7283987.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216527/7084e8cd-1de8-7c89-2ade-471cade3fdc0.png)

# 最後に
- アクセス制御ができたので、見せたい対象の方を簡単ですが制御できるようになりました。
- これで作ったOpenAPIのコードは隠しつつ、ReDocだけを表示制御が実現しました。
- SSL認証やドメイン設定は行なえませんでしたが、またいつか別の機会に試そうと思います。
Visual Studio Codeの新しいウィンドウをターミナルから起動する

細かいところですが、新しく `create-react-app` などしたターミナルから移動せずにVS Codeを起動したいなと思い調べました。



```
code -n 対象ファイルかディレクトリ
```

`-n`フラグは`--new-window`でも構いません。

これで一歩快適になりましたね！

### 参考
[The Visual Studio Code command-line options](https://code.visualstudio.com/docs/editor/command-line)
【AWS】インスタンスの購入方式

#プログラミング勉強日記
2021年5月16日

#インスタンスの購入方式
　インスタンスの購入方式に応じて割引価格が提供されるので、用途に応じて割引価格を利用した方がいい。

##オンデマンドインスタンス
　通常のインスタンス購入方式で、何も設定しなければオンデマンドインスタンスが起動される。長期契約はなく、コンピューティング性能に対して秒単位や時間単位で料金を支払う。起動・停止・休止・開始・再起動・終了などを自由に制御できる。


##リザーブドインスタンス
　1年または3年の期間を長期利用する予約する。キャパシティーを予約したうえで事前支払いをするか、後で支払うかを設定することができる。また、特定のAZまたはリージョンで使用するキャパシティーを予約できる2パターンある。割引率はインスタンスの種類や支払い形態に応じて違うが、通常のオンデマンド料金に比べると大幅に割引される。

##リザーブドインスタンスの特徴
　リザーブドインスタンスにはスタンダードとコンバーティブルという2つのタイプがある。

| | スタンダード | コンバーティブル |
|:--:|:--:|:--:|
| 利用期間と割引価格 | 1年(40%割引), 3年(60%割) | 1年(31%割引), 3年(54%割引) |
| AZ/インスタンスサイズ/ネットワーク変更可否 | 〇 | 〇 |
| インスタンスファミリー/OS/テナンシー/支払いオプションの変更可否 | × | 〇 |
| リザーブドインスタンスマーケットプレイスでの販売可否(途中でいらなくなったときに販売できるか) | 〇 | 今後可能となる予定 |

　コンバーティブル(convertible)はその名の通り、変更できる要素が多い。スタンダードの方が変更できる属性が少ないが、割引価格がより高くなっている。

##スケジュールドリザーブドインスタンス
　1年にわたって毎日、毎週、毎月ベースの指定された開始時間・期間で繰り返しキャパシティーを予約できる。(毎日1日2時間だけ使うといった指定した時間だけ)　継続的に実行されないが、定期的なスケジュールで実行されるバッチ処理などに向いている。

##スポットインスタンス
　オンデマンドの料金よりも安く利用できるインスタンス。AWS側の管理用に保持されている未使用のEC2インスタンスを一時的にユーザに貸している(万が一のために未使用のEC2インスタンスを複数持っている)。AWS用のインスタンスなので、途中で中断される可能性のある長期利用できないインスタンス。そのため、最大で90%割引で利用できる最も安いインスタンス。
　実行時間に柔軟性がある場合や中断できる処理に利用する。

#物理対応可能なインスタンス
　物理サーバにインスタンスを起動して制御可能なタイプのインスタンス。これも値段は変わるが、値段よりも用途によって選ぶことが重要。

##ハードウェア専有インスタンス(Dedicated Instances)
　専用HWのVPCで実行されるEC2インスタンス。VPC構成をするときにDedicatedを選ぶとハードウェア専有インスタンスを選択できる。ホストHWで他のAWSアカウントに属するインスタンスから物理的に分離する。同じAWSアカウントのインスタンスとはHWを共有する可能性があるので注意が必要。

##Dedicated Host
　Dedicated Instancesと似ているが、同じAWSアカウントであっても別のIAMグループと物理的なサーバーを共有することがない。EC2インスタンス容量をユーザ専用として利用できる物理的なサーバー。サーバーに割り当てられてる既存のソフトウェアライセンス利用できる。

##Bare Metal
　特殊な仮想サーバーの方式で、アプリの基盤になるサーバーのメモリやプロセッサに直接アクセス可能なインスタンス。通常仮想サーバーは物理的なインスタンスのメモリやプロセッサに直接アクセスして設定はできないが、Bare Metalは物理的なサーバーをオンデマンド形式でアクセスできる。
GoogleAppsScriptとGoogleスプレッドシートを連携したWEBアプリケーションを作成してみた【第一回】

###GoogleAppsScriptとGoogleスプレッドシートを連携したWEBアプリケーションを作成します
こんにちは。システムエンジニアのDiavoloです。
チーム内で利用するWEBアプリケーションを作成しましたので、備忘録として作成方法を記事にします。主な利用目的としましては、課題に対する対応を記録しておいて、閲覧、更新できるようにするWEBアプリケーションです。完成までを複数の記事に分けて投稿する予定です。
第一回目の記事としましては、HelloWorldを表示するところまでになります

##GoogleAppsScriptを起動して以下のコードを入力します。最初に書いてあるmyFunction()は削除します。
```JavaScript:コード.gs
function doGet() {
  var tpl = HtmlService.createTemplateFromFile('index');
  return tpl.evaluate();
}
```
##index.htmlを追加します
追加方法です。ファイル->HTMLを選択して、無題をindexに変更します。ファイルの拡張子(.html)は自動的に付与されますので、入力する必要はありません。index.htmlは以下のテンプレートが入力された状態で生成されます。

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    
  </body>
</html>
```
##index.htmlのbody部にHello Worldを入力します。
```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    Hell World!!
  </body>
</html>
```
これでソースコードは完成です。お次はデプロイです。
##デプロイします。
デプロイ->新しいデプロイ->デプロイを実行します。
WEBアプリという画面が表示されますので、そこに書かれているURLをクリックします。
ブラウザが起動し以下の画面が表示されます。
![HelloWorld.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321513/a33d6b6b-0421-bd90-6086-dea62418ef46.png)

第一回目の記事はこれで終わります。次回以降はよりWEBアプリケーションらしい実装をして参ります！！
RaspberryPi4にUbuntu Desktop21.04を導入

# 経緯
MongoDBつかって色々検証したかったけど、メインマシンで動作させっぱなしも無駄に電気代かかる。
てことで、うちにあるRaspi4でMongoDB入れてやればいいか、と思ったけどのバージョンが2.4と古すぎて微妙。そういえば、RaspiでUbuntu動くようになったのを思い出して切り替えてみることにした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477929/4ca201c0-fe27-daee-7bab-f9e3808b17b8.png)


# Ubunto21.04 Desktopをダウンロード
Ubuntuの[Install Ubuntu on a Raspberry Pi (https://ubuntu.com/download/raspberry-pi)](https://ubuntu.com/download/raspberry-pi)からUbuntu Desktop 21.04をダウンロード
今回の運用的にはServerでもいいけど、なんとなくDeskTopにした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477929/d448e6b0-28c5-d8c7-3e19-e8087803368e.png)

で、ダウンロードファイルが ubuntu-21.04-preinstalled-desktop-arm64+raspi.img.xz で1.6Gぐらい。
これを展開すると、ubuntu-21.04-preinstalled-desktop-arm64+raspi.img ができて8.4Gになる。

# OSをSDカードに書き込む
公式から RaspberryPi OSの書込ツールの[Raspberry Pi Imager (https://www.raspberrypi.org/software/)](https://www.raspberrypi.org/software/)がでているのでダウンロードする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477929/14e3b937-c79a-c421-d835-1486a03b5b61.png)

##Rasberry Pi Imager使い方
* Operation System の CHOOSE OS をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477929/d7605d0e-79b7-c7c5-77c9-9168b0bc4384.png)


* Use custiom → さっき展開した ubuntu-21.04-preinstalled-desktop-arm64+raspi.img を選択
実は、さっきダウンロードしたイメージをつかなくとも、書き込めるのだがかなり時間がかかるのでイメージを自分のPC内に持ってきたほうがいい。
Ubuntu Desktop 21.04(RPi4/400)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477929/307830de-bb31-bf6e-9b52-4abc869ff4da.png)


* StorageをクリックしてSDカードリータを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477929/bae27952-20c8-7e62-6d9e-5c7f783a50b5.png)


* WRITEボタンが押せるようになるのでクリックするとSDカード内のデータが削除されることの確認ダイアログが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477929/724b98d7-47ba-4fe0-ad1f-7bd01506291c.png)

* YESを押すと、書き込みが始まるのでしばらく待つ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477929/1c051570-85ac-28c9-1450-72d40597b9cd.png)


* 書き込みが完了すると以下の画面が表示されるので、CONTINUE をクリックしてSDカードを取り出す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1477929/ae23eab2-05ff-1fc8-c238-74b5de79a59a.png)


# Ubuntu Desktop21.04 起動

とりあえず、立ち上がって Ubuntu21.04が起動することを確認。

まず、ターミナルからパッケージを最新にする。

```
sudo apt update
sudo apt upgrade
sudo apt autoremove
```

で、いろいろ試してたけど調子悪い。
まず、Bluetoothキーボードで文字入力できない、これは致命的にダメ。
ログイン画面では入力できるんだけど、そのアプリとかで文字入力できない。
ただ、検索バーでは文字入力できてるからとりあえずなんかおかしい。

調べてみたけど、RaspberryPi4 の Ubuntu21.04はでたばっかでまだ問題が多いみたいね。
VNCが調子悪かったり、キーボードが認識しなかったりであんまりよろしくない。
自分もまったく同じ症状になったので以下のフォーラムを監視しながら対応されたらなんとかするかな。

* [Update to Ubuntu 21.04 and VNC server doesn't work](https://www.raspberrypi.org/forums/viewtopic.php?f=131&t=310288)
* ubuntu 21.04 -- keyboard not typing in apps(https://www.raspberrypi.org/forums/viewtopic.php?t=310293)


やりたいことにはSSHがあれば問題ないのでSSHサーバいておく。

```
sudo apt install openssh-server
```

まともに動くようになったらリモートでVNCとかやりたいから記事追記しよう。

Pythonは3.9.4の最新が入ってるから次はMongoDBだな。
Flutter+FirebaseでGoogleアカウントでログイン

情報は色々あるけど、すんなり動かなかったのでメモ

## 参考

- 手順はここを参考にした。firebaseのプロジェクト作成やアプリの登録など。コードはうまく動かなかった。
https://zenn.dev/takumiendoh/articles/42d870436bc9c882bb85

-  info.plistの編集も忘れないように...
https://zenn.dev/welchi/articles/firebase-auth

- コードは以下参照
 https://firebase.flutter.dev/docs/auth/usage
 https://firebase.flutter.dev/docs/auth/social


## pubspec.yaml

バージョンは最終的に以下のような感じで、ログインだけならcoreとcloud_firestoreはいらないはず。
```yaml

dependencies:
  flutter:
    sdk: flutter
  firebase_auth: ^0.14.0+5
  google_sign_in: ^4.0.14
  firebase_core: ^0.4.0+9
  cloud_firestore: ^0.12.9+5

```


## main.dart

1画面にログインボタンとログアウトボタンとカレントユーザをコンソールにプリントする３つのボタンを配置してるだけ。

```dart
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'dart:developer';

Future<void> main() async {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // アプリ名
      title: 'LoginDemo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LoginPage(),
    );
  }
}

// ログイン画面用Widget
class LoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              child: Text('ログイン'),
              onPressed: () => {signInWithGoogle()},
            ),
            ElevatedButton(
              child: Text('ログアウト'),
              onPressed: () => {signOut()},
            ),
            ElevatedButton(
              child: Text('カレントユーザー'),
              onPressed: () => {currentUser()},
            ),
          ],
        ),
      ),
    );
  }

  // ログイン処理
  Future<void> signInWithGoogle() async {
    FirebaseUser user = await FirebaseAuth.instance.currentUser();
    if (user != null) return user;

    debugPrint("signInWithGoogle");
    final GoogleSignInAccount googleUser = await GoogleSignIn().signIn();
    final GoogleSignInAuthentication googleAuth =
        await googleUser.authentication;

    // Create a new credential
    final AuthCredential credential = GoogleAuthProvider.getCredential(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );
    //ログイン
    return await FirebaseAuth.instance.signInWithCredential(credential);

  }

  // ログアウト
  Future<void> signOut() async {
    debugPrint("signOut");
    await FirebaseAuth.instance.signOut();
  }
  // カレントユーザー
  Future<void> currentUser() async {
    debugPrint("currentUser");
    FirebaseUser user = await FirebaseAuth.instance.currentUser();
    inspect(user);
  }
} //class


```


こんな感じ。１回認証すればとりあえずはcurrentUserが取れる。
アプリ全体としてデータの保存などにログイン必須なら、アプリの頭で判定する所を用意すれば良いか。
バックアップに使う程度なら...その時だけログインすればいいね。
Rubyで解くAtCoder ABC 201 (C問題 Rubyでは最短実行時間)

# C - Secret Number

https://atcoder.jp/contests/abc201/tasks/abc201_c

# 問題内容

0000~9999までの4桁の暗証番号について，どの文字が使われていたかを10文字の文字列で与えられるので，ありえるパターンの数を答える問題
例えば`o?xx?oxoxx`でが与えられれば，左から順に 0,1,2..9 と見ていって，

- o : 確実に1回以上使われる( 0,5,7 は 1~4 個)
- ? : 使われたかもしれない( 1,4 は 0~4 個)
- x : 使われない( 2,3,6,8,9 は 0 個)

この条件でありえる暗証番号のパターン数は84通りなので，84を出力すればよいです。


# 本番で提出したコード

```ruby:ABC201_C.rb
str = gets.chomp.split('')
o = 0
q = 0

10.times do |i|
    o += 1 if str[i] == 'o'
    q += 1 if str[i] == '?'
end

if o >= 5
    puts 0
elsif o == 4
    puts 24
elsif o == 3
    puts 24 * q + 36
elsif o == 2
    puts 12 * q * q + 24 * q + 14
elsif o == 1
    puts 4 * q * q * q + 6 * q * q + 4 * q + 1
else
    puts q * q * q * q
end
```

最初の`times`文のところまでで，`o`と`?`の個数を数えて,変数`o`,`q`に入れています。あとから見直すと，結構直したくなってくる...

- 配列にしてるのに変数名`str`なのは違和感
- 文字列のまま`count`で数えたほうがスマート


`if`文で，変数`o`の値によって，条件分岐させながら，計算しました。
(高校数学でこんなのやったなあと思い出しながら...)


## o が 5 個以上

4桁の暗証番号なので，これはありえない！
$0$ 通り


## o が 4 個

4個全てをパターンしかないので
$4! = 24$ 通り


## o が 3 個

#### oの3種類のみで考えられるパターン
$4!$に対し，同じ数字が2個あるので$2$で割って，どの数字を2個使うかで3パターンあるので$3$をかけます。
$ \frac{4!}{2}×3 = 36 $ 通り

#### oの3種類に?から1個使うパターン
どこに?を使うかで$4$通り,oの並べ方で$3!$通り，さらに?の個数分だけ$q$通りあるので
$ 4 × 3! × q = 24q $ 通り

#### 合計は
$ 24q + 36 $ 通り


## o が 2 個

#### oの2種類を2個ずつ使うパターン
$4!$ に対し，同じ数字が2個ずつあるので $2×2$ で割ります。
$ \frac{4!}{2×2} = 6 $ 通り

#### oの2種類を1個,3個で使うパターン
どちらを1個にするかで $2$ 通りに，1個のほうがどこに来るかで $4$ をかけます。
$ 2 × 4 = 8 $ 通り

#### oの2種類を1個,2個で使い，?から1個使うパターン
どこに?を使うかで $4$ 通り,oの並べ方(どこに1個のほうがくるかで3通り，どっちを1個にするかで2通り)で $ 3 × 2 $ 通り，さらに?の個数分だけ$q$通りあるので
$ 4 × 3 × 2 × q = 24q $ 通り

#### oの2種類を1個ずつ使い，?から2個使うパターン
どこに?を使うかで $_4 C _2 = 6$ 通り,oの並べ方(どこに1個のほうがくるかで3通り，どっちを1個にするかで2通り)で $ 3 × 2 = 6 $ 通り，さらに?の個数分だけ $q^2$ 通りあるので
$ 6 × 6 × q^2 = 36q^2 $

#### 合計は
$ 36q^2 + 24q + 14 $ 通り


## o が 1 個

#### oを4回使うパターン
$1$ 通りしかないです。

#### oを3回,?を1回使うパターン
どこに?を使うかで $4$ 通り，さらに?の個数分だけ $q$ 通りあるので
$4q$ 通り

#### oを2回,?を2回使うパターン
どこに?を使うかで $_4 C _2 = 6$ 通り，さらに?の個数分だけ $q^2$ 通りあるので
$6q^2$ 通り

#### oを1回,?を3回使うパターン
どこにoを使うかで $ 4 $ 通り，さらに?の個数分だけ $q^3$ 通りあるので
$4q^3$ 通り

#### 合計は
$ 4q^3 + 6q^2 + 4q + 1 $ 通り


## o が 0 個

?の個数を4回かければよいので
$ q^4 $ 通り


# 解説記事

### 公式解説
https://atcoder.jp/contests/abc201/editorial/1825

$10^4$ 通りなので，全部数えるようにしてもできそうですね。

### ユーザー解説

https://blog.hamayanhamayan.com/entry/2021/05/15/235640

こちらは場合分けしていますね。


# 感想

今回はC問題までを45分で解くことができました。

D問題は解けなかったので，次回こそチャレンジ！
structure.sqlを使いたい！

# はじめに
Railsではdb:migrateすると、デフォルトでdb/schema.rbを生成されて、このファイルでスキーマ管理をしてくれます。
しかし、ユニークインデックスにwhereを付けるようなRDB固有の命令については、Rails標準のschema.rbで管理し続けるのは限界があるのではないかという問題点があります。
それを解決してくれるのが`structure.sql`で、SQLでスキーマ情報を管理することも可能です。

## structure.sql生成方法
`config/application.rb`に以下を記述して、`rails db:migrate`を実行することで生成されます。

```config/application.rb
config.active_record.schema_format = :sql # デフォルトでは「:ruby」となっています
```

### structure.sqlをロードする
生成されたstructure.sqlファイルは、下記のコマンドでデータベースへロードできます。

```ruby
$ rails db:structure:load
```

### SQLファイルだけ欲しい場合
SQLダンプファイルのみが欲しい場合は、下記コマンドでstructure.sqlのみを生成することができます。

```ruby
$ rails db:structure:dump
```

### 注意点
migrationファイルに基づいてstructure.sqlは更新されていくので、中身を変更したい時は手動では無く`rails db:migrate:reset`などでmigrationを実行し直す。

# 終わりに
最近では、structure.sqlでスキーマ管理することも増えてきている？っぽいので、どういったものか？ということくらいは掴んでおいた方がいいかもしれないですね！
Ruby初心者（私）がやった構文ミス

# はじめに
はじめまして、Rubyにてプログラミング学習をはじめたkat_logと申します。
学習の中でやった間違いをご紹介いたします💦

# 一覧
## 数値指定が必要なのに文字列で指定した
##### ミス

```
print_info("USBメモリ", "1200")
```

#####正解

```
print_info("USBメモリ", 1200)
```

初心者にありがちなミスですかね…

## if文のelseに条件式を記載した
別の条件で分岐させる時は`elsif`が正しいのですが`else`としていたため意図しない結果が出てきました。
##### ミス

```ruby:total.rb
total = 50

if total >= 200
    #25円引き
    total -= 25
else total >= 100
    #10円引き
    total -= 10
end

puts total # => 40
```

100円以上の時に10円引きしたいのに、100円より小さい値でも10円引きされてしまいました。
#####正解

```ruby:total.rb
total = 50

if total >= 200
    #25円引き
    total -= 25
elsif total >= 100
    #10円引き
    total -= 10
end

puts total # => 50
```

2つ目の条件の時は`elsif `ですね！
`else`に条件を書いていても実行時にエラーは出ず、実行後に気づきました！💧

## メソッド作成時に`return`付け忘れ
※2021/05/19修正、この場合`return`不要、むしろRubyでは`return`は付けないほうが主流とのことです！
（@jnchito さんよりご教示いただきました。）
##### ミス（ではありません）

```ruby:friday.rb
def sale_day?
    # 金曜日判定
    today = Date.today
    today.friday?
end
```


#####正解（とも言い切れません💦）

```ruby:friday.rb
def sale_day?
    # 金曜日判定
    today = Date.today
    return today.friday?
end
```

~~処理が書けて満足してたら忘れてました！~~
今回の場合忘れてOKです！

# おわりに
ここまで読んでいただきありがとうございました。
ミスは他にもあるのですが今回は3つだけご紹介しました。
慣れていないこともありこれだけの記事でも大変だと思いました…！

ランキングに載るような記事をまとめられている方々は知識はもちろん集中力や構成力も持たれているのだと思い尊敬します。

学習の過程ではたくさん間違えますが、間違えたときほど記憶には残っているとポジティブに捉えて今後も学習進めていきたいと思います😅

最後に、記事の投稿が初めてでして技術の面でも、「こうすると見る側に親切だよ」といった記事の面でもアドバイス等ありましたらフィードバックいただけたらと思います。
ありがとうございました！

# 参考
 - [Progate](https://prog-8.com/courses/ruby "Progate Ruby")
 - [Let'sプログラミング](https://www.javadrive.jp/ruby/ "Let'sプログラミング Ruby入門")
[Unity] TopDown EngineのLoft3Dデモでプレイヤーキャラクターを差し替える(備忘録)

# はじめに
Unityの有料アセット、TopDown EngineのLoft3Dデモでプレイヤーキャラクターを差し替える際に行った作業を備忘録としてまとめておきます。

# Suspendersのプレハブをコピーしてモデルを差し替え
Loft3Dデモでは、プレイヤーキャラクターとしてPrefabs/PlayableCharactersの下のSuspendersプレハブが使用されています。
まずはこれをコピーして、名前を適当に変えます。

複製したプレハブのSuspenders@Idle(1)以下は必要ないので削除し、代わりに使用したい3Dモデルを子オブジェクトとして追加します。

# Animatorの設定
追加した3DモデルのAnimatorのControllerをSuspendersAnimationControllerに変更します。

# Weapon IKの追加
追加した3Dモデルが武器を構えられるように、Weapon IKコンポーネントを追加します。
Weapon IKコンポーネントの追加は、Animatorコンポーネントが設定されているオブジェクトに対して行います。
パラメーターはデフォルトのまま。

# 武器を装備した時の武器の座標を表すオブジェクトを追加
キャラクターの3Dモデルに対して、武器を装備した時の武器の位置をTransformとして持つオブジェクトを追加します。
今回はSuspendersのWeaponAttachmentContainer以下をそのままコピーして、3Dモデルに追加しました。

# CharacterHandleWeaponの設定
CharacterHandleWeaponのWeapon Attachmentに、先ほどコピーしたWeaponAttachmentContainerの下のWeaponAttachmentオブジェクトを指定します。

# CharacterCrouchの設定
CharacterCrouchのObjectsToOffsetにWeaponAttachmentContainerを指定します。
これにより、キャラクターがしゃがんだり這ったりするときに、武器の位置をそれに合わせてOffsetCrouch/OffsetCrawlの分だけ移動させることができます。

# LevelManagerのPlayer Prefabsの設定
LevelManagerのPlayer PrefabsからSuspendersプレハブを削除し、今回作成したプレハブを指定します。

# 完成
シーンを再生して、プレイヤーキャラクターが正常に動作するか確認します。
Ubuntu の apt upgrade で "not upgraded" と表示された時の対処法

## きっかけ

Ubnntu を利用しており、ソフトパッケージの差分更新時に `not upgraded` と表示され、気持ち悪かったので修正しました。

## 表示例

自分の環境では以下のように表示されていました。

```cmd
$ sudo apt upgrade
Reading package lists... Done
Building dependency tree
Reading state information... Done
Calculating upgrade... Done
The following packages have been kept back:
  docker-ce
0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
```

 `0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.` の部分です。
上記では `docker-ce` のパッケージ更新が保留されていました。

## 修正方法

こちらは単に更新が`保留`されているだけで、明示的にパッケージをインストールすること（`apt install docker-ce`）で解消されます。

以下が、修正時の例です。

```cmd
$ sudo apt install docker-ce
```

インストール完了後、 `update` と `upgrade` を実行し、`not upgraded` の有無を確認してみます。

```cmd
$ sudo apt upgrade
Reading package lists... Done
Building dependency tree
Reading state information... Done
Calculating upgrade... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
```

表示されなくなりました！
AIを実装するデファクトスタンダード2021、インストール編

## この記事の内容
AI、機械学習をウェブ上に実装するときにどういう技術を使えば良いかわからないときに自分ならこういう構成にするという記事を書きます。
ひとによって技術的な観点が異なるので、もしかしたら全然違う人もいるかもしれませんが、ご了承ください。
サンプルアプリケーションとして文章の末尾に絵文字を付けるアプリケーションを作成します。

### 完成イメージ
https://twitter.com/noriakioshita/status/1357851329775820806?s=20

## この記事で使う技術
- PyTorch
- FastAPI
- Next.js（React.js）
- TailwindCSS
- Docker
- Kubernetes
- MLFlow
- ElasticSearch
- Azure

## インストール
Pythonの環境の構築は省略します。
PyTorchのインストールにはPoetryを使用します。これは依存環境を自動的に作ってくれるソフトウェアです。

[Poetryのインストール方法](https://github.com/python-poetry/poetry)

Pythonの実行環境の構築

```
poetry new emoji_app
```

ディレクトリ構造

```
tree emoji_app/
#output
emoji_app/
├── README.rst
├── emoji_app
│   └── __init__.py
├── pyproject.toml
└── tests
    ├── __init__.py
    └── test_emoji_app.py
```

また、以下の環境の構築用の設定ファイルが生成されます。

```
[tool.poetry]
name = "emoji_app"
version = "0.1.0"
description = ""
authors = ["oshita-n <*******@*******>"]

[tool.poetry.dependencies]
python = "^3.7"

[tool.poetry.dev-dependencies]
pytest = "^5.2"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
```

Poetryの準備ができたらPyTorchをインストールします。

```
poetry add torch
```

次に今回APIの作成に利用するfastapiをインストールします。

```
poetry add fastapi
```

おつかれさまでした。これでPythonに関するソフトウェアのインストールは終了です。
次回はAIモデルを作成します。
Spring-Bootアプリをパソコンを切ってもEC2上で起動させておく手順(デーモン化)

configurationタグの箇所3行を記入したjarファイルを作ります。これにより後述のsystemd enableとstartが実行可能になります。

```pom.xml
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<executable>true</executable>
				</configuration>
			</plugin>
		</plugins>
	</build>


```

ここからの手順はHogeをご自身のアプリ名に読み替えて下さい。以降EC2上での実行コマンドです。

```
sudo vi /etc/systemd/system/Hoge-0.0.1-SNAPSHOT.service

```
<hr>
vimでUnitを作成します。vimの編集の際には一度aを押してINSERTと表示されてる状態にし下記スクショの内容を記入、作成完了後はEscキーを押下し:wqと入力して保存・終了します。

```
[Unit]
Description = 任意のアプリ説明
After=syslog.target

[Service]
ExecStart = /home/ec2-user/Hoge-0.0.1-SNAPSHOT.jar
Restart = no
Type = simple
User = ec2-user
Group = ec2-user
SuccessExitStatus = 143

[Install]
WantedBy = multi-user.target
```

```
sudo systemctl daemon-reload
```

```
sudo chmod 744 Hoge-0.0.1-SNAPSHOT.jar
```



```
sudo systemctl enable Hoge-0.0.1-SNAPSHOT.service 
```

```
sudo systemctl start Hoge-0.0.1-SNAPSHOT.service 
```
<hr>

jarファイルの再デプロイは下記の順番で行います。

```
sudo systemctl disable Hoge-0.0.1-SNAPSHOT.service 
```
```
sudo systemctl stop Hoge-0.0.1-SNAPSHOT.service 
```

EC2jar削除
EC2新jar追加
reload(すでに記述済み)
chmod(すでに記述済み)
start(すでに記述済み)
enable(すでに記述済み)
バリデーションの種類

こんにちは！
今回の記事はバリデーションについて
あれこれアウトプットしていこうと思います！
僕の理解した範囲のバリデーションについて
記述していこうと思います！


<h1>バリデーションとは？</h1>
バリデーションとはデータを登録する際に
一定の制約をかけることを言います。
*新規登録ユーザー名が空のデータで登録されるのを防ぐ。
*新規パスワード登録の際に最低６文字以上は入力を強制させる。
といった例が挙げられます。

バリデーションを設定する際はvalidatesメソッドを使用します。
記述方法は以下のとおりです。

```モデル
validates :カラムの種類, バリデーションの種類

validates :name, presence: true 
```

基本的にデータの登録などテーブルとの
やり取りに関する情報は
モデルを使用します。
コントローラーはモデルの機能を利用して処理を
呼ぶだけの簡単な処理を記述します。


<h1>バリデーションの種類</h1>

```モデル
validates :name, presence: true 
```

presence: tureは名前が空欄だとデータの登録ができない
というバリデーションです。空欄のまま登録を試みるとエラーが起こります。


```モデル
validates :name, absence: true
```

absence: trueはpresence: trueの逆で
名前が空欄であるというバリデーションです。

```モデル
validates :name, acceptance: true,
```

acceptance: trueはモデルにチェックボックスをチェックしたかを
確認させるバリデーションです。
利用規約の同意などでこの記述が用いられます。

![info_table_20190722.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435543/a8ad755c-fb1b-9f87-5527-0c0e38f1942a.png)


```モデル
validates :name, presence: true length: { maximum: 6 }
```
lengthを指定することで指定した属性の文字数制限をチェックすることができます。
length: { maximum: 6 }の通り、6文字以内の文字制限があるため、
７文字以上記述しようとするとエラーが発生します。


```モデル
validates :name, presence: true length: { minimum: 6 }
```

逆にこちらは７文字以上は記述しなければいけません。

```モデル
validates :email, uniqueness: true
```

emailは一意となるようにRails側でバリデーションをかけることができます。

<h1>バリデーションの共通オプション</h1>

```モデル
validates :name, presence: true on: :create
```

onオプションはバリデーション実行のタイミングを設定できます。
on: :createを指定することでレコードに新規作成時に
バリデーションが行われます。


```モデル
validates :name, length: { maximum: 6 }, allow_blank: true
```
allow_blank: trueは値が空の場合にバリデーションを実行します。
この記述で、値が空の場合と７文字以内でデータを登録しようとすると
エラーを返されます。


```モデル
validates :email, format: { with: /\A[a-zA-Z]+\z/,
    message: "英文字のみが使用できます" }
```

messageオプションを使用するとバリデーション失敗時にエラ〜メッセージを
表示することができます。
また、formatはwithオプションを指定した正規表現と一致するかどうかを調べます。
mdBookを使ってみた（導入編）

# mdBook使ってみた

[mdBook](https://rust-lang.github.io/mdBook/index.html)を使うと、マークダウン形式でブックをつくることができる
ブックとは、まさにリンク先のページのようなもの
左に目次があってその他のスペースが記事になる

この記事では、雛形を作成し目次をカスタマイズするところまで行う

## 前提

[Rust](https://www.rust-lang.org/ja)がインストールされていること

``` Powershell
> cargo --version
# cargo 1.51.0 (43b129a20 2021-03-16)

> rustc --version
# rustc 1.51.0 (2fd73fabe 2021-03-23)
```

## 環境構築

デフォルトのページを表示するまで行う

### mdbookコマンドラインツールをゲットする

``` Powershell
# 10分くらいかかった
cargo install mdbook
```

### 作業ディレクトリを初期化する

``` Powershell
mkdir book-test
cd .\book-test\
mdbook init

# Do you want a .gitignore to be created? (y/n)
y
# What title would you like to give the book? 
my_first_book:wa

# All done, no errors...
```

### ビルドしてページを見てみる

`mdbook build -o`

![build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/a3f28ea8-1cd8-e1aa-3dca-9e9205753d44.png)


## カスタマイズ

`SUMMARY.md`ファイルを追加編集してブックをカスタマイズする
編集内容をブラウザへ反映するために`mdbook watch -o`をつかう

``` Powershell
# Summary

1. [Chapter 1](./chapter_1.md)

1. [Chapter 2](./chapter_2.md)
    1. [Chapter 2 Sub](./chapter_2_sub.md)

# Another Section

1. [Chapter 3](./chapter_3.md)
```

![custom.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/82b71dbb-4e32-41d7-6925-00430667addd.png)


ここまでのディレクトリ階層

```
作業ディレクトリ
│  .gitignore
│  book.toml
│  
├─book
|       # ここにはたくさんのファイル
│          
└─src
        chapter_1.md
        chapter_2.md
        chapter_2_sub.md
        chapter_3.md
        SUMMARY.md
```

以上
yukicoder contest 295 参戦記

# yukicoder contest 295 参戦記

## [A 1505 Zero-Product Ranges](https://yukicoder.me/problems/no/1505)

0になるものを数え上げるのは大変なので、1になるものを数え上げて引けば良い. 0で分割されたそれぞれのブロックについて、その長さをn<sub>i</sub>とすると、それぞれの組み合わせの数は <sub>n<sub>i</sub>+1</sub>C<sub>2</sub> となる.

```python
N, *A = map(int, open(0).read().split())

c = 0
l = 0
for i in range(N):
    if A[i] == 1:
        continue
    t = i - l + 1
    c += t * (t - 1) // 2
    l = i + 1
t = N - l + 1
c += t * (t - 1) // 2
print((N + 1) * N // 2 - c)
```

A を文字列として扱って、0を区切り文字として split したほうが楽だったかな.

```python
N = int(input())
A = input()

print((N + 1) * N // 2 - sum((len(s) + 1) * len(s) // 2 for s in A.replace(' ', '').split('0')))
```


## [B 1506 Unbalanced Pocky Game](https://yukicoder.me/problems/no/1506)

A<sub>i</sub>≦10<sup>9</sup> ではあるが、結局は0にして渡すか1にして渡すかの2択でしかない. A<sub>i</sub>が1の時だけは0にして渡すの一択になるが. 後はメモ化再帰すれば片付きます.

```python
from sys import setrecursionlimit

setrecursionlimit(10 ** 6)

N, *A = map(int, open(0).read().split())

cache = [[None] * (N + 1) for _ in range(2)]


def f(i, turn):
    if i == 0:
        return turn ^ 1

    if cache[turn][i] is not None:
        return cache[turn][i]

    if A[i - 1] == 1:
        t = f(i - 1, turn ^ 1)
        cache[turn][i] = t
        return t

    t = f(i - 1, turn)
    if t == turn:
        cache[turn][i] = t
        return t
    t = f(i - 1, turn ^ 1)
    cache[turn][i] = t
    return t


if f(N, 0) == 0:
    print('Alice')
else:
    print('Bob')
```
さくらのVPSで外部接続を許可する

#概要
あきひ [@ahikicoin](https://twitter.com/ahikicoin "Symbolに未来を感じ、ノードを構築したものの、委任してくれる人が増えずTwitterで呟く活動を始めてみました。おまけに、いろんなツールを開発していきます。") さん作成の[Symbol node List](https://symbol-tools.com/symbolTools/view/tool/nodeList.html "Symbol Node List")に私のノードを掲載させて頂きたく、VPSのルートディレクトリに設定ファイル（nodeSetting.json）を配置した時の備忘録です。

コマンドからファイアーウォールのtcp/80ポートを許可したり、色々いじってみたのですが上手くいかず、、結果コントロールパネルの「パケットフィルタ」から設定するだけで良かったというオチでした(・_・;)


####環境
サーバー：さくらのVPS
OS：Ubuntu 20.04.1
Webサーバー：Apache 2.4.41

#設定ファイルの設置箇所
まず、Symbol node Listのサイト下部に設定についての記載があります。
>設定方法は、各ノードのHTTP(80番ポート)のルートURLに「nodeSetting.json」を配置してください。(http://xxx.xxx.xxx.xxx/nodeSetting.json)

ルートURLのディレクトリはどこ？
http://xxx.xxx.xxx.xxx にアクセスしたときのドキュメントルートは
<b>/var/www/html</b>
ですが、Apacheをインストールしていないとディレクトリ「www」は存在しない様です。
#Apacheをインストール
ユーザー：ubuntu
以下コマンドでApacheをインストールします。rootユーザーでもOK

```
$ sudo apt install apache2
```
####バージョンを確認

```
$ apache2 -v
Server version: Apache/2.4.41 (Ubuntu)
```
####Apacheの状態を確認

```
$ sudo systemctl status apache2
・・・
Active: active (running) 
・・・
```

無事インストールされた様です。
ファイアーウォールの状態も確認してみます。

```
$ sudo ufw status
Status: inactive
```
ファイアーウォールは無効になっている様ですが、コマンドでの操作はここまで良みたいです。

#コントロールパネルの設定
次はコントロールパネルの「パケットフィルタ」からTCPポート:80 / 443を許可します。
[パケットフィルタ｜さくらVPSのドキュメント](https://manual.sakura.ad.jp/vps/network/packetfilter.html)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1271725/84cde42a-5df5-758f-a540-8b725601cc5c.png)
↓設定後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1271725/285df939-7df3-b769-9c1f-dfe822550380.png)

http://160.16.225.71/
にアクセスしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1271725/deba325e-b99b-c3df-4ee0-6468450957fc.png)
ルードディレクトリのindex.htmlが表示されました
#設定ファイルの設置
新規でjsonファイルを作成して

```
/var/www/html$ vi nodeSetting.json
```
｛ ｝内に

- 委任ハーベスト数
- Twitterアカウント名（半角でOK）
- コメント

の３つを記載

```
{
        "limitHarvesterCount": "10",
        "twitterAccount": "demi_l2r",
        "comment": "イヴァリース王国"
}
```
これで設定完了です、数十分でリストに反映されていました。
【JavaScript 変数】var、let、constの違いや使い分けなど

#変数

変数とは**文字列や数値のデータを格納して、何度も使えるようにする**箱のようなものです。
変数を宣言するときには以下のように、右の値を左の変数に代入することになります。
<br>


```.js
var "変数名" = "値や文字列";

var a = 1;
let apple = 3;
const banana = 'バナナ';
```

**var**、**let**、**const**はJavaScriptで変数を宣言すると気に使うキーワードです。




#var, let , constの使い分け

var, let, constはそれぞれできること、できないことがあります。

 |var| let|const
-|-|-|-
**再代入**|○|○|×
**再宣言**|○|×|×
**スコープ**|関数|ブロック|ブロック

<br>
###再代入
再代入とは宣言した変数の値を再び別の値で代入することです。

varやletで宣言した変数を再代入とすると代入後の値が適用されます。
constで代入するとするとエラーが出ます。

```.js
// var
var a = 1 // 変数の値を宣言
a = 2 // 再代入

console.log(a) // '2'と出力される。再代入された'a = 2'が適用されるため。

// let

let b = 1 // 変数の値を宣言
b = 3 // 再代入

onsole.log(b) //'3'と出力される。再代入された'b = 3'が適用されるため。

// constはエラーがでる。
```

<br>
###再宣言
再宣言とは一度宣言した変数を再び別の値で宣言しなおすことです。

varで再宣言すると、あとに宣言した変数が適用されます。
letやconstやで再宣言するとエラーがでます。


```.js
//var
var a = 1 //最初の宣言
var a = 2 //2回目の宣言

console.log(a) //'2'と出力される。2回目で再宣言された a = 2 が適用されるため。

//let, constはエラーがでる。
```

<br>
###スコープ

スコープとは宣言した変数が使える範囲のことです。
varは関数スコープ、letやconstやはブロックスコープの範囲で変数の値が適用されます。

####関数スコープ
関数とは複数の処理をひとまとめにしたものです。
varで変数を宣言すると、同じ関数内であればどこでも呼び出せることができます。

```.js
//関数
function kansuu {

  //ifで条件づけられたブロック
  if (true) {
    var a = 1
  }

console.log(a) // '1'が出力される。varで変数を宣言すると関数内のどこでも呼ぼび出すことができるため。

}
```


####ブロックスコープ
' {　} 'でくくられた範囲のことをブロックといいます。

letやconstで変数を宣言すると、同じ関数内であってもブロック内でなければ変数を呼び出すことができません。


```.js
//関数
function kansuu {

  //ifで条件づけられたブロック
  if (true) {
    let a = 1
    const b = 2

    console.log(a) // '1'が出力される。ブロック内で'a'の値を呼び出したため。
  }

console.log(b) // 出力されない。ブロック外で'b'の値を呼び出したため。

}
```

<br>
RSpec(model)の読みやすい書き方

#Rubyでテストを書くにあたって:point_up:
コメントにてご指摘をいただき、
Rspecをrailsなしで、ruby上で使うための設定方法を調べてみました。
https://stackoverflow.com/questions/12307097/how-to-use-rspec-without-rails


##userモデル
今回はこちらのメソッドへのテストの書き方について！

```ruby:user.rb

class User
  def fullname
    [name, surname].join(' ') if middle_name.nil?
    [name, middle_name, surname].join(' ') if middle_name.nil?
  end
end
```
##userモデルRspec
userの名前が定義されている状況に応じて異なるフルネームを返す。

```ruby:user_spec.rb

 describe 'fullname' do

    context 'with surname and name' do
      let(:user) { build(:user, surname: 'delicious', name: 'banana') }

      it 'shows full name without middle name' do

        expect(user.fullname).to eq('banana delicious')
        
      end
    end

    context 'with surname, name and middle name' do
      let(:user) { build(:user, surname: 'delicious', name: 'banana', middle_name: 'super') }

      it 'shows full name with middle name' do

        expect(user.fullname).to eq('banana super delicious')
        
      end
    end
  end
```
#どこに何を書けば良い？:writing_hand:
``describe``: メソッド名
``context``: 状況設定
``it``: returnされる結果

describe後にメソッド名のみを記載する事で、
後にテストを探す際、"describe 'メソッド名'"で探すと瞬時に見つけることができ、便利になります。

改善のアドバイス等ある方はコメントいただけると嬉しいです！:pray:
[Flutter] Gitリポジトリからダウンロードしたプログラムでエラー

<h2>はじめに</h2>
Windowsで作成したFlutterアプリをGitリポジトリを通してMacにダウンロード。
それを起動させようとしたらエラーが出てきた。
Firebase関連のプラグインのバージョンを変えたりして、試行錯誤していたら余計にハマった。
バージョンがあってないやら、ファイルがみつからないやら、、、、、
あまりにも適当にやりすぎてエラーを再現できないが、備忘録としてエラー回避できた方法をいくつか残す。

<h2>エラー内容</h2>

    Error output from CocoaPods:
    ↳
        [!] Automatically assigning platform `iOS` with version `9.0` on target `Runner` because no
        platform was specified. Please specify a platform for this target in your Podfile. See
        `https://guides.cocoapods.org/syntax/podfile.html#platform`.

    Exception: Error running pod install

<h2>対策①</h2>
1.ダウンロードしたプログラムファイルの``プログラム名/ios/Runner.xcworkspace``を``xcode``で開く
2.赤枠で囲んだ部分のバージョンを``iOS 13.0``に変更
![dev001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223039/80ccd36a-0dff-7d79-e16d-8343f4181e8d.png)
3.``xcode``を保存して閉じる
4.``flutter run``

<h2>対策②</h2>
1.``flutter clean``
2.``flutter build``

<h2>対策③</h2>

1.``flutter clean``
2.``flutter pub get``
3.``cd ios``
4.``pod install``
5.``pod repo update``
6.``pod update``
7.``cd ..``
8.``flutter run``

<h2>対策④</h2>

1.対策①の3までやる
2.対策③を全部やる

<h2>参考URL</h2>
https://github.com/FirebaseExtended/flutterfire/issues/1979
https://dolphinetech.com/flutter/error-running-pod-install/
https://fluttercorner.com/solved-error-could-not-find-included-file-generated-xcconfig-in-search-paths-in-target-runner/

<h2>最後に</h2>
エラーが出るとどうしてもあわわなる、、、
落ち着いてエラー内容をちゃんと読めば何とかなるさ！

最初からMacで作ればいいじゃない
【Rails】Herokuにデプロイ後、一部のページで500エラー(Internal Server Error)

#はじめに
本番環境にて500エラーが発生し
1週間ほど悩み通してようやく改善したのでこの機会にまとめておきたいと思います。

#発生している問題
ローカル環境では問題なく動くが、(PostgreSQLへの対応などは済ませてある)
Herokuにデプロイすると、一部のページを開いたときに500エラーが出て「We're sorry, but something went wrong.」となる。
![error500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1397163/5734db7f-c0a4-8715-efc5-5f25b974a715.png)

`heroku logs -t`でログを見ても500と書いてるだけで何が悪いのかよくわからない

```
2021-05-14T16:33:21.741002+00:00 heroku[router]: at=info method=GET path="/recipes" host=myapp.herokuapp.com request_id=58d9aaaf-b1c3-46ab-a97c-51d54f102341 fwd="14.10.86.33" dyno=web.1 connect=1ms service=23ms status=500 bytes=1827 protocol=https
```

#対処
**マイグレーションの実行**
DBのマイグレーションがうまくいっていない場合が多いみたいなので、`heroku run rails db:migrate`を試してみるが、特にエラーも出ず実行できた。だがそれでも改善しない。

設定などあちこち見ても悪いとこはなさそう・・・

#結論
もう一度Herokuのログを見直してみると何やら書いてあった。

```
FATAL -- :  ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR:  relation "recipes" does not exist
```
```
WHERE a.attrelid = '"recipes"'::regclass
```
調べてみるとどうやら「テーブルが無いよ」という意味らしい。


そこで`heroku run rails c`でコンソール起動し`モデル名.column_names`でカラム名確認するとテーブルが無いとエラーが出た。
原因はこれだったみたい。
`db:migrate`で上手くいかなかったのでDBリセットで対処することに。

`heroku pg:reset DATABASE_URL`コマンド実行

```
WARNING: Destructive action
 ▸    データベース名 will lose all of its data
 ▸    
 ▸    To proceed, type アプリ名 or re-run this command with --confirm
```
こういったメッセージが出るので、アプリ名を入力して実行すればリセット完了。

もう一度`heroku run rails db:migrate`実行し、コンソールでテーブル確認すると今度はきちんとテーブルができてる。
デプロイしたアプリも正常に動くようになった。

#最後に
今回学んだのはログってすごく重要だということ。
何がダメかちゃんと書いてあるし、これからはしっかり見るようにしよう。

500エラーで悩んでる人結構いると思うので
この記事がお役に立てれば幸いです。