2019/04/30
今回は、2019年のGW期間(10日間)を全て費やして取り組むポートフォリオの製作過程
を取りまとめた内容を投稿させて頂きます。(投稿は毎日行う予定)
全体通した取り組みの詳細については、前回までの記事をご参照ください。
【10日間でポートフォリオ作成に挑戦】1日目:要件定義〜記事投稿のCRUD
【10日間でポートフォリオ作成に挑戦】2日目:アクセス制限〜コメントのCRUD機能
【10日間でポートフォリオ作成に挑戦】3日目:ページネーション~CKEditorの導入
ここからは、今日1日で取り組んだ作業内容をご説明します。
まず、かなり大雑把に見積もった為、現実の進捗との乖離が大きくなってきた工数の見積もりを修正しました。
とりあえず、必須だけは、何とか10日間で終わらせたいと考えています。
Postテーブルに寄せていたdescription
を、当初のER図の通り、別テーブルに分けました。
なお、切り出したPostDescription
についてはaccepts_nested_attributes_for
を利用して、親レコードであるPostが保存された時に、同時に保存される様にしています。
class Post < ApplicationRecord
belongs_to :user
has_many :post_comments, dependent: :destroy
has_one :post_description, dependent: :destroy
accepts_nested_attributes_for :post_description, allow_destroy: true
end
class PostDescription < ApplicationRecord
belongs_to :post
end
(中略)
def post_params
params.require(:post).permit(:id, :title, post_description_attributes: [:description])
end
こうする事で、下記の様に親モデルのインスタンスを保存する処理の記述だけで済みます。
〜(前略)〜
def create
@post = current_user.posts.build(post_params)
if @post.save
redirect_to posts_path, notice: t('common.message.post_create')
else
render :new
end
end
〜(中略)〜
def update
if @post.update(post_params)
redirect_to edit_post_path, notice: t('common.message.post_update')
else
render :new
end
end
〜(後略)〜
分割するにあたって、色々と問題が発生したのですが、それは「今日の失敗」で紹介します。
昨日導入したCKEditorを使える状態にしました。
= javascript_include_tag 'https://cdn.ckeditor.com/ckeditor5/11.2.0/classic/ckeditor.js'
:javascript
const image_relation = document.querySelector( '#image_relation' ).value;
const csrf_token = document.querySelector( '#csrf_token' ).value;
window.ClassicEditor
.create( document.querySelector( '#editor' ), {
ckfinder: {
uploadUrl: '/images?image_relation=' + image_relation + '&csrf_token=' + csrf_token
},
toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'Blockquote', 'bulletedList', 'numberedList', 'ImageUpload', 'undo', 'redo'],
heading: {
options: [
{ model: 'paragraph', title: 'paragraph', class: 'ck-heading_paragraph' },
{ model: 'heading1', view: 'h1', title: 'heading1', class: 'ck-heading_heading1' },
{ model: 'heading2', view: 'h2', title: 'heading2', class: 'ck-heading_heading2' }
]
},
image: {
toolbar: [ 'imageStyle:full' ],
styles: [ 'full' ]
}
})
.then( editor => {
editor.ui.view.editable.editableElement.style.height = '800px';
} );
(中略)
= f.fields_for :post_description do |ff|
= ff.label :description
= ff.text_field :description, id: 'editor'
= f.hidden_field :image_relation, value: 'DescriptionImages', id: 'image_relation'
= f.hidden_field :csrf_token, value: @csrf_token, id: 'csrf_token'
= ff.object.errors.full_messages_for(:description).join(',')
とは言え、viewに直接スクリプトを埋め込んでいるのと画像アップロード機能との紐付けなどはまだなので、その辺りは明日のタスクとしています。
ここからは、本日の失敗談を紹介します。
Postテーブルから、description
を切り出したのですが、アソシエーションで凡ミスを繰り返してしまい、かなり時間をロスしてしまいました。
まず、エラーの現象としては、保存をしても、変更内容が反映されないという状況になりました。
ターミナルの処理結果を見ると、パラメーターが許可されていないというエラーが出ていました。
Unpermitted parameter: :post_description
しかし、ストロングパラメーターはきちんと設定してありました。
なんだかんだ調べて見ると、一対一のアソシエーションなのに、一対多で組んでいました・・・
has_many :post_descriptions, dependent: :destroy
それを修正したのですが、直りません。
もう一度確認すると、なぜか親モデルもbelongs_to
で組んでました・・・もうめちゃくちゃです・・・
belongs_to :post_description, dependent: :destroy
そして最終的に正しいのが、こちら。
has_one :post_descriptions, dependent: :destroy
よくよく確認すると、fields_for
のモデルの記述方法が間違っていたので修正しました。
= f.fields_for :post_description do |ff|
そうこうしてようやく完成。
これに至るまでに「2時間以上」掛かってしまいました・・・
相談出来る相手も居ない為、一度ハマってしまうと、中々抜け出すことが出来ないのが、個人開発の難しいところだと、改めて感じました。
開発の過程で、何度か下記の様なエラーに遭遇しました
translation missing: ja.activerecord.errors.messages.record_invalid
これは前回デフォルトの言語を日本語にしたのですが、他言語に対応させる為のgemを導入し忘れていました。
gem 'rails-i18n'
明日にはこの二つを完成させるところまで持って行きたい。
そしてテストコードを書きます。書かないと本当に駄目だ・・・無理・・・
そして、ransack
の導入くらいまでは進めたいと考えてます。
※追記:五日目の記事を投稿しました
【10日間でポートフォリオ作成に挑戦】5日目:CKEditorへ画像アップロード機能を追加