概要
新規投稿ページの枠組みをつくったので、これに投稿機能を実装する。
準備
投稿画像ディレクトリー
投稿画像ファイル保存用のディレクトリーを作成する。
public/post_images
ビュー
新規投稿のnewビューは再掲。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<div class="new_post"> <h1>新規記事投稿</h1> <div class="contents"> <%= form_with(model: @post, url: '/posts', local: true) do |f| %> <h2>メッセージ入力</h2> <div class="field"> <%= f.text_area(:message, class: "message") %> </div> <h2>画像アップロード</h2> <div class="field"> <%= f.file_field(:upload_file) %> </div> <button>登録する</button> <% end %> </div> </div> |
コントローラー
post_paramsヘルパー
ビューのフォームからパラメーターを受け取る際のヘルパーで、コントローラーで扱うパラメーターを許可している。
:upload_file
は直接保存しないので含めていない。
1 2 3 4 5 6 7 8 |
class PostsController < ApplicationController ..... def post_params params.require(:post).permit(:message) end end |
createアクション
フォーム入力を受けて投稿記事を生成・保存する本体。ファイルのアップロードについてはこちらを参照。
- 記事を投稿したユーザーをデータベースから拾っている(L7)
- メッセージか画像かどちらかがあれば投稿できる(L10-13)
app/controllers/posts_controllers.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
class PostsController < ApplicationController ..... def create # 記事を投稿したユーザーをDBから取得 @user = User.find(user_in_session.id) # フォーム入力されたアップロードファイルを取得 upload_file = params[:post][:upload_file] # メッセージと画像ファイルの両方がないとエラー if post_params[:message].blank? && upload_file.nil? flash[:danger] = "メッセージか画像か少なくともどちらかを入れてください" redirect_to new_post_path and return end # Postオブジェクトを生成 @post = Post.new(post_params.merge(user_id: @user.id)) # 画像ファイルが選択された場合 if upload_file # アップロードファイルのファイルタイプが妥当かどうか検証 case upload_file.content_type when "image/jpeg" extention = ".jpg" when "image/png" extention = ".png" else flash.now[:danger] = "JPEGかPINGの画像ファイルを指定してください" render new_post_path and return end # 保存する画像ファイル名をランダム文字列に upload_file_name = random_string(20) + extention # 投稿画像を保存するディレクトリー upload_dir = Rails.root.join("public", "post_images") # アップロードする投稿画像ファイルのフルパス upload_file_path = upload_dir + upload_file_name # アップロードファイルの書き込み File.binwrite(upload_file_path, upload_file.read) # 生成済みのPostオブジェクトに従属させてPostImageオブジェクトを生成 if !@post.post_images.build(post_id: @post.id, file_name: upload_file_name) flash[:danger] = "投稿画像が保存できませんでした" redirect_to new_post_path and return end end # エラーがなければPostオブジェクトをデータベースに保存 if @post.save redirect_to top_path and return else flash.now[:danger] = "投稿メッセージが保存できませんでした" redirect_to new_post_path and return end end ..... end |
メッセージと画像、メッセージのみ、画像のみの投稿後のデータベースの例は以下のとおり。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
mysql> SELECT id, user_id, message FROM posts; +----+---------+-------------------------------------------+ | id | user_id | message | +----+---------+-------------------------------------------+ | 1 | 1 | こんにちは | | 2 | 2 | よろしく。 メッセージだけ。 | | 3 | 3 | | +----+---------+-------------------------------------------+ 3 rows in set (0.00 sec) mysql> SELECT id, post_id, file_name FROM post_images; +----+---------+--------------------------+ | id | post_id | file_name | +----+---------+--------------------------+ | 1 | 1 | Z579R0dXcpxF6BZqqmN8.jpg | | 2 | 3 | qFpkBIPhopF5JBhLluoY.jpg | +----+---------+--------------------------+ 2 rows in set (0.00 sec) |