【超簡単】Railsでレシピ検索アプリ作ってみた（楽天API）

# 今回やりたいこと
料理の検索をしたい
検索したいワードを入力するとワードに合った料理を提案してくれる

完成形こんな感じ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/b15734d5-b76b-5b94-f8c2-6957b13ed4d5.gif" width=70%>

# 楽天APIに登録
https://webservice.rakuten.co.jp/

楽天会員としてログイン
登録がまだなら楽天会員に登録しときましょう

右上の「アプリID発行」をクリック
![Screenshot 2023-03-06 10.21.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/bdb9a3a8-ed5f-c222-2b56-569ecc0d2947.png)
アプリを作成できたらIDとか色々もらえます
```.env
RAKUTEN_APPLICATION_ID = "****************"
```
ID発行できたら、自分のrailsアプリの.envファイル内に書いといてください
ここまでで楽天APIの登録は終わりです
今回使うのは楽天APIの中の「楽天レシピ系API」っていうやつです
それ以外にもたくさんのAPIがありますが、今回はレシピ系のみで説明します
# 楽天レシピ系APIの概要
楽天レシピ系APIには2つのAPIが含まれています。
（逆にいうとこの2つ以外のことはできません）
* 楽天レシピカテゴリー一覧API
    * `https://app.rakuten.co.jp/services/api/Recipe/CategoryList/20170426?format=json&applicationId=*******`
* 楽天レシピカテゴリー別ランキングAPI
    * `https://app.rakuten.co.jp/services/api/Recipe/CategoryRanking/20170426?format=json&applicationId=*******`

一つ目の楽天レシピカテゴリー一覧APIはその名の通りカテゴリー一覧が見れます。
カテゴリーというのは3段階に分かれていて、large、medium、smallです。
どういうことかというと、例えばsmallのカテゴリに「生ハム」というものがあります。
これはlarge「肉」>medium「ハム」>small「生ハム」という3つの段階でカテゴリが決まっています。
またこのそれぞれにcategoryIdというものが存在し、それを「-」で繋いでカテゴリを判別します。
例）10-67-1491
10...肉のcategoryId
67...ハムのcategoryId
1491...生ハムのcategoryId

二つ目の楽天レシピカテゴリー別ランキングAPIは上で判別したカテゴリ内のランキング上位4品のレシピを取得できます。
`https://app.rakuten.co.jp/services/api/Recipe/CategoryRanking/20170426?applicationId=<自分のアプリID>&categoryId=<カテゴリID>`
つまり
`https://app.rakuten.co.jp/services/api/Recipe/CategoryRanking/20170426?applicationId=<自分のアプリID>&categoryId=10-67-1491`
このように10-67-1491を指定しているので生ハム料理の上位4品が取得できます。

<details><summary>具体的には↓↓↓↓</summary><div>

```json
{
    "result": [
        {
            "foodImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/6621468b3cd7a114f0b2a25f92aa5db2769f899d.60.2.3.2.jpg",
            "mediumImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/6621468b3cd7a114f0b2a25f92aa5db2769f899d.60.2.3.2.jpg?thum=54",
            "nickname": "なでしこ2",
            "pickup": 0,
            "rank": "1",
            "recipeCost": "100円以下",
            "recipeDescription": "野菜嫌いの甥っ子も♪僅かのニンニク魔法使い。色々組合せお試しを！アイルランド人友直伝自慢の一品！家に常備の材料だけでレストランより◎\n続絶賛編はチーズケーキ❤",
            "recipeId": 1210004462,
            "recipeIndication": "5分以内",
            "recipeMaterial": [
                "レタス（グリーンレタスやプリーツレタス）",
                "★葉っぱ類水菜等全て(芯の多いのは不可)",
                "オリーブオイル(サラダ油OK)",
                "あれば＊出がらし昆布（海草、海藻）",
                "薄切りにんにく<みじん切り>",
                "塩、こしょう",
                "酢（米酢か穀物酢ほか糖分ゼロのもの）",
                "********************",
                "以上が基本です☆以下お好みで野菜追加例",
                "玉葱、大根、人参、ズッキーニ、胡瓜",
                "柿、キウイ、リンゴ、オレンジ、蜜柑他果物",
                "茗荷、マッシュルーム、ピーマン、トマト",
                "筍＊固茹で、大葉、セロリ、マッシュルーム",
                "ビーンズ、ヒマワリの種、コーン、バナナ",
                "キノコ（椎茸など＊酒蒸し、バター炒め）",
                "＋チーズ、サーモン、生ハム、ベーコン、",
                "鶏肉、牛肉、豚肉など<サッと茹でる>",
                "★豆苗、貝割菜、ベビーリーフ、春菊、菊菜",
                "法蓮草、水菜、アイスプラント、金時草、",
                "わさび菜など"
            ],
            "recipePublishday": "2012/09/21 02:16:11",
            "recipeTitle": "絶賛♪グリーンサラダ～基本だけでも♪簡単野菜サラダ",
            "recipeUrl": "https://recipe.rakuten.co.jp/recipe/1210004462/",
            "shop": 0,
            "smallImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/6621468b3cd7a114f0b2a25f92aa5db2769f899d.60.2.3.2.jpg?thum=55"
        },
        {
            "foodImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/9ab68abbb65be2d795d3ee7b8747adbee383079d.07.2.3.2.jpg",
            "mediumImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/9ab68abbb65be2d795d3ee7b8747adbee383079d.07.2.3.2.jpg?thum=54",
            "nickname": "メリッコ",
            "pickup": 0,
            "rank": "2",
            "recipeCost": "300円前後",
            "recipeDescription": "きゅうりを生ハムでくるくる巻いた簡単おつまみです。",
            "recipeId": 1370004639,
            "recipeIndication": "5分以内",
            "recipeMaterial": [
                "きゅうり",
                "生ハム（長いタイプ）",
                "●オリーブオイル",
                "●レモン果汁",
                "●塩、こしょう"
            ],
            "recipePublishday": "2012/07/27 20:16:47",
            "recipeTitle": "お酒のお供に♪きゅうりの生ハム巻き",
            "recipeUrl": "https://recipe.rakuten.co.jp/recipe/1370004639/",
            "shop": 0,
            "smallImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/9ab68abbb65be2d795d3ee7b8747adbee383079d.07.2.3.2.jpg?thum=55"
        },
        {
            "foodImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/3de220104a85d26476f9702df8383d43f45a0129.91.2.3.2.jpg",
            "mediumImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/3de220104a85d26476f9702df8383d43f45a0129.91.2.3.2.jpg?thum=54",
            "nickname": "ラムちゃん1224",
            "pickup": 0,
            "rank": "3",
            "recipeCost": "300円前後",
            "recipeDescription": "生ハムの薔薇の花の飾り切りと、切らずに作る方法と全部で４パターン、手順写真つきで載せてみました(*＾o＾*)♪",
            "recipeId": 1390027956,
            "recipeIndication": "5分以内",
            "recipeMaterial": [
                "生ハム　スライス",
                "あれば　ベビーリーフ　フリルレタスなど"
            ],
            "recipePublishday": "2015/04/29 10:32:29",
            "recipeTitle": "生ハムの薔薇の花の飾り切り☆お祝いおもてなしに♪",
            "recipeUrl": "https://recipe.rakuten.co.jp/recipe/1390027956/",
            "shop": 0,
            "smallImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/3de220104a85d26476f9702df8383d43f45a0129.91.2.3.2.jpg?thum=55"
        },
        {
            "foodImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/ccb778a38a0f6ec58d299fc9fc7a3b5542a25d29.83.9.3.3.jpg",
            "mediumImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/ccb778a38a0f6ec58d299fc9fc7a3b5542a25d29.83.9.3.3.jpg?thum=54",
            "nickname": "Anoa",
            "pickup": 0,
            "rank": "4",
            "recipeCost": "指定なし",
            "recipeDescription": "生ハムの塩味と干し柿の甘み♡相性がいいです❣\n白菜のシャキシャキ食感もദ്ദി ˃ ᵕ ˂ )♫",
            "recipeId": 1720065072,
            "recipeIndication": "5分以内",
            "recipeMaterial": [
                "白菜",
                "生ハム",
                "干し柿",
                "さけるチーズ(今回はモッツァレラ)",
                "コーン缶",
                "⭐オリーブオイル",
                "⭐バルサミコ酢",
                "⭐マヨネーズ",
                "⭐醤油",
                "⭐レモン果汁",
                "⭐ブラックペッパー",
                "⭐岩塩"
            ],
            "recipePublishday": "2023/01/23 16:08:46",
            "recipeTitle": "白菜と生ハムと干し柿のサラダꕤ୭*",
            "recipeUrl": "https://recipe.rakuten.co.jp/recipe/1720065072/",
            "shop": 0,
            "smallImageUrl": "https://image.space.rakuten.co.jp/d/strg/ctrl/3/ccb778a38a0f6ec58d299fc9fc7a3b5542a25d29.83.9.3.3.jpg?thum=55"
        }
    ]
}
```
</div></details>

# Railsアプリの設定
rails g contoller rakutens

次に、rails側で登録した楽天APIから情報を取得していこうと思います。
```ruby:Gemfile
gem 'dotenv-rails'
gem 'httpclient'
```
dotenv-railsはenvファイルを扱うためで、httpclientはHTTP通信をするためのGemです。
```terminal:terminal
bundle install
```
アプリケーションディレクトリ直下に.envファイルを作成
```.env
RAKUTEN_APPLICATION_ID = "自分のApplication ID"
```
```.gitignore
/.env
```
コントローラ作成
```terminal:terminal
rails g contoller rakutens
```
ルーティング
```ruby:routes.rb
get "rakutens", to: "rakutens#index"
```
```ruby:rakutens_controller
class RakutensController < ApplicationController
  def index
    client = HTTPClient.new()
    # 楽天レシピカテゴリー一覧API
    res = client.get("https://app.rakuten.co.jp/services/api/Recipe/CategoryList/20170426?format=json&applicationId=#{ENV['RAKUTEN_APPLICATION_ID']}")
    categories = JSON.parse(res.body)["result"]["small"]
    @hit = true
    if params[:search].present?
      # categoryNameの中で検索したワードが入っているカテゴリーを配列として取得する
      categories_list = categories.select{|x| x["categoryName"].include?(params[:search]) }
      if categories_list.empty?
        @hit = false
      else
        # 取得した配列の中からランダムで1つを抽出し、そのカテゴリーIDを取得している
        categorie_id = categories_list.sample["categoryUrl"].split("/").last
        # 取得したカテゴリーIDからそのカテゴリーの中の人気料理を取得している（楽天レシピカテゴリー別ランキングAPI）
        categories_ranktop = client.get("https://app.rakuten.co.jp/services/api/Recipe/CategoryRanking/20170426?applicationId=#{ENV['RAKUTEN_APPLICATION_ID']}&categoryId=#{categorie_id}")
        # 取得した料理を8種の形にする
        @foods = JSON.parse(categories_ranktop.body)["result"]
      end
    else
      # 何も検索欄に書かれていない時、人気料理を表示する
      pop = client.get("https://app.rakuten.co.jp/services/api/Recipe/CategoryRanking/20170426?applicationId=#{ENV['RAKUTEN_APPLICATION_ID']}&categoryId=30")
      @foods = JSON.parse(pop.body)["result"]
    end
  end
end
```
views
```html:rakutens/index.html.erb
<h1>料理レシピ検索</h1>

<%= form_tag({controller:"rakutens",action:"index"}, method: :get) do %>
  <%= text_field_tag :search %> <br>
  <%= submit_tag '検索する'  %>
<% end %>

<% if @hit %>
  <% @foods.each do |f| %>
    ランキング：<%= f["rank"] %> <br>
    タイトル：<%= f["recipeTitle"] %> <br>
    かかる時間：<%= f["recipeIndication"] %> <br>
    <%# 写真をクリックするとレシピの詳細が見れる %>
    <%= link_to f["recipeUrl"] do %>
      <%= image_tag f["foodImageUrl"], size: '300x200' %> <br>
    <% end %>
  <% end %>
<% else %>
  <h1>ヒットなし</h1>
<% end %>
```
終わり〜
http://localhost:3000/rakutens
ここまでで下のようになっていれば成功です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2586059/8e2794b8-86be-5ae0-6bd2-f0e1ca44b95f.png)