Rails6 rakutenAPI 公式documentを見ながら実装

## 初めに
今回この記事では、簡単にgemを用いてruby on railsでrakutenAPIを叩き、データを取得する方法を解説していこうと思います。
rakutenAPIの記事はかなり溢れているのですが、APIkeyを扱うのに直接initilizerに貼り付けたりや、公式のリンクが期限切れになっているものが多かったので書かせていただきました。

### 環境
- ruby 
    - 3.1.2(rbenv) <- 2.7以上であればOK
- rails 
    - 6.1.6.1 <- 6系であれば同じ

## 実装手順

- APIkey取得

rakuten developersにアクセス
[こちら](https://webservice.rakuten.co.jp/)にアクセス

右上のログインからrakutenの会員情報を使ってログインする。（通常の楽天アカウントでok!)

ログインできたら、右上の+new appをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1717562/9d72d960-b1cc-0e28-ddbd-37d534247271.png)

するとこのページが表示されるので、必要事項を埋めていく。
必要な箇所としては、requiredと書かれている箇所が必要になる。
1. Application name(これから作成するアプリの名前　なんでもOK!)
1. Application URL(ローカル環境なら[このリンクをコピー](http://localhost:3000/),cloud9ならpreviewで立ち上げた時のrootで表示されるページのURLを入力（多分）
1. CAPTCHAこの項目は、画像に表示されている文字を入力するこの場合であればputama

すると、APIkeyが生成される。
複数作成される中で使用するのは、`Application ID/developer ID(applicationId / developerId)`と`Affiliate ID(affiliateId)`の二つを使用する。
ここまで作成できれば、次はgemの導入に移る。

- 使用するgemの解説
今回実装するのに当たって使用するのは、2つ。

**'dotenv-rails'**
rakuten developersで取得したAPIkeyを、.envで管理し環境変数として扱うために使うgem
<font color="Red">apikeyを直接ファイルに記述して扱うのは大変危険</font>

**'rakuten_web_service'**
rakutenから、商品の検索を行ってくれるgem
詳しくは[こちら](https://github.com/rakuten-ws/rws-ruby-sdk)を参照

***

追加が完了したら、ターミナルを起動して`bundle install`


- APIを叩き表示をする処理

#### projectの準備
```
$ rails new rakutenAPIPractice(ここはなんでもいい)
$ cd rakutenAPIPractice
## ↓アプリを使える状態にし、booksコントローラーとviews/books/index.htmlを作成（&でつなげずに一行ずつ実行してもok)
$ bundle install&yarn install&rails g controller books index
```
#### gemの追加
```
## gemfile
gem 'dotenv-rails'
gem 'rakuten_web_service'
```

#### .envに中身を埋める
```
## .env 
RAKUTEN_APPLICATION_ID=楽天developersで取得したApplication IDを貼り付ける
RAKUTEN_AFFILIATE_ID=楽天developersで取得したAffiliate IDを貼り付ける
```

#### .envの内容確認
```
## consoleからそれぞれ.envファイルで登録した内容と同じ内容が出力されるかを確認
$ spring stop
$ rails c 
> ENV['RAKUTEN_APPLICATION_ID']
> ENV['RAKUTEN_AFFILIATE_ID']
```
**注意**
`applicationid`と`affiliateid`は`''`や`""`で囲まずに入力してください。
consoleで出力されない場合は、全角スペースが挿入されていないか、もしくはたまにスペースを空けることによって認識されないことがあるので、スペースを詰めてから再度`rails c`で立ち上げてみてください。

#### rakutenAPIを使用するための準備
```
## 楽天の検索をするために設定ファイルである、rakuten.rbを作成する
$ touch config/initializers/rakuten.rb

## rakuten.rbを開き下記の内容をコピペする
  RakutenWebService.configure do |c|
    ##　先ほど.envで設定した内容を反映させる。
    c.application_id = ENV['RAKUTEN_APPLICATION_ID']
    c.affiliate_id = ENV['RAKUTEN_AFFILIATE_ID']
    c.debug = true # default: falseになっている。
  end
```

#### rakuten.rbが作成できたら、いざAPIを叩く
>rails g controller books index

このコマンドで、books_controllerとindex.htmlを作成したので、今回はcontroller側でrakutenにアクセスをし、viewにAPIを叩いた時に返却される値を出力していく。

```
## books_controller 
def index 
    ## 今回は例としてpythonに関する本を検索していく。
    @books = RakutenWebService::Books::Book.search(title: "Python")
end
```
>RakutenWebService::Books::Book.search

この書き方は楽天が用意しているSDKを使った検索の方法になります。検索方法としては、公式documentに行き、公式のdocumentは[こちら](https://webservice.rakuten.co.jp/documentation/books-book-search)左のAPIの一覧メニューからbooks/book/searchを選び、開かれたページのAPI documentationのUsing the SDK to retrieve dataという欄があります。こちらで、phpかrubyを選択することができますので、rubyを押すと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1717562/76c43e9b-4225-522f-a84a-1ab34b8acd37.png)

このような形でSDKを使って検索をすることができますのでご参照ください。

なので、もし楽天市場の商品を検索かけたいのであれば`RakutenWebService::Ichiba::Item.search()`で検索をかけ[こちら](https://webservice.rakuten.co.jp/documentation/ichiba-item-search)のdocumentを参考に書品検索を行う形になります。

>RakutenWebService::Books::Book.search(title: "Python")

また今回は、titleというカラムで検索をかけていますが、title以外にもauthorやsize(本の大きさ)でも検索をかけることができます。parameterとして使用することができるのは、[公式のdocument](https://webservice.rakuten.co.jp/documentation/books-book-search)の**input parameters**という項目を参照してください。

### どのようなデータが返ってきているのか?

controllerのindexのアクションでrakutenAPIに検索をかけた検索結果はどのような値が変えるのでしょうか？

どのような値が返ってくるのかを公式documentから確認することができます。
確認の方法としては、[公式document](https://webservice.rakuten.co.jp/documentation/books-book-search)のapi documentationの一番下までスクロールすると、
<font color='red'>API Test Form</font>というタブがあるのでクリックするとweb上でAPIを叩くことができます。試しにtitleのところに太陽と入れて検索をしてみると、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1717562/52ee6de4-d15f-c9a3-00f1-b7561c97116d.png)

このような形で擬似的にデータを取得することができます。

**注意**

webでデータを取得する場合は、検索の箇所が日本語しか入らない設定になってるみたいなので英語を入れて取得すると一致しなくなります。（実際の開発では英語もok）

#### 取得したデータをviewに反映

それでは、controllerで取得したデータを実際にviewに渡してみましょう。

```
## books/index.html.erb

## @booksに入っているデータをtableで表示していきます。

<% @book.each do |book| %>
    <%= book.title %>
<% end %>
```

初めに、取得した本のタイトルの一覧を出力できるか確認してみましょう。
titleの確認ができたら他の値でも確認してみましょう。
今回books:book.searchで使うことのできる値一覧↓
```
"affiliateUrl": "",
"author": "はらだ みずき",
"authorKana": "ハラダ ミズキ",
"availability": "1",
"booksGenreId": "001003001001/001004008006",
"chirayomiUrl": "",
"contents": "",
"discountPrice": 0,
"discountRate": 0,
"isbn": "9784093866514",
"itemCaption": "小柄な点取り屋・小檜山太陽と大型ＦＷ・大原月人。個性のまったく異なる二人は、プロサッカー選手になるため熾烈な競争であるセレクションに挑む。",
"itemPrice": 1540,
"itemUrl": "https://books.rakuten.co.jp/rb/17197927/",
"largeImageUrl": "https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/6514/9784093866514_1_3.jpg?_ex=200x200",
"limitedFlag": 0,
"listPrice": 0,
"mediumImageUrl": "https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/6514/9784093866514_1_3.jpg?_ex=120x120",
"postageFlag": 2,
"publisherName": "小学館",
"reviewAverage": "0.0",
"reviewCount": 0,
"salesDate": "2022年07月28日頃",
"seriesName": "",
"seriesNameKana": "",
"size": "単行本",
"smallImageUrl": "https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/6514/9784093866514_1_3.jpg?_ex=64x64",
"subTitle": "サッカー・ドリーム",
"subTitleKana": "サッカードリーム",
"title": "太陽と月",
"titleKana": "タイヨウトツキ"
```

**注意**
例えば、titleKanaという値を出力したい場合に、`<%= book.titleKana %>`と記述をするとエラーになります。その理由としては、実際に使用できる値はtitleKanaではなく、`<%= book.title_kana %>`になるからです。２単語以上のカラム名はつなぎ目を_にし、先頭の文字を小文字にして使用しましょう。


一通りのカラムの確認ができたら、このままだとcssも当たっておらずかなりみずらいのでtaliwind.cssを使って整えていきましょう。
今回はCDNで導入をしていきます。

application.hrml.erbのheadタグの中に`<script src="https://cdn.tailwindcss.com"></script>`を記述してください。

```
## application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>APIPracticeRails</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <script src="https://cdn.tailwindcss.com"></script>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>
```

上記の作業で、tailwindcssの導入は完了しましたので、次はtailwindcssを使ってstyleを当てていきます。

```
## books/index.html.erb

<div class="container px-10">
  <table class="table-auto">
    <tbody>
      <% @books.each do |book| %>
        <tr>
          <td><%= image_tag book.medium_image_url %><td>
          <td><%= book.title %><td>
          <td><%= book.author %></td>
          <td><%= book.item_price %><td>
        </tr>
      <% end %>
    </tbody>
  </table>
</div>
```

ブラウザを立ち上げて確認すると、、、
デザインがマシになりました。今回は、tailwindcssがメインではないので解説などは行いませんので、
[tailwindcss](https://tailwindcss.com/)からclassを確認してカスタマイズしてみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1717562/a76220d1-1512-b97f-9185-4fc952a4c2b9.png)