OmniAICreator/Qiita-1.07M huggingface dataset:
heroku postgresのバックアップ/データ移行のコマンド一覧

この記事では、herokuのpostgresのバックアップ関連で使うコマンドを一覧で紹介しています。
後半では、pg:copyを使ったプラン変更時のデータ移行のコマンドを実行順に紹介しています。

参考: [Heroku PGBackups](https://devcenter.heroku.com/articles/heroku-postgres-backups)

# heroku-postgresの情報を確認する

```bash
heroku pg:info --app sushi
```


# バックアップに使うコマンド類

```bash

# マニュアルバックアップする(--verbose フラグで実行ログを見られます)
heroku pg:backups capture --app sushi

# バックアップをキャンセルする
heroku pg:backups:cancel --app sushi

# バックアップを削除する
heroku pg:backups:delete b999 -a sushi

# JST 午前0時にバックアップをスケジュールする
heroku pg:backups schedule DATABASE_URL --at '00:00 Asia/Tokyo' --app sushi

# スケジュールを確認する
heroku pg:backups schedules --app sushi

# スケジュールを削除する
heroku pg:backups unschedule DATABASE_URL --app sushi

# heroku上のバックアップデータからリストアする
heroku pg:backups restore b999 DATABASE_URL --app sushi

# sushiからsashimiへバックアップデータを使ってリストアする
heroku pg:backups restore sushi::b999 DATABASE_URL --app sashimi --confirm sashimi

# AWS S3などにアップ済みのバックアップファイルをURLで指定してリストアする
heroku pg:backups:restore 'https://s3.amazonaws.com/me/items/sushi_backup.dump' DATABASE_URL -a sushi

# バックアップの公開URLを取得する
heroku pg:backups public-url --app sushi

# バックアップのdumpファイルをローカルに取得する
heroku pg:backups:download  --app sushi

# 実行中のバックアッププロセスを確認する
heroku pg:psql -c "select * from pg_stat_activity where application_name = 'Heroku Postgres Backups'" --app sushi
```


# heroku pg:copy を使った新しいプランへのデータ移行の一連のコマンド
* pg:copyコマンドは、データサイズは10Gまでの制限があります。
* 10Gを超える場合は、同一アプリ内ならpg:upgradeが利用できるようです。
* 別アプリへのデータ移行は、バックアップファイルからリストア先を変更してコピーすることもできます。

```bash

# 新しいプランのpostgresが追加されている前提です
# 新しいデータベースでtimezoneを設定する
heroku pg:psql -a sushi
$ show timezone;
$ alter database your_database_name set timezone = 'Asia/Tokyo';
$ select current_timestamp;
$ \q

# DATABASE_URLのアタッチが正しいか確認する
heroku config -a sushi | grep DATABASE

# メンテナンスモードにする
heroku maintenance:on -a sushi

# ワーカーがあれば停止しておく
# heroku schedulerを使っていればはGUIから停止する
heroku ps:scale worker=0 -a sushi

# バックアップを取る
heroku pg:backups capture DATABASE_URL -a sushi

# バックアップを確認する
heroku pg:backups -a sushi

# pg:copyでデータを新しいデータベースへコピーする
heroku pg:copy DATABASE_URL {NEW_DB_NAME} -a sushi

# 新しいデータベースを昇格させる
heroku pg:promote {NEW_DB_NAME} -a sushi

# 昇格されたのを確認する
heroku config -a sushi | grep DATABASE

# バックアップスケジュールを確認する
heroku pg:backups schedules -a sushi

# 新しいpostgresの方でバックアップを取る
heroku pg:backups -a sushi

# ワーカーを再開する
# heroku schedulerはGUIから再開する
heroku ps:scale worker=1 -a sushi

# メンテナンスモードをオフにする
heroku maintenance:off -a sushi

# 古いデータベースを削除する
heroku addons:destroy {OLD_DB_NAME} -a sushi

```

# postgresのデータの他のアプリケーションへのコピー

```bash
# sushiアプリ から sashimiアプリ へデータをコピーする
heroku pg:copy sushi::DATABASE_URL DATABASE_URL --app sashimi
```

# データベースのアタッチとデタッチ
* 参考: [Sharing Heroku Postgres between applications](https://devcenter.heroku.com/articles/heroku-postgresql#sharing-heroku-postgres-between-applications)

```bash
# データベースをattachする
heroku addons:attach my-originating-app::DATABASE --app sushi

# データベースをdetachする
heroku addons:detach HEROKU_POSTGRESQL_BRONZE --app sushi
```
0.1ぐらいから始めるProjectEuler@python　Problem 6

どもども、最近ボッチなとある学生です。
というわけで、6問目書いていきましょう。

```python:Problem_6.py
#最初の10個の自然数について, その二乗の和は,1^2 + 2^2 + ... + 10^2 = 385
#最初の10個の自然数について, その和の二乗は,
#(1 + 2 + ... + 10)**2 = 3025
#これらの数の差は 3025 - 385 = 2640 となる.
#同様にして, 最初の100個の自然数について二乗の和と和の二乗の差を求めよ. 
a=1
b=0
c=0
d=0
e=0
while not a>100:
    c+=a
    e=a**2
    b+=e
    a+=1
    d=c**2
print(d-b)
```
解　25164150
はい、私はこう書きました。
今回はすごい簡単でしたね。（難易度の差が激しいと思うのは私だけですかね？）
####解き方の解説をしていきます。
cにaを入れ続けて、eにaを2乗した値を入れ続け、それをbに入れ続けて、
aに１を足し続けて、dにcを２乗したものを入れて、最後にd-bを出力するって感じです。

無駄が多すぎてびっくりです。
これからは、解けたら終わりではなくもっといいプログラム？になるように考えてから投稿します。
でもまぁひとまずは、こんな感じですかね？もしわからないことやアドバイス等あればコメントしていただければと思います。
というわけで気が向いたら次も見ていってください。よろしくお願いします。
RFC 8252 OAuth 2.0 for Native Apps

[RFC 8252 OAuth 2.0 for Native Apps](https://tools.ietf.org/html/rfc8252) ざっくりまとめ

※ 外部User Agent、埋め込みUser Agentといった独自用語の定義は[Terminology](https://tools.ietf.org/html/rfc8252#section-3)を参照

5 Using Inter-App URI Communication for OAuth

* ネイティブアプリは外部User Agent（一般的にはブラウザ）を使って認可要求を行わなければならない (MUST)
  * ブラウザが持つSSOセッションや認証コンテキストを活用できる

6 Initiating the Authorization Request from a Native App

* ネイティブアプリ（Public Clientとなるもの）はPKCEを実装しなければならない (MUST)
* 認可要求を受け取る外部User Agentについて、本ドキュメントではブラウザを推奨する (RECOMMENDED) が、他の認可要求を扱う専用のアプリといった他の外部User Agentを利用してもよい (MAY)
* in-app browser tabがサポートされるプラットフォームでは、ユーザビリティのためにin-app browser tabの使用が推奨される (RECOMMENDED）
  * in-app browser tab：ブラウザのタブをアプリから使う機能（ブラウザのセキュリティコンテキストを使うことができる）

7 Receiving the Authorization Response in a Native App

* 認可サーバーはネイティブアプリの認可応答受信方法について、少なくとも次の3つをサポートしなければならない (MUST)
* Private-Use URI Scheme Redirection：アプリ間で通信するための独自URIスキームを使う方法
  * ネイティブアプリはドメインを逆順にしたURIスキームを使わなければならない (MUST)
  * 例：`com.example.app:/oauth2redirect/example-provider`
* Claimed "https" Scheme URI Redirection：httpsスキームのURIをアプリで受信する方法
  * ネイティブアプリのIdentityを特定できるため、この方法が使えるプラットフォームはこれを使うべきである (SHOULD)
* Loopback Interface Redirection：httpスキームのループバックI/F（例：`http://127.0.0.1:12345/oauth2`）を使う方法（デスクトップアプリなど特定のループバックI/Fポートを監視できるもの向け）
  * 認可サーバーはリダイレクトURIのうちポート番号を可変にしなければならない (MUST)
  * ネイティブアプリはIPv4・IPv6両方のループバックI/F利用を試みて利用可能な方を使う、という実装が推奨される (RECOMMENDED)

8 Security Considerations

* 認可サーバーはPKCEを使わないPublic Clientからの認可要求を拒否すべきである (SHOULD)
  * リダイレクトURIにhttpsスキームを使ったとしても認可コードの傍受のリスクは（Private-Use URIやLoopback Interfaceよりも低いが）残る
* Implicit GrantはPKCEを使えないため、ネイティブアプリでは推奨されない (NOT RECOMMENDED)
* Loopback Interfaceを使う場合は、認可要求から認可コード受信の間のみポートを開け、Redirect URIにはlocalhostではなくLoopback IPアドレスを使うべきある (SHOULD)
* 認可サーバーはネイティブアプリをPublic Clientとして登録しなければならない (MUST)
* 認可サーバーはクライアントにクライアントに完全なリダイレクトURIを登録を要求し、登録されたURIに完全一致しない（Loopback URIでのポート番号を除く）認可要求を拒否しなければならない (MUST)
* Private-Use URIを使う場合、認可サーバーはドメイン名の逆順のスキームを利用をすべきであり、少なくともピリオドを含まないURIは拒否すべきである (SHOULD)
* 認可サーバーはアプリのパッケージ名やバンドル名といった、クライアントのIdentityを検証するためのプラットフォーム依存の情報を要求してもよい (MAY)
* ネイティブアプリを共有鍵（Client Secret）で認証することは、クライアントIDをリクエストパラメータに入れる以上の意味を成さないため推奨されない (RECOMMENDED)
  * 共有鍵でネイティブアプリを認証する場合も、認可サーバーはネイティブアプリをPublic Clientとして扱わなければならない (MUST)
* 認可サーバーはクライアントのIdentityが証明できない場合は、（過去に同意があったとしても）ユーザーとの対話なしに認可を進めるべきでない (SHOULD NOT)
  * httpsスキームのリダイレクトURIの使用はIdentityの証明と扱ってもよい (MAY)、またプラットフォームによってはIdentityを証明する別の手段を用意していることもある。
* ネイティブアプリにおいても、アプリにおけるCSRF攻撃を防止するために、stateパラメータを使うことが推奨される (RECOMMENDED)
* Mix-up攻撃に対応するため、ネイティブアプリは認可サーバーごとに異なるリダイレクトURIを使わなければならない (REQUIRED)
  * ネイティブアプリは認可要求時のリダイレクトURLパラメータを保管し、認可応答のURIと完全に一致することを検証しなければならない (MUST)
* 本ドキュメントでは外部User Agentとしてブラウザを推奨するが、他の外部User Agentについては言及しない。
* ネイティブアプリは認可要求に埋め込みUser Agentを使ってはならなく (MUST NOT)、認可サーバーは認可要求エンドポイントへの埋め込みUser Agentからのリクエストを検知してブロックしてもよい (MAY)
  * 埋め込みUser Agentでは、ユーザーが入力した認証情報やCookieにアプリからアクセスできてしまう。
  * First-partyアプリであっても、アプリに不要な権限を与えることとなり、またユーザーに正当なサイト以外でも認証情報を入力してよいと認識されてしまう。
compTIA security+に受かったので初qiitaです

# compTIA security+に受かったので初qiitaです

## せっかちな人向けの結論
- Security+ テキスト SY0‐501対応 (実務で役立つIT資格CompTIAシリーズ)を買って勉強する
- TACのweb模擬試験を解きまくる、7割くらいそのままの問題が出てくる
- ネットワークのトラブルシューティングの問題があるため、慣れていない人はネットワークのコマンドやARPテーブルの見方、ファイアウォールのルールの見方を覚えておく

## compTIA security+について
> CompTIA Security+は、ベンダーニュートラルの認定資格です。Security+認定は、業務を遂行する上で必須となるエントリーレベルのセキュリティスキルおよび知識を判断する、国際的に認められた認定試験で、世界中の企業およびセキュリティプロフェッショナルに活用されています。

> CompTIA Security+認定資格試験に合格することで、アプリケーション、ネットワーク、デバイスのセキュリティを確保するために必要なシステムのインストールと設定、プラットフォームへの脅威を分析して適切な手法で緩和する対応、関連するポリシーや法規制を正しく認識した運用を行うために必要な知識とスキルを証明します。また、これらのタスクを、機密性、完全性、可用性の三大要件を維持し実行が可能なスキルを証明します。  出典 https://www.comptia.jp/certif/core/comptia_security/

サイバーセキュリティ関係の世界的に有名な資格だそうです。

このcompTIAという資格の問題を制作する際には様々な大企業や組織が関わっているそうです。
~~イカれたメンバーを紹介するぜぇ！~~
- IBM
- デロイトトーマツ(世界最大の会計事務所)
- アメリカ軍（陸軍海軍空軍海兵隊）
- ミネソタ州(アウトドア系が多いらしい)
- e-secure
- サウスイースタンルイジアナ大学

米軍が関係してくるというのがなかなか興味深いです、試験の注意事項や各種アンケートに「退役軍人局が～」「あなたは退役した～」と平然と書かれているのが、この資格が今まで受けてきた資格と色々違うんだなぁと感じました。~~あとミリオタの血が騒ぐ~~

## ここがいいぞcompTIA security+
- 世界的に評価されてる資格（らしい）
- セキュリティ系の需要が世界的に増えていく
- 実技問題があるので少し評価が上かも.....
- __ここ重要__ 米国防総省では情報資産に関わる人に取得を義務付けているhttps://www.comptia.jp/information/2019/05/comptia-dod.html
- ~~とりあえず米軍とかトーマツが関わってると言えばハッタリになるかも~~

今後セキュリティの需要が増えればこの資格の需要も増えるんじゃないかなぁと思います、過剰に専門的な事（ツールの使い方など）を問われないため持っていて損はしないタイプだと思います~~（増えて）~~

## ここが悪いぞcompTIA security+
- 高すぎる受験料(さっき見たら39756円とか書いてあった)
- 日本語の情報量が少ないため勉強しずらい
- ところどころ英語を読む根気が必要
- 3年更新なので財布が薄くなる

英語の方はまぁgoogle翻訳と根気があれば中学英語すら怪しい私でもどうにかなりました。
問題は金です、正直会社が負担するでもないとお値段7情報処理技術者試験、または2switchなので受ける気が起きないと思います。
海外の資格みると1情報処理技術者試験が安いんやなって。

#### 受験方法
海外の資格を受ける人ならおなじみピアソンから申し込めます。私が住んでる日本のチベットこと岩手県でも会場があるので結構多いのかも？CBT受験になっております。人混みが苦手な人でも安心！

参考
https://www.pearsonvue.co.jp/Clients/CompTIA.aspx

#### どうやって合格したか
　~~タダで受けれたから~~セキュリティへの強い興味と今後増大するサイバー犯罪から情報資産を守りたいと考えたため勉強してた私ですが、
- テキストを最後まで読んで気になったところを調べる
- TACの模擬試験の問題を頭に叩き込む
この2つでどうにかなりました。
内容はテキストにある範囲でだいたい収まるのでしっかり勉強すれば合格自体は難しくないかと。セキュリティ関係の本職の方ならテキストを流し見すればいけるかもしれませんが（特に実技問題）、ネットワーク関係が苦手な人は勉強必須だと思います。

TAC製の問題集の問題が本番で出てくる問題と被っていたため、それを解いていると正答率が大幅に上がります。
~~いや～不思議なこともあったもんだぁ~~

　おそらく一番厄介なのは実務問題です。トラブルシューティングの問題があります。
　ネットワークの構築やトラブルシューティングをやってきてないと理論でARPテーブルやファイアウォールの操作を覚えていても実際に何度か設定をしてみないと正解は難しいと思います。

合格率を少しでも上げたい方はファイアウォールやARPの設定やネットワーク関係のコマンドを一通り覚えておくといいと思います。
コマンドといっても基礎的なping,tracert,arp,netstatくらい分かれば十分解けたので、勉強はそこまで時間はかからないかもしれません。


## 個人的な困ったこと
### 2枚身分証の提示を要求される
- https://www.pearsonvue.co.jp/test-taker/Tutorial/Identification-2.aspx

見出し通りです、まず身分証を複数携帯する人はそうそういないと思いますので、出発前にしっかり確認してください。
社員証や学生証を持っている人ならば保険証やクレカなどで通るという例外もあるので上記のサイトをよく見ていただきたいです。

持ってない人は顔写真付きの公的な身分証を用意する必要がある。おそらくパスポートと写真付き住基カード、マイナンバーカードが入手しやすいかと

### 合格証が来るまで8週間かかる
合格後貰えるレポートの番号を使って申請できる。ただ到着までかなり時間がかかるため、転職などに使う方は到着まで時間がかかることを見越して動いたほうがいいと思います。

## 最後に
模擬問題が本番だったとか色々ありましたが、やっていくとフィッシングも経営陣向けのホエーリングなどサイバー攻撃にも色々あるなど得られた知識は多かったので個人的にやってよかったと思いました。
正直個人でこの金額を出すのは厳しいですが、会社が負担してくれるなど機会があれば是非とも受けてみてほしいと思います。

ここまで拙い文章でしたがご覧いただきありがとうございました。


![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447503/de20fd25-b6e3-93d8-b230-0e5564a9804e.png)

2020/02/29
ストック通知をとても嬉しく感じています、ありがとうございます...
AWS認定ページへのログインと試験予約ページへの行き方


# AWS認定の試験予約ページへの行き方メモ

※更新履歴
2022/06/26, AWS認定へログインしたらログイン方法が変わっていたので記事を全体的に更新しました。
2022/07/05, AWS側でもログイン方法の切り替え中なのか、古いログイン画面に飛ばされることもあります。記事中に注意書きを追加しました。

## 1. AWS認定ページへのログイン

※2022/06/26更新時点の情報です。AWSサイトはコロコロ変わるので、ログイン方法が変わっていたら、コメントに書き込んでいただけると嬉しいです。

1. 右記リンクから  [AWS トレーニングと認定](https://www.aws.training/Certification/) へ入る。
1. 「AWS認定」が表示されるので、画面中央に表示された「サインイン」をクリック。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238650/4e9308ba-fc7a-4a47-b73a-9ece82d8319c.png)
1. 「アマゾンでログイン」をクリック
    - ここは人によるため、最適なものを選んでください。
    - 僕は買い物等に使うAmazonアカウントでAWS認定も管理しているので「アマゾンでログイン」です。
    - 初回のAWS認定申込み時に使ったAmazonアカウントで、今後もAWS認定を管理することになる（と思う 汗）
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238650/e6f81e5f-e376-b48f-ff4d-6f8ffff921b9.png)
    - <font color="Blue">※上記画面にならずリージョンを聞かれる画面に行く場合、「旧記事」を参考にすると良いかもしれません。AWS側もログイン画面を切り替え中なのかもしれません。</font>
1. 「Eメールまたは携帯電話番号」と「パスワード」を入力してログインする。
1. 再度「AWS認定」が表示されるので、画面中央に表示された「アカウントに移動」をクリック。
1. やっと、AWS認定ページに入れます。ここから認定に関する情報が閲覧できます。

## 2. 試験の予約ページ
1. AWS認定ページへログインしたところから開始。
1. 上部の「試験登録」タブをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238650/851cdeb2-87f3-2d42-4638-32e402a84e4d.png)
1. 「試験登録」ページが表示。ここから試験関係の操作が出来ます。
1. 受験したい試験を探します。
    - ブラウザの検索機能や、試験名 or 試験コードでの検索
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238650/c913d8e6-897e-8a1e-0a07-66fd457d2a42.png)
1. 資格名の右側から「PSI」「ピアソンVUE」の入り口があるので好きな方へ入る。
    ※2019年4月からピアソンVUE利用可。自分はピアソンVUE派です。
1. ここからは画面の指示に沿って操作。

※こういうエラーが出て試験登録できない場合もありますので、時間を置いて試してみてください。
> 事前承認された試験の適格性が遅延する可能性があることに注意してください。あなたのアカウントが優先されるよう自動的に更新しました。Pearson VUE または PSI の試験のスケジュールを設定できない場合、アカウントからログアウトし、1～2 時間以内にやり直してください。この時間はシステム上の負荷によって異なります。当社チームが解決に向けて尽力しています。ご迷惑をおかけしますがご理解のほどよろしくお願いします。


## 3. スコアレポートの置き場所

1. AWS認定ページへログインしたところから開始。
2. 上部の「試験履歴」タブを選択すると「スコアレポート」がダウンロードできます。 
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238650/f53f4682-05bc-1685-c99d-9be94b1a3df1.png)
3. 受験後から発行まで５日かかるという情報もありますが、僕の場合は１日～２日程で発行されました。





<br>

## 3. 旧記事をしばらく残します。
<details>
<summary> <b>クリックで「旧記事」の内容を展開</b>  </summary>
<div>
■ こちらは旧記事です。念のためしばらく残しておきます ■

## ■試験の予約ページ

1. 右記リンクから  [AWS トレーニングと認定](https://www.aws.training/Certification/) へ入る。
2. AWSトレーニングと認定が表示されるので、右上「サインイン」をクリック。
3. 表示されたページでamazon側の「日本」にチェックして「サインイン」をクリック。
4. 既存のamazonアカウントでログイン（またはTraining用に新規アカウント作成）
    + [AWSトレーニングのFAQ](https://aws.amazon.com/jp/training/faqs/)
        - AWS tranigアカウントの作成方法
        - AWS tranigアカウント と AWSアカウントは関連付けされない
5. ダッシュボードが表示されたら、上部の「認定」をクリック。
6. AWS認定が表示されたら、中央付近「アカウントに移動」をクリック。
    ※↑アカウント作成状態により異なるかも。
7. AWS認定アカウントが表示。ここから試験関係の操作が出来ます。

8. 右側「新しい試験の予約」をクリック。
9. 試験の申し込みが表示されたら、「SAA-C01」で検索。
10. 検索ヒットの右側から「PSI」「ピアソンVUE」の入り口があるので好きな方へ入る。
    ※2019年4月からピアソンVUE利用可。自分はピアソンVUEを使いました。
11. ここからは画面の指示に沿って操作。

## ■スコアレポート

1. 「試験の予約ページ」の「1～7」を実施。

2. AWS認定アカウント上部の「これまでの受験履歴」を選択すると「スコアレポート」がダウンロードできます。 ※発行まで５日かかるという情報もありますが、１日～２日程で発行されるようです。

</div>
</details>


<br>
【リモート参加でも臨場感が伝わる不思議さ】吉祥寺.pm 19 Twitter参加レポ #kichijojipm

今回は直前に都合が付かなくなり、泣く泣くTwitter参加。
でも楽しい感じが伝わってきた。不思議なもんだ。
Twitter参加って意外とやったことないので、不思議な体験をした。

#### [イベント詳細はこちら](https://kichijojipm.connpass.com/event/138022/)

イベント中はハッシュタグがトレンド入りしてたし、TLの流れが速くて追っていくのが大変だった。
でも、写真がたくさん上がってたり、登壇資料が即アップされるなど、臨場感は高いなと感じた。

映像も音声もないので（Twitterだから当然か）、写真と登壇資料のアップは嬉しい。
あとで読み返すのも良いんだけど、なぜかイベント中に読むと伝わるものが違ってきて楽しいんだな。

LTの順番が入れ替わったり、ノートパソコンのバッテリートラブルがあったり、起きたことがリアルタイムで伝わってくる。
一句詠んだときの拍手が聞こえてくるようだ。

イベント終了　⇒　移動　のあいだはツイートがいったん止まるところとか、懇親会が始まるとビールジョッキがたくさん写ったり、ハッシュタグをきちんと付けてる人が結構いたり。なんというか、楽しそうだなと。

懇親会、メンバー足りたようで、何より。
懇親会後のツイートは、エモさが増していたり。

ダイジェスト感があって、見てて飽きない。
こういう参加の形態もあるんだなーと。
これを参加者が自主的にやってるんだから、そういった意味でもありがたいし、今後はツイートの仕方も、工夫できるように思った。いつも写真をアップしてくれる人とか、ありがたいなと思った。
form_forの種類 

# form_forとは
railsで情報を送信するためのヘルパーメソッドです。

そのため多くのrailsアプリケーションで使用されます。

# 基本構文
簡単なフォームの書き方

```haml:◯◯◯.haml
form_for(モデルオブジェクト , オプション) do |f|
  フォームコントロールの設置
```

# form_forの種類
|メソッド名|説明|
|:---------|:---------------|
|check_box|チェックボックス|
|color_field|色の入力欄|
|date_field|日付の入力欄|
|datetime_field|日時の入力欄（グローバルタイム）|
|datetime_local_field|日時の入力欄（ローカルタイム）|
|email_field|emailアドレスの入力欄|
|fields_for|form_forの中で別のモデルを指定したフォーム|
|file_field|画像や文章などのファイルを選択するフォーム|
|hidden_field|隠しフィールドの生成|
|label|ラベルの生成|
|month_field|月の入力欄|
|number_field|数値入力欄|
|password_field|パスワード入力欄|
|telephone_field,phone_field|電話番号入力欄|
|radio_button|ラジオボタンの生成|
|range_field|範囲選択バー|
|search_field|検索ボックスフォーム|
|text_area|文字列入力欄|
|text_field|文字列入力欄|
|time_field|時間入力欄|
|url_field|URL入力欄|
|week_field|週の入力欄|
|submit|送信ボタン|

### 以上簡単な使い方と種類です
小娘が基本情報技術者試験に一発合格した話

　情報系の学部に所属する女子大学生が、2ヶ月半の勉強で基本情報技術者試験(以下FE)に合格した話。投稿の練習がてら何を書こうと思った時、申し込み今頃だったなぁと思い出したため、書いてみました。

FEのリンクを貼っておきます。
[IPA 独立行政法人 情報処理推進機構:基本情報技術者試験](https://www.jitec.ipa.go.jp)

#資格前の知識レベル
　私がFEに挑戦したのは大学2年の秋。国家資格を得たいという欲望と、情報の基礎知識を定着したいという願望のもと8月から勉強を始めた。
　

- この時点で知識があった分野
    - ソフトウェア
    - ハードウェア
    - アルゴリズム・プログラミング
    - ネットワーク(多少)
    - セキュリティ(多少)   
    
- この時点で知識がなかった分野
    - データベース
    - 開発技術
    - マネジメント
    - システム戦略・サービス戦略
    - 法務


これはかなり知識に偏りがありますね…。

#使った参考書
[平成30年度-イメージ-クレバー方式でよくわかる栢木先生の基本情報技術者教室](https://www.amazon.co.jp/平成30年度-イメージ-クレバー方式でよくわかる栢木先生の基本情報技術者教室-情報処理技術者試験-栢木/dp/4774193275/ref=pd_sbs_14_3/354-4729588-4219709?_encoding=UTF8&pd_rd_i=4774193275&pd_rd_r=8fa8413f-f4d2-4e79-8302-195c1850241a&pd_rd_w=9pGDZ&pd_rd_wg=nLcDR&pf_rd_p=ad2ea29d-ea11-483c-9db2-6b5875bb9b73&pf_rd_r=Q4TG0FDBSEWPZCHSXY38&psc=1&refRID=Q4TG0FDBSEWPZCHSXY38)
[平成31/01年 イメージ&クレバー方式でよくわかる 栢木先生の基本情報技術者教室(最新版)](https://www.amazon.co.jp/平成31-01年-イメージ-クレバー方式でよくわかる-栢木先生の基本情報技術者教室/dp/4297101831/ref=dp_ob_title_bk)
　猫の表紙が特徴的な一冊。わかりやすい説明と演習があるので取り組みやすい。半年に一回新しい本が出ているようなので、現在(2019年8月3日)の最新版も載せておきます。



[過去問道場](https://www.fe-siken.com/fekakomon.php)
　参考書ではないが午前対策で使っていたサイト。午前の過去問をひたすらおこなえる。分野別で解けたり出題年度を指定できたりして、移動時間の勉強に便利だった。


午後は、IPAさんが公開している過去問を使用して勉強した。

#勉強方法
午前の勉強がほとんどです。午後は過去問を少しだけやった程度。

###最初の一ヶ月で参考書を読み切る
　先ほど紹介した柏木先生の参考書を購入し読み始めた。しかしこの参考書、出題範囲が広いためしょうがないが、心がめげそうになる程分厚かった。
　そこで私は、最初の一ヶ月で参考書を読み切ることを目標にした。内容が概ね理解できる程度に読み進め、苦手だった箇所は読み切った後に復習することに決め実行した。

###残り一ヶ月半で過去問や復習
　参考書を読み切った後、苦手な範囲だけ何回も読み返した。一通り頭に入った後は、過去問道場を使いひたすら演習。
　この過去問道場は分野別の正答率も出してくれるので、苦手な分野がすぐわかる。苦手がわかったらまた復習というように、ひらすらループして弱点を潰した。

#本番
###午前
　体感として、過去に出題された問題が3割程度でた。そのため、見たことがある問題も多くあまり焦らず解くことができた。ちなみに時間はギリギリでした。
###午後
　午後は過去問で対策したぐらいで全然勉強してなかったので、時間配分に失敗。もっと問題を早く読み解く力が必要だったと思う。アローダイアグラムなど得意な問題が出題されたため、こんな私でもなんとか点が取れた。

#本番を経て感じたこと
主に3点

- 午前は過去問演習が大事
- 午後は、午前の知識をどれだけ活用できるか
- どちらも本番の試験時間を想定して、演習に取り組むべき

　午前に関しては、思っていたより過去問が出て簡単だと感じた。実際、周りの友人も午前は合格点とれていたという子が多かった。
　午後に関しては、どれだけ知識を自分のものにできているかが問われるような感じがした。これも問題慣れしておく必要あり。また、アルゴリズムやプログラム言語に触れたことのない人は、かなり時間をかけないと難しいレベルだった。時間をかけて理解するか、最初から捨てるかしかないのかなぁ……。


　まあまあ難しいレベルの資格だとは思うが、正直IT系に進む人はとっておきたいところ。まずは申し込みから始めよう!!!
herokuにgit pushしたURLを開くと、Method Not Allowed と表示されてしまう

# ※初学者向けです。
Ruby on Railsで`git push`したURLを開くと、`Method Not Allowed`と表示されてしまって困った時の対処法をメモ。

# 結論
開くURLが間違っています。正しいURLを開けば即解決します。

# 経緯
作成したファイルをコミットして、いざ`git push`！
※開発環境は、AWS C9を使用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/c923ceb2-43f8-0f14-82d3-14f10dbda5e1.png)

すると、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/c042e697-9fa8-90d9-6438-d0d2ffa4668a.png)

`Method Not Allowed`と記載されたページが開いてしまいました。
こんなはずじゃない...(泣)

# 対処
少しの間悩みましたが、原因は単純でした。
クリックすべきは、下記のURLの方でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/7d06c24f-bd88-b980-54a5-f115914c2caa.png)

よく見ると、正しいURLの横に`deployed to Heroku`とも書いてありましたね(汗)

というわけで、以上です。
同じ問題にぶつかった方の一助になれば幸いです。
サクラエディタ：JavaScriptでマクロ実装（置換編）複数行を一行毎に置換する

##複数行を置換するマクロになります。
####下記サンプルコードは、選択されている部分に対して、一行毎に『あ』で始まり『お』で終わる行を置換します。
```replace.js
function sakuraReplace(str00) {
 var i=0;
 var lines="";
 var str01="";
 
 lines = str00.split(/(\r|\n|\r\n)/); // 改行コードで分割して変数に代入
 
 for (i in lines) // 分割したライン数をループ
 {
    // 『あ』で始まり『お』で終わる行を置換します。
    str01 +=  lines[i].replace(/^あ.*お$/,'【選択されていた文字を置換しました。】',6) + "\r\n";
 }
 return(str01);
}

var str00 = Editor.GetSelectedString(0); // 選択部分を変数に代入
if ( str00 !== "" ) Editor.InsText(sakuraReplace(str00));
```
HTMLページでマウスオーバーすると背景画像が変わるJavaScriptを組む

#前提
　個人サイトを立ち上げる関係で、参考にしたサイトがスライドショーを実装していて「かっこいいな」と思い、自分なりに力技で解決した。
##マウスオーバーすると背景が変わる
　仕組み自体は単純で、HTML上でdivにクラスを設定、そのクラスにJavaScriptのdocument.querySelctor()とstyle.backgroundプロパティでスタイルをいじるだけです。

```HTML:index.html
<div class="top">
	<ul>
		<li><a href="foo.html"><span class="record" id="1">examplePicture1</span></a></li>
		<li><a href="foo.html"><span class="record" id="2">examplePicture2</span></a></li>
		<li><a href="foo.html"><span class="record" id="3">examplePicture3</span></a></li>
		<li><a href="foo.html"><span class="record" id="4">examplePicture4</span></a></li>
	</ul>
</div>
```
```js:script.js
document.querySelectorAll('.record').forEach((targetbox) =>{
	targetbox.addEventListener('mouseover', () =>{
		const topPic = document.querySelector('.top');
		if( targetbox.id == '1'){
			topPic.style.background = 'url(imgs/examplePic1.png)';
		}else if( targetbox.id == '2'){
			topPic.style.background = 'url(imgs/examplePic2.jpg)';
		}else if( targetbox.id == '3'){
			topPic.style.background = 'url(imgs/examplePic3.png)';
		}else if( targetbox.id == '4'){
			topPic.style.background = 'url(imgs/examplePic4.png)';
		}
	})
})
```
　この2つをそのまま実装すると、箇条書きになったリンクをマウスオーバーすることでdivブロック内の背景が変わります。

　ifとelseでつなげている部分がとっても力技めいていて改善の余地ありです。どうにかswitch文に変えてみてもいいかもしれません。

##仕組み
　HTML側はクラスとIDを設定しているだけなので割愛します。

```js:
document.querySelectorAll('.record').forEach((targetbox) =>{
	targetbox.addEventListener('mouseover', () =>{
```

　ここでクラス「record」を付与されている要素をすべて選択し、イベントリスナーを使ってマウスオーバーされた要素を選択しています。

```js:
const topPic = document.querySelector('.top');
		if( targetbox.id == '1'){
			topPic.style.background = 'url(imgs/examplePic1.png)';
```

　マウスオーバーされた要素のIDがNだった場合、style.backgroundで背景をN番目のものに変える……という動作をif文で繰り返します。力技です。気になる方はconsole.log(targetbox)を適当な場所に挿入して確かめてみてください。
##今後
　数十秒ごとに画像やhoverが変わるスライドショー型スクリプトの実装や、リンクの視認性を高めるための画像加工スクリプトを（あれば）実装していきたいと思っています。順次投稿予定。
Leetcode #399: Evaluate Division

```swift
class Solution {
    private var dict = [String: [String]]()
    private var vDict = [[String]: Double]()

    func calcEquation(_ equations: [[String]], _ values: [Double], _ queries: [[String]]) -> [Double] {
        for i in stride(from: 0, to: equations.count, by: 1) {
            vDict[[equations[i][0], equations[i][1]]] = values[i]
            vDict[[equations[i][1], equations[i][0]]] = 1.0 / values[i]
            if let value = dict[equations[i][0]] {
                dict[equations[i][0]] = value + [equations[i][1]]
            } else {
                dict[equations[i][0]] = [equations[i][1]]
            }
            if let value = dict[equations[i][1]] {
                dict[equations[i][1]] = value + [equations[i][0]]
            } else {
                dict[equations[i][1]] = [equations[i][0]]
            }
        }
        var answer = Array(repeating: -1.0, count: queries.count)
        for (i, query) in queries.enumerated() {
            var value = 1.0
            var visited = Set<String>()
            if helper(query[0], query[1], &value, &visited) {
                answer[i] = value
            }
        }
        return answer
    }

    func helper(_ start: String, _ target: String, _ value: inout Double, _ visited: inout Set<String>) -> Bool {
        if let ar = dict[start] {
            if start == target {
                return true
            }
            visited.insert(start)
            for str in ar {
                if visited.contains(str) {
                    continue
                }
                value *= vDict[[start, str]]!
                if str == target || helper(str, target, &value, &visited) {
                    return true
                }
                value /= vDict[[start, str]]!
            }
        }
        return false
    }
}
```
vagrant packageした時にThe Vagrant virtual environment you are trying to package must be powered off.とでる場合の対処法

vagrant packageした場合に表題のエラーが出る場合があります。

これは仮想マシンが正常に終了していない場合に発生します。

普通なら

```
vagrant halt
```

して仮想マシンをシャットダウンすればいいのですが、仮想マシンを起動中にホストマシン（PC本体）の電源を切るなどした場合は一度立ち上げてからシャットダウンしないといけません。

つまり

```
vagrant reload
```

して立ち上がったら

```
vagrant halt
```

して

```
vagrant package
```

します。
iOS Safariでcss filterを掛けると表示が壊れるときの対処法

css filter はぼかしや色変化など、要素に様々なフィルターを掛けるときに使います。
https://developer.mozilla.org/ja/docs/Web/CSS/filter

しかし、これを使用していると、iOS Safariに限って以下のような表示崩れに遭遇しました。
以下は複数の要素にdrop-shadowを適用していた際の出来事です。

<img width="375" alt="IMG_0004.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89220/76a08ac7-1e9a-b095-ff62-b1207cf6b807.png">

Webフロントエンドをやっていてこのような崩れ方（というよりは壊れ方）をしたのが初めてで何が起きているのかさっぱりわかりませんでした。

同じような現象に遭遇している方々
https://iwb.jp/safari-css-filter-images-apply-bug/
https://vanillaice000.blog.fc2.com/blog-entry-818.html

# 原因
要素にハードウェアアクセラレーションが効いていないことが原因のようです。

通常、3D Transform やcss filter などが適用された要素にはGPUレイヤーが作成され、描画が高速化されます。
しかしiOSでは、iOS6よりcss filter ではGPUレイヤーが作成されず、高速化されなくなったようです。

真意はわかりませんが、GPU処理はRAMや電力を大量消費することから、省電力化のために無効にされたのではないでしょうか。

現象を確認したのがiPhone7で、XR等の最新機種では発生しなかったことや、
GPU支援がない状態で描画されることから、CPU能力に依存して発生するSafariのバグである可能性がありそうです。

# 対策
GPUレイヤーを作成するようSafariに促します。

## 方法１
```css
.hoge {
  filter: drop-shadow(0 0 8px rgba(0, 0, 0, .1));
  transform: translateZ(0);
}
```
transformを用いることでGPUレイヤーの作成を促します。
昔から使われている方法ですね。

## 方法２
```css
.hoge {
  filter: drop-shadow(0 0 8px rgba(0, 0, 0, .1));
  will-change: filter /* or transform */
}
```
本来の使い方ではありませんが、will-change を用いることでもGPUレイヤーを作成することが出来ます。

# 対策による副作用
GPUを使用することで確かに描画は高速化されますが、端末のリソースをたくさん割くことになるので、例えば次のようなことは推奨されません。

```css
*,
*::before,
*::after {
    will-change: all;
}
```

今回も本来作成されないはずのGPUレイヤーを作成しているので、良くないように思われるかもしれません。
しかし本来iOS Safari以外のブラウザでは作成されるものなので、そこまで神経質にならなくても大丈夫だと思います。

# 終わりに
現代のIEこと、Safariは面倒の見がいがありますね。

# 参考文献
http://indiegamr.com/ios6-html-hardware-acceleration-changes-and-how-to-fix-them/
https://stackoverflow.com/questions/47756158/ios-11-browsers-image-bug
https://stackoverflow.com/questions/21363230/slow-css-filters-on-iphone
https://postd.cc/css-will-change-property/
Oculus Go / Quest を、adbコマンドで操作する

Oculus Go / Quest に、adbコマンドを使って接続し、色々と操作したいときのメモです。

## 無線で接続する

1. Oculus Go / Quest を、USBケーブルでPCに接続
2. `adb shell ip addr show wlan0`（192.168...から始まる番号が、Oculus Go / Quest のIPアドレス）
3. `adb tcpip 5555`
4. USBケーブルを抜く
5. `adb connect XXX.XXX.XXX.XX`（先ほど調べた「192.168...」から始まる番号）
6. `adb devices` で確認し、接続が確認できれば成功

## アプリをインストールする

1. `adb install [apkファイルのパス]`（Windowsの場合、パスが分からないときは、apkファイルを「Shift + 右クリック」で、「パスとしてコピー(A)」を選択すれば取得できる）

## アプリを削除する

1. `adb shell pm list package`
2. `adb uninstall [パッケージ名]` （パッケージ名は、Unity上で「Build Settings > Player Settings > Other Settings > Package Name」を確認）
コマンドラインで .heic ファイルをJPEGやPNGに変換する

iOS 11 以降を搭載した iOS 端末で撮影した写真を PC に転送すると、`.heic` という見慣れない拡張子で出現することがあります。

# `.heic` とは何者か？

`.heic` は HEIF (High Efficiency Image File Format) と呼ばれる高圧縮な写真保存用フォーマットを表す拡張子です。

[Apple 製のデバイスで HEIF／HEVC メディアを扱う](https://support.apple.com/ja-jp/HT207022)：

>iOS 11 と macOS High Sierra では、以下の新しい業界標準のメディアフォーマットに対応しました。
> 
>    HEIF (High Efficiency Image File Format)：写真用。
>    HEVC (High Efficiency Video Coding)：H.265 と呼ばれることもあります。ビデオ用。
>
>HEIF と HEVC は JPEG や H.264 よりも圧縮率が高いため、デバイス本体や iCloud 写真の容量はさほど占有しないのに、同等の画質に仕上がります。

[設定] - [カメラ] - [フォーマット] で [カメラ撮影] の項目を [互換性優先] に設定することで従来のJPEG形式で保存することもできますが、折角の高圧縮フォーマットなので普段は HEIF で保存していきたいところですね。

Windows で HEIF ファイルを開く方法を検索すると日本語が怪しげなソフトウェアを購入することを勧められたりもしますが、個人的には Microsoft ストア から Microsoft 公式の [HEIF 画像拡張機能](https://www.microsoft.com/ja-jp/p/heif-画像拡張機能/9pmmsr1cgpwg) （無償）を導入する方法がおすすめです。 [^1]

[^1]: 一部の HEIF ファイルは [デバイス製造元からの HEVC ビデオ拡張機能](https://www.microsoft.com/ja-jp/p/hevc-video-extensions-from-device-manufacturer/9n4wgh0z6vhq)（無償）もしくは [HEVC ビデオ拡張機能](https://www.microsoft.com/ja-jp/p/hevc-ビデオ拡張機能/9nmzlz57r3t7) （税込み120円）の導入が必要になる場合もあるようです。

この拡張機能を導入すると、「フォト」アプリや [Paint.Net](https://www.getpaint.net/) などを利用して HEIF ファイルを閲覧・編集したり、従来の画像フォーマットに変換して保存することができます。


# ImageMagick を利用して HEIF ファイルを JPEG や PNG に変換する

しかし、PC 上で画像を取り扱うなら従来のファイルフォーマットを利用したくなることも多くあります。そんなとき、一つ一つ画像を開いて変換していくのが面倒になのでコマンドラインで処理したくなります。

[ImageMagick](https://imagemagick.org/index.php) は画像を取り扱う際に利用する非常に著名なソフトウェアスイートですが、HEIF も対応フォーマットの中に含まれています。ですので ImageMagick をインストールし、パスを通している環境なら以下のコマンドを入力するだけで HEIF ファイルを任意のファイルフォーマットに変換できてしまいます：

<pre>
magick convert from.heic dest.png
</pre>

簡単ですね！
1------------------------1 はなぜ計算できてしまうのか？

#はじめに
まずは、ruby や python で「1------------------------1」を計算してみてください。
以下はPythonの例です。

```python:qiita.py
>python
Python 3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 1------------------------1
2
>>>
``````
一見エラーとなりそうなコーディングですが、エラーとなりませんね。
さて、どうしてでしょうか？
#マイナス記号(-)には3つの意味がある。
実はマイナス記号は次の３つの意味を持っています。
#####1.負数を表す「符号」としてのマイナス記号
これは一番ポピュラーですね。つまり、「-1」「-2」「-100」とか、負の数字を表す符号としてのマイナスです。
厳密にいうと、負符号のマイナス記号は単項演算子なのですが、わかりにくいので符号ということにしましょう。
#####2.「単項演算子」としてのマイナス記号
これは、例えば「-a」「-(b+c)」のマイナスです。
意味としては、直後の数字（aやb+c）の符号を逆転する（負なら正、正なら負）にする、となりますね。
#####3.「二項演算子」としてのマイナス記号
これは「a-b」のマイナスですね。aからbを引くという意味ですね。

以上をもとに順にひも解いていってみましょう。
#####(1) 1--1
この式は 1-(-1) と解釈されます。
つまり、最初のマイナス記号は「二項演算子」で、２つ目のマイナス記号は「符号」ですね。計算結果は2になりますね。
#####(2) 1---1
この式は、1-(-(-1)) と解釈されます。
すなわち、１つ目のマイナス記号が「二項演算子」、２つ目のマイナス記号が「単項演算子」、３つ目のマイナス記号が「符号」です。
計算結果は0ですね。
#####(3) 1----1
この式は、1-(-(-(-1))) と解釈されます。
最初が「二項演算子」、最後が「符号」、中の２つが「単項演算子」ですね。計算結果は2です。

つまり、1と1の間に、マイナスがn個あるとすると、1番目のマイナス記号は「二項演算子」、最後（n個目）のマイナス記号は「符号」、そして、中の(n-2)個のマイナス記号は「単項演算子」と見なされるわけです。
また、計算結果は、nが偶数のときは2、奇数のときは0になることは数学的帰納法で証明できますね。

#最後に
参考まで、グーグル検索窓に「1------------------------1」を入れてみたら下記のようになりました。
計算過程まで表示してくれるので、なぜ2になるのかがよくわかりますね。

![2019-08-03 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329906/d8e42f58-5e23-430b-2396-fbcb6a754322.png)
python map関数の使い方

#いつ使えるのか
- 基本的に複数要素を持ったもの(リストなど)に対して同じ処理をしたいときに用いる。

#使用法
**map(関数 or lambda式,引数(listなど))**

- このようにすると、引数のそれぞれの要素に関数やlambda式が適用される。

#具体例
入力が

```
1
2 3
```

だったなら、

```python:WelcomeToAtcoder
a=imput()
b,c=map(int,imput().split())
print(a,b,c)
```

とすれば

```
1 2 3 
```

が出てくる。
chat-spece DB設計

# README

### DB設計図

## group_users

|Column|Type|Options|
|------|----|-------|
|user_id|integer|null: false, foreign_key: true|
|group_id|integer|null: false, foreign_key: true|
### Association
- belongs_to :group
- belongs_to :user

## groupsa
|Column|Type|Options|
|------|----|-------|
|name|string|null: false, default:|
### Association
- has_many :messages
- has_many :users, through: :group_users
- has_many :group_users

## messages
|Column|Type|Options|
|------|----|-------|
|body|text|
|image|string||
|user_id|integer|null: false, foreign_key: true, index: true|
|group_id|integer|null: false, foreign_key: true, index: true|
### Association
- belongs_to :user
- belongs_to :group


## users
|Column|Type|Options|
|------|----|-------|
|name|string|null: false, default: |
|email|string|null: false, default: |


### Association
 - has_many  :messages
 - add_index :users, :name,     unique: true
 - add_index :users, :email,    unique: true
 - has_many  :groups, through: :group_users
 - has_many  :group_users
例外処理の設計のやり方

# 例外処理とは
`例外処理とは、想定内のエラー（例外）が起きた時に、その内容に応じて実行される処理のことです。`
なぜ、例外処理が必要なのかを説明すると、もしプログラムに適切な例外処理が実装されていない場合、プログラム実行中にエラーが発生してしまうと、意図しない構造のデータが保存されたり、異常終了してしまう事態を招きます。また、その時に発生したエラーを調査するのに時間がかかってしまいます。
ですが、`適切な例外処理を実装していれば、データを整合性を保つ事ができ、簡単にかつデバッグしやすい信頼性の高いコードを組むことができます。もし例外が起きてしまっても原因の調査がしやすくなります。`
`このように、アプリケーションを作成するにあたって適切な例外処理の設計をすることは重要なポイントになります。`

# 例外（エラー）を分類
例外（エラー）と一言で表現していますが、例外（エラー）には複数に分類する事ができます。その中でも、`例外処理を実装すべき業務エラー`と`それ以外のシステムエラー`の2つに大きく分類していきましょう。以下が２つの分類を表した図です。
<img width="853" alt="スクリーンショット 2019-08-03 7.45.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459450/dc17f1be-e3be-3c6a-93a4-eaa5a78a0c73.png">


`このように、業務エラーは主にユーザーの誤入力・誤操作が原因のエラーで、システムエラーは主にユーザー側で対処する事ができないエラーです。`

次は、2つに分類したそれぞれのエラーをどのように対処していくのかを考えていきましょう。

# 例外（エラー）の対処
さてここでは、2つに分類した例外（エラー）の対処方法について考えていきます。
まずは`業務エラー`について考えていきましょう。

先に説明したように、`業務エラー`とは主にユーザーの誤入力・誤操作が原因のエラーであり、`その対処方法としてはユーザーに誤入力・誤操作を取り消してもらい、正常な入力・正常な操作を行ってもらう事が対処方法になります。`

その為には、`正常な入力・正常な操作を行ってもらえるような例外（エラー）を考えていく必要があります。`
正常な入力・正常な操作を行ってもらうには、まず`何が誤入力・誤操作だったのかをユーザーに指摘する`事が考えられるでしょう。例えばメールのフォーマットが違う場合、『エラーが起きました。』のような抽象的なメッセージを表示するのではなく、『不正なメールのフォーマットです。』のような`具象的なメッセージを画面を用いて表示させる事が適切です。`


次は、`システムエラー`の対処方法について考えていきましょう。

システムエラーとは主にユーザー側で対処する事ができないエラーです。例えばプログラム内部のバグが原因でエラーが起きたとしましょう。その時は`システム開発者がプログラムを修正する事が対処方法`になります。ユーザー側はバグを修正することは不可能な為、開発者にエラーが発生した詳しい状況を伝えてもらえるような画面を表示する必要があります。また、`バグが原因のエラーが発生した後にプログラムを実行してしまうと以降のプログラムの実行結果が正しいことが保証できない為、安全に終了してもらう必要があります。`
開発者側は、システムエラーが起きたときに素早く対処できるように、`ログにエラー内容を出す`ようにしましょう。また`Errbitなどのエラー監視サービスを導入し、Slackなどと連携しておくとエラー時に迅速な対処が行えるでしょう。`

<img width="783" alt="スクリーンショット 2019-08-03 8.46.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459450/b06a609d-dc7a-4ef5-21e8-da1f73bbd878.png">
# まとめ
ということでここまで例外処理の設計について説明してきました。

`例外処理とは想定内の例外が起きた時に、その内容に応じて実行される処理のことです。`

例外設計を行う時はまずは例外を`業務エラー`と`システムエラー`に分類することから考えていきましょう。そこからそれぞれのエラーに対してどのように設計するのがいいのかを考えていきましょう。適切な例外処理を実装するためにも悩んだ時は開発メンバーと相談しながら決めていくのが無駄のない良い設計になっていくと思われます。


## 参照
[Railsアプリケーションにおけるエラー処理（例外設計）の考え方](https://qiita.com/jnchito/items/3ef95ea144ed15df3637#%E6%AD%A3%E5%B8%B8%E7%B3%BB%E3%81%A8%E7%95%B0%E5%B8%B8%E7%B3%BB%E3%82%A8%E3%83%A9%E3%83%BC%E3%82%92%E5%88%86%E9%A1%9E%E3%81%99%E3%82%8B)
[プログラム設計でのエラー処理](https://medium.com/@sjnk88/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%A7%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E5%87%A6%E7%90%86-7d6b6edea0bf)
[運用を困らせないインターフェースのエラー処理とリカバリ設計](https://mhisaeda.com/archives/2100)
ムームードメインでDDNSする。

# ムームードメインにはDDNSがない
ムームードメインにはDDNSのAPIがありません。 
その変わり安いです。googleドメインでは*.tokyoドメインが使えません。

# myDNS事情
今まではmyDNSを使ってました。
でもメールが届かなくなり、パスワードを変更できなくなってサブドメインを追加できなくなったのでseleniumでスクリプトを書くことにしました。

# Ruby スクリプト
クーロンで動かすかと思ったけど、バカみたいにリクエストするの行儀が悪いからサーバーでIPを監視して変更が確認したら実行するようにしたい。

```ruby
require 'selenium-webdriver'
require 'resolv'
ip_str = Resolv::DNS.new(:nameserver=>'ns1.google.com').getresources("o-o.myaddr.l.google.com", Resolv::DNS::Resource::IN::TXT)[0].strings[0]

options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
driver = Selenium::WebDriver.for :chrome, options: options

driver.get('https://muumuu-domain.com/checkout/login')

driver.find_element(:xpath, '//*[@id="session_muu_id"]').send_keys 'xxxxxxxxx@xxxxxx.com'
driver.find_element(:xpath, '//*[@id="session_password"]').send_keys '*********'
driver.find_element(:xpath, '//*[@id="form-login"]/div[3]/div[1]/button').click

driver.navigate.to "https://muumuu-domain.com/?mode=conpane&state=muudns_list"
driver.find_element(:xpath, '//*[@id="muudns_list_main_tbl"]/tbody/tr/td[2]/table/tbody/tr[2]/td[2]/table/tbody/tr[2]/td[2]/a/img').click
sleep(1)

driver.find_element(:xpath, '//*[@id="addrecord"]/tbody/tr[2]/td[2]/input').clear
driver.find_element(:xpath, '//*[@id="addrecord"]/tbody/tr[2]/td[2]/input').send_keys 'sub'
element = driver.find_element(:xpath, '//*[@id="rec_type_1"]')
select = Selenium::WebDriver::Support::Select.new(element)
select.select_by(:value, 'A')
driver.find_element(:xpath, '//*[@id="addrecord"]/tbody/tr[2]/td[4]/input').clear
driver.find_element(:xpath, '//*[@id="addrecord"]/tbody/tr[2]/td[4]/input').send_keys ip_str

driver.find_element(:xpath, '//*[@id="addrecord"]/tbody/tr[3]/td[2]/input').clear
driver.find_element(:xpath, '//*[@id="addrecord"]/tbody/tr[3]/td[2]/input').send_keys ''
element = driver.find_element(:xpath, '//*[@id="rec_type_2"]')
select = Selenium::WebDriver::Support::Select.new(element)
select.select_by(:value, 'A')
driver.find_element(:xpath, '//*[@id="addrecord"]/tbody/tr[3]/td[4]/input').clear
driver.find_element(:xpath, '//*[@id="addrecord"]/tbody/tr[3]/td[4]/input').send_keys ip_str


driver.find_element(:xpath, '//*[@id="setup_btn"]/a').click
sleep(2)
driver.switch_to.alert.accept
sleep(2)
driver.switch_to.alert.accept

driver.find_element(:xpath, '/html/body/table/tbody/tr[2]/td/form/table/tbody/tr/td[2]/table/tbody/tr[2]/td[2]/div[8]/a').click

sleep(1)
driver.save_screenshot("status.png")

driver.quit
```
# 結果
これで、sub.example.domainとexample.domainが更新できる。
ReactとaxiosでLaravel製のAPIにPUTしたら405エラーが出た

# axios便利すぎんか？

ある商品の情報を更新するための関数として,以下のようなものを書いてました.
情報には画像が含まれるのでcontent-typeにmultipart/form-dataを指定.

```javascript

updateProduct() {
    const params = new FormData();
    params.append('title', this.state.title)
    params.append('image', this.state.image)
    axios
        .put(
            `/api/products/${this.state.id}`,
            params,
            {
            headers: {
                'content-type': 'multipart/form-data',
            }
        })
        .then((res) => {
            this.setState({
                title: '',
                image: '',
            })
        })
        .catch(error => {
            console.log(error)
        })
}
```

そして意気揚々とPUTしてみると405エラーが帰ってきた.
どうやらPUTは禁止されているメソッド(?)らしい.
というわけで解決します.

# 解決法
PUTがダメならPOSTしちゃえばいいじゃない！！
ということで以下の記事を参考にさせて頂いて解決しました(ありがとうございます！！).

[Axios で multipart/form-data にした PUT リクエストが失敗する際の対策](https://qiita.com/komatzz/items/21b58c92e14d2868ac8e)

編集後の関数は以下の通り.
無理やりpostして中身をPUTで書き換えています.

```javascript

updateProduct() {
    const params = new FormData();
    params.append('title', this.state.title)
    params.append('image', this.state.image)
    axios
        .post(
            `/api/products/${this.state.id}`,
            params,
            {
            headers: {
                'content-type': 'multipart/form-data',
                'X-HTTP-Method-Override': 'PUT',
            }
        })
        .then((res) => {
            this.setState({
                title: '',
                image: '',
            })
        })
        .catch(error => {
            console.log(error)
        })
}
```

#
HTTPが現在GETとPOSTにしか対応していないことが原因ですかね.
他のメソッド(DELETEとか)でも応用できそうなので覚えておこうと思います.
Cognitoに独自ドメインが設定できた

# Cognitoで独自ドメインが設定できなかった

できたよー
ググっても中々解決策が見当たらなかったので書いておくます

## 環境
* Route53でドメインを管理している
* ACMでSSL証明書を発行できている（バージニア北部リージョンじゃないとダメです）
* Cognitoは正しく動作している
* 「自分が保有するドメイン」だけがうまくいかない

## こうなるはず
エイリアスターゲットに、CloudFrontのドメインが表示されるはず。。
![うまくいったときの絵](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/a9a13127-58ee-dd84-821f-a96bae971d23.png)

## だがしかしできない
![入力欄](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/d03d6ee4-afe0-5b57-3569-51d272fb7e5b.png)
こんなエラーが出て。。。
![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/27e5018b-8180-4210-6782-99f4de271f68.png)

```
Custom domain is not a valid subdomain: Was not able to resolve the root domain, please ensure an A record exists for the root domain. (Service: AWSCognitoIdentityProviderService; Status Code: 400; Error Code: InvalidParameterException
```

## [AWSドキュメント](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-pools-add-custom-domain.html)に書かれている事

### 日本語
![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/c38b0640-4547-2265-e728-97a3e67f2751.png)
### English
![図5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185989/153db41e-616d-709f-87cb-b6d1206bb91a.png)

❌ DNSの有効なレコード
⭕️ DNSの有効なAレコード
機械翻訳してるから、太字であえて“A record”と表現している部分が
変換できなかったんだろう。。

つまり、
Cognitoで独自ドメインを使いたいのなら
Route53に登録しているルートドメイン(example.com)に対して、Aレコードが設定されていることで
ドメインの所有者だとみなします。
という意味かと思われ。。

## 解決
Route53でサブドメイン無しのAレコードを適当に設定したのち
Cognitoで再びドメイン設定してみたらできた。

## まとめ
つたない英語でAWSさんには、フィードバックしておきました。
この記事で解決した方は、“いいね”お願いします！！
Git-ftpを途中から導入して事故りかけた件

# 背景

タイトル通り[Git-ftp](https://github.com/git-ftp/git-ftp)を途中から導入しようとして、事故を起こしかけました。

[git ftpを使えるようにする(Windows, Mac)
](https://qiita.com/sayama0402/items/d3d11bbc6b09b9b78527)のようにGoogle検索してトップページに出るのをそのまま参考に操作しました。

Git-ftpの初期化の際以下のコマンドがありますが、このコマンド**全ファイルをアップロード**します(公式ドキュメントにはちゃんと書いてあります)。

~~initだからローカル環境のみの操作じゃなかったのか...~~

```
$ git ftp init -v
```
レンタルサーバFTPの場合、Gitでの管理ファイルと実際のレンタルサーバ間で差分がある場合があるので(本来の用途としてよくないですが)、全ファイルアップロード上書きをやりかけて事故りそうになりました。

途中から導入する場合は、こちらのコマンドを使うようにしましょう。

```
git ftp catchup
```

catchupであれば、全ファイルをアップロードすることなく`git-ftp.log`のみアップロードします。

それ以降は

```
$ git ftp push
```

でOKです。

自分に向けての再周知ですが、何かやるときは**公式ドキュメントを必ず参照してから**やりましょう。

## 参考

[git ftpを使えるようにする(Windows, Mac)
](https://qiita.com/sayama0402/items/d3d11bbc6b09b9b78527)
[Git-ftp -- uploads to FTP servers the Git way
](https://github.com/git-ftp/git-ftp)
Firebaseのバックエンド担当になったときに作ったパッケージ構成

# 構成

> firebase init

で色々聞かれるけどその後必要があって諸々追加する

```
.
├── README.md
├── firebase
│   ├── README.md
│   ├── admin_scripts 
│   │   ├── config.js // 環境ごとの設定を入れたりなど
│   │   ├── run_test.js
│   │   └── user      // 各コレクションごとにscaffoldするスクリプトなど
│   │       ├── create.js
│   │       └── delete.js
│   ├── bulk_data     // 作成するサンプルデータの管理
│   │   ├── images
│   │   └── users.json
│   ├── credentials   // 環境ごとのcredential
│   │   ├── secret.dev.json
│   │   ├── secret.prod.json
│   │   └── secret.stg.json
│   ├── firebase.json
│   ├── firestore.indexes.json
│   ├── firestore.rules 
│   ├── functions     // デフォでtsにできる
│   │   ├── etc
│   │   ├── lib
│   │   ├── node_modules
│   │   ├── package-lock.json
│   │   ├── package.json
│   │   ├── src
│   │   ├── tsconfig.json
│   │   └── tslint.json
│   ├── package-lock.json
│   ├── package.json
│   ├── public   // フロントの動きを確認できるなにかを実装する
│   │   └── index.html
│   ├── storage.rules
│   ├── test
│   │   ├── build // tsをビルドしたjsが入る
│   │   ├── helper
│   │   └── users.ts // firebase.rulesにあるルールのテスト
│   └── tsconfig.json
```

# cmd

```json
    "bulk-create-user-dev": "babel-node ./admin_scripts/user/create.js --env dev",
    "bulk-delete-user-dev": "babel-node ./admin_scripts/user/delete.js --env dev",
    "serve-firestore": "firebase serve --only firestore",
    "deploy-functions": "firebase deploy --only functions",
    "deploy-rule": "firebase deploy --only firestore:rules",
    "deploy-storage": "firebase deploy --only firestore:storage",
    "pretest": "tsc",
    "test": "mocha test/build/*"
```

注意なんですが、`admin sdk`を使ってbulkしているんですが、これは

- rulesを無視して実行できてしまう
- stg/prodにもすぐ実行できてしまう

ので運用フェーズになったときには運用を変えないといけない。ローンチ前はそこまで考えないで柔軟性重視でこのまま。ruleのdeployも本来CDに任せたほうがいい。

## tsをrule testで利用する

```tsconfig.json
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "sourceMap": true,
    "experimentalDecorators": true,
    "lib": [ "es6", "dom" ],
    "types" : [
      "node"
    ],
    "outDir": "test/build/"
  }
}
```

```package.jsonのdependencies
"dependencies": {
    "@firebase/testing": "^0.11.4",
    "@types/jest": "^24.0.15",
    "@types/mocha": "^5.2.7",
    "babel-cli": "^6.26.0",
    "commander": "^2.20.0",
    "csv": "^5.1.1",
    "csv-parse": "^4.4.3",
    "filesystem": "^1.0.1",
    "firebase": "^6.2.2",
    "firebase-admin": "^8.2.0",
    "mocha": "^6.1.4",
    "mocha-typescript": "^1.1.17",
    "nanoid": "^2.0.3",
    "ts-node": "^8.3.0",
    "typescript": "^3.5.3"
  }
```

## 反省

- admin_scriptsをtsにしたかった
- functionsが別でパッケージ管理されているのがやや気持ち悪い
- testのパッケージ管理が全体のパッケージ管理に含まれているのがやや気持ち悪い
VCIのSubItemの水平垂直出し(Y軸のみ回転させXZに0セット)

#概要
VCIはオイラーに代入できない？ので、特定の軸だけ回転させたい時に悩みましたので共有します。

#スクリプト
```lua
local item = vci.assets.GetSubItem("item")
local ang = item.GetRotation().eulerAngles
item.SetRotation(Quaternion.identity)
item.SetRotation(Quaternion.AngleAxis(ang.y, Vector3.up))
```

or

```lua
local item = vci.assets.GetSubItem("item")
local ang = item.GetRotation().eulerAngles
local rot = Quaternion.Euler(0, ang.y, 0)
item.SetRotation(rot)
```

#例
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">向き調整出来るようになりそうです。 <a href="https://t.co/FYu9S8oaOb">pic.twitter.com/FYu9S8oaOb</a></p>&mdash; 120 (@120byte) <a href="https://twitter.com/120byte/status/1157313827618164742?ref_src=twsrc%5Etfw">August 2, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#所感
なんかもっと良い方法がある気がします。
グラフDBのNeo4jで都内の路線図っぽいのを作成

#Neo4jを使用して都内の駅関係を示す
今回は、駅情報から駅と駅の繋がりをグラフDBに作成しようと思います．
##駅情報のソース
今回は、以下サイトの情報を利用します．
[駅データ.jp](http://www.ekidata.jp/doc/station.php)
こちらのサイトでは無料版で駅情報を取得することが可能です．
使用したデータは、駅データと接続駅データの2種類です．

##Neo4jに駅ノードの作成
まず、はじめに駅データから都内の駅のみを抽出してNeo4j上にノードを作成します．

```node_create.rb
require 'csv'
require 'neography'

@neo=Neography::Rest.new({:authentication =>'basic',:username =>"neo4j",:password =>"****"})#Neo4jへの接続情報

i=0
CSV.foreach("./stations.csv") do |row|	#station.csvは駅データをcsvに変換したものです．
	if row[6]=="13" then	#row[6]は、都道府県コード(pref_cd)で、pref_cd=13が東京です．
		station_code=row[0]
		station_g_cd=row[1]
		station_name=row[2]
		line_cd=row[5]
		e_sort=row[14]
		
		node1=@neo.create_unique_node("Tokyo_of_Station_Test","station_id",station_g_cd ,{"station_name"=>station_name,"station_g_cd"=>station_g_cd,"line_cd"=>line_cd,"e_sort"=>e_sort})
		#駅ノードを作成
		@neo.add_label(node1,"Tokyo_of_Station_Test")#labelを付けます．
		@neo.add_node_to_index("Tokyo_of_Station_Test", "station_code", station_code, node1)
	end
	i+=1
end
p i
```

こちらで駅データのノード作成が完了です．
MATCH (n:Tokyo_of_Station_Test) RETURN n LIMIT 25を実行したのが以下の図です．

![スクリーンショット 2019-08-03 14.25.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430353/aa2a3cb2-481f-28a7-c140-e1a867ea5ae3.png)

駅ノードが作成できていることがわかります．
node作成時に、uniqueキーにstation_codeでなくstation_g_cdを指定しているのは同名駅の重複を防ぐためです．
#駅の接続関係を表す．
次は、駅と駅の繋がりを表すために接続駅データを用います．
ノード間にrelationship名”connection"を持たせます．

```node_connection.rb
require 'csv'
require 'neography'

@neo=Neography::Rest.new({:authentication =>'basic',:username =>"neo4j",:password =>"****"})#Neo4jへの接続です．

CSV.foreach("./station_connect.csv") do |row|	#station_connectは接続駅データのcsvです．
	n= @neo.get_node_index("Tokyo_of_Station_Test","station_code",row[1])#indexからノードを取得します．

	begin
		no1= n[0]#始点ノード
		s1=no1["data"]["station_g_cd"].to_i
		n2=@neo.get_node_index("Tokyo_of_Station_Test","station_code",row[2])
		no2=n2[0]#終点ノード
		s2=no2["data"]["station_g_cd"].to_i
		if s1>s2#Uniqueキー作成
			connect=s1,"->",s2
		else
			connect=s2,"->",s1
		end
		@neo.create_unique_relationship("Tokyo_of_Station_Test","station_connct",connect,:connection,no1, no2)
	rescue
		#Error処理
	end

end

```
こちらで駅の接続関係を保存することができました．(Neo4jは無向グラフをサポートしていません．無向グラフを利用したい場合は一方向のリレーションを結んでおき、データ照会を行なう際にリレーションの向きを無視するよう照会する方法が推奨されています。)
relationshipを設定する際には、重複してrelationを作成しないように気をつける必要があります．ノード作成時に複数の同名駅を纏めて保存しているので．

実行結果が以下です．(東京駅を中心に表示しています)

![スクリーンショット 2019-08-03 14.32.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430353/0c0971d1-e85a-fcf9-0a26-1e73bbc99589.png)

##終わり
データセットを作成するのが大変なので今回は、駅データを利用しました．
リファクタリングとは

処理の内容を変えずに冗長なコードを削除したり、コードを改善すること。

【リファクタリングのメリット】

・読み手が最短時間でコードを理解できるようになる
・修正がしやすくなる

【リファクタリングを行うための要素】
・制御フロー
・式の分割
・変数
・メソッドの抽象化
・関心の分離
・短いコードを書く
【Swift】オプショナル型とは？

##はじめに
オプショナル型とは、簡単に言えば**「nil(空の値)を許容する型」**のことです。Swiftでは変数の生成時にはnilを代入することができないため、オプショナル型を使います。オプショナル型を使うことでnilの状態を安全に扱うことができますが、オプショナル型の値は他の型の値と同じように扱うことはできず、その値を使う際にはアンラップをする必要があります。宣言時の「?」や「!」とアンラップ時の「?」や「!」の違いについて説明していきます！

##宣言時の「？」と「！」の違い
通常Swiftでオプショナル型を宣言する際には、型の後ろに「?」をつけます。こうすることでnilを代入することができるようになりますが、Optional型で宣言した値は通常の型とは少し異なります。例えば以下の例では、numberは`Int?`は`Int`とは異なり、出力結果は`Optional(1)`のようにラップされた状態になっています。Int型として扱うためにはアンラップをする必要があります。

```swift
var number: Int?
number = 1
print(number) //Optional(1)
```

では「！」は何かと言うと、暗黙的アンラップ型と言うオプショナル型の一種です。暗黙的アンラップ型も通常のオプショナル型と同じようにnilを代入することができますが、実行時に自動的にアンラップされる点において異なります。例えば以下の例では`Int!`とオプショナル型で宣言していますがアンラップをせずとも出力結果は通常の`Int`になっています。アンラップをする必要がないため実行時までに必ず値が代入されることが保証されている場合には便利ですが、**nilのまま実行すると実行時エラーになるため注意が必要です**。

```swift
var number: Int!
number = 1
print(number) //1
```

##オプショナル型のアンラップ
###1. 強制的アンラップ
強制的アンラップはオプショナル型にどんな値が入っていたとしても強制的にアンラップし、値を取り出す方法です。オプショナル型の値の後に`!`を記述するだけでアンラップすることができます。しかしオプショナル型の変数の中身がnilであった場合は実行時エラーとなるため、あまり安全なアンラップ方法とは言えません。

```swift
var number: Int?
number = 1
print(number) //Optional(1)
print(number!) //1
```

###2. オプショナルバインディング
オプショナルバインディングは`if文`を用いてオプショナル型の変数に値が入っているかをチェックしてから値を取り出す、安全なアンラップ方法です。条件式の中でオプショナル型の変数を別の変数に代入し、nilであるかどうかをチェックします。

```swift
var number: Int?
number = 1
if let unwrappedNumber = number {
   print(number) //1
} else {
   print("nilです")
}
```

###3. オプショナルチェイニング
オプショナルチェイニングもオプショナル型を安全にアンラップする方法の1つです。アンラップ時にオプショナル型の変数の後ろに`?`をつけることで変数の中身がnilであった場合も実行時エラーとならず、**nilを返します**。オプショナルチェイニングはオプショナル型の変数に続いてプロパティやメソッドを呼び出す場合に`オプショナル型の変数?.プロパティ`や`オプショナル型の変数?.メソッド()`といった形で使用します。**オプショナル型の変数の中身がnilであった場合はそれに続く処理が行われないため、安全に処理を行うことができます**。ただし、**返り値がオプショナル型になっており、アンラップする必要があるので注意してください**。

```swift:nilでない場合
var animal: Animal? = Animal()
animal?.name //Optional(イヌ)
animal?.bark() //Optional(ワンワン)
```

###4. おまけ
`??`を使ってアンラップをすることも可能です。??を用いると、オプショナル型の値がnilでなかった場合はその値をアンラップし、nilであった場合は??の後ろに記述したものをオプショナル型の変数に代入します。例えば以下の例ではnumberに値が入っていれば1が返ってきますが、nilであった場合は空文字列が変数に代入されて返ります。

```swift
var number: Int?
number = 1
let unwrappedNumber = number ?? ""
print(number) //1
```
Leetcode #543: Diameter of Binary Tree

```swift
func diameterOfBinaryTree(_ root: TreeNode?) -> Int {
    var diameter = 0
    helper(root, &diameter)
    return diameter
}

func helper(_ node: TreeNode?, _ diameter: inout Int) -> Int {
    if node == nil {
        return 0
    }
    var leftLength = 0
    var rightLength = 0
    if node?.left != nil {
        leftLength += 1
        leftLength += helper(node?.left, &diameter)
    }
    if node?.right != nil {
        rightLength += 1
        rightLength += helper(node?.right, &diameter)
    }
    diameter = max(diameter, leftLength + rightLength)
    return max(leftLength, rightLength)
}
```
LSI SAS 9207-8iにITファームウェアを焼く

## 準備
* [9207_8i_Package_P19_IR_IT_Firmware_BIOS_for_MSDOS_Windows] (https://docs.broadcom.com/docs/12350492) 
* [Installer_P20_for_UEFI](https://docs.broadcom.com/docs/Installer_P20_for_UEFI.zip)
* [EFI Shell(Version1)](https://github.com/tianocore/edk2/raw/UDK2017/EdkShellBinPkg/FullShell/X64/Shell_Full.efi) 
* USBメモリ

最新版のファームウェアはP20ですが，これはバグがありLinux環境と相性が悪いようなので，P19ファームウェアを焼くことにします
EFI ShellはVersion1の物を使います，現在出回っているものは主にVersion2ですが，Version2でファームウェアの更新を行おうとすると`InitShellApp: Application not started from Shell ` エラーが発生します。

## 手順(準備)
1. USBメモリーをFAT32でフォーマット
2. ダウンロードしたEFI Shellを`Bootx64.efi` にリネームして，USBの`/boot/efi/`に配置
3. `sas2flash.ufi` `9207-8.bin` `mptsas2.rom`をUSBの直下に配置

### USB内ファイル構成
* /boot/efi/Bootx64.efi
* sas2flash.ufi
* 9207-8.bin
* mptsas2.rom

## 手順(更新)
1. USBからUFE Shellをブート

``` bash
fs0: 
sas2flash.efi -list  # 表示されない場合はfs1:で試してみる
sas2flash.efi -o -e 6 # ファームウェアの消去(ここでPCの電源を落とすと，SASがオシャカになるので注意)
sas2flash.efi -f 9207-8.bin -b mptsas2.rom # 新しいファームウェアの書き込み
sas2flash.efi -list # ファームウェアが更新されていることを確認する
```