生粋のキャンプ好きが、キャンプ場検索に特化したサービス【TO_CAMP】を開発&リリースしました。（Rails/Docker/CircleCI/Heroku）

##はじめに

- **この記事はポートフォリオとして開発した、キャンプ場検索サービス「TO_CAMP」の紹介記事です。**

https://www.to-camp.com/

また、「TO_CAMP」という名前は、これからキャンプ場を探して「キャンプへ（行く）」という意味を込めて名付けました。

<img width="669" alt="スクリーンショット 2021-08-26 9 32 58" src="https://user-images.githubusercontent.com/78259954/130881622-9a62e927-8328-4e88-8099-cc55771390c1.png">

出典：Google翻訳
https://translate.google.com/?hl=ja&tab=TT

##目次
[1.自己紹介](#1-自己紹介)
[2.TO_CAMPとは](#2-TO_CAMPとは)
[3.アプリの特徴](#3-アプリの特徴)
[4.機能一覧](#4-機能一覧)
[5.使用技術](#5-使用技術)
[6.テストフレームワーク](#6-テストフレームワーク)
[7.DB設計](#7-DB設計)
[8.インフラ構成図](#8-インフラ構成図)
[9.技術選定理由](#9-技術選定理由)
[10.ポートフォリオ作成する中で工夫したこと](#10-ポートフォリオ作成する中で工夫したこと)
[11.苦労したポイント](#11-苦労したポイント)
[12.実際にサービスとしてリリースすることを前提に考えたこと](#12-実際にサービスとしてリリースすることを前提に考えたこと)
[13.リリース後の改善点・今後の課題](#13-リリース後の改善点・今後の課題)
[14.学習方法](#14-学習方法)
[15.学習期間(2021年1月末〜6月末)](#15-学習期間(2021年1月末〜6月末))
[16.開発期間(2021年6月末〜8月末)](#16-開発期間(2021年6月末〜8月末))
[17.おわりに](#17-おわりに)

##自己紹介

幼い頃から家族でキャンプに行っていた生粋のキャンプ好きです。
公務員として働きながら、オリジナルの「キャンプ場検索サービス」を作りたいと考え、プログラミング学習を開始しました。
ProgateでHTML.CSS.Rubyなどを学んでいる内に、プログラミングの楽しさに惹かれ「Web系エンジニアになりたい」と考えました。
学習にコミットするために公務員を退職し、2021年4月〜本格的にプログラミングを学習し、キャンプ場検索サービスを開発&リリースしました。
現在、転職活動中の30歳です。
※2021.10 渋谷にあるWeb系自社開発企業のバックエンドエンジニアとして転職が決まりました。
2021.12〜エンジニアとしてキャリアをスタートします！

##【TO_CAMP】とは

:::note info
現在、TO_CAMPでは「広島県・岡山県・鳥取県」のキャンプ場データを検索できます。R3.8.26時点
キャンプ場は随時追加予定です。
:::
<img width="965" alt="スクリーンショット 2021-08-26 6 56 15" src="https://user-images.githubusercontent.com/78259954/130869806-818460dc-8983-46fa-b6ab-aebde34d63d0.png">

キャンプ場検索に特化したWebアプリケーションです。
様々な条件でキャンプ場を便利に検索することができます。
また、キャンプ場ごとの情報を豊富にまとめているため、キャンプをする人（以下、キャンパーと言います）が知りたい情報をひと目で知れるような構成にしています。

▼アプリのURLはこちら▼
https://www.to-camp.com

**ゲストログイン**も実装していますので、実際に操作していただくことも可能です。
**レスポンシブ対応**しているため、スマホやタブレットからもご覧頂けます。

##開発理由

- **キャンプ場を検索しやすく、情報がまとまったサイトが欲しい**

きっかけはシンプルな理由でした。 
キャンプ場を検索するときに、自分の知りたい情報を１つのWebサイトで完結できず、いくつかのサイトを訪問して情報を集めなければならない。

「もっとキャンプ場を調べやすくて、自分の知りたい情報が集まったサイトがあれば良いのにな。。」

そんなことを考えながらいつもキャンプ場を探していました。
そして、「サービスが欲しいなら自分で作れば良いんだ」と考えました。

▼GitHubのURLはこちらです▼
https://github.com/mocchann/campfs
コードもご覧頂けますと幸いです。

##アプリの特徴

一番の特徴は**「様々な方法でキャンプ場を検索できること」**です。
また、自分自信がキャンパーという立場から、キャンプ場を検索するときに必要な情報をまとめました。

###日本地図からキャンプ場を選ぶ「地図検索」

<img width="967" alt="スクリーンショット 2021-08-26 8 10 47" src="https://user-images.githubusercontent.com/78259954/130876471-2a283c30-cbbf-468a-8347-e8ed0788752c.png">

<img width="979" alt="スクリーンショット 2021-08-27 6 00 20" src="https://user-images.githubusercontent.com/78259954/131035358-fcb7bc68-9471-47a1-a47e-c13415ce6dd0.png">

まず地方を選択し、そのあとは都道府県単位でキャンプ場を検索できるようにしました。

###人それぞれのこだわり条件をチェックして、当てはまるキャンプ場を探せる「こだわり条件検索」

<img width="965" alt="スクリーンショット 2021-08-26 8 11 56" src="https://user-images.githubusercontent.com/78259954/130876511-61a637aa-b17e-45c7-914b-1aba2a1aac1b.png">

行きたいキャンプ場は人それぞれ違うため、キャンパーの好みに合ったキャンプ場にたどり着けるよう、こだわり条件検索を実装しました。

この検索機能は当サービスの強みであり、ユーザーからも「この検索は使いやすい」と好評を頂いております。

###自分のキャンプスタイルに合わせて検索候補を絞れる「キャンプスタイル検索」

<img width="964" alt="スクリーンショット 2021-08-26 8 12 10" src="https://user-images.githubusercontent.com/78259954/130876735-3de7bebe-10ba-4c41-ade1-560f4ad021f3.png">

- キャンプはするけど、車は持っていない方
- 登山有りきでキャンプもされる方
- キャンプで直火がしたい方（焚き火台と呼ばれる器具を使わずに、地面で直接焚き火をすることを直火と言います）

それぞれの目的別に選べるよう、キャンプスタイル検索も実装しました。（ウォシュレット検索や人気キャンプ漫画の聖地となっているキャンプ場をまとめた"ネタ的検索"も入れてみました）

###自分だけの「気になるキャンプ場リスト」を作れるブックマーク機能
私自信が**行きたいキャンプ場をメモアプリに書いてまとめる**という習性があるため、「ユーザーがキャンプ場リストを作れると便利かもしれない」と考え、ブックマーク機能を実装しました。

なお、こちらの機能はログインしたユーザーのみ使用可能となっています。

<img width="767" alt="スクリーンショット 2021-08-27 6 21 26" src="https://user-images.githubusercontent.com/78259954/131037906-98ff6dc0-1d70-4cfe-b854-d424a710607d.png">

このマークをクリックすると

<img width="781" alt="スクリーンショット 2021-08-26 10 27 02" src="https://user-images.githubusercontent.com/78259954/131037822-a95c8f29-5d9e-4a9b-886c-d021c5e483c7.png">

**気になるキャンプ場△**と表示され
（こちらはAjaxで実装しています）

<img width="957" alt="スクリーンショット 2021-08-27 6 29 30" src="https://user-images.githubusercontent.com/78259954/131038720-edad75bd-6440-4f6d-bea1-96a4a979dcaf.png">

ログイン後のアイコンをクリックするとドロップダウンリストが表示され、その中に**「気になるキャンプ場リスト」**があります。

<img width="957" alt="スクリーンショット 2021-08-26 9 12 26" src="https://user-images.githubusercontent.com/78259954/130880233-876af806-c56c-40ba-8eea-58228bc8726f.png">

このように、気になるキャンプ場ページに追加されています。

###まとまったキャンプ場情報

<img width="929" alt="スクリーンショット 2021-08-26 10 27 15" src="https://user-images.githubusercontent.com/78259954/130888211-0f81be5a-5ae1-4252-8995-1d4c6d414562.png">

私がキャンプ場検索サービスを作りたいと考えた原点とも言える**「キャンプ場詳細情報」**です。

実際にキャンプに行ったときの流れを考え、キャンプ場だけでなく周辺施設の情報もまとめています。

また、こちらの情報も自分が欲しい情報に加え、Twiterで「どんなキャンプ場情報がまとまっていたら良いか」を教えてもらい、テーブルを作成していきました。

▽TwiterのURLはこちら▽
https://twitter.com/freebblog

##機能一覧
R3.8.27時点での機能は以下のとおりです。

- **ログイン機能(devise)**
アイコン設定、ユーザー名登録、ゲストログイン機能

- **パスワードリセット機能(MailGun)**
- **検索機能(ransack)**
キャンプ場名検索、都道府県検索、各種条件絞り込み検索

- **ローディング(jQuery)**
検索時ローディング画面表示

- **口コミ機能**
- **星評価機能**
JQuery Raty.js、星評価平均値算出
- **ページネーション(kaminari)**
標高並べ替え機能

- **ブックマーク機能**
- **SNSシェアボタン**
Twitter、Facebook、LINE
- **Google maps API**
- **管理者機能(active admin)**
- **お問い合わせ機能(Google form)**
- **画像リサイズ(imagemagick, minimagick)**
- **SEO対策**
メタタグ(meta-tags)、サイトマップ(sitemap_generator, roboto, whenever)、サイト解析(google-analytics-rails)

##使用技術

・Ruby 2.6.8
・Ruby on Rails 6.1.4
・Puma 5.3.2
・Docker 20.10.6
・MySQL 8.0
・AWS S3
・CI/CD CircleCI
・RSpec
・Rubocop
・Heroku

##テストフレームワーク

- **RSpec**

factories
models spec
requests spec
system spec

##DB設計
ER図は「MySQL Workbench」を使って作成しました。

<img width="967" alt="スクリーンショット 2021-08-26 13 08 15" src="https://user-images.githubusercontent.com/78259954/130899450-bd275a20-fb84-481d-a85d-65402ea30ea4.png">

キャンプ場のデータをすべてFieldsテーブルに入れているため、データベースの正規化が今後の課題です。(2023.04 正規化してみました)
![スクリーンショット 2023-05-18 23.41.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1194218/d17a0191-b73b-d4db-7e69-d94c2a79cca1.png)


また、現状「有料キャンプ場」を検索対象としていますが、今後入力予定の「無料キャンプ場」については別途テーブルを作成し、検索対象に加える予定です。

##インフラ構成図
本番環境のインフラ構成図です。
CircleCIによる自動デプロイの流れも補足しました。
Dockerfileをpushし、Heroku側でbuildする方式を使っています。

![TO_CAMP インフラ構成図](https://user-images.githubusercontent.com/78259954/130965489-e031b1dd-0525-4b6b-8c38-65bcfbdb02df.png)

##技術選定理由
###前提
ポートフォリオの技術選定をする上で「実際にサービスとして運用すること」を念頭に置いて考えていきました。

###開発環境/Docker・Docker-compose
- 環境構築が短時間で行える
- コンテナのため軽量
- Web系企業の開発環境に使われている

###フロントエンド/Bootstrap5.jQuery
- グリッドシステムにより、素早くレスポンシブ対応できる
- 表示がわかりやすく、作業時間の短縮が期待できる
- 短いコードでデザインできる

###バックエンド/Ruby.Ruby on Rails
バックエンドには、Ruby/Railsを使用しました。
開発をはじめた当初は「クックパッド」や「食べログ」をイメージしてキャンプ場検索サービスを作ろうと考えており、それらのサービスに使われている技術を調べるとRuby/Railsが使われていたためです。
また、Rubyは日本で開発された言語であり、情報リソースも他の言語と比較しても多いということも決め手になりました。

###インフラ/Heroku
インフラは、Herokuを使用しています。
理由は2つあり、**サービス素早くリリースしたかったこと**と**ランニングコストを抑えたかったこと**です。
ポートフォリオの開発がある程度終わったところで、学習コストのかかるAWSではなくHerokuにデプロイしました。
また、リリースするだけでなく、その後のサービス運用を考えると、ランニングコストを抑えられるHerokuを選択しました。
また、AWSについては実務を行う上で必要なスキルであるため、現在学習しながら、別のアプリケーションをAWSのEC2上にデプロイを試みています。

※デプロイが完了すれば、こちらに追記予定です。

##ポートフォリオ作成する中で工夫したこと

###開発には「GitHub Flow」を使用
実務と同じように開発できているわけではないと思いますが、できるだけ実務を想定した開発を行うために「GitHub　Flow」を使用しました。
まずGitを用いた開発フローを調べると「Git Flow」と「GitHub Flow」の2種類があるとわかりました。
また、「Git Flow」は大規模な開発に用いられるということで、個人開発で1日に何度もデプロイを行うアプリケーション開発を考えていた私は「GitHub Flow」を採用することにしました。


###タスク管理はNotionを使用
ポートフォリオ開発において必要な工程をタスク分けし、Notionアプリに書き出してタスク管理を行いました。

<img width="844" alt="スクリーンショット 2021-08-27 6 51 34" src="https://user-images.githubusercontent.com/78259954/131041172-0ac8d04d-3d04-4884-a940-cc4213284e7c.png">

また、開発途中でタスク管理にはGitHubのissueが便利だということを知ったため、issueについてはユーザーからのフィードバックをもらったものをタスク化して利用しています。

<img width="960" alt="スクリーンショット 2021-09-02 13 26 20" src="https://user-images.githubusercontent.com/78259954/131781709-07949a3d-db56-4dd2-83ed-6a6f89557324.png">

###エラー解決や実装方法をメモしてオリジナルリファレンスを作成

<img width="1037" alt="スクリーンショット 2021-08-27 6 58 31" src="https://user-images.githubusercontent.com/78259954/131041670-0a6c1f94-034f-46f5-9462-9d7f3f2829f2.png">

こちらもタスク管理同様Notionアプリを使って作成しています。
エラーでハマったところ、解決方法をメモしておいたおかげで、似たようなエラーに遭遇したときに
「確か、これメモしたような、、、あった！」
といった具合で解決までの時間を短縮することができ、開発の効率を高めることができました。

##苦労したポイント
###技術選定
まずgemを使うか、自作で実装するか。また、gemを使うなら、どのgemが自分の作りたいアプリケーションに適しているのか。判断の連続で常に頭を使いながら、作業を進めました。判断基準としては、まず素早く開発できる点を重視し、その上でサービスを運用するために便利な機能が備わっているという点を意識して技術選定をしていきました。
###星評価の実装
プログラミングスクールではJavaScriptとjQueryの学習時間が一番短かったため、ポートフォリオに組み込む際は実装に時間が掛かりました。
ですが、鍛えられた自走力のおかげで自力で調べて実装することができました。

###パスワードリセット機能の実装
コードを書くだけではなく、ネームサーバーやDNSレコードの設定などインフラの知識も必要となるため、仕組み自体を理解するのに頭を捻りました。
実装方法は、公式ドキュメントを読んで一つずつ理解していきました。
また、必要なときは翻訳アプリの「DeepL」を使用して、米国の本社と直接メールでやり取りしました。

##実際にサービスとしてリリースすることを前提に考えたこと

###実際にユーザーになる方に要望を募り、出てきた情報を元に要件定義する

「自分が欲しかったキャンプ場検索サービス」という考え方をベースにしつつ、それに加えてTwiterで実際にユーザーとなる方からの要望を取り入れ、要件定義を進めていきました。
また、要件定義にもNotionを使いました。実装したい機能をチェックリストとして箇条書きにして、実装できればひとつずつチェックを入れながら開発を進めていきました。

<img width="974" alt="スクリーンショット 2021-09-02 13 38 35" src="https://user-images.githubusercontent.com/78259954/131782739-a2d3b44e-de3d-4b28-acd2-13dedba49c36.png">

###SQLのクエリ数N+1問題

ログでSQL発行数を確認しながら実装しました。allメソッドは使わず、includesメソッドでテーブルへのアクセス回数を削減しました。
また、HerokuのjawsDBのプランに、クエリ数の上限が設定されているということもあり、SQLの発行数は確認しつつ進めていきました。
学習をはじめて間もない頃はSQLのクエリ数を少なくするために、N+1問題を意識するという表面的な部分しかわかっていませんでしたが、実際にサービスを作って行く中でサイトの処理スピードに影響したり、クエリ発行数によって、DBのプランを気にしなければならないなど、学びが数多くありました。

###ユーザーが投稿できる機能の制限について

開発当初は**「クックパッド」**のようにユーザー自身が情報を投稿・共有するサイトを考えていました。
しかし、それでは情報の正確性が保てなかったり、情報が乱立してキャンプ場検索サイトとしてユーザビリティが悪くなる懸念がありました。
その問題を解決するために管理者機能を実装し、ベースとなるキャンプ場データは開発者が入力し、ユーザーには、口コミを投稿してもらうよう実装して、情報をわかりやすく表示できるように工夫しました。

##リリース後の改善点・今後の課題

###Fieldsテーブルの正規化

現在、キャンプ場の情報は全てFieldsテーブルに入った状態になっています。
これは知識不足で、DB設計がきちんとできていないことが原因です。
テーブルのカラム数が多いため、関連する情報だけを抜き取って別テーブルに移したあと、古いカラムを削除するという手順で構造をシンプルにする必要があると考えています。
しかし、時間のかかる作業であり、今回のアプリは個人プロダクトのため現状そのままにしています。。また優先順位が上がってきたときに、修正を試みようと企んでいます。

###口コミへの対応

口コミ投稿機能には「悪意ある書き込み」や「誹謗中傷などの書き込み」にどう対処するかという問題があります。
この課題については今後「口コミ報告機能」を実装するなど、改善の必要があると考えています。

###膨大なキャンプ場データの入力方法

現状キャンプ場のデータは1件1件手入力で進めていますが、そのため早くても1件のデータ入力に30分以上の時間が掛かってしまいます。
この部分をプログラミングを使って一部だけでも自動化できないか。この視点を持って別言語の学習をしても良いのではないかと考えています。

##学習方法

###独学+プログラミングスクール

学習についてはProgateの無料範囲で、HTML.CSS.Ruby.コマンドラインを学習後、プログラミングスクール+Railsチュートリアルを利用しました。
プログラミングスクールを選んだ理由は「独学よりもスピードを出したかったから」です。
しかし、プログラミングスクールに入る予算があれば、学習教材を購入したり、メンターと契約して「スクールと同じ環境を作ること」は可能ということも事実としてあると思います。そのあたりは色々な選択肢がありますので、個人で事前によく調べてから決断することをおすすめします。
また、書籍やyoutubeなどでも学習を行いました。

###定期的にもくもく会を主催&参加

所属するオンラインコミュニティ内で週３〜４回もくもく会を開催しています。作業時間だけでなく、合間に雑談時間も設けており、現役のエンジニアの方とお話をする中で新しい技術を知ったり、エラーの解決に繋がったりと自分から行動していくことで有益な情報を知る機会を作ることができました。
また、もくもく会には私と同じくWeb系エンジニアを目指している方も参加されており、お互いに刺激し合いながら情報交換もしています。

##学習期間(2021年1月末〜6月末)

2021年1月〜学習を開始し、トータルで約5ヶ月間です。
在職中は業務量が多く、プログラミングの学習時間が取りにくい部分はありました。
それでも「プログラマーになりたい一心」でコツコツと学習を続けました。
そこで「このまま働きながらだと学習スピードが出ない」と考え、退職を決意してプログラミング学習にコミットする方法を選びました。
退職後は、約3ヶ月間でプログラミングスクールのカリキュラムに加えて、Railsチュートリアルを集中して修了しました。

##開発期間(2021年6月末〜8月末)
トータル2ヶ月間です。
ポートフォリオに関しては全て独学で開発しました。
エラーが出たときは、Qiita記事や個人ブログだけでなく、公式リファレンスやStack Overflowの英語文献にもDeepL翻訳アプリを駆使して立ち向かいました。

##終わりに

本記事に関して誤っている箇所があれば、ご指摘頂けると大変助かります。

今回、はじめてゼロからアプリケーションを開発する中で、非常に多くの学びがありました。
開発したポートフォリオは今後もアップデートを続けて「キャンパーにとって最高に使いやすいサービス」にできるよう開発を続けていきます。
サービスを開発する中で、なかなかエラーが解決できなくて発狂しそうになることもありました。笑
それでもググりまくってトライ＆エラーを繰り返した結果、プログラムが動いたときの快感は、プログラミングでしか味わえないと考えています。

現在、転職活動中ですが、1日でも早く実務を自走してこなせるエンジニアとなるために、前のめりにプログラミングを楽しみながら継続して学習していきます。

長文となってしましましたが、最後まで記事を読んで頂き、ありがとうございました。