【個人開発】独学 + 職業訓練校でプログラミングを学び、ブックマークサービスを作りました。

# 1. はじめに
シンプルを追求したブックマークサービス「5Keeps」（ファイブキープス）を作りました。
[![5Keeps_ogp_jp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1048052/ecccda94-9098-ca42-c67e-6eb9e5aa5a1f.png)](https://five-keeps.herokuapp.com/)
2020年11月に未経験からプログラミングの学習を開始して、あっという間に１年が過ぎ去り、ようやく自作アプリのリリースにこぎつけました。この記事では、前半に開発したサービスについて解説し、後半に1年間の学習の過程をまとめています。

- 5Keepsへのリンク
https://five-keeps.herokuapp.com/

- ソースコード
https://github.com/daichihayasaka/five_keeps_ver01

# 2. サービスについて
### 2-1. サービス概要
#### 解決したい課題
プログラミング学習の環境は、時間や場所によって様々です。私の場合、家やカフェではMacbook、学校ではWindows、電車ではスマホを使ってます。最初はブラウザのブックマーク機能を活用してましたが、以下の課題を感じました。 

- ブックマークが増えすぎて、今必要な情報にすぐアクセスできない。
- ブックマークの整理が大変。  

そこで、これらの課題を解決するブックマークサービスを、自作アプリの題材に選びました。

#### 解決方法
以下のように機能を制限し、「今」必要な情報だけを、「分かりやすく」保存できる仕様にすることで、課題を解決しています。

- グループを5つまで作成できる。
- リンクをグループ毎に5つまで作成できる。
- リンクには必ずタイトルをつける。

----

### 2-2. 使い方（お試し用）
**1. 言語を選択し、「まずはお試し」ボタンからゲストページに移動**
* 会員登録をすると、作成したブックマークを保持できます。
![select_lang.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1048052/b11bf0ae-0f2e-f41f-9945-5ec47a6d432e.gif)
---
**2. グループを作成**
* 「ホーム」からグループを作成できます。
![create_group.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1048052/b46679d3-d7f9-1cf9-3793-664c2ea118ef.gif)
---                  
**3. グループを選択し、リンクを作成**
* 「ホーム」では全てのリンクが更新順に表示され、検索も可能です。
![create_link.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1048052/1d6ada15-1a6c-4b7c-9eee-6b85c1ff18c4.gif)
---
### 2-3. 機能一覧
**ユーザー関係**
・ユーザーの作成、編集、削除
・ユーザー認証（ログインの保持を選択可）
・メールを使用したアカウント有効化
・メールを使用したパスワード再設定
・ゲストログイン機能（詳細は後述）

**グループ関係**
・グループの作成、表示、編集、削除（非同期通信）

**リンク関係**
・リンクの作成、表示、編集、削除（非同期通信）
・URLから、リンク先WebサイトのOGP情報を取得・表示（RubyのNokogiri gemを使用）
・検索機能

**その他**
・お問い合わせ機能（Gmailを使用）
・言語切り替え機能（日本語/ 英語）

---

### 2-4. ゲストログイン機能について
様々な実装方法があると思いますので、別途詳細をまとめました。

**1. usersテーブルにboolean型の「guest属性」を追加**

```ruby:db/migrate/xxxx_add_guest_to_users.rb
class AddGuestToUsers < ActiveRecord::Migration[6.1]
  def change
    add_column :users, :guest, :boolean, default: false
  end
end
```

**2. ゲストページ用のルーティングを追加**

```ruby:config/routes.rb
post '/guest', to:'users#create_guest'
get  '/guest', to:'static_pages#guest'
```

**3. usersコントローラーにcreate_guestアクションを作成**

```ruby:app/controllers/users_controller.rb
  # POST /guest
  # 現在のユーザーがゲスト => ゲストページにリダイレクト
  # 現在のユーザーがいない => 新たにゲストを作成 (emailのアカウント名/passwordはランダムな英数字)
  def create_guest
    if current_user && current_user.guest?
      redirect_to guest_path
    else
      user = User.create(name: "Guest User",
                        email: SecureRandom.alphanumeric(15) + "@guest.com",
                     password: SecureRandom.alphanumeric(10),
                        guest: 1)
      log_in user
      flash[:success] = t('.flash.success')
      redirect_to guest_path
    end
  end
```

**4. static_pagesコントローラーにguestアクションを作成**

```ruby:app/controllers/static_pages_controller.rb
  # GET /guest
  # 現在のユーザーが「nilである」または「guestではない」=> ルートにリダイレクト
  def guest    
    redirect_to root_url if !current_user || !current_user.guest?
  end
```

**5. ゲストユーザーを定期的に削除**
Herokuのschedulerアドオンを利用し、以下のrakeタスクを1日1回、日本時間1時AMに実行してます。 

```ruby:lib/tasks/scheduler.rake
desc "This task is called by the Heroku scheduler add-on"
task :delete_all_guests => :environment do
  puts "Updating guests..."
  # 1日より前に作成されたゲストユーザーを全て削除
  User.where(guest: :true).where("created_at < ?", 1.day.ago).destroy_all
  puts "done."
end
```

*参考：http://railscasts.com/episodes/393-guest-user-record?view=asciicast*

---

### 2-5. 使用技術一覧
**バックエンド**
・Ruby 2.6.3
・Ruby on Rails 6.1.4

**フロントエンド**
・Sass
・Vanilla JS

**データベース**
・MySQL 8.0

**インフラ**
・Heroku

**テスト**
・Minitest

---

### 2-6. ER図
![5keeps_er_diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1048052/b2a85373-6641-4a81-82e1-4a05b8c72f95.png)

---

### 2-7. 今後やりたいこと
**機能面**
・スマホ画面でのUI・UXを改善する。
・非同期通信時の処理速度をあげる。
・ソーシャルログイン機能を実装する。
・レスポンシブ対応を細分化する。(現状だとPC/ Mobileの2パターン)

**技術面**
・RSpecでテストを書き換える。
・開発環境でDockerを導入する。
・インフラをHerokuからAWSに変更する。
・APIモードでシステムを作り変えてみる。

# 3. アプリ完成までの道のり
### 3-1. 学習開始（2020年11月〜2021年1月）
Progateとドットインストールを用いて、HTML、CSS、JavaScript、Ruby、SQL、UNIXコマンド、Git、Railsの基礎を学びました。JavaScriptの`forEach()`が中々理解できず苦戦したことや、始めてターミナル上でUNIXコマンドを叩いた時、想像していたプログラマー像を彷彿とさせる作業に興奮したことを、覚えています。

### 3-2. 苦しみつつ継続（2021年2月〜5月）
Railsチュートリアルに突入しましたが、第1章から大きくつまづきました。どうやってもHerokuにデプロイできず、泣きそうになりながらググりまくり、何とか解決しました。今思えば良い経験になったと思います。その後は、*難しすぎて離脱→別途学習→復帰*を繰り返しながら、少しずつ進め、6月に職業訓練校に入学するまでに、10章まで完了させました。（理解度は６割程度だったと思います。）

### 3-3. オブジェクト指向への理解が深まる（2021年6月〜8月）
学校では、Java→ HTML/CSS→ JavaScript→ Servlet/JSP→ SQL→ Linux→ Gitの順で授業が進みました。放課後や週末の学習では、Progate、ドットインストールも活用し、一旦Javaに集中しました。

JavaはRubyと違い、様々なことを明示的に指定します。例えばメソッドを作る時、 *戻り値はある？引数はある？それぞれ型は何なの？* などを明確にします。そんなJavaを使って、授業の中で何度も、クラスやインターフェース、メソッドを作ったおかげで、引数とは？戻り値とは？インスタンス変数とは？コンストラクタとは？アクセッサとは？継承とは？などを身体で理解し、プログラミング全体やオブジェクト指向への理解が深まりました。

Javaの学習がある程度落ち着いてから、Railsチュートリアルを再開し、全14章を完走しました。そしてついに、人生初の自作アプリ「5Keeps」の実装を始めました。

### 3-4. CRUD処理やデータベースへの理解が深まる（2021年9月）
学校では9月末の１回目の発表会に向けて、制作期間に入りました。授業は午前中のみで、午後は制作の時間です。この期間は、「5Keeps」の開発を、2つの方法で進めました。学校では**Servlet/JSP**、放課後や週末は**Rails**です。

Servletとは、JavaでWeb開発をするための、基本的なプログラムです。Servlet単体ではMVCのControllerを担当し、Viewを担当するJSP(Rubyで言うERBのようなもの)と連携して、Webページを動的に生成します。

>*Java Servlet（ジャバ サーブレット）とは、サーバ上でウェブページなどを動的に生成したりデータ処理を行うために、Javaで作成されたプログラム及びその仕様である。*
引用：Wikipedia ( https://ja.wikipedia.org/wiki/Java_Servlet ）

>*JavaServer Pages (JSP) は、HTML内にJavaのコードを埋め込んでおき、Webサーバで動的にWebページを生成してクライアントに返す技術のこと。*
引用：Wikipedia ( https://ja.wikipedia.org/wiki/JavaServer_Pages )

Servlet/ JSPはフレームワークではないので、Rubyのフレームワークである**Rails**やJavaのフレームワークである**Spring Boot**と比べると、手動でやらなければならないことが多いです。大変ですがその分学びが多く、特に以下の2点はその後の開発に大きく役立っています。

**CRUD処理の流れが身体に染み付く**
Servletは、リクエストの種類に応じて、呼び出すメソッドが変わります。GETリクエストで`doGet()`が呼び出され、POSTリクエストで`doPost()`が呼び出されます。Servlet/ JSPで開発を進める中で、リクエストの種類によって処理を使い分ける作業を、何度も繰り返しました。そのおかげで、CRUD処理の流れが身体に染み付きました。典型的な例は以下の通りです。
・ `doGet()`：URLパラメータの値を取得/ データベースから値を取得→JSPで表示
・ `doPost()`：フォームに入力された値を取得→データベースを更新→`doGet()`にリダイレクト

**データベースを強く意識**
Railsチュートリアル一周目では、ORマッパーである Active Recordを何となく使い、データベースのことをあまり意識できてなかったです。Servletを使った開発では、データベースとの接続を手動でおこない、生のSQLを沢山書き、データを追加するたびに「MySQL Workbench」で確認する作業を繰り返しました。そのおかげで、Railsを使ったアプリ開発においても、データベースを強く意識できるようになりました。

### 3-5. ググりながら実装（2021年10月）
Servlet/ JSP版「5Keeps」の発表が無事に終わり、学校では最後の大きなトピックとして、Javaのフレームワーク「Spring Boot」を学習しました。Railsと比較しながら学ぶことで、フレームワークとは？O/Rマッパーとは？パッケージ管理とは？などの理解が深まりました。

一方Rails版「5Keeps」は、ユーザー認証等、ベースとなる機能の実装が完了し、グループ・リンク関係機能の実装に突入しました。ここからは、Railsチュートリアルの枠を越えた未知の領域です。最初は不安でしたが、日本語記事はもちろん、時には英語で調べながら、1つ1つ機能を実装していきました。ググりながら実装していく中で、自力で問題を解決していく力が身についたと思います。

**大変だったこと【非同期通信】**
グループとリンクの作成・表示・編集・削除を全て非同期通信で行うことで、UXの向上を図ってますが、新たに追加した要素にイベントを追加するなど、RailsとJavaScriptの連携に苦労しました。

**こだわったこと【OGP情報の取得】**
アプリの機能がシンプルな分、デザイン面での寂しさがありました。それを改善するため、RubyのNokogiri gemを利用して、URLからリンク先WebサイトのOGP情報を取得しています。Webスクレイピングは未知の技術でしたが、いくつかの記事を参考にし、始めてOGP画像を取得できた時は、とてもテンションが上がりました。
*参考：https://zenn.dev/arao99/articles/40cde7168279f899d0f5*

### 3-6. ついにリリース！(2021年11月5日)
リリース直前まで、iOS特有の問題（ボタンの色や形が変わる等）を解決したり、学校の講師から「何のアプリなのかわかりずらい」と指摘を受けて、トップページに「使い方」を追加したりバタバタしましたが、11/5にTwitter上でリリースを発表することができました。

### 3-7. 職業訓練校という選択肢（余談）
プログラミングの学習を始めた当初は、会社員として働きながら、出勤前後や週末を使って学習をしていましたが、仕事との両立が難しく、思うように進みませんでした。一旦会社を辞めるべきか悩んでいる時に、職業訓練校のことを知り、応募することにしました。無事合格し、実際に受講してますが、入学して本当によかったと思ってます。理由は以下の通りです。

- 訓練校の期間中は失業手当を受給できるので、勉強に集中できる。
- 講師に質問や相談ができるので、挫折することなく学習を進められる。
- 「学校」という場所があることで、モチベーションを維持しやすい。

独学に限界を感じているが、金銭的にスクールに通うのが厳しいという初学者の方には、職業訓練校という選択肢もありだと思います。

# 4. さいごに
未経験から1年間プログラミングを学びましたが、正直最初は甘くみていました。プログラミングは難しいです。ひとつ壁を乗り越えたと思ったら、更に巨大な壁が現れます。とはいえ、コツコツ学習を続ける中で、少しずつできることが増え、その分楽しさが増していきました。
「5Keeps」をいったんリリースできましたが、完成ではないです。今後も改善を続けて、どんどん良いサービスにしていきます。
まだまだ学びたいことが沢山あるので、まずはエンジニア就職を成功させ、経験を重ねつつ、今後も技術を磨いていきたいと思います。日々の学びをTwitterで発信してるので、もしよければ覗いてみてください。(https://twitter.com/hayasakadaichi)