pokemon APIを使用し、日本語入力のポケモン名を検索・画像表示する機能を作成
背景
pokemon APIというポケモンやアイテムの詳細データを取得することができるAPIを見つけたので、APIにリクエストを飛ばし、JSONファイルにまとめた名前と一致する名前を検索し画像表示させる機能を作成してみました。
rails でpokemonAPIについて解説している記事が少なかったので、これからpokemonAPIの使用を検討している方の参考になれば良いなと思い作成しました。
データベースに登録する機能は下記の記事に載っているので、入力フォームから検索した名前のポケモンとポケモンアイテムを画像として表示させる機能を作成するのに時間がかかったので、この機能の実装方法について解説していきます。
参考
https://pokeapi.co/docs/v2#pokemon-section
https://qiita.com/harashoo/items/8da4a21a22b6ff6952e5
https://zenn.dev/rinda_1994/articles/cbe636700c04b1
完成画像
(app/views/pokemons/index.html.erb)
(app/views/items/index.html.erb)
検索結果(app/views/pokemons/search.html.erb)
ポケモン名の検索機能
app/views/pokemons/index.html.erb(ゲットしたポケモン一覧のページ)
<h1>Pokemon</h1>
<%= render "shared/search", { path: search_path } %>
<div>
<h3>ゲットしたポケモン</h3>
<div class="main-content">
<% if @pokemons.present? %>
<% @pokemons.each do |pokemon| %>
<div style="display: inline-block;">
No. <%= pokemon.order %>,
Name: <%= pokemon.name %>
<div>
<%= image_tag(pokemon.image_url, size: "200") %>
</div>
</div>
<% end %>
<% end %>
</div>
</div>
<div><%= link_to "アイテムページへ", items_path %></diV>
app/views/pokemons/search.html.erb(ポケモン検索結果を表示するページ)
<h1>Pokemon</h1>
<%= render "shared/search", { path: search_path } %>
<div>
<% if @pokemon.present? %>
<%= render "shared/error_messages", { object: @pokemon } %>
<table>
<tr>
<td>No.</td>
<td><%= @pokemon.order %></td>
</tr>
<tr>
<td>Name:</td>
<td><%= @pokemon.name %></td>
</tr>
</table>
<%= image_tag(@pokemon.image_url, size: "200") %>
<%= form_with model: @pokemon, local: true do |f| %>
<%= f.hidden_field :order %>
<%= f.hidden_field :name %>
<%= f.hidden_field :image_url %>
<%= f.submit 'ゲット', name: nil %>
<% end %>
<% else %>
<p>検索してね!</p>
<% end %>
</div>
<br>
<div><%= link_to "トップページへ", root_path %></div>
./pokemon.json(ポケモンの日本語名と英語名を配列の1つの要素としてオブジェクトにまとめたもの。)
[{"ja": "フシギダネ","en": "Bulbasaur"},{"ja": "フシギソウ","en": "Ivysaur"},・・・]
app/controllers/pokemons_controller.rb(searchメソッドはポケモン名で検索)
class PokemonsController < ApplicationController
def index
@pokemons = Pokemon.all
end
--- 省略 ---
# ポケモン名で検索
def search
# 検索キーワードを@searchに代入
@search = params[:search]
# ポケモンの英語と日本語表記をまとめたJSONファイルを読み込ませる
File.open("pokemon.json") do |file|
json = JSON.load(file)
# JSONファイルの中から検索したキーワードを配列のハッシュオブジェクトとして取得(これが検索機能)
result = json.select { |x| x["ja"].include?(@search) }
# JSONファイルの中に入力した値があれば、if文の中を実行
if result.present?
# 先ほど取得したハッシュオブジェクトのkeyが英語のvalueを取得する。
val = result[0]["en"].downcase
# pokemon APIを叩く
raw_response = Faraday.get "https://pokeapi.co/api/v2/pokemon/#{val}"
raw_response.status == 200
response = JSON.parse(raw_response.body)
# Pokemonインスタンスの作成
@pokemon = Pokemon.new(order: response["id"], name: @search, image_url: response["sprites"]["front_default"])
else
redirect_to root_path
end
end
end
--- 省略 ---
end
今回解説するのは、検索機能を有するpokemons_controller.rb searchメソッドの中です。
ここでポケモン名の検索が行われています。
検索機能の仕組みは、index.html.erb <%= render "shared/search", { path: search_path } %> の検索フォームからキーワードを入力し、入力した日本語の値が作成したJSONファイルの中にあるかどうか調べ、もしあるならpokemonAPIを叩き、search.html.erbという検索結果を表示させます。
また、もし入力した日本語の入力値がJSONファイルの中になかったら、root_pathに設定したindex.html.erbに戻ります。
これが作成した検索機能のおおまかな仕組みです。
一番注目して欲しい部分は、下記の部分です。
# JSONファイルの中から検索したキーワードを配列のハッシュオブジェクトとして取得(これが検索機能)
result = json.select { |x| x["ja"].include?(@search) }
pokemonAPIは英語表記であり、もし日本語入力の検索機能を実装するとなると、何か工夫しなければいけません。
そこでこちらの記事を参考に、ポケモン名を英語と日本語表記を1つのオブジェクト要素としてまとめた配列を作成し、JSONファイルの中にまとめました。
そして、その内容を「json」という変数に変換し、selectメソッドで入力された日本語のポケモン名がJSONファイルの中から探し出し、resultという変数に代入させました。
次にpokemon APIを叩くために入力した日本語表記のポケモン名を英語表記に変換させました。
実行箇所は下記になります。
# 先ほど取得したハッシュオブジェクトのkeyが英語のvalueを取得する。
val = result[0]["en"].downcase
# pokemon APIを叩く
raw_response = Faraday.get "https://pokeapi.co/api/v2/pokemon/#{val}"
pokemon APIを叩くためには、ドキュメントに記載がありますが、API部分(https://pokeapi.co/api/v2/pokemon/ のこと)の一番最後の部分が {id or name} でなければいけません。
さらに、nameは全て小文字でなければならず、JSONファイルの英語表記は先頭が大文字なので、先頭の文字をdowncaseで小文字に変換させ val に代入しました。
また、APIを叩くためにFaradayというruby製のHTTPクライアントライブラリがあったのでそのライブラリを使用しました。
上記の内容がポケモン名で検索機能を実装するときに重要である箇所の説明となります。
また、pokemonAPIのドキュメントよりポケモンで出てくるアイテムも上記の内容でAPIを叩くことができたので、下記に記載させていただきます。
参考程度にしていただけると幸いです。
アイテム名の検索機能
app/controllers/items_controller.rb
class ItemsController < ApplicationController
--- 省略 ---
def item_search
@search = params[:search]
File.open("item.json") do |file|
json = JSON.load(file)
result = json.select { |x| x["ja"].include?(@search) }
if result.present?
# 取得したポケモンアイテムの英語表記を先頭を小文字、かつ、空白を「-(ハイフン)」に変更
val = result[0]["en"].downcase.gsub(' ', '-')
raw_response = Faraday.get "https://pokeapi.co/api/v2/item/#{val}"
response = JSON.parse(raw_response.body)
@item = Item.new(item_id: response["id"], name: response["names"][0]["name"], image_url: response["sprites"]["default"])
else
redirect_to items_path
end
end
end
--- 省略 ---
end
./item.json
[{ "ja": "むしよけスプレー", "en": "Repel" }, { "ja": "シルバースプレー", "en": "Super Repel"}, ... ]
ポケモン名から画像を表示させるメソッド(先ほどのsearchメソッド)と異なる点は下記の箇所です。
# 取得したポケモンアイテムの英語表記を先頭を小文字、かつ、空白を「-(ハイフン)」に変更
val = result[0]["en"].downcase.gsub(' ', '-')
ドキュメントに記載がありますが、APIを叩くためにはポケモン名を検索する時と同様にhttps://pokeapi.co/api/v2/item/ の最後の部分を { id or name } でなければいけません。
アイテム名はポケモン名と同様に、 wiki を参考に日本語と英語表記を1つのオブジェクト要素とした配列を作成し、JSONファイルにまとめているときに気づいたのですが、「Super Repel(シルバースプレー)」のように先頭が大文字かつ空白があるアイテム名が多く記載されていました。
このままだとAPIを叩くことができませんでした。
調べると「Super Repel」のような文字列は、「super-repel」のように先頭が小文字かつ空白に「-(ハイフン)」が記述してあればAPIを叩くことができるようです。
そこで上記のようにdowncaseメソッドで先頭の文字を小文字に変換し、gsubメソッドで空白に「-」を記述するようにし、APIを叩くことができるように実装しました。
以上の説明がポケモン名の検索機能とアイテム名の検索機能の異なる箇所となります。
まとめ
今回は初めてpokemonAPIやFaraday、downcaseメソッドやgsubメソッドなどを使用しポケモン名やアイテム名の検索機能を実装してみました。
今回紹介させていただいた検索機能の実装も大変でしたが、wikiにまとめられたアイテム名をcsv→JSONファイルに変換する作業も地味に苦戦したので、今後はそのやり方もご紹介できたらいいなと思いました。
また、今後は実務で使用しているreactを使用し、もう少しフロントの部分に動きをつけることができたらいいなと思いました。
Discussion