2019/05/01
今回は、2019年のGW期間(10日間)を全て費やして取り組むポートフォリオの製作過程
を取りまとめた内容を投稿させて頂きます。(投稿は毎日行う予定)
全体通した取り組みの詳細については、前回までの記事をご参照ください。
【10日間でポートフォリオ作成に挑戦】1日目:要件定義〜記事投稿のCRUD
【10日間でポートフォリオ作成に挑戦】2日目:アクセス制限〜コメントのCRUD機能
【10日間でポートフォリオ作成に挑戦】3日目:ページネーション~CKEditorの導入
【10日間でポートフォリオ作成に挑戦】4日目:テーブル分割〜CKEditorのフォームへの反映
ここからは、今日1日で取り組んだ作業内容をご説明します。
先日実装したCKEditorで、画像を利用した編集が出来る様に画像アップロード機能を実装しました。
画像アップロードについてはshrine
をベースに下記のgemを導入しています。
gem 'shrine'
gem 'image_processing'
gem 'mini_magick'
最終的に出来上がったものが、こちらです。
'shrine'は初めて利用したという事もあり、かなり苦労しました。
その辺りのエピソードは、「今日の失敗」にてご紹介します。
テストについては、単体テスト(モデル・コントローラー)と統合テストの両方を書いて行きます。
テストには、Rspec
を利用しています。
$ rails g rspec:install
まだ全てのテストを描ききれていませんが、参考にPostモデルのテストコードを掲載しておきます。
require 'rails_helper'
RSpec.describe Post, type: :model do
describe '#create' do
let!(:user) { create(:user) }
context 'can save' do
it 'is valid with title' do
expect(build(:post, user_id: 1)).to be_valid
end
end
context 'can not save' do
it 'is invalid without title' do
messages = build(:post, title: nil, user_id: 1)
messages.valid?
expect(messages.errors[:title]).to include('を入力してください')
end
it 'is invaid without user_id' do
messages = build(:post, user_id: nil)
messages.valid?
expect(messages.errors[:user]).to include('を入力してください')
end
end
end
end
まだまだ触り程度ですが、やっぱりテストコードはいいですね!!ゲームみたいで書いていて楽しいです!!!!
ここからは今日の失敗をまとめて行きます。
一通りコードを書いて、実際にアップロードを試そうとすると、下記の様なエラーが発生しました。
ターミナルを見てみると、下記の様な処理結果が出ていました。
Started POST "/images?image_relation=DescriptionImages&csrf_token=" for ::1 at 2019-05-01 13:25:52 +0900
Processing by ImagesController#create as */*
Parameters: {"upload"=>#<ActionDispatch::Http::UploadedFile:0x00007fbcffb81848 @tempfile=#<Tempfile:/var/folders/m0/h9_nmc1n5lg1ghdq5s4_4jc40000gn/T/RackMultipart20190501-49423-16e02tc.png>, @original_filename="pop_reiwa_hatsu.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"upload\"; filename=\"pop_reiwa_hatsu.png\"\r\nContent-Type: image/png\r\n">, "ckCsrfToken"=>"xJ5fKnWr0dw2IepjwvbFBWvHbJ7o3TqH9qpYKyK7", "image_relation"=>"DescriptionImages", "csrf_token"=>""}
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)
401
エラーは認証に失敗している事を表しますが、慌ててページを更新すると、ログイン状態が解除されていました。
そういえば、初期データを投入し直した(bin/setup)ので、その時にログインが解除されていたのですが、ページを更新していなかったので、それに気づかなかったという間抜けなエラーです・・・
次にログインしてアップロードを試しましたが、同じ動きになりました。
再度ターミナルを見ると、下記の様なエラーでした。
Completed 500 Internal Server Error in 16ms (ActiveRecord: 0.4ms)
LoadError (cannot load such file -- image_processing/mini_magick):
app/uploaders/image_uploader.rb:1:in `<top (required)>'
app/models/image.rb:2:in `<class:Image>'
app/models/image.rb:1:in `<top (required)>'
app/controllers/images_controller.rb:6:in `create'
また、gemの導入漏れです・・・何回やったら気が済むのでしょう・・・
次に発生したエラーは下記の内容です。
ちなみにエラーが発生した箇所は、下記のコントローラーのimage.save
です。
def create
image = Image.new(
image: params[:upload],
image_relation: params[:image_relation]
)
if image.save
render json: {
url: image.image[:standard].url,
uploaded: true
}
else
render json: {
error: {
message: image.errors.full_messages
},
uploaded: false
}
end
end
今回、Imageテーブルは、Postの画像以外にも、Userのアイコンなどでも利用する可能性がある事から、ポリモーフィック関連付けを使用しています。
なので、生成したImageインスタンスには、imageable_type
とimageable_id
のデータを持たせる必要があるのですが、pryで生成されたインスタンスの中身を確認してみるとnil
になっていました。
正直、このポリモーフィック関連付けの仕組みを理解しておらず、
本来はPostDescriptionの情報を持たせるべきなのでしょうが、新しく記事を投稿する際など、idが確定していない状態で、どの様に紐づければ良いのか、判断が付きませんでした・・・
なので、一旦current_user
の情報を持たせることにしました。
def create
image = current_user.images.new(
image: params[:upload],
image_relation: params[:image_relation]
)
if image.save
(中略)
とりあえずUserのアイコンは、現時点で実装の予定は無いので、一先ずはこれで動作する状態に持って行きたいと考えています。
下記の通り、新しく編集ページを開くと、CKEditorが表示されず、再読み込みを行うと表示されるというバグが発生しました。
コンソールのエラーを確認すると、どうやらTurbolinksが干渉している様でした。
なので、一旦Turbolinksは外しています。
ransack
は使った事が無いのですが、またそれで予定が狂いそうな予感がしています・・・
見積もりスキルをきちんと伸ばしたいですね。
※追記:六日目を投稿しました
【10日間でポートフォリオ作成に挑戦】6日目:テストコードの実装