[個人開発]Rails×LIFF×Linebot(MessagingAPI) 子供の名前候補をストック・シェアするアプリ「BabyNames」を作りました

# どんなアプリ
[![Image from Gyazo](https://i.gyazo.com/144be074325dd586a863d5aebff4ca11.png)](https://gyazo.com/144be074325dd586a863d5aebff4ca11)
LINE上で赤ちゃんの名前候補の管理、評価ができて、ユーザー同士でアカウント共有をできるアプリです。

※現在heroku有料化に伴い、サービスを停止しています。
https://www.baby-names-app.com/

# どんなことができる？

<img width="300" alt="LINEメッセージで 名前の候補を登録 (1).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/b39fe6c0-629a-f9b8-0bc6-06175f0e114b.png">

<img width="300" alt="LINEメッセージで 名前の候補を登録.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/b204b549-0b52-876b-a63a-746bdd0c0741.gif">



<img width="300" alt="LINEメッセージで 名前の候補を登録 (2).gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/c66fa3e9-2b2b-ec72-0def-91df1bd6143e.gif">


<img width="300" alt="LINEメッセージで 名前の候補を登録.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/b19e491a-cfbd-f31d-bc56-d22d041020a1.png">

このほかにも、
・twitterとLineで拡散機能
・〇〇年の名前ランキング
・姓名判断の結果表示
・管理者ページ
などがあります。

# なぜ作った?
今、2人目の子供が生まれたばかりですが、今回も子供の名前を決めるのにとても悩みました。
名前をお薦めしてくれたりメモできるようなアプリはあるのですが、名前の候補を夫婦で共有できるアプリがないので、スプレッドシートを作って情報を共有していましたが、とてもやりにくかった経験からこのアプリを作ってみようと思いました。

# LIFFとLinebotを使用した理由
LIFFであればログインが不要になること、LineBotと組み合わせることでよく目にするアプリで気軽に開いてもらえると思ったからです。自分の場合、名前決めを後回しにしがちだったので、わざわざwebページに飛んでログインして名前を見ることは心理的な障壁が高いよなーと思っていたのでLIFFを使うことにしました。

# 使用技術
* Ruby(3.0.3)
* Rails(6.1.4.1)
* JavaScript
* jQuery
* LIFF(LINE Front-end Framework)
* LINE Messaging API
* amazon S3
* Nginx
* RSpec

### 主なGem
* line-bot-api (LINE通知)
* nokogiri(姓名判断の結果をスクレイピング)
* aws-sdk-s3(サイトマップをs3に保存)
* rails-i18n (国際化)
* dotenv-rails (環境変数の管理)
* gon(環境変数をview側で使用)

### 主なJavascriptライブラリ
* chart.js(姓名判断結果の表示に使用)
* raty.js(評価の変更時に使用)

### ER図

[![Image from Gyazo](https://i.gyazo.com/2c96a44189a94f6688b03881c9d4710a.png)](https://gyazo.com/2c96a44189a94f6688b03881c9d4710a)

# 難しかった点
LIFFを使ったログイン機能・アカウント共有機能を作るのが難しかったです。

◯LIFFを使ったログイン機能
ログインしてない状態から名前一覧ページに遷移する流れとしてはこんな感じ

![ユーザーの識別情報.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/6d06ffc9-2f16-9af5-1d48-9370338d1d95.png)

長いですね。。。細かいことを抜いてざっくりいうと

①・・・ページ遷移後すぐにJavascipt上でIDトークンという認証に必要な情報をLINE側から取得する

②・・・取得したIDトークンをrailsに投げて、
　　　　railsからIDトークンとrailsアプリのLIFF登録情報(チャネルID)をLINEサーバーに投げる

③・・・LINEIDなどの情報が返ってくるので、DBから登録しているUserを探してsessionに入れる。
　　　　ユーザー情報付きでJavascript上に返す

④・・・ユーザー情報を元に遷移

IDトークンを取得→サーバーからuserIDなどを取得する流れを理解して、コードとして機能させるまでがなかなか時間がかかりましたが、ドキュメントも日本語でわかりやすかったので助かりました。

https://developers.line.biz/ja/docs/liff/using-user-profile/#sending-id-token

◯アカウント共有機能について

夫婦で使ってもらう想定だったので、アカウントの共有機能を作りました。

Userカラムとは別にGroupカラムを作成して、
Group(1)対User(多)のアソシエーションを組みました。

ユーザーの導線としては先に登録したユーザーから招待url(uuid付き)を送る→それをクリックすることで
招待元ユーザーを把握できるようにして、同じgroupにユーザーを登録させています。

アカウントが既にある状態で招待リンクを踏んだ場合は?
アカウントのリセットを作るとしたらどういう挙動にする？
など、アカウント共有機能を作成するにあたって考えることが結構あって悩みましたが、形にできてよかったです。

# 工夫した点

名前を決めるときに、音の響きや、漢字、姓名判断の結果など、ユーザーによって何を大切にして名前を決めるかが違うと思います。
なので、ユーザーが何を大切するか最初に設定してもらって、名前を登録する際にもその名前ごとに各項目の評価をそれぞれしてもらい、結果を元に並び替える機能を作成しました。

<img width="700" alt="ユーザーの識別情報 (1).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/6d48af7a-4e35-0d01-103c-a226bd7edbde.png">



(ユーザーの設定値✖︎名前登録時の評価)をuserごとに5点満点で評価して、グループメンバーでの平均点を出して比較します。この順位を見るには「名前一覧ページ」のデフォルトの「総評価」で上から順に表示されます。

<img width="300" alt="IMG_D0C3565EE437-1のコピー.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1816474/98a87ab4-0611-4033-a15f-b35599126f13.jpeg">

並び替え機能には「総評価」の他に、各項目で並び替えができるように「音の響き」「姓名判断」「漢字」の項目があります。

# 作成後に追加した機能

### チュートリアル機能の拡張

使っていただいた方から、
「招待されたユーザーはトップページを経由せずにいきなりスタートになるので何ができるアプリかよくわからない。」
と意見をもらったので、招待された人は最初のページでモーダルでアプリ説明を表示する機能を追加しています。


# 今後実装したい機能

### コメント機能

それぞれの名前に対して、コメント機能があるといいかなと思ってます。どういう由来か、なんで候補に挙げたか、を残せると比べる判断基準として残せるかなーと思ってます。

# 最後に

ポートフォリオに入ってから、思ったものを形にするためにコードを書いていくのはとても楽しかったです。
特にLIFFで検索しても出てこなかった機能(アカウント共有機能)をなんとか形にできた時はとても嬉しかったです。（ググりきれなかっただけかもしれないですが）


妊娠中の方や旦那さんに使ってもらえるととても嬉しいです。
より使ってもらえるように改善を進めていきたいと思います！

ぜひ使ってみてください！
https://www.baby-names-app.com/

最後までご覧いただきありがとうございました！