個人アプリ開発日記 #5


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

まずは,何はともあれ

rails g controller drinks
rails g model Drink

を実行

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

画像も投稿したいので

% brew install imagemagick

をターミナルで実行

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

というgemをinstallして

bundle install

drinks_controller

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


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

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

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

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

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

drink.rb

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

<%= 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/index.html.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/show.html.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 %>

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

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

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