Help us understand the problem. What is going on with this article?

楽天APIのデータをテーブルに格納する方法

はじめに

ポートフォリオ等でwebアプリを開発していると、「外部APIを利用してみたい」という方もいるかと思います。

今回紹介する楽天APIに関しては、データを取得すること自体は、そんなに難しくありません。
アプリIDを取得してgemをインストールすれば、割と簡単にデータを取得することができます。

ただし、「APIのデータをテーブルに格納して他のテーブルと関連付けて…」というように、取得したデータをアプリ内で活用しようとするとやや難易度が上がります(個人的な考えですが笑)

本記事では「取得したデータをテーブルに格納する方法」と「アソシエーションの設定」について記載していきます。
また、最後にアプリ内で検索機能を設けて、必要なデータを表示させるコードも簡単に記載しました。

これから楽天APIを使ってみたいという方の参考になれば幸いです。

注意

  • 本記事は楽天APIについて言及しております。
    また楽天APIにも様々ありますが、今回は楽天ブックス書籍検索APIを用います。

  • 本記事では、APIのデータ取得の部分(アプリIDの取得とgemのインストール)は割愛します。
    データ取得部分については、以下の記事を参考にしてみてください。
     
    https://freesworder.net/rakuten-api-rails/
    https://qiita.com/hakusai_it/items/6453c4577647cb8995d3

環境

  • Ruby version 2.7.2
  • Rails version 6.0.3.4

ER図

今回は以下のER図にて、話を進めていきます。
Bookテーブルがデータを格納するテーブルです。
取得した本について、レビューを記載するために、Reviewテーブルを設けています。

ER図.png

Bookテーブルのカラムについて少し説明します。
今回Bookテーブルのprimary_keyは『id』ではなく、商品の固有の番号である『isbn』を使っていきます。
『title』,『author』はそれぞれ、本のタイトルと著者名です。
『item_caption』は商品の説明、『item_url』は楽天の商品のurl、『middleimage_url』は本の画像です。
その他にも様々なデータがありますので、気になる方は以下のURLを参考にしてください。
https://webservice.rakuten.co.jp/api/booksbooksearch/

実装工程

概要

以下のような流れで実装していきます。

step1. テーブルの作成
step2. アソシエーションの設定
step3. ルーティングの設定
step4. コントローラーの設定
step5. 検索ページの作成

「アソシエーションの設定」はstep1・step2、
「取得したデータをテーブルに格納」はstep3・step4、
「検索ページの実装」はstep5で実装します

step1. テーブルの作成

各テーブルを作成していきます。
前述の通り、今回は User, Book, Reviewテーブルを作っていきます。

Userテーブル作成

Userテーブルは特に変わったことはしません。
モデルを作成して、マイグレーションを実行していきましょう!

$ rails g model User name:string email:string password_digest:string
$ rails g db:migrate

Bookテーブル作成

まずはモデルを作成していきます。

$ rails g model Book title:string author:string isbn:bigint url:string image_url:string

次にmigrationファイルを書き換えていきます。
Bookテーブルのprimary_keyは『id』ではなく、商品の固有の番号である『isbn』を使っていくため、ファイルの書き換えが必要になります。

ファイル名の米印にはMigration ID(日付等が書いてある数字)が入ります。
ActiveRecord::Migration[6.0]の部分は人によって異なると思います。

isbn部分にnull: false, primary_key: trueを追記します。

**************_create_books.rb
class CreateBooks < ActiveRecord::Migration[6.0]
  def change
    create_table :books, id: false do |t|
      t.string :title
      t.string :author
      t.bigint :isbn, null: false, primary_key: true
      t.string :url
      t.string :image_url

      t.timestamps
    end
  end
end

マイグレーションファイルを書き換えたらマイグレーションしていきます。

$ rails g db:migrate

Reviewテーブル作成

最後にReviewテーブルを作成していきます。

$ rails g model Review content:string user:references book:references

次にmigrationファイルを書き換えていきます。
ファイル名の米印にはMigration ID(日付等が書いてある数字)が入ります。
ActiveRecord::Migration[6.0]の部分は人によって異なると思います。

**************_create_reviews.rb
class CreateReviews < ActiveRecord::Migration[6.0]
  def change
    create_table :books, id: false do |t|
      #bookの部分に記載してあったforeign_key: trueを削除する
      t.references :book, null: false
      t.references :user, null: false, foreign_key: true

      t.timestamps
    end
    #この部分の新たに以下のコードを記載
    add_foreign_key :bookcases, :books, column: :book_id , primary_key: :isbn
  end
end

マイグレーションファイルを書き換えたらマイグレーションを実行していきます。

$ rails g db:migrate

これでテーブルの作成は以上です。
次はアソシエーションの設定です。

step2. アソシエーションの設定

各model.rbのアソシエーションを設定してきます。
ここでもBookテーブルのprimary_keyを『isbn』になるようコードを書いていきます。

user.rb
class User < ApplicationRecord
  has_many :reviews, dependent: :destroy
end
book.rb
class Book < ApplicationRecord
  self.primary_key = "isbn"
  has_many :reviews, dependent: :destroy
end

review.rb
class Bookcase < ApplicationRecord
  belongs_to :user
  belongs_to :book, primary_key: "isbn"
end

step2までで、テーブル作成とアソシエーションの設定は終了です。
step3以降はBookテーブルにデータを格納する方法を主に説明していきますので、User, Reviewモデルについては割愛し、Bookモデルについてのみ記載していきます。

step3. ルーティングの設定

今回は検索欄と検索結果を表示するために/searchアクションを設けています。
必要であれば、ご自身で追加のアクションを設定してください。

routes.rb
get 'books/search', to: "books#search"

step4. コントローラの設定

まずはコントローラファイルを作成していきます。

$ rails g controller books

作成したコントローラファイルに以下のコードを記載していきます。

books_controller.rb
class BooksController < ApplicationController

  def search
    #ここで空の配列を作ります
    @books = []
    @title = params[:title]
    if @title.present?
      #この部分でresultsに楽天APIから取得したデータjsonデータを格納します
      #今回は書籍のタイトルを検索して一致するデータを格納するように設定しています
      results = RakutenWebService::Books::Book.search({
        title: @title,
      })
      #この部分で@booksにAPIからの取得したJSONデータを格納していきます
      #read(result)についてはprivateメソッドとして設定しております
      results.each do |result|
        book = Book.new(read(result))
        @books << book
      end
    end
    #「@books内の各データをそれぞれ保存していきます
    #すでに保存済の本は除外するためにunlessの構文を記載しています
    @books.each do |book|
      unless Book.all.include?(book)
        book.save
      end
    end
  end

  private
  #「楽天APIのデータから必要なデータを絞り込む」、且つ対応するカラムにデータを格納するメソッドを設定していきます
  def read(result)
    title = result["title"]
    author = result["author"]
    url = result["itemUrl"]
    isbn = result["isbn"]
    image_url = result["mediumImageUrl"].gsub('?_ex=120x120', '')
    book_genre_id = result["booksGenreId"]
    item_caption = result["itemCaption"]
    {
      title: title,
      author: author,
      url: url,
      isbn: isbn,
      image_url: image_url,
      book_genre_id: book_genre_id,
      item_caption: item_caption
    }
  end
end

step4までで、テーブルへのデータ格納は実装完了です。
step5では検索ページと結果の出力ページを作成していきます。

step5. 検索ページの作成

search.html.erbというファイルを作成し、コードを書いていきます。
※本記事では最低限のコードのみ記載しております。適宜classを設定し、見た目を改善しましょう!

search.html.erb
#検索バーを表示
<%= form_tag(books_search_path, method: :get) do %>
  <%= text_field_tag :title, @title %>
  <%= button_tag type: "submit" %>
<% end %>

#検索結果を表示
<% if @books %>
  <% @books.each do |book| %>
  #ご自身が表示させたいデータを記載してください
  #以下のコードではは画像タイトル著者名商品の説明を表示させています
    <%= image_tag book.image_url %>
    <%= book.title %>
    <%= book.author %>
    <%= book.item_caption %>    
  <% end %>
<% end %>

以上で実装工程は終了となります。
何かご不明点や誤っている点がございましたら、コメントにて教えていただけると幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away