【個人開発】初心者向けにホラー映画を紹介するアプリを開発しました。

# 初めに
初めまして、にっしー（@naoki6431042）と申します。
2024年4月20日に、プログラミングスクールRUNTEQに入学し、エンジニア転職を目指しています。
この度、2025年3月28日にホラー映画を見た事がない人向けにB級ホラー映画を紹介するアプリ「[こみてらっ！](https://xn--28jvb3dvb.com/)」を開発いたしました。
![komitera2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3841425/d3dd7c43-4f4d-4e51-85a1-48943056a304.jpeg)

今回はこちらのサービス紹介記事となります。具体的にはREADMEの内容に解説などを追加したものとなります。

### サービスURL
https://xn--28jvb3dvb.com/

### Git hub
https://github.com/nissy456789/horror_comedy

# 目次
[- 概要](#概要)
[- 開発背景](#開発背景)
[- サービス紹介](#サービス紹介)
[- 使用技術](#使用技術)
[- ER図](#ER図)
[- こだわった点](#こだわった点)
[- 今後の改善点](#今後の改善点)
[- 最後に](#最後に)

# 概要
少しコミカルなB級ホラー映画紹介を中心としたレビューアプリです。 
ホラー映画を観た事がないユーザー向けに映画のハードルを下げるためのアプリで、ホラー映画を見たことがあるユーザーは普段観ない作品を見つける事ができます。

# 開発背景
#### **初心者向けホラー映画の選択肢の少なさ**  
一般的に「初心者向けホラー映画」として紹介される作品は10作品ほどに限られることが多く、それ以上の選択肢が提供されていないのが現状です。しかし、実際には「そこまで怖くないホラー映画」はもっとたくさん存在します。  
「ホラー初心者だからといって、限られた作品しか選べないのはもったいない」と感じ、より多くの作品を知ってもらうためのプラットフォームを作ることを決意しました。  

#### **「怖そう」という先入観による視聴のハードルの高さ**  
怖いのが苦手な人は、映画のポスターやあらすじ、不気味な映像を見ただけで「自分には無理」と判断してしまいがちです。実際には怖さの度合いがさまざまで、ホラー映画の中にはコメディ要素が強いものや、アクション寄りの作品もあります。それでも、「ホラー」というだけで敬遠されることが多い実情です。  
このアプリでは、そういった人でも気軽に「観てみようかな」と思えるような作品を紹介し、視聴のハードルを下げることを目的としています。  

#### **開発者自身の経験に基づく課題意識**  
私自身もかつてはホラー映画に対して「怖いから見たくない」と思っていました。しかし、『マリグナント』を観たことで、その考えが大きく変わりました。この作品は、冒頭こそホラーらしい雰囲気があるものの、実際にはアクション映画のような展開が主体で、ホラー要素はそこまで強くありませんでした。  
この体験を通じて、私は「ホラー映画は怖いものばかりではない」と気づき、むしろその非日常的なスリルや楽しさに惹かれていきました。この経験をもとに、同じように「ホラー映画＝怖い」と思い込んでいる人に、ホラー映画の楽しさを伝えたいと考えました。  

#### **「ホラー映画は観ない」という固定観念の打破**  
私がホラー映画にハマったことを知人に話すと、「映画は観るけど、ホラー映画は怖いから観ない」という人が多くいました。しかし、そういった人たちも、本当は「怖くないホラー映画があるなら観てもいい」と思っていることに気づきました。
この「ホラー映画＝怖い」という固定観念を払拭し、「実は怖くないホラー映画もある」という新しい視点を提供することで、ホラー映画を敬遠している人たちにも興味を持ってもらえるのではないかと考えました。  

#### **「こみてらっ！」が目指す解決策**  
このアプリでは、以下のような方法で「ホラー映画は怖いから観ない」という課題を解決します。   

1. **コメディ要素やアクション要素の強い作品の紹介**  
   - 単純に怖いだけではなく、エンタメ要素が強いホラー映画を紹介することで、初心者でも楽しめる作品を見つけやすくする。  

2. **「怖くないホラー映画」のレビュー・感想の共有**  
   - 実際に視聴した人の感想を集め、「意外と怖くなかった」「コメディ要素が強くて楽しかった」といったリアルな意見を見てもらうことで、不安を和らげる。  

3. **ユーザーが自分のペースでホラーに慣れていける仕組み**  
   - 「最初は怖くない作品から徐々にステップアップできる」といった導線を作り、無理なくホラー映画に触れられるようにする。  

このように、「こみてらっ！」は「ホラー映画の楽しさをもっと多くの人に知ってもらう」ことを目的としたアプリです。

# サービス紹介
| ユーザー登録 / ログイン |
| :---: | 
| ![](https://i.gyazo.com/bf4a98723b277bf14fa32e0efc259f62.png) |
| <p align="left">『名前』『メールアドレス』『パスワード』『確認用パスワード』を入力してユーザー登録を行います。ユーザー登録後は、自動的にログイン処理が行われるようになっており、そのまま直ぐにサービスを利用する事が出来ます。<br>また、Googleアカウントを用いてGoogleログインを行う事も可能です。</p> |
<br>

| 作品一覧 |
| :---: | 
| ![](https://i.gyazo.com/830868d3c22e31e1e7f1bbb8ce454eb8.jpg) |
| <p align="left">映画のポスター画像をカード型にしております。</p> |
<br>

| 作品詳細、ブックマーク/レビュー投稿、一覧画面 |
| :---: | 
| ![](https://i.gyazo.com/be211c6de16dd36c1fff248912f9a48c.jpg) |
| ![](https://i.gyazo.com/756f48b1b3c6e1a8ef7fd9a95ac628c6.png) |
| 作品詳細画面には作品のあらすじ紹介文とブックマークボタン、「観た！」ボタンを表示しております。
「観た！」ボタンを押すと、観た人数が増えてランキングに反映されます。<br>ログインするとレビューが投稿できる様になります。未ログイン状態で投稿するとログイン画面へ遷移します |
<br>

| ランキング |
| :---: | 
| ![](https://i.gyazo.com/1e6297cd21d8cc288f7ab701491a81b7.jpg) |
| <p align="left">「観た！」ボタンを押した人数をカウントしていますので、ボタンを押された数が多い映画のうち上位３つを表示しています。</p> |
<br>

| レコメンド |
| :---: | 
| ![](https://i.gyazo.com/a95def5097e28acf867174592e3f3ea9.jpg) |
| <p align="left">ユーザーがブックマークした作品をもとに、同じ作品をブックマークした他のユーザーを探します。<br>次に、そのユーザーがブックマークしている別の作品をランダムに表示します。<br>もし、ブックマークした作品が無い場合や、類似したユーザーが見つからない場合は、ランダムな作品を表示します。|

# 使用技術
| カテゴリ | 技術内容 |
| --- | --- | 
| サーバーサイド | Ruby on Rails  7.1.3・Ruby 3.3.6 |
| フロントエンド | Ruby on Rails・JavaScript・HTML |
| CSSフレームワーク | Tailwindcss + daisyUI |
| Web API | Google API |
| データベースサーバー | PostgreSQL |
| ファイルサーバー | AWS S3 |
| アプリケーションサーバー | render |
| バージョン管理ツール | GitHub・Git  |

# ER図
![こみてらっ！ER図jpg.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3841425/721bd975-3ad3-4e22-8442-7c067b226936.jpeg)

## テーブル説明
テーブル構成は大きく分けて２つで構成されており、**「ユーザー情報」**と**「映画情報です」**

### ユーザー情報に関するテーブル
こちらでは、ユーザーの名前やメールアドレスなど基本的な情報を`usersテーブル`で管理しております。
また、映画をブックマークするために`Bookmarksテーブル`や、ランキング機能のために`Watchedsテーブル`と連携しています。

`Watchedsテーブル`では注目度が高い映画のランキングを作成するために、作品を観た人数を集計しています。


### 映画に関するテーブル
こちらでは作品タイトルや作品の画像、映画のあらすじなどの情報を`moviesテーブル`にて管理しております。
またレビューを投稿してもらうために`Reviewsテーブル`やランキング機能のためのWatchedsテーブルと連携しています。

# こだわった点
- ### ランキング機能
ユーザーが「観た！」ボタンを押すことによってどのユーザーがボタンを押したのかwatchedテーブルで管理しています。
「観た！」を押すとwatchedテーブルにuser_idとmovie_idが保存されることで映画を観た人数が何人いるのかが分かるようになります。

- ### レコメンド機能
ユーザーベースの協調レコメンド機能を実装しており、自身がブックマークした作品が他ユーザーの誰とも被らなかった場合、全作品の中からランダムに紹介する様にしています。
以下のコードを使用することでレコメンド表示画面では@recommend_moviesに代入された作品を表示しています。
```
class RecommendsController < ApplicationController
  before_action :set_recommend_movies, only: %i[index recommend_explanation]

  def index; end
  def recommend_explanation; end
  private

  # レコメンドを設定する
  def set_recommend_movies   
    @recommend_movies = recommend_movies
  end

  #類似ユーザーを探す
  def similar_users
    bookmarked_movie_ids = current_user.bookmarks_movie.pluck(:movie_id)
    similar_user_ids = Bookmark.where(movie_id: bookmarked_movie_ids)
                               .where.not(user_id: current_user.id)
                               .distinct.pluck(:user_id)
    User.where(id: similar_user_ids)
  end

  #類似ユーザーのブックマークから映画を提案する 
  def recommend_movies

    if current_user.nil?
      return # 画面遷移せずに処理を終了
    end
  
    bookmarked_movie_ids = current_user.bookmark_movies.pluck(:movie_id)
    similar_users = similar_users
  
    if similar_users.present?
      similar_user_movie_ids = Bookmark.where(user_id: similar_users.ids)
                                        .where.not(movie_id: bookmarked_movie_ids)
                                        .distinct.pluck(:movie_id)
    else
      similar_user_movie_ids = []
    end
  
    # 推薦映画のIDを取得
    recommended_movie_ids = Movie.where(id: similar_user_movie_ids)
                                   .where.not(id: bookmarked_movie_ids)
                                   .where.not(id: Recommend.where(user_id: current_user)
                                                           .distinct.pluck(:movie_id)).pluck(:id)
  
    # レコメンドがない場合は全作品から3つ取得
    if recommended_movie_ids.empty?
      Movie.all.sample(3) 
    else
      Movie.where(id: recommended_movie_ids).sample(3)  # レコメンドがある場合は従来通り
    end
  end
end

```


- ### UI/UX
世界観を作るために背景は黒色、大事なボタンはオレンジ色にして目立たせました。
それ以外の色は使わないように色の種類を抑えました。
トップページとOGPの画像は、ユーザーに「怖くないホラー映画」という印象を持たせる為に、モンスター達が楽しく団欒している様子にしました。
<br>ランキング画面では、文字が無くてもランキングを理解できるようにイラストを使用しました。
また、全画面にサイドバーを表示することでいつでも任意の画面に遷移する事ができます。

 # 運用して気づいた課題
運用していく中で幾つか気づきがありました。

1つはユーザーから頂いたフィードバックで「**Google認証を使用してアカウント作成をすると本名が表示されてしまうので名前変更機能が欲しい。**」というフィードバックを頂きました。

2つ目はユーザーが作品を投稿する機能が無いのでアプリに発展性が無いことです。
こちらはGoogleアナリティクスのユーザー数を見て投稿されているレビューの少なさに気づきました。

3つ目はカテゴリー検索や俳優、監督等で検索する機能が無いので映画を探しにくい状態になっている事を使用しる中で気づきました。

 # 今後の改善点
上記の課題を解決するために以下の事を改善したいと思います。
（一部改善済み）
- ユーザー名の変更機能を実装（済）
任意の名前に変更することでレビュー投稿のハードルが下がると考えたからです。
<br>

- ホラー映画投稿機能の実装  
画像とあらすじを投稿できるようにすることで、誰でも簡単に“怖くないおすすめのホラー映画”を紹介できるようになります。これにより、アプリの発展性や継続的な利用が期待できます。
<br>

- 映画ごとにカテゴリーやタグを設定
映画のジャンルや出演俳優、監督の名前が分かることで、「推しが出演しているから」「推しが関わっている作品だから」といった理由で映画を観るきっかけを提供できることが期待できます。


# 最後に
初めてアプリを1から作成してみて、様々な知識がまだまだ浅いことを痛感しましたが、間違いなく１番楽しい時間でした。とても良い勉強になりました。
どんな小さな機能でも、実装できた喜びは最高のご褒美でした。
１年後、アプリを見直した時にクソコードすぎて見せられないよ...と思えるように今後も継続して学習を行なっていきます！！！