S3に保存した画像をRailsで取得する

## 結論
```
s3_resource = Aws::S3::Resource.new(xxx)
s3_resource.bucket('BUCKET_NAME').object(KEY_NAME).get.body.read
```

## 背景
S3にアップロードしてある画像データを、RailsのViewで動的に表示したかった。

## 調べたこと
1. S3に画像がどう格納されているか
1. そもそもの画像データ

## S3にどう画像が格納されているか

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/UsingObjects.html
> Amazon S3 は、一意のキー値を使用して、必要な数のオブジェクトを保存できるオブジェクトストアです。これらのオブジェクトは 1 つ以上のバケットに保存し、各オブジェクトのサイズは最大 5 TB です。

つまり、S3にアップロードしている画像やテキストデータ = **オブジェクト**
オブジェクトにアクセスできるのが**キー**。
オブジェクトを保管しているのが**バケット**。


``` s3.rb
## バケットのリスト取得
s3_resource.buckets
=> #<Aws::S3::Bucket::Collection:0x0000ffff584ea680
 @batches=#<Enumerator: ...>,
 @limit=nil,
 @size=nil>

## バケット単体取得
s3_resource.buckets.first
=> #<Aws::S3::Bucket:0x0000ffff542af388
 @arn=nil,
 @client=#<Aws::S3::Client>,
 @data=#<struct Aws::S3::Types::Bucket name="test_bucket", creation_date=2022-06-24 14:23:15.155 UTC>,
 @name="test_bucket", # 　<-- bucket名 -->
 @resolved_region="us-east-1",
 @waiter_block_warned=false>

## バケット名を指定する
s3_resource.bucket("test_bucket")
#<Aws::S3::Bucket:0x0000ffff61881240
 @arn=nil,
 @client=#<Aws::S3::Client>,
 @data=#<struct Aws::S3::Types::Bucket name="test_bucket", creation_date=2022-06-24 14:23:15.155 UTC>,
 @name="test_bucket", # 　<-- bucket名 -->
 @resolved_region="us-east-1",
 @waiter_block_warned=false>

## バケット名を指定してオブジェクトのリスト取得する
s3_resource.bucket("test_bucket").objects
=> #<Aws::S3::ObjectSummary::Collection:0x0000ffff5c03cda0
 @batches=#<Enumerator: ...>,
 @limit=nil,
 @size=nil>

## バケット名とオブジェクトのキーを指定してオブジェクトを取得する
s3_resource.bucket("test_bucket").object("1")
=> #<Aws::S3::Object:0x0000ffff5c145738
 @bucket_name="test_bucket",
 @client=#<Aws::S3::Client>,
 @data=nil,
 @key="1",
 @waiter_block_warned=false>
```

ここまでで、オブジェクトにたどり着くことができましたが、画像ってどう取ればいいんだ？
という謎になり、画像について調べます。

## そもそもの画像データ
https://medium-company.com/%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E3%83%87%E3%83%BC%E3%82%BF/
> バイナリデータ（binary data）とは、コンピュータが理解しやすいデータ（2進数で表現されたデータ）
バイナリデータは、画像ファイルや音声ファイル、動画ファイル、圧縮ファイルなど、コンピュータが扱えるファイルは、すべてバイナリデータです。 

つまり、S3のオブジェクトからバイナリデータを取得すれば良いということがわかりました。


ここで、[Aws::S3::Objectのドキュメント](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#get-instance_method)から、オブジェクトの読み込みのメソッドの`get`を発見します。

```s3.rb
s3_resource.bucket("test_bucket").object("1").get
=> #<struct Aws::S3::Types::GetObjectOutput
 body=#<StringIO:0x0000ffff5c011ab0>,
 delete_marker=nil,
 accept_ranges="bytes",
 expiration=nil,
 restore=nil,
 last_modified=2022-06-24 14:23:15 +0000,
 content_length=24972,
 etag="\"e4b088734dace101b4302a729f22cd70\"",
 checksum_crc32=nil,
 checksum_crc32c=nil,
 checksum_sha1=nil,
 checksum_sha256=nil,
 missing_meta=nil,
 version_id=nil,
 cache_control=nil,
 content_disposition=nil,
 content_encoding=nil,
 content_language=nil,
 content_range=nil,
 content_type="binary/octet-stream",
 expires=nil,
 expires_string=nil,
 website_redirect_location=nil,
 server_side_encryption=nil,
 metadata={},
 sse_customer_algorithm=nil,
 sse_customer_key_md5=nil,
 ssekms_key_id=nil,
 bucket_key_enabled=nil,
 storage_class=nil,
 request_charged=nil,
 replication_status=nil,
 parts_count=nil,
 tag_count=nil,
 object_lock_mode=nil,
 object_lock_retain_until_date=nil,
 object_lock_legal_hold_status=nil>
```


戻り値である`Aws::S3::Types::GetObjectOutput`の `body`がStringIOの型だったので怪しいと思い、調べるとビンゴ。Object dataを返してくれるそうです。
https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Types/GetObjectOutput.html

```s3.rb
s3_resource.bucket("test_bucket").object("1").get.body
=> #<StringIO:0x0000ffff60e958d0>

# StringIOを読み込む
s3_resource.bucket("test_bucket").object("1").get.body.read
=> "\xFF\xD8\xFF\xE0\u0000\u0010JFIF\u0000\u0001\xDB\u0000C\u0000\u0003\u0002\u0002\u0002\u0002\u0002\u0003\u0002\u0....
```

き、、きたーーー。2進数ではないけど見たことある画像データっぽいやつ！
これでS3から画像データを取得することができました。

## わかったこと
- S3から画像を取得するには `Aws::S3::Types::GetObjectOutput`を使うこと
- 画像データはバイナリデータ
- S3では画像などをオブジェクトという