12
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

就活用ポートフォリオとしてWebサービス「Asobi」を作りました。

Last updated at Posted at 2019-12-11

はじめに

こんにちは、ササクラ(@n_sasakura870)と申します。
受託開発の会社で働いておりましたが色々あって会社都合での退職となりました。今はWeb業界に転職するべく就活中です。

今回は僕のポートフォリオを紹介するとともに、

  • どういった技術を使用して開発したか
  • どういった反省点、課題点が生まれたか

を解説できればと思います。

作ったもの

Asobi

top.png 様々なローカルルールや自分で考えた遊びを記録・共有するサービスです。 URL : http://www.asobi-app.com/ GitHub : https://github.com/sasakura870/asobi

作った背景

友達とたまーにローカルでアナログな遊び(トランプ使ったゲームとかレクリエーションとか)をやることがあるんですが、結構面白くて盛り上がるんですよね。ただ、ふとやりたいなーと思ってググるとローカルルールって探してもあんまり出てこないことが多いんです。
なのでそういったローカルな遊びを記録・共有できるサービスがあれば、投稿して後で思い出せると考え、作ってみました。

制作日数

GitHubへの最初のコミットからデプロイまでちょうど100日でした。

選定した技術

ここでは使用した技術の紹介と、めぼしい技術の選定理由を説明します。

バックエンド

  • Ruby 2.6.3
  • Ruby on Rails 6.0.0
    • Webpacker 4.39.3
    • ActiveStorage
    • ActionText
    • slim 4.0.1
    • kaminari 1.1.1
    • ActiveRecord-Import 1.0.3
    • counter_culture 2.2.4
  • RSpec 3.9

選定理由

ActionText

サービスの要件上、遊びのルール説明にリッチテキストエディタを使用したかったため。
これがまあ簡単に実装できて素晴らしいものだったので、またQiitaに記事を書こうと思います。

ActiveRecord-Import

Rails6からバルクインサート機能が実装されたのですが、直接SQLを発行するものでIDのオートインクリメントやvalidation, callbackが効かなかったため。
公式リファレンスはこちら

Rails6の新しいバルクインサートメソッドに関してはこちらをご覧ください。
Rails6 のちょい足しな新機能を試す85(insert_all upsert_all編)

フロントエンド

  • Vue.js 2.6.10
    • Vue Croppa 1.3.8
  • FontAwesome 5.10.2
  • sweetalert2 8.18.3
  • Tippy.js 5.1.1
  • selectize.js 0.12.6

最初CSSフレームワークにBootstrapを採用していましたが気に入ったデザインにならず、最終的にFLOCSSに基づいて自作しました。
自分でCSSを書いてみると、思った100倍楽しかったです。

選定理由

Vue.js

jQueryを使用したことはあったのですが、DOMの操作がより簡単そうだったため。

Vue Croppa

ユーザーアイコンのトリミング機能に使用。Cropper.jsと悩みましたが、UIがこちらの方が好みだったのでこちらを採用しました。
公式リファレンスはこちら

sweetalert2

アラート機能、トースト機能に使用。ポップで可愛いデザインがAsobiにぴったりだと思い採用しました。
カスタマイズ性が高く、Ajaxを絡めた実装も簡単でした。
公式リファレンスはこちら

selectize.js

投稿画面のタグ入力フォームに使用。こちらもカスタマイズ性が高く使いやすかったです。
公式リファレンスはこちら

インフラ

  • AWS
    • VPC
    • EC2
    • Route 53
    • RDS
      • PostgreSQL 11.5
    • S3
  • Nginx 1.16.1
  • Unicorn 5.5.1

選定理由

一度HerokuでデプロイしたことがあったのでAWSに挑戦しました。
SSL化したかったのですがまだできていません…。ここはもっと学習しないといけないです。
2020/1/19 追記
Let's Encryptを利用してSSL対応しました。

データベース設計

スクリーンショット 2019-12-12 12.32.40.png
  • ユーザーに関するusersテーブル
  • ユーザーが投稿する遊びに関するarticlesテーブル
  • タグに関するtagsテーブル
  • いいねに関するfavoritesテーブル
  • コメントに関するcommentsテーブル
  • ユーザー同士のフォローを実装するrelationshipsテーブル
  • usersテーブル、articlesテーブルとtagsテーブルの中間テーブルであるtag_mapテーブル

Qiitaのようなユーザーがタグをフォローできる機能を実装するために、tag_mapテーブルにポリモーフィック関連を実装しました。

主な機能

機能やUIはQiitaを参考に設計しました。
機能の概要はGitHubのREADMEにも記載しているので、こちらではより技術的な部分に踏み込んだ説明をしていきます。

ユーザー

登録

signup.gif
Railsチュートリアル第11章を参考に、登録後送られてくるメールのリンクから本登録が完了するシステムを採用しました。
仮登録状態では、一部のページへアクセスした場合に仮登録完了ページへリダイレクトすることで機能を制限しています。
また、仮登録完了ページにメール再送リンクを作成し、Ajaxで登録されたアドレスにメールを再送する処理を実装しています。

ゲストログイン

登録せずとも一通りの機能を試してもらえるようにゲストログイン機能を実装しました。
ゲストログイン後は本登録ユーザーと同じように操作することができます。(退会とメールアドレス変更のみ禁止しています。)

ユーザーアイコン

usericon.gif
Vue.jsVue Croppaを使って画像をトリミングしてユーザーアイコンに設定する機能を実装しました。
画像作成後、適応するボタンを押すことでVue Croppaで作成された画像のBase64形式のデータを送信し、Rails側がそのデータをエンコードしてActiveStorageに保存する処理が走ります。

永続ログイン

remember.gif
ログイン時、またはユーザー設定のアカウント画面から「ブラウザを閉じた後もログイン状態を保持するか」を設定できます。
こちらはRailsチュートリアル第9章を参考に実装しました。

投稿

post.gif
タグ入力にselectize.jsを使用しています。編集時には遊びに関連付いているタグを取得し、フォームに初期値として入れるように実装しています。
本文入力フォームにはActionTextを使用しています。自動生成されるactiontext.scssのCSSが入力フォームと本文の両方に適応されるのがいいですね。

いいねとフォロー

ajax.gif
いいねボタンとフォローボタンはVue.jsでコンポーネント化し、Ajaxで処理をするように実装しました。

Asobiガチャ

capsule_toy.gif
他のWebサービスにはない機能として、「Asobiガチャ」機能を実装しました。
ボタンを押すとAjaxでRails側でランダムに遊びを1つ取得し、そのデータをjson形式でフロントに渡してJavascriptで表示しています。
使いやすさを向上させるため、引いた後に「もう一度引く」ボタンで再度ガチャが引けるようになっています。

反省点

頑張らないと投稿出来ないような雰囲気のサービスにしてしまった

遊びのルールを記録・共有するサービスのため、しっかりとした記事が書けるようにリッチテキストエディタを採用しました。
そのためぱっと見で投稿するハードルの高いWebサービスになってしまいました。
もう少し投稿する心理的なハードルが下がるように工夫をしたいと考えています。

ドメイン駆動設計に憧れてService層とか作っちゃった

作成途中にドメイン駆動開発(DDD)を知り、「なにこれすげー!」と手を出したのが失敗でした。
Service層を作りながら「どこまでがこのServiceクラスの責務なんだ…?」と悩むタネを増やしてしまい、完成に余計な時間がかかりました。
最終的にHandlerクラスというものまで作成し、こういった処理の流れになりました。
スクリーンショット 2019-12-11 17.07.16.png
Controllerは自分のクラス、アクションに合ったHandlerクラスを呼び出し、HandlerクラスServiceクラスを呼び出しています。
Serviceクラスは「ログインする」「タグ入力フォームに記載されたタグを取得または作成する」「いいねする」といった最小単位の処理のみ実行することで、様々なHandlerクラスから再利用できる仕組みです。
…が、振り返れば単純なCRUDしかしないアプリにこんな大層なアーキテクチャを採用する必要はなかったと感じています。

テストをほぼ書いていない

先ほどのドメイン駆動開発(DDD)で各処理を切り分けておきながら、テストを書いていません。何のためのDDDなんだ…
GitHubには制作初期に書いたRSpecのテスト(ほぼ通らない)が置いてあります。

DockerとかCircleCIとか触ってみたかった

これは制作中に存在を知ったので手を出しませんでした。次のポートフォリオで採用してみようと思います。

今後の課題点

HTTPS化

AWSのELBCloudFrontを使ってサイトのHTTPS化を行いたいです(挫折済み)。

2020/1/19 追記

Let's Encryptを利用してSSL対応しました。

レスポンシブ対応

サービスの要件上、モバイルからのアクセスの方が多そうなので(実際アクセスされるかは別として)レスポンシブ対応したいです。

入力フォームのエラーメッセージの表示

スクリーンショット 2019-12-11 17.40.18.png 現状だと新規登録や投稿画面の入力フォームのエラーメッセージが画面上部に表示される仕様です。 これもsubmitの前に、validationチェックし、エラーがあれば入力フォームの近くにそれぞれのエラーメッセージを表示するようにしたいです。

ソーシャルログイン機能

Twitterログインを実装してもっと利用しやすい仕組みにしたいと考えています。

作ってみた感想

自分で考えたWebサービスを形にするということは予想以上に大変でした。
Railsチュートリアルと違って道筋がない(当たり前ですが)ので、「この機能で本当にいいのか?」「このUIでいいのか?」「この処理はどこに書けばいいんだ?」と常に迷子になりながらコーディングしていました。その分デプロイできた時は脳汁出まくりで気持ちよかったです。

振り返れば大変だった以上に楽しかったです。エラー出しまくりながらやりたいことが実装できた時の感動は他では味わえないです。
このWebサービスを最後まで作りきることが出来たのも、ひとえにQiitaやSlackやもくもく会でアドバイスを下さった皆様のおかげです。本当にありがとうございます。

今後もこのWebサービスを改修しながら別のWebサービスも作りつつ、就活に励む所存です。

あとがき

名古屋でもくもく会を開催するのでよかったら参加してください。
https://connpass.com/event/158832/

12
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?