個人アプリ開発日記 #5

# 投稿したり、投稿詳細表示、削除、一覧表示を実装していきます

まずは,何はともあれ

```
rails g controller drinks
```

```
rails g model Drink
```
を実行

コーヒーの感想を投稿しあうアプリなので、モデル名や、コントローラー名をcoffeeにしたかったのですが、
coffeeは不可算名詞なので、できるだけ避けた方が賢明。
という事でdrinkと命名しました、、、！！

画像も投稿したいので

```
% brew install imagemagick
```

をターミナルで実行

```gem
gem 'mini_magick'
gem 'image_processing', '~> 1.2'
```

というgemをinstallして

```
bundle install
```



# drinks_controller

```ruby
class DrinksController < ApplicationController
  include SessionsHelper
  before_action :logged_in_user, only: [:index,:destroy]
  def index
    @drinks = Drink.includes(:user).order("created_at DESC")
  end

  def show
    @drink = Drink.find(params[:id])
    @user = @drink.user
    @drinks = @user.drinks
  end

  def new
    @drink = Drink.new
  end

  def create
    @drink = current_user.drinks.build(drink_params)
    if @drink.save
      redirect_to drinks_path
    else
      redirect_to 'new'
    end
  end

  def destroy
    Drink.find(params[:id]).destroy
    redirect_to root_path
  end

  private
  def drink_params
    params.require(:drink).permit(:name,:price,:explain,:image).merge(user_id: current_user.id)
  end
end


```

```ruby
  def index
    @drinks = Drink.includes(:user).order("created_at DESC")
  end
```
 は

一覧画面で表示する投稿の情報には、ユーザー情報も紐付いて表示されます。
この場合、投稿に紐付くユーザー情報の取得に、投稿の数と同じ回数のアクセスが必要になるので、N+1問題が発生します。

<strong>要は投稿に紐ずくユーザーの情報を一挙に取得するから早くなるよってことです</strong>


```ruby
  def create
    @drink = current_user.drinks.build(drink_params)
```

は、user.rbとアソシエーションを組むことで.buildというメソッドが使えます
このメソッドを使うことで勝手にuserと上手い感じに紐付けた投稿が可能になります



# drink.rb

```ruby
class Drink < ApplicationRecord
  belongs_to :user
  has_one_attached :image
  with_options presence: true do
    validates :name
    validates :explain
  end
end
```

with_optionメソッドはまとめてバリデーションを設定することができるメソッドです。
存在性だけでなく、フォーマットの検証にも使えて便利なのでぜひ調べて使ってみてください


## まずはコーヒーに関する投稿をしていきたいと思います！
   
   投稿する内容は,コーヒーの名前、画像、値段、説明です

# drinks/new.html.erb

```erb
<%= form_with model: @drink,local: true do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
      <%= f.text_field :name, placeholder: "商品名" %>
      <%= f.text_field :price, placeholder: "値段" %>
      <%= f.text_area :explain, placeholder: "商品の説明", rows: "10" %>
      <h3>コーヒーの写真を投稿してください</h3>
      <%= f.label :image %>
      <%= f.file_field :image %>
      <%= f.submit "SEND" %>
<% end %>
```

![drinks:new.html.erb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653881/cef31b59-8319-4e95-41a4-08093a2dd6b9.jpeg)


ビューにするとこんな感じ

何か投稿してみましょう

# drinks/index.html.erb

```erb
<% @drinks.each do |drink| %>
  <%= drink.name %>
  <%= image_tag drink.image.variant(resize: '500x250') if drink.image.attached? %>
  <%= drink.price %>
  <%= drink.explain %>
  <%= link_to drink.user.nickname ,drink_path(drink) %>
<% end %>
<%= link_to "投稿する", new_drink_path %>
<%= link_to "トップページ", root_path %>
```

投稿後はdrinks#indexを呼び出すようにしてます

![drinks:index.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653881/8841dec7-94a6-b2c5-dcd6-3cfb71d1f01f.jpeg)

レイアウト崩れまくりですがしっかり画像つきで表示されてて安心しました

次は投稿詳細をみてみましょう

# drinks/show.html.erb

```erb
<%= @drink.user.nickname%>
  <% @drinks.each do |drink| %>
      <%= drink.price%>
      <span class="name"><%= drink.name %></span>
      <p><%= drink.explain %></p>
      <%= image_tag drink.image.variant(resize: '500x250') if drink.image.attached? %>
      <%= link_to "削除",drink_path(drink.id),method: :delete %>
  <% end %>
```

![drinks:show.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653881/57686285-7a64-c5a3-7142-b1d4b9ed9e3b.jpeg)

今のところは投稿の詳細ページを押したところで殺風景ですが、ここにこの投稿がついたコメントがダラーっと表示される感じにしたいですね、、、！！


削除はまぁいいでしょう、、、、

<strong>一通りの基本的な機能はできたので次回は見た目をめちゃくちゃよくしていきたいと思います、、、！！！</strong>