#導入
現在制作中のアプリケーションに投稿機能を実装したいと思います。
投稿には文章と画像を投稿することが可能になってます。Twitterの投稿機能をイメージしていただくとわかりやすいと思います。
#開発環境
ruby '2.6.5'
rails '6.0.0'
#現状
アプリケーションには、ユーザー管理機能(devise)が、すでに実装されています。
ログインするとトップ画面に遷移され、「こんにちは、〇〇さん」表示されます。
deviseの導入方法は下記の記事からご確認ください。
https://qiita.com/ghexcffb/items/7f2b708ed34e84cca15b
#今回のゴール(完成品写真を載せたい)
ログイン状態のユーザーが「画像+テキスト」を投稿し、トップ画面に一覧表示できるようにします。画像についてはActiveStarageで実装します。
#実装
###postモデルとテーブルを作成します。
% rails g model post
マイグレーションファイルに必要なカラムを追加します。今回はpost_textです。また(references型)でuserを参照するための外部キーを記述します。
class CreatePosts < ActiveRecord::Migration[6.0]
def change
create_table :posts do |t|
t.string :post_text, null: false
t.references :user, foreign_key: true
t.timestamps
end
end
end
マイグレーションを実行しDBにpostテーブルが存在していることを確認します。
% rails db:migrate
###アソシエーションの記述
PostモデルとUserモデルにアソシエーションを記述します。
class Post < ApplicationRecord
belongs_to :user
end
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_many :posts, dependent: :destroy
end
##Active Strageの導入
GemfileにGemを記述しインストールします。
gem 'mini_magick'
gem 'image_processing', '~> 1.2'
% bundle install
次にActive Strageをインストールし、マイグレーションを実行します。
rails active_storage:install
rails db:migrate
postモデルにimageカラムとのアソシエーションを記述します。
class Post < ApplicationRecord
belongs_to :user
has_one_attached :image
end
##バリデーションの設定
最後に投稿機能のルールに合うようにバリデーションを設定します。今回は投稿内容のpost_text、image共に必須になります。したがって両者のバリデーションを設定します。
条件が複数存在しわかりにくい時は、以下のように表で整理することでミスをなくせると思います。
###条件
|カラム名|必須|
|:--:|:--:|:--:|
|post_text|◯|
|image|◯|
###バリデーション
class Post < ApplicationRecord
belongs_to :user
has_one_attached :image
validates :post_text, presence: true
validates :image, presence: true
end
##アクションとルーティングの設定
投稿機能と表示に必要なアクションとルーティングを設定します。投稿なのでnewとcreateのアクションを設定します。
同時にストロングパラメーターも記述します。post_textとimageを許可しましょう。
class PostsController < ApplicationController
def index
@posts = Post.all
end
def new
@post = Post.new
end
def create
@post = Post.new(post_params)
if @post.save #もしセーブしたら
redirect_to root_path #root_pathに戻る
else #それ以外なら
render :new #newのページに戻るよ
end
end
private
#ストロングパラメーター↓
def post_params
params.require(:post).permit(:post_text, :image).merge(user_id: current_user.id)
end
#ストロングパラメーター↑
end
Rails.application.routes.draw do
devise_for :users
get 'posts/index'
root to:'posts#index'
resources :posts #post全てのルーティングを設定
end
##ビューファイルの設置
最後に新規投稿画面に必要なビューを設置します。完成ビューは以下の写真です。
これで実際に投稿するとDBに反映されトップ画面に戻ってきます。
<h1 class="post_new_title">新規post</h1>
<%= form_with(model: @post, local: true) do |f| %>
<div class="field">
<%= f.label :post_text, "投稿内容" %><br />
<%= f.text_field :post_text %>
</div>
<div class="field">
<%= f.label :image, "画像" %><br />
<%= f.file_field :image %>
</div>
<div class="actions">
<%= f.submit "保存する", class: :form__btn %>
</div>
<% end %>
</div>
###一覧表示
投稿内容を一覧表示させるために、each文を使って表示します。
<% @posts.each do |post| %>
<%= link_to image_tag(post.image), post_path(post.id) %>
<%= link_to post.post_text, post_path(post.id) %>
<%= link_to "by#{post.user.last_name}", root_path(post.user.id) %>
<% end %>