Rails6.0で作る交流会サイトの作成ログ(2)
▼免責事項
本記事により発生した如何なる損害についても当方は責任をおいません。
前回は、会員登録機能を作りました。
今回は、イベント機能投稿機能を作っていきたいと思います。
Rails6は、リッチテキストというブログ投稿みたいに編集できる機能が備わっています。
それを使って投稿機能を作っていきます。
$ rails action_text:install
$ rails db:migrate
さて、準備もできたら、早速作っていきましょう!今回、イベント情報で必要なのは次のデータです。
・イベント作成者
・タイトル
・イベントアイキャッチ画像
・カテゴリー
・参加定員
・開催場所
・会場名
・開催日
・開催時間
・イベント内容の詳細
・ステータス(下書き、公開中、終了)
今回はコマンドで打つのが面倒なので、マイグレーションファイルを作ってからカラムを登録します。
$ rails g scaffold Meeting
# db/migrate/作成したファイル.rb
class CreateMeetings < ActiveRecord::Migration[6.0]
def change
create_table :meetings do |t|
t.references :user, foreign_key: true
t.string :title
t.text :body
t.string :image
t.string :category
t.string :event_place
t.string :event_address
t.date :event_date
t.time :open_time
t.time :close_time
t.integer :capacity
t.integer :status
t.timestamps
end
add_index :meetings, :title
add_index :meetings, :category
add_index :meetings, :event_address
add_index :meetings, :event_date
add_index :meetings, :open_time
add_index :meetings, :body,length: 255 # 検索できる文字数が255文字と制限する。
add_index :meetings, :status
end
end
# app/models/meeting.rb
class Meeting < ApplicationRecord
has_one_attached :image
has_rich_text :body
belongs_to :user
validates :title, presence: true, length: { maximum: 200 }
validates :body, presence: true
validates :image, presence: true
validates :category, presence: true
validates :event_place, presence: true
validates :event_address, presence: true
validates :event_date, presence: true
validates :open_time, presence: true
validates :close_time, presence: true
validates :capacity, presence: true
validates :status, presence: true
end
# app/models/user.rb
class User < ApplicationRecord
before_save { email.downcase! }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }, confirmation: true, unless: :uid?, on: :create
validates :image, presence: true
has_one_attached :image
has_secure_password
has_many :meetings, dependent: :destroy
end
# app/views/meetings/_form.html.erb
<%= form_with(model: meeting, local: true) do |form| %>
<% if meeting.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(meeting.errors.count, "error") %> prohibited this meeting from being saved:</h2>
<ul>
<% meeting.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label "イベント画像" %>
<%= form.file_field :image %>
<% meeting.errors.full_messages_for(:image).each do |message| %><p style="color:red"><i><%= message %></i></p><% end %>
</div>
<div class="field">
<%= form.label "タイトル" %>
<%= form.text_field :title %>
<% meeting.errors.full_messages_for(:title).each do |message| %><p style="color:red"><i><%= message %></i></p><% end %>
</div>
<div class="field">
<%= form.label "カテゴリー" %>
<%= form.select :category, [["勉強会", "勉強会"], ["セミナー", "セミナー"], ["座談会", "座談会"], ["読書会", "読書会"],["相互コーチング", "相互コーチング"] ], :prompt => "選択してください" %>
<% meeting.errors.full_messages_for(:category).each do |message| %><p style="color:red"><i><%= message %></i></p><% end %>
</div>
<div class="field">
<%= form.label "開催場所" %>
<%= form.text_field :event_address %>
<% meeting.errors.full_messages_for(:event_address).each do |message| %><p style="color:red"><i><%= message %></i></p><% end %>
</div>
<div class="field">
<%= form.label "会場名" %>
<%= form.text_field :event_place %>
<% meeting.errors.full_messages_for(:event_place).each do |message| %><p style="color:red"><i><%= message %></i></p><% end %>
</div>
<div class="field">
<%= form.label "開催日" %>
<%= form.date_field :event_date,{} %>
<% meeting.errors.full_messages_for(:event_date).each do |message| %><p style="color:red"><i><%= message %></i></p><% end %>
</div>
<div class="field">
<%= form.label "開始時間" %>
<%= form.time_field :open_time %>
<% meeting.errors.full_messages_for(:open_time).each do |message| %><p style="color:red"><i><%= message %></i></p><% end %>
</div>
<div class="field">
<%= form.label "終了時間" %>
<%= form.time_field :close_time %>
<% meeting.errors.full_messages_for(:close_time).each do |message| %><p style="color:red"><i><%= message %></i></p><% end %>
</div>
<div class="field">
<%= form.label "定員人数" %>
<%= form.number_field :capacity %>
<% meeting.errors.full_messages_for(:capacity).each do |message| %><p style="color:red"><i><%= message %></i></p><% end %>
</div>
<div class="field">
<%= form.label "イベントの詳細" %>
<%= form.rich_text_area :body %>
<% meeting.errors.full_messages_for(:body).each do |message| %><p style="color:red"><i><%= message %></i></p><% end %>
</div>
<div class="actions">
<%= form.submit "イベントを作成する" %>
<small>※下書き状態になります。公開設定をしてください。</small>
</div>
<% end %>
# app/controllers/meetings_controller.rb
class MeetingsController < ApplicationController
before_action :set_meeting, only: [:show, :edit, :update, :destroy]
# GET /meetings
# GET /meetings.json
def index
@meetings = Meeting.all
end
# GET /meetings/1
# GET /meetings/1.json
def show
end
# GET /meetings/new
def new
@meeting = current_user.meetings.build
end
# GET /meetings/1/edit
def edit
end
# POST /meetings
# POST /meetings.json
def create
@meeting = current_user.meetings.build(meeting_params)
@meeting.status = 1 # 0が公開状態、1が下書き状態
respond_to do |format|
if @meeting.save
format.html { redirect_to @meeting, notice: 'Meeting was successfully created.' }
format.json { render :show, status: :created, location: @meeting }
else
format.html { render :new }
format.json { render json: @meeting.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /meetings/1
# PATCH/PUT /meetings/1.json
def update
respond_to do |format|
if @meeting.update(meeting_params)
format.html { redirect_to @meeting, notice: 'Meeting was successfully updated.' }
format.json { render :show, status: :ok, location: @meeting }
else
format.html { render :edit }
format.json { render json: @meeting.errors, status: :unprocessable_entity }
end
end
end
# DELETE /meetings/1
# DELETE /meetings/1.json
def destroy
@meeting.destroy
respond_to do |format|
format.html { redirect_to meetings_url, notice: 'Meeting was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_meeting
@meeting = Meeting.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def meeting_params
params.require(:meeting).permit(:title,:body,:image,:category,:event_place,:event_address,:event_date,:open_time,:close_time,:capacity,:status)
end
end
# app/views/meetings/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>イベント作成者:</strong>
<%= @meeting.user.name %>
</p>
<p>
<strong>タイトル:</strong>
<%= @meeting.title %>
</p>
<p>
<strong>Image:</strong>
<%= image_tag @meeting.image,style: "width:300px;" %>
</p>
<p>
<strong>category:</strong>
<%= @meeting.category %>
</p>
<p>
<strong>event_place:</strong>
<%= @meeting.event_place %>
</p>
<p>
<strong>event_address:</strong>
<%= @meeting.event_address %>
</p>
<p>
<strong>event_date:</strong>
<%= @meeting.event_date %>
</p>
<p>
<strong>open_time~close_time:</strong>
<%= @meeting.open_time %> ~ <%= @meeting.close_time %>
</p>
<p>
<strong>status:1が下書き状態、0が公開中</strong>
<%= @meeting.status %>
</p>
<p>
<strong>イベント詳細:</strong>
<%= @meeting.body %>
</p>
<%= link_to 'Edit', edit_meeting_path(@meeting) %> |
<%= link_to 'Back', meetings_path %>
いやー、諸々長い編集でしたね。
では、諸々確認していきましょう!まずは、イベント投稿ページ
イベント詳細のところに、文章を編集できるボタンが色々並んでいますよね。
これが、rails6.0から追加された新機能です!すごいですね。
では、実際に投稿してみましょう!
イベントの詳細のところは、装飾機能が動作するか埋め込み画像が表示されるかも確認してください。
あれ・・・。画像が表示されてない。
ちょっと、色々調べて原因はよくわからんけど、blobの取り扱い方が間違っているらしい。
自動で作られている、_blob.html.erbを修正します。
# app/views/active_storage/blobs/_blob.html.erb
<figure class="attachment attachment--preview attachment--<%= blob.filename.extension %>">
<%= image_tag blob %>
<figcaption class="attachment__caption">
<% if caption = blob.try(:caption) %>
<%= caption %>
<% else %>
<span class="attachment__name"><%= blob.filename %></span>
<span class="attachment__size"><%= number_to_human_size blob.byte_size %></span>
<% end %>
</figcaption>
</figure>
これで、もう一度見てみましょう!
今度は完璧です!!!
いやー、なかなか長かったですねw
私はここまで4時間ほどかかりました(笑)
さてさて、次はここまで作ったアプリをherokuにデプロイして行きますー。
いいなと思ったら応援しよう!
サポートしていただけると、泣いて喜びます!
嬉しくて仕事をめちゃめちゃ頑張れます。