【Rails】Amazon PA API v5.0 で書籍検索

amazonの書籍検索のAPIで少々てこずったのでメモ。
他に日本語の記事が見つからなかったので参考にしていただけると幸いです。
## はじめに
書籍検索にはGoogleやAmazonなどのAPIを使うことができるのですが、Google（Google Books API）では物足りない部分もあったのでAmazonのPA（Product Advertising）APIを使うことにしました。

しかし2020年の4月からPA APIのバージョンが変わって、amazon-ecsのgemを使ったやり方だとうまく行かないという事態に…
（[この記事](https://qiita.com/tatsuki-m/items/043f14e7d4504277c947)のやり方を参考にしたのですがデータが取得できなかった…）

[amazon-ecsのリファレンス](https://github.com/jugend/amazon-ecs)をみると別のgem（paapi）を使うと良いと書かれていたのでそれを使ってみることにしました。
[paapiのリファレンス](https://github.com/dkam/paapi)


ちなみにこのAPIを利用するためには、先にアマゾンアソシエイトへの登録、申請が必要なので、まだの方は[こちらの記事](https://qiita.com/tatsuki-m/items/043f14e7d4504277c947)を参考ください。
審査のハードルが割と高めなので、すぐ使いたいという方は厳しいと思います。
（自分の場合は1ヶ月くらいかかりました）

## 完成イメージ
検索の完成イメージはこんな感じです。
ちゃんと画像やURLが取得できているのがわかると思います。
![85a1b44b0aecfa2b419158ec43da4af8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605568/b0d3b39b-e929-d28c-1752-d7b9e5d83887.gif)


## 実装方針
今回は以下のような処理を実装していきます
１. フォームにキーワードを入力してリクエストを送る
２. APIを叩いて入力されたキーワードで検索
３. APIからのレスポンスを加工してデータを表示

## 各種ファイル

### Gem
```ruby:Gemfile
gem 'paapi'
```
忘れずにbundle installしましょう。（サーバー起動していたら再起動も忘れずに）

### config
config/initializers直下に`paapi.rb`を作成して鍵やIDの設定を書きます。
・access_key：　 アクセスキー
・secret_key：　 シークレットキー
・partner_tag：　アソシエイトID（22で終わる自分のID）

```ruby:config/initializers/paapi.rb
Paapi.configure do |config|
  config.access_key  = Rails.application.credentials[:pa_api][:access_key_id]
  config.secret_key  = Rails.application.credentials[:pa_api][:secret_key]
  config.partner_tag = Rails.application.credentials[:pa_api][:associate_tag]
end
```
自分の場合はcredentialsから呼び出して使ってます。(流出するとなんとなく嫌なので)
credentialsの使い方がわからない場合は[こちら](https://qiita.com/koki_73/items/2dc70e4a3fb169015884)を参考にしてください。


### コントローラー
今回はサンプルなので適当にsearchesコントローラを作成しました。
実際はbookディレクトリ内に作成して何の検索かわかりやすくしたほうが良いです。

```:ターミナル
$ rails g controller searches
```

```ruby:searches_controller
class SearchesController < ApplicationController
  before_action :call_client, only: :index
  
  def index
    si = @client.search_items(keywords: keyword_params, SearchIndex: "Books")
    @items = si.items
  end
  
  private
  
  def call_client
    require 'paapi'
    @client = Paapi::Client.new(access_key: Rails.application.credentials[:pa_api][:access_key_id],
                                secret_key: Rails.application.credentials[:pa_api][:secret_key],
                                market: :jp,
                                partner_tag: Rails.application.credentials[:pa_api][:associate_tag])
  end
  
  def keyword_params
    params.require(:keyword)
  end

end
```
clientのインスタンスを作成し、それに対して検索メソッドを適用して商品情報を取得しています。
今回は商品検索でジャンルを本に限定していますが、商品番号を指定して情報を取得したり、別のジャンルを指定したりできるので用途に合わせて使い分けください。

商品検索すると10件分のデータが取得され、レスポンスクラスのデータになります。
この中にitemsのデータが入ってるので`.items`で取り出せばItemクラスのデータとして取り扱うことができます。
（Itemクラスはgemで用意されているもので、便利なメソッドが使えます。後ほどまた説明します。）

### ルーティング
忘れずに設定しておきましょう。

```ruby:routes.rb
Rails.application.routes.draw do
  # (略)
  resources :searches, only: [:index]
end
```

### ビューファイル
まずは検索フォームを用意しておきます。

```haml:検索フォーム
.book-search
  = form_with url: {controller: 'searches', action: 'index' }, method: :get, local: true do |f|
    = f.text_field :keyword
    = f.submit "検索"
```


次に検索して取得したデータを表示するページです。
今回は`searches/index`に表示させます。

```haml:views/searches/index
- @items.each do |item|
  .url
    = "url: #{item.detail_url}"
  .title
    = "title: #{item.title}"
  .author
    - authors = item.contributors.select { |e| e['RoleType'] == "author" }&.map { |e| e.dig('Name') }&.reject {|n| n.to_s.empty?}
    = "author: #{authors[0]}"
  .image
    = image_tag "#{item.image_url}", height: '170px', width: '120px'
  .asin
    = "asin: #{item.asin}"
```
titleメソッドやdetail_urlメソッド、image_urlメソッドを使うと、Itemクラスのデータから商品タイトルやURL、画像などを簡単に取得することができます。

他にもいろいろ取得できるので、[リファレンス](https://github.com/dkam/paapi/blob/master/lib/paapi/item.rb)を見て試してみると良いかと思います。

ちなみにauthorsはリファレンスどおりに（authorsメソッドを使って）やってもうまくいかなかったので、自分で調整しました。
（RoleTypeがauthorであるものを探さないといけないのに、用意されたメソッドではRoleがAuthorであるものを探している）

【2020.08.21追記】
gemの管理者に報告したら直してくれました！
`item.authors`でデータ取得できるようになりました。
gemのバージョンは0.1.2以上である必要があります。

## 参考
・Scratchpad
　APIを叩いてどんなデータが取得されるか試せるページです。
　https://webservices.amazon.co.jp/paapi5/scratchpad/

・APIリファレンス
　Product Advertising API 5.0の公式リファレンスです。
　https://webservices.amazon.com/paapi5/documentation/api-reference.html