【Rails】ログイン後の投稿

ユーザの[ログイン後](https://qiita.com/gussan-dayo/items/48f8542d02314a346eb3)の投稿についてのメモです。

ログインしたユーザを通して、投稿記事の取得を行うイメージです。
また、モデルは1対多でいきます。
こちらの記事を参照してみてください。
https://qiita.com/kazukimatsumoto/items/14bdff681ec5ddac26d1

ユーザ(1)に対して、投稿(多)です。

##全体像
###モデル

Micropost(投稿)
 content:string user:references

User(ユーザ)
name:string amail:string password_digest:string


###コントローラ
micropostsコントローラ
toppagesコントローラ

###ビュー
microposts
-無し(createとdestroy機能のみ)


toppages
-index(一覧画面に、投稿内容の表示、投稿フォーム、投稿の削除機能を取り付ける)


##モデルの作成

MicropostとUserモデルを上記のカラムで作成します。

```app/models/micropost.rb
class Micropost < ApplicationRecord
  belongs_to :user
end
```
すると、こんな感じでコードが書かれてると思います。
```
belongs_to :user
```
は、1人のUserが、多数のMicropostを投稿する場合、Micropostが、1人のUserに紐づいてますよ！と、捉えることが出来ます。
例えば、「この投稿は誰がしたの？」というときに、Micropostを通して、Userを取得することができます。

Userモデルを見てみましょう。

```app/models/user.rb
class User < ApplicationRecord
  has_many :microposts
end
```
こちらの
```
has_many :microposts
```
は1人のUserが、多数のMicropostを投稿する場合、Userが多数のMicropostに紐づいてますよ！と捉えることができます。
例えば、「誰がこの投稿をしたの？」というときに、Userを通して、Micropostを取得することができます。Micropostは「多」なので、複数形になってます。


##ルータ
次に、ルータを見ていきましょう！

```config/routes.rbs
Rails.application.routes.draw do
  root to: 'toppages#index'

  resources :users, only: [:index, :show, :new, :create]

  resources :microposts, only: [:create, :destroy]
end

```

投稿(Microposts)機能で使用するルート情報です。
投稿の表示や、投稿画面は、投稿機能の中に入れずに、投稿機能にはcreateとdestoroyのみを持たせています。

##コントローラとビュー

###トップページ

```app/controllers/toppages_controller.rb
class ToppagesController < ApplicationController
  def index
    if logged_in?
      @micropost = current_user.microposts.build  
      @microposts = current_user.microposts.order('created_at DESC').page(params[:page])
    end
  end
end
```

トップページでは、投稿の作成と、投稿の一覧の表示を行います。
```
@micropost = current_user.microposts.build
```
は、投稿機能用のコードです。current_userはrailsが提供しているメソッドで、現在ログインしているユーザを取得します。
microposts.buildは、モデルで定義したmicropostsをbuild(新規作成)するという意味です。
なので、@micropostには、現在ログイン中にユーザがmicropostsを新規作成するための箱ですよ～っていう意味です。

また、
```
@microposts = current_user.microposts.order('created_at DESC').page(params[:page])
```
は、投稿一覧用に作成してます。作成したmicropostsをorder('created_at DESC')で作成日時順に並び変えて、page(params[:page])ページメント機能(kaminari)を付けています。


では、トップページを見ていきます。


```app/views/toppages/index.html.erb

<% if logged_in? %>

  <%= form_for(@micropost) do |f| %>
    <div class="form-group">
      <%= f.text_area :content, class: 'form-control', rows: 5 %>
    </div>
    <%= f.submit 'Post', class: 'btn btn-primary btn-block' %>
  <% end %>
  <p>
  <P>投稿内容</p>
  <% @microposts.each do |micropost| %>
    <div>
      <%= link_to micropost.user.name, user_path(micropost.user) %> <span class="text-muted">posted at <%= micropost.created_at %></span>
    </div>
    <div>
      <p><%= micropost.content %></p>
    </div>
  <% end %>

<% end %>

```

ログイン後にトップページを開くと、投稿フォームと投稿内容が表示されるようになっています。


![スクリーンショット (46).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203857/420bd519-c976-3dd5-74ed-ed36b9e7cdf0.png)


質素ですが、トップページはこんな画面になる予定です。
(まだ投稿機能を実装していないで、投稿内容が表示されてなくても大丈夫です。)


###投稿機能
投稿機能について見ていきましょう！

コントローラから見ていきます。
micropostsという名前でコントローラを作成します。投稿機能で使用するアクションは、createとdestroyのみです。


```app/controllers/microposts_controller.rb
class MicropostsController < ApplicationController
  before_action :correct_user, only: [:destroy]

  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = 'メッセージを投稿しました。'
      redirect_to root_url
    else
      @microposts = current_user.microposts.order('created_at DESC').page(params[:page])
      flash.now[:danger] = 'メッセージの投稿に失敗しました。'
      render 'toppages/index'
    end
  end

  def destroy
    @micropost.destroy
    flash[:success] = 'メッセージを削除しました。'
    redirect_back(fallback_location: root_path)
  end

  private

  def micropost_params
    params.require(:micropost).permit(:content)
  end

  def correct_user
    @micropost = current_user.microposts.find_by(id: params[:id])
    unless @micropost
      redirect_to root_url
    end
  end
end
```

特に難しいところは無いかと思いますが、
投稿時に
```
  def micropost_params
    params.require(:micropost).permit(:content)
  end
```
で、投稿内容にストロングパラメータを渡しています。
また、削除時に
```
  before_action :correct_user, only: [:destroy]
```
と
```
  def correct_user
    @micropost = current_user.microposts.find_by(id: params[:id])
    unless @micropost
      redirect_to root_url
    end
  end
```
で、削除を実行するユーザが投稿したユーザかの確認を行っています。

では、トップページに削除ボタンを付けてみましょう

```app/views/toppages/index.html.erb
<% if logged_in? %>

  <%= form_for(@micropost) do |f| %>
    <div class="form-group">
      <%= f.text_area :content, class: 'form-control', rows: 5 %>
    </div>
    <%= f.submit 'Post', class: 'btn btn-primary btn-block' %>
  <% end %>
  <p>
  <P>投稿内容</p>
  <% @microposts.each do |micropost| %>
    <div>
      <%= link_to micropost.user.name, user_path(micropost.user) %> <span class="text-muted">posted at <%= micropost.created_at %></span>
    </div>
    <div>
      <p><%= micropost.content %></p>
    </div>
    <div>
    <% if current_user == micropost.user %>
      <%= link_to "Delete", micropost, method: :delete, data: { confirm: "You sure?" }, class: 'btn btn-danger btn-xs' %>
    <% end %>
  </div>
  <% end %>

<% end %>
```

投稿も削除も出来ていますね！

![スクリーンショット (47).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203857/801e3520-341e-2d8b-3812-40a75dc1bb94.png)


##まとめ

current_userで、ログイン中のユーザと投稿機能を紐づけることができました！
railsのミソの部分なんですかね。。

次は多対多の機能について投稿するので、よければ読んでってください！！