2
5

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 1 year has passed since last update.

【Rails】映画の公式情報を取得・投稿できるようにする。「TMDb API」

Last updated at Posted at 2023-02-20

経緯

やっぱり映画関連のアプリ作るなら公式情報を利用して作りたいよね~
てことで、「The Movie DataBase(TMDB)」のAPIを使っていきます。
初学者ゆえ、かなり脳筋な実装となっております。

TMDBって?

Let's talk about TMDB
The Movie Database (TMDB) is a community built movie and TV database. Every piece of data has been added by our amazing community dating back to 2008. TMDB's strong international focus and breadth of data is largely unmatched and something we're incredibly proud of. Put simply, we live and breathe community and that's precisely what makes us different.

要はコミュニティによって作られた映画やテレビ番組のデータベースという感じですかね。
このTMDBが出しているAPIを使って映画の公式情報を取得していきます。

この記事でできる事

1.映画の情報を取得&検索できる。
2.選択した映画の情報を利用しながら感想などを付け加えて投稿できる
3.映画の取得件数の調整やページネーション

完成イメージ

映画関連のMVCとしてMovieを用意

本記事で取得する映画情報は以下の通り
(取得したい情報→それに対応するAPI内の映画情報
タイトル→title
ポスター→poster_path
あらすじ→overview
公開日→release_date

その他に欲しい映画情報は以下を参照するなり用意してください。

選択した映画を投稿するMVCとしてPostを用意

本記事ではAPIで取得した映画情報を投稿する為にそれぞれに対応したカラムを用意して投稿できる仕様なので、以下の様なカラムを用意。
公開日の投稿はしない事にしました。
(API内の映画情報→対応させるため用意したカラム名:データ型
title→title:string
poster_path→image:string
overview→overview:text
これらのカラムに加え映画に自分のコメントを残せるよう、contents:textも用意した。

手順

1.APIの登録
2.映画用のMVC作成
3.投稿用のMVC作成

1-1.APIの登録

こちらにてアカウント登録とAPIの登録(申請をしましょう)

APIの登録は以下を参考にしてみてください
※すべて英語ですがスクショ等あるので翻訳機能等を活用しましょう

古い記事ですがこちらも参考までに

API登録に関してポイント
1.Application URLは適当に入れていても恐らく問題ないが、心配だったら先にリリースしてURLを貼っておく。
2.Application Summaryは英語で書く。
もしかしたらテキトーに登録してもいけるかもですが、一応ね!

取得できたAPIキーは忘れずメモしておきましょう!
サイトからAPIキーを確認したい時は 「右上ユーザーアイコン→プロフィール編集→左側サイドバーのAPI」 をクリックすると確認できます。

1-2.APIの登録(環境変数にする)

APIキーが外部に公開されるのを防ぐために
gemのdotenv-railsを利用します。

①gemfileに以下を追加・gemのインストール

Gemfile
    gem 'dotenv-rails'
ターミナル
bundle install

②app直下の階層に.envファイルを作成
qiita-tmdb-env.png
③作成した.envファイルに追記

.env
    TMDB_API=取得した自分のTMDB APIキー

TMDB_APIに自分のAPIキーを代入しています。
スペースを空けずに先ほど取得したAPIキーをコピペしましょう。
④.gitignoreに追記

.gitignore
    /.env

2.映画用のMVC作成

①moviesコントローラーの作成

ターミナル
    rails g controller movies index show

②routes.rbの修正
※-と書かれてる列は削除 +と書かれている列は追記の意
rootは別途で作成している場合は追記しなくてもよい

routes.rb
Rails.application.routes.draw do
- get 'movies/index'
- get 'movies/show'
+ resources :movies, only: [:index ,:show]
+ root 'movies#index'
end

③movies_controller.rbの記述

movies_controller.rb
class MoviesController < ApplicationController
  def index
    if params[:looking_for]
      movie_title = params[:looking_for]
      url = "https://api.themoviedb.org/3/search/movie?api_key=#{ENV['TMDB_API']}&language=ja&query=" + URI.encode_www_form_component(movie_title)
    else
      url = "https://api.themoviedb.org/3/movie/popular?api_key=#{ENV['TMDB_API']}&language=ja"
    end
    @movies = JSON.parse(Net::HTTP.get(URI.parse(url)))
  end

  def show
    movie_id = params[:id]
    url = "https://api.themoviedb.org/3/movie/#{movie_id}?api_key=#{ENV['TMDB_API']}&language=ja"
    @movie = JSON.parse(Net::HTTP.get(URI.parse(url)))
  end
end

詳しい説明は書き始めると長くなるのでここでは省きます。
気になる方はこちらを参考にしてみてください。

④index.html.erbの記述
映画の一覧と検索フォームの記述です

views/movies/index.html.erb
<div class="search">
    <%= form_tag(root_path, method: :get) do %>
        <%= search_field_tag :looking_for, nil, placeholder: 'Movie Title...' , :size => "40*40" %>
        <%= submit_tag 'search' %>
    <% end %>
</div>
<div class = "movies-container">
    <% @movies.each do |movie| %>
        <div class = "movie-data">
            <p><%= movie['title'] %></p>
            <%= link_to movie_path(movie['id']) do %>
                <% if movie['poster_path'] %>
                    <p><%= image_tag 'https://image.tmdb.org/t/p/w200' + movie['poster_path'],class: "card-img" %></p>
                <% end %>
            <% end %>
            <p><%= link_to "詳細へ", movie_path(movie['id']) %></p>
        </div>
    <% end %>
</div>

⑤show.html.erbの記述
投稿ページへのリンクは現地点ではエラーが出るので、コメントアウトしています。
リンク先のcrudが完成したらコメントアウトを外してください。

views/movies/show.html.erb
<div class="movie-detail">
    <p><%= @movie['title'] %></p>
    <p><%= @movie['release_date'] %></p>
    <% if @movie['poster_path'] %>
        <p><%= image_tag 'https://image.tmdb.org/t/p/w200' + @movie['poster_path'],class: "card-size" %></p>
    <% end %>
    <p><%= @movie['overview'] %></p>
    <%#= link_to "投稿ページへ", new_post_path(movie_id: @movie['id']) %>
</div>

3.投稿用のMVC作成

通常のCRUDを実装しましょう。

カラムの関係上Postモデルの作成コマンドは表記していますが、Postモデルに対応するpostsコントローラーやルーティングの記述もCRUDが問題なく作動するように完成している前提で以降の説明は進めます。

①Postモデルの作成

ターミナル
rails g model post title:string image:string overview:text contents:text 

②Postsコントローラーのnewアクションに追記

posts_controller.rb
class PostsController < ApplicationController
    def index
        @posts = Post.all
    end

    def new
        @post = Post.new
+       movie_id = params[:movie_id]
+       url = "https://api.themoviedb.org/3/movie/#{movie_id}?api_key=#{ENV['TMDB_API']}&language=ja"
+       @movie = JSON.parse(Net::HTTP.get(URI.parse(url)))
    end

    def create
        post = Post.new(post_params)
        if post.save
            redirect_to :action => "index"
        else
            redirect_to :action => "new"
        end
    end

    def show
        @post = Post.find(params[:id])  
    end

    def edit
        @post = Post.find(params[:id])
    end

    def update
        post = Post.find(params[:id])
        if post.update(post_params)
            redirect_to :action => "show", :id => post.id
        else
            redirect_to :action => "new"
        end
    end

    def destroy
        post = Post.find(params[:id])
        post.destroy
        redirect_to action: :index
    end

    private
    def post_params
        params.require(:post).permit(:title, :contents ,:image ,:overview)
    end
end

③new.html.erbの記述
取得した映画情報が変更されないようhidden_fieldを使います。

views/posts/new.html.erb
<h1>posts#new</h1>
<%= form_for @post do |f| %>
    <div class="field">
        <p><%= f.label :title %>:<%= @movie['title']%></p>
        <p><%= f.hidden_field :title, :size => 140, value: @movie['title']%></p>

        <p><%= image_tag 'https://image.tmdb.org/t/p/w200' + @movie['poster_path'] %></p>
        <p><%= f.hidden_field :image, value: 'https://image.tmdb.org/t/p/w200' + @movie['poster_path'] %></p>

        <p><%= f.label :overview %>:<%= @movie['overview']%></p>
        <p><%= f.hidden_field :overview, :size => 140, value: @movie['overview'] %></p>
        <%= f.label :contents,"感想" %>
        <p><%= f.text_area :contents, :size => "20x5"%></p>
    </div>
    <%= f.submit "postする" %>
<% end %>
<%= link_to "post一覧に戻る", posts_path %>

以上で投稿まで実装できているかと思います。

おまけ

実は今の状態だと映画は20件までしか取得できていない状態です。
100件ぐらいは取得しときたいですよね!
ついでにgem kaminariを用いて映画一覧のページネーションも実装しちゃいましょう!

①gemfileに以下を追加・gemのインストール

Gemfile
    gem 'kaminari'
ターミナル
bundle install

②movies_controller.rbのindexアクションの内容を変更
下記内容に全て書き換えましょう

movies_controller.rb
def index
    if params[:looking_for]
      movie_title = params[:looking_for]
      movies = []
      (1..5).each do |page|
        url = "https://api.themoviedb.org/3/search/movie?api_key=#{ENV['TMDB_API']}&language=ja&query=" + URI.encode_www_form_component(movie_title) + "&page=#{page}"
        response = Net::HTTP.get_response(URI.parse(url))
        if response.code == "200"
          result = JSON.parse(response.body)
          movies.concat(result["results"])
        end
      end
    else
      movies = []
      (1..5).each do |page|
        url = "https://api.themoviedb.org/3/movie/popular?api_key=#{ENV['TMDB_API']}&language=ja&page=#{page}"
        response = Net::HTTP.get_response(URI.parse(url))
        if response.code == "200"
          result = JSON.parse(response.body)
          movies.concat(result["results"])
        end
      end
    end
    @movies = Kaminari.paginate_array(movies).page(params[:page]).per(20)
  end

作品数を変えたい場合は(1..5).each do |page|(1..5)の数字を変更してください。
1ページあたり20作品、本記事では5ページ目までと指定しているので100作品分取得しているという感じです。

kaminariの仕様については以下を参照してください。

以上です!

ここまでの差分はこちら

参考記事

今回もたくさんの先人たちのおかげで実装することが出来ました。

https://qiita.com/kazuhito_nakayama/items/c9cf578058d1e4f078a1
https://weblion303.net/1262
https://developers.themoviedb.org/3
https://github.com/kaminari/kaminari
https://docs.ruby-lang.org/ja/3.0/class/Net=3a=3aHTTPResponse.html

2
5
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
2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?