Day14 AmazonS3・その他修正

#画像データのValidation
本番環境の画像保存先を用意する前に、画像のValidationがまだだったので、Userモデル等と違って、ImageUploaderを使いValidationを実装した。
**ImageUploaderでの定義**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/a304f3fe-02f3-9cb8-4e0e-2828f818d93f.png)
**ymlファイルでメッセージの定義**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/5b5f28b0-3079-632c-5537-43c69e5b492b.png)
**参考**
https://qiita.com/IKEA_dless/items/f8f2dc27ed2356da4e50
http://arthurxxx.hatenablog.com/entry/2018/03/08/222925

#画像アップロード先をAmazonS3に変更
Herokuは立ち上げるたびに、仮想サーバが作り変えられてしまうためherokuローカル上に保存された画像は消えてしまう。そこで外部のストレージサービスを利用する必要があり、Rails Tutorialでもお勧めされているAmazon S3が一番信頼性も高くエラー時のドキュメントも豊富なことから選択した。
##大まかな流れ
(前提）・・・画像アップローダやリサイズの機能が実装されていること。
1 gem 'fog-aws'のインストール
**-AWS側の設定**
2 IAMユーザの作成（Cloud9で作ったのと手順はほぼ同じ。ユーザ作成して権限を付与）
>
S3へのFull Access権限を選択。

3 Bucketの作成
>
Bucketのパケットポリシーの設定でInvalid Principal Errorが出たが、文法上のエラーだった。１２桁のIDにハイフンは要らず、そのままユーザのARNをコピーしてPrincipalに添付して解決。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/737cabd0-b457-6550-aa08-5cbd7f6b4dc0.png)
<img width="381" alt="スクリーンショット 2020-01-28 19.30.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/fc948be3-1512-757a-4cc0-169080ab87e6.png">


**-Rails側の設定**
4 config/initialize/carrierwave.rbのファイルの作成及び設定
>
config.asset_hostにはバケット名ではなく、下記のようにHTTPからのものを環境変数に定義する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/9f224be5-23f2-4bcc-3689-f307c64001c6.png)
Access Diniedの原因はこれだった。
参考
https://qiita.com/tktcorporation/items/ec2dbc2fe540e313f917
https://qiita.com/yukiyukimiyaiwa/items/a9e0103c8342b81f6ac1

5 4で使う環境変数を定義
>heroku config:set AWS_S3_BUCKET = ""　で定義
heroku config:get AWS_S3_BUCKET　　　　で中身を確認

詳しいフローは、下記のサイトを参照した。
https://morizyun.github.io/infrastructure/aws-s3-with-iam-policy.html
https://morizyun.github.io/ruby/rails-function-form-carrierwave-fog-s3.html
https://remonote.jp/rails-carrierwave-fog-s3

##発生した問題
**１　Access Dinied**
上述したとおり、config.asset_hostの環境変数の定義が問題で、バケット名だけでなく、HTTPからのものを格納することで解決した。
**２　サムネイルだけ表示されない**
S3への画像アップロードもS3側で問題なくできていることが確認できたが、アプリ側でサムネだけが表示されなかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/8788c3da-8bed-660a-8a5d-103da6a64e43.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/cbf8bd18-b760-f3c7-06f5-1313d96f0dd8.png)
アプリ側で生成されたHTMLソースからサムネのリンクに飛ぶと、上のようなエラーが表示されてしまう。
バケットへのアクセス権限等の問題は、同じ階層にあるサムネではない画像は表示されていることから考えにくかったため、それ以外の原因を考え、生成されたHTMLソースとバケットに表示されるソース（オブジェクト URL）を比較してみた。


例えばjpgファイルをアップロードすると、次のような挙動になった。（ImageUploarderはすべてpngに変換する設定をしてある）
サムネイル画像の生成されたソースはファイルの拡張子が.jpgであるのに対し、バケット側では.pngだった。サムネではない画像表示の方は、生成ソースはjpgでバケット側もjpgであるため表示された。つまり拡張子が違っていたため、URL自体も異なるものにアクセスして弾かれていたということである。
>
HTMLソース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/d0518b76-0d75-dd13-7a55-36b6e9bc2802.png)
バケット側のソース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/c52ee6d8-a22f-3a6a-f33f-affc1c146d1e.png)

とりあえずの解決策として、ImageUploaderのその設定をコメントアウトすることで、保存される形式とあげた時の形式に齟齬がないようにしたところ、しっかりとサムネイルも表示されるようになった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/530eed4a-7fa1-0edb-2deb-cf42cfdb86b1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565105/72a8be5b-340a-8df1-a1c2-0fa0f5460ead.png)


**残る疑問**
なぜpngとして保存する設定がサムネイルにのみ適用されていたのか、また、保存時はpngとして保存したはずなのになぜHTMLの表示ではpngで表示されてしまっていたのか。

#修正
**グラフ削除**
何もデータがないのにグラフ削除のアクションが実行されたときの対策がされていなかったので実装した。
if Graph.findとかで存在自体をチェックしていれば問題がないのだが、それがされていなかったのでその点追記した。
これで複数タブで開き、片方で削除後、また別のタブで削除リンクを押されても問題ない。