Rails 複数 画像投稿 Cloudinary CarrierWave

# 環境
ruby 3.0.2
Rails 6.1.4.4

# 実装
cloudinaryの登録を済ませてください

https://cloudinary.com/

## gemの追加

```ruby:Gemfile
gem 'carrierwave' 
gem 'cloudinary'
```

```
$ bundle install
```

## モデルの作成
PostとImageは1対多のアソシエーションで実装します

```
$ rails g model post body:string
$ rails g model image post:references image:string
$ rails db:migrate
```
```ruby:models/image.rb
class Image < ApplicationRecord
  belongs_to :post
  mount_uploader :image, ImageUploader
end
```
```ruby:models/post.rb
class Post < ApplicationRecord
  has_many :images
end
```

## Uploaderの作成
```
$ rails g uploader Image
```


## 画像の複数選択を許可
```ruby:posts/new.html.erb
<%= form_with(model: post) do |form| %>
  <div class="field">
    <%= form.label :body %>
    <%= form.text_field :body %>
  </div>

  <div class="field">
    <%= form.label :images %>
    <%= form.file_field :images, multiple: true %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>
```

ファイルを複数選択する場合は、Shiftキー、もしくはctrl、commandとクリックで選択できます。

## 複数画像の保存

```ruby:posts_controller.rb
def create
  @post = Post.new(post_params)
  if @post.save
    # ここから
    params[:post][:images]&.each do |image|
      Image.create!(image: image, post_id: @post.id)
    end
    # ここまで
    redirect_to :action => "index"
  else
    redirect_to :action => "new"
  end
```

## 複数画像の表示
```ruby:posts/index.html.erb
<% @posts.each do |post| %>
  <%= post.body %>
  <% post.images.each do |image| %>
    <%= image_tag image.image_url, size: "250x200" %>
  <% end %>
<% end %>
```

```ruby:posts/show.html.erb
<%= @post.body %>
<% @post.images.each do |image| %>
  <%= image_tag image.image_url, size: "250x200" %>
<% end %>
```

## クラウドストレージに画像を保存
```ruby:app/uploaders/image_uploader.rb
  # Choose what kind of storage to use for this uploader:
  include Cloudinary::CarrierWave
  CarrierWave.configure do |config|
    config.cache_storage = :file
  end
  # storage :fog
```

## APIキーの設定

### credentialsを使う場合

※.envで登録できている場合は、この作業をする必要はありません

Macの場合
```
$ EDITOR="code -w" bin/rails credentials:edit
```

windowsの場合
```
$ set EDITOR="code -w"
$ rails credentials:edit
```
済んだら保存、VScodeを閉じると設定が反映される

```credentials.yml.enc
# aws:
#   access_key_id: 123
#   secret_access_key: 345
# ↓追記ここから
cloudinary:
  cloud_name: *********
  api_key: **************
  api_secret: ******************
# ↑追記ここまで
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: 96dd81......　#ここは元の記述から変更しない
```
*****の値はCloudinaryのマイページから取得した値に変更

ちゃんと保存できているか、確認してみましょう

```
$ rails c
irb(main):001:0> Rails.application.credentials.cloudinary[:cloud_name]
=> "abcdaiueo"
irb(main):002:0> Rails.application.credentials.cloudinary[:api_key]
=> 123456789
irb(main):003:0> Rails.application.credentials.cloudinary[:api_secret]
=> "a1b2c3d4e5f6g7h8i9"
```
自分が入力した値が出てくれば成功です！


新しいファイルを作成します

```config/cloudinary.yml
development:
  cloud_name: <%= Rails.application.credentials.cloudinary[:cloud_name] %>
  api_key: <%= Rails.application.credentials.cloudinary[:api_key] %>
  api_secret: <%= Rails.application.credentials.cloudinary[:api_secret] %>
  enhance_image_tag: true
  static_file_support: false
production:
  cloud_name: <%= Rails.application.credentials.cloudinary[:cloud_name] %>
  api_key: <%= Rails.application.credentials.cloudinary[:api_key] %>
  api_secret: <%= Rails.application.credentials.cloudinary[:api_secret] %>
  enhance_image_tag: true
  static_file_support: false
test:
  cloud_name: <%= Rails.application.credentials.cloudinary[:cloud_name] %>
  api_key: <%= Rails.application.credentials.cloudinary[:api_key] %>
  api_secret: <%= Rails.application.credentials.cloudinary[:api_secret] %>
  enhance_image_tag: true
  static_file_support: false
```

# 完成
以上で完成です。