みんなの「作ってみた」

【10日間でポートフォリオ作成に挑戦】2日目:アクセス制限〜コメントのCRUD機能

2019/04/28

ryoutaku
ryoutaku
2018年12月から3年間「毎日技術ブログ書く」と宣言して現在も継続中。IBMのWatsonきっかけでエンジニアに憧れて、28歳未経験で転職。バックエンドの開発を担当(Ruby,AWS)社会にインパクトを与えるプロダクトの開発に携わりたい一心で、愚直にアウトプットを継続。今の関心事は自然言語処理。

概要

今回は、2019年のGW期間(10日間)を全て費やして取り組むポートフォリオの製作過程
取りまとめた内容を投稿させて頂きます。(投稿は毎日行う予定)

全体通した取り組みの詳細については、前回までの記事をご参照ください。

【10日間でポートフォリオ作成に挑戦】1日目:要件定義〜記事投稿のCRUD

今日一日の作業内容

ここからは、今日1日で取り組んだ作業内容をご説明します。

非ログイン時のアクセス制限

非ログイン状態でも記事の投稿などが出来ると問題ですので、下記のコードをapplication_controllerに記述して、全てのアクションで、未ログインの場合は、ログイン画面に遷移する様にしています。

controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :authenticate_user!
end

しかし、それだと使い勝手が悪い為、投稿内容の閲覧(一覧・詳細)は、強制遷移から除外しています。

controllers/posts_controller.rb
class PostsController < ApplicationController
  before_action :authenticate_user!, :except=>[:index, :show]

seedファイルでの初期データの生成

ブラウザ上で動きを直接テストする際に、都度データを作成するのは非常に手間なので、seedファイルから初期データを投入出来る様にしました。

db/seed.rb
if Rails.env.development?
  # User
  User.create! do |user|
    user.id = 1
    user.name = '田中太郎'
    user.email = '[email protected]'
    user.password  = "password"
  end

  # Post
  (1..100).each do |idx|
    Post.create! do |post|
      post.user_id = 1
      post.title = "タイトルですよ#{idx}"
      post.description = "詳細ですよ#{idx}"
    end
  end

  # PostComment
  (1..100).each do |idx|
    (1..10).each do |ids|
      PostComment.create! do |comment|
        comment.user_id = 1
        comment.post_id = idx
        comment.content = "コメントですよ#{ids}"
      end
    end
  end
end

直接データを生成・削除して、データベースの内容が変わった場合にも、bin/setupコマンドを実行すれば、データベースを再構築して初期データを投入し直してくれます。

Materializeの導入

前回のタスクでCSSフレームワークに「Bootstrap」を利用すると書いていましたが、まだ「Bootstrap」は実践経験がなく、リファレンスを見ても結構なボリュームでしたので、予定を変更して、以前使用した事があるMaterializeを導入する事にしました。

Materialize

コメントのCRUD機能

そして、コメントのCRUD機能を実装しました。
こちらのコードも典型的なCRUDの処理などで省きます。

Materializeを導入したものの、フロントまで力を入れる余力が無かったので、こちらもとりあえずサーバーサイドだけ実装を行いました。

今日の失敗

renderを活用してない

この一覧表示機能についてなのですが、当初はeachで処理していました。

views/posts/index.html.haml
- @posts.each do |post|
  .div
    = post.title
    = post.description
    = link_to t('common.button.show'), post_path(post)
    = link_to t('common.button.delete'), post_path(post), method: :delete, data: { confirm: t('common.message.confirm_delete') }

しかしrenderを使えば下記の様に実装することも可能です。

views/posts/index.html.haml
= render @posts
views/posts/_post.html.haml
.post
  = post.title
  = post.description
  = link_to t('common.button.show'), post_path(post)
  = link_to t('common.button.delete'), post_path(post), method: :delete, data: { confirm: t('common.message.confirm_delete') }

こちらの方がパフォーマンスも優位性が高い為、一覧機能に関しては、この方法で実装するのが良いと考えています。

アソシエーションの組み忘れ

モデルのアソシエーションを組むのを忘れていて、エラーに遭遇する事が何度かありました。

ActiveModel::UnknownAttributeError: unknown attribute 'content' for Post.

アソシエーションについては、モデル生成と一緒に行うことを習慣化させて、この辺りの凡ミスを防いで行きたいと考えています。

フロントサイド実装の時間を見込んでいなかった

今の現場はフロントとサーバーサイドがはっきり分かれているので、そのノリでフロント実装の工数を見積もって無かった💦
それでも必須要件は終わるだろう・・・たぶん・・・

明日の予定

フロントの分でスケジュールが大幅に変更になる見通し。
下記の実装は終えたいところ。

  • 記事一覧のページネーション(kaminari)
  • 画像のアップロード機能(Shrine)
  • CKEditorによる記事の編集機能

CKEditorまで導入出来たら、一気にテストを書いていく。

※追記:三日目の記事を投稿しました
【10日間でポートフォリオ作成に挑戦】3日目:ページネーション~CKEditorの導入