instagramのクローンアプリを作る②

##はじめに
タイトルの通り、簡易版instagramのアプリを作っていきます。
下記の工程に分けて記事を執筆していきますので、順を追って読んでいただけたらなと思います。

①[アプリ作成〜ログイン機能の実装](https://qiita.com/maca12vel/items/d1d558dbf55a82b98990)
②[写真投稿機能の実装](https://qiita.com/maca12vel/items/592c78d435a8d950c434)　←イマココ
③[ユーザーページの実装]
(https://qiita.com/maca12vel/items/c716702b02f977303011)
④[フォロー機能の実装]
(https://qiita.com/maca12vel/items/2760d33f3683fac91de5)
⑤投稿削除機能の実装

##Active Storageの導入
Active Storageとは...
ファイルアップロードを行うための機能で、
これを使えばフォームで画像の投稿機能などが簡単に作れます。
※以下、アプリケーションのディレクトリで

```:ターミナル
rails active_storage:install
```

続けてphotoモデルを作成します。
``photo``は``user``に紐づいているので``user:belongs_to``
``caption:text``とすることで、text型のカラムも作成

```:ターミナル
rails g model photo user:belongs_to caption:text
```

そして

```:ターミナル
rails db:migrate
```
最後にコントローラの作成を行います。

```:ターミナル
rails g controller photos
```
下準備完了です。

##写真投稿ページへのリンクを作成

まず、ルーティングの設定を行います。

```routes.rb
Rails.application.routes.draw do
  root 'homes#index'

  devise_for :users

  resources :photos # ←ここ
end
```

次にホーム画面を編集していきます。

```erb:app/views/homes/index.html.erb
<h3>home</h3>

<div>
  <%= link_to 'logout', destroy_user_session_path, method: :delete %>
</div>

<div>
  <%= link_to '写真投稿', new_photo_path %>
</div>
```

``new_photo_path``は**rails routes**のPrefixで確認
[![Image from Gyazo](https://i.gyazo.com/771645e3ba688fa6e74ff6f48bd5e677.png)](https://gyazo.com/771645e3ba688fa6e74ff6f48bd5e677)

photosモデルに``new.html.erb``を作成し、確認用に下記のように記述してみます。

```erb:app/views/photos/new.html.erb
<h3>写真投稿</h3>
```
下記のように、ホーム画面から写真投稿のページに遷移できていれば成功です。
[![Image from Gyazo](https://i.gyazo.com/f70fe7e5af34ed794f3dcead0c482291.gif)](https://gyazo.com/f70fe7e5af34ed794f3dcead0c482291)

##コントローラの設定
``rails g controller photos``で作成したコントローラに記述していきます。

```photos_controller.rb
class PhotosController < ApplicationController
  before_action :authenticate_user!

  def new
    @photo = current_user.photos.new
  end

  def create
    @photo = current_user.photos.new(photo_params)

    if @photo.save
      redirect_to :root
    else
      render :new
    end
  end

  private

  def photo_params
    params.require(:photo).permit(:caption, :image)
  end
end
```

``before_action :authenticate_user!``で、
ログインユーザーのみ投稿できるように設定しています。

``createアクション``で引数``(photo_params)``とし、
``private``以下で``(photo_params)``を定義しています。

また``createアクション``で
保存に**成功すればホーム画面**に、
**失敗すれば新規投稿画面**に戻る（留まる）よう設定しています。

##新規投稿画面のviewを編集
その前に、``userモデル``と``photosモデル``のアソシエーションを確認します。
userとphotosは１対多の関係なので、以下のように編集します。

```user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  has_many :photos # ←ここ
end
```

```photo.rb
class Photo < ApplicationRecord
  belongs_to :user # ← rails g model photo時に記述済み

  has_one_attached :image # ←ここ
end
```

``has_one_attached :カラム名``はモデルに1つの画像を紐づけるときに使います。
複数の画像を紐づけるときは``has_many_attached :カラム名``です。

今回は1つの画像なので``has_one_attached``としています。
ちなみにoneとmanyで、画像を表示させる際の記述の仕方が異なります。

```erb:has_one_attached
<%= image_tag(@photo.image) %>
```

```erb:has_many_attached
<% images.count.times do |i| %>
  <%= image_tag(@photo.image[i]) %>
<% end %>
```
``has_many_attached :カラム名``だと、
imageは配列として格納されるので上記のようになります。

前置きが長くなりましたが、新規投稿画面のviewを編集していきます。

```erb:app/views/photos/new.html.erb
<h3>写真投稿</h3>

<%= form_with model: @photo, local: true do |f| %>
  <div>
    <%= f.file_field :image %>
  </div>
  <div>
    <%= f.text_area :caption %>
  </div>
  <%= f.submit %>
<% end %>
```

投稿された画像をホーム画面に表示させるようにします。
※とりあえずの確認用なので、後々修正していきます。

```erb:app/views/homes/index.html.erb
<h3>home</h3>

<div>
  <%= link_to 'logout', destroy_user_session_path, method: :delete %>
</div>

<div>
  <%= link_to '写真投稿', new_photo_path %>
</div>

<% current_user.photos.each do |photo| %>
  <div>
    <p><%= photo.caption %></p>
    <%= image_tag photo.image %>
  </div>
```

each文で全ての投稿を表示させるようにしています。

新規投稿ページから``ファイル選択``、``caption入力``、``Create Photo``をクリックで、
以下のように投稿できていればとりあえずはカタチになっているかと思います。
[![Image from Gyazo](https://i.gyazo.com/d3ef5881b9c889153a9d05e1ac4b9958.gif)](https://gyazo.com/d3ef5881b9c889153a9d05e1ac4b9958)

---

以上です。お疲れ様でした。

次へ → ③[ユーザーページの実装]
(https://qiita.com/maca12vel/items/c716702b02f977303011)