【Rails】openBDのWebAPIによる書籍検索でmodelにバリデーションを実装

公開日:2018-11-21
最終更新:2018-11-21

プログラミングに入門して5ヶ月。個人開発のリアルRPG系Webアプリ「まちかどルートをv4.0rc1にバージョンアップしました。

今回追加したのは書籍や漫画を読んだら投稿してレベルアップできる機能です。

openBDの書籍検索APIを使う

openBD - 書誌情報・書影を自由に
https://openbd.jp/

フリーで利用できてレスポンスが高速。アクセスキーも不要ですし、とても使いやすいと思いました。

↓書籍検索時の動画です。

JQueryで書籍検索を簡単実装

こちらの記事を参考にしました。

<script>
$(function() {
    $('#getBookInfo').click( function( e ) {
        e.preventDefault();
        const booktitle = $("#booktitle").val();
        const bookisbn = booktitle;
        const url = "https://api.openbd.jp/v1/get?isbn=" + booktitle;

        $.getJSON( url, function( data ) {
            if( data[0] == null ) {
                alert("書籍が見つかりません");
            } else {
                if( data[0].summary.cover == "" ){
                    $("#thumbnail").html('<input type=\"hidden\" name=\"post[bookisbn]\" value=\"' + bookisbn + '\"><input type=\"hidden\" name=\"post[bookpublisher]\" value=\"' + data[0].summary.publisher + '\"><input type=\"hidden\" name=\"post[bookauthor]\" value=\"' + data[0].summary.author + '\"><input type=\"hidden\" name=\"post[bookpubdate]\" value=\"' + data[0].summary.pubdate + '\"><input type=\"hidden\" name=\"post[bookcover]\" value=\"' + data[0].summary.cover + '\">');
                } else {
                    $("#thumbnail").html('<div><img src=\"' + data[0].summary.cover + '\" style=\"border:solid 1px #000000\" /></div><input type=\"hidden\" name=\"post[bookisbn]\" value=\"' + bookisbn + '\"><input type=\"hidden\" name=\"post[bookpublisher]\" value=\"' + data[0].summary.publisher + '\"><input type=\"hidden\" name=\"post[bookauthor]\" value=\"' + data[0].summary.author + '\"><input type=\"hidden\" name=\"post[bookpubdate]\" value=\"' + data[0].summary.pubdate + '\"><input type=\"hidden\" name=\"post[bookcover]\" value=\"' + data[0].summary.cover + '\">');
                }
                $("#booktitle").val(data[0].summary.title);
            }
        });
    });
});
</script>

$("#thumbnail").htmlのところにinputのhidden属性をいくつか書いてあります。これはopenBDで取得できる著者名bookauthorなどの各種書籍情報を検索フォームには表示させずデータベースにいったん保存しておき、index.html.erbといった別のviewで読み込んで表示するためです。また、下記バリデーションにも活用しています。

form.html.erb

viewの書籍検索フォーム部分(一部抜粋)です。

ちなみにWebデザインにはBootstrap 4(bg-secondary p-2btn-smなど)というCSSフレームワークを使い、アイコン部分にはWebフォントのOPENICONIC(oi oi-bookoi-magnifying-glassなど)を利用しています。

<%= form_with model: @post, local: true do |f| %>
(中略)
<div class="bg-secondary p-2" style="border-radius: 3px 3px 0px 0px; opacity: 0.9;">
    <span class="oi oi-book text-white ml-1 mb-2" title="本" aria-hidden="true"></span> <span class="font-weight-bold text-white">読んだ本を登録してね</span>
    <div class="input-group">
        <input id="booktitle" type="text" name="post[booktitle]" value="" class="form-control" placeholder="本のISBNコード(-不要)で検索">
        <div class="input-group-text">
            <span class="btn-sm p-0" id="getBookInfo">
                    <span class="oi oi-magnifying-glass" title="書籍検索" aria-hidden="true"></span>
            </span>
        </div>
    </div>
    <% if @post.errors.messages[:bookisbn].any? %>
        <span class="font-weight-bold text-warning"><%= @post.errors.messages[:bookisbn][0] %></span>
    <% end %>
    <div class="mt-1" id="thumbnail"></div> 
</div>
(中略)
<%= submit_tag "投稿する", class: "btn btn-lg btn-blue700_rsd", data: { disable_with: "投稿中..." } %>
<% end %>

modelのバリデーションに条件を付ける

検索フォームにきちんと情報が入力されないままデータベースに保存されることのないよう、バリデーションを追加してみました。それにはRailsに標準装備のメソッドvalidatesを使いました。

ただ使うだけでなく、条件もしっかり指定しないとうまくいかなかったので、下記のようにmodel(まちかどルートの場合はpost.rb)に記述しました。

with_options if: :book_select? do
    validates :bookisbn, presence: { message: '本の裏表紙に記載のISBNコードを入力して検索ボタンを押してね' }
    validates :bookauthor, presence: true
end

def book_select?
    title == "書籍や漫画を読んだ"
end

まず少なくとも書籍のISBNコードと著者名が存在していればOKだと思ったので、複数のバリデーションを一度に指定できるメソッドwith_optionsを使いました。これによってbookisbnbookauthorが両方とも入力されているかをチェックします。

さらにif: :book_select?という条件式を加えることによって、書籍投稿時だけこのバリデーションを行うようにしました。まちかどルートではほかにもいろいろ投稿できるんですけど、投稿の種類をtitle (post.title)によって判別しているんです。

というわけで、バリデーションを通過できないとエラーメッセージが表示されます。modelだとmessage、viewのform.html.erbだと下記3行のコードがそれです。

<% if @post.errors.messages[:bookisbn].any? %>
    <span class="font-weight-bold text-warning"><%= @post.errors.messages[:bookisbn][0] %></span>
<% end %>

補足

書籍のISBNコードからWeb APIを通じて各種情報を取得し、さらに投稿ボタンを押したときにバリデーションで投稿内容をチェックする...。この一連の流れを実装するのに3日もかかってしまいました。

Web APIをこんなふうに使うのは初めてだったので苦労しましたが、今回の経験でほかのAPIも使っていけそうな自信がちょっとだけつきました。これからも必要に応じて少しずつ学んでいきます。

記事が少しでもいいなと思ったらクラップを送ってみよう!
54
+1
@west2538onRailsの技術ブログ

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする