質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

受付中

Railsでサッカーの APIを利用して、サッカー選手の検索結果を出したいのですが、レスポンスがかえって来ずJSON::ParserErrorが帰っってきます。

masakingu
masakingu

総合スコア11

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

1回答

0グッド

0クリップ

308閲覧

投稿2022/11/27 21:41

前提

Railsでサッカー選手の検索できるように、実装しているのですが、viewで検索した選手のレスポンスが返ってきません。レスポンスが返ってくるように、実装するためにアドバイスを下さい。

実現したいこと

JSON::ParserError (859: unexpected token at ''):

searchアクションを実行して、上記のエラーを解決して、search viewに検索結果を表示したいです。

発生している問題・エラーメッセージ

Started GET "/players/search?season=2018&player_name=cavani&commit=%E6%A4%9C%E7%B4%A2" for ::1 at 2022-11-26 23:35:17 +0900 Processing by PlayersController#search as HTML Parameters: {"season"=>"2018", "player_name"=>"cavani", "commit"=>"検索"} Completed 500 Internal Server Error in 1520ms (ActiveRecord: 0.0ms | Allocations: 3193) JSON::ParserError (859: unexpected token at ''): app/controllers/players_controller.rb:75:in `search'

該当のソースコード

players_controller.rb

class PlayersController < ApplicationController require 'uri' require 'net/http' require 'openssl' require 'json' before_action :set_q, only: %i[search] def index @players = Player.all end def show end def edit end def update respond_to do |format| if @player.update(player_params) format.html { redirect_to player_url(@player), notice: "Player was successfully updated." } format.json { render :show, status: :ok, location: @player } else format.html { render :edit, status: :unprocessable_entity } format.json { render json: @player.errors, status: :unprocessable_entity } end end end # DELETE /players/1 or /players/1.json def destroy @player.destroy respond_to do |format| format.html { redirect_to players_url, notice: "Player was successfully destroyed." } format.json { head :no_content } end end def search url = URI.parse('https://api-football-v1.p.rapidapi.com/v3/players?team=85&search=cavani&season=2018') http = Net::HTTP.new(url.host, url.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Get.new(url) request["x-rapidapi-host"] = 'api-football-v1.p.rapidapi.com' #実際にはAPI KEYを記載してます。 request["x-rapidapi-key"] = 'API KEY' response = http.request(request) result = JSON.parse(response.body) @player = Player.new end private def set_q @q = User.ransack(params[:q]) end # Only allow a list of trusted parameters through. def player_params params.require(:player).permit(:player_name, :season) end def search_params params[:q]&.permit(:player_name, :season) end end

serach.html.erb

<div class="container"> <div class="row"> <div class="col-lg-8 offset-lg-2"> <div class="player"> <%= form_with url: search_players_path, method: :get, local: true do |f| %> <div class="form-group"> <%= f.text_field :season, class: 'form-control', placeholder: '西暦を入力してください(例: 1997)' %> <div class="search2 "> <%= f.text_field :player_name, class: 'form-control', placeholder: '選手名を入力してください' %> <%= f.submit '検索', class: 'btn btn-primary' %> </div> </div> <% if @players.present? %> <%= render 'players/player' %> <% end %> <% end %> </div> </div> </div> </div>

_player.html.erb

<div class="container"> <div class="row"> <div class="col-lg-8 offset-lg-2"> <h1>player</h1> <div> <% if @player.present? %> <table> <tr> <td>player_name</td> <td><%= @player["firstname"+"lastname"] %></td> </tr> <tr> <td>team</td> <td><%= @player["team"] %></td> </tr> <tr> <td>season</td> <td><%= @player["season"] %></td> </tr> </table> <% end %> </div> </div> </div> </div>

補足情報(FW/ツールのバージョンなど)

外部API:https://www.api-football.com/documentation-v3
Rails: 6.1.5

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

0

http.request(request) が成功していないのでは?
response.code や response.message や response.status などで確認しましょう。

投稿2022/11/27 23:07

winterboum

総合スコア22588

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

masakingu

2022/12/04 20:44 編集

players_controller.rb ``` def search url = URI.parse('https://api-football-v1.p.rapidapi.com/v3/players?team=85&search=cavani&season=2018') http = Net::HTTP.new(url.host, url.port) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE request = Net::HTTP::Get.new(url) request["x-rapidapi-host"] = 'api-football-v1.p.rapidapi.com' #実際にはAPI KEYを記載してます。 request["x-rapidapi-key"] = 'API KEY' response = http.request(request) #下記の1行部分を加えることで、レスポンスが返って来ました、 puts response.read_body result = JSON.parse(response.body) @player = Player.new end ``` ``` puts response.read_body ``` 加えることで、レスポンスが返って来ました。 ``` Started GET "/players/search?season=2018&player_name=cavani&commit=%E6%A4%9C%E7%B4%A2" for ::1 at 2022-11-30 04:35:31 +0900 Processing by PlayersController#search as HTML Parameters: {"season"=>"2018", "player_name"=>"cavani", "commit"=>"検索"} {"get":"players","parameters":{"team":"85","search":"cavani","season":"2018"},"errors":[],"results":1,"paging":{"current":1,"total":1},"response":[{"player":{"id":274,"name":"E. Cavani","firstname":"Edinson Roberto","lastname":"Cavani G\u00f3mez","age":35,"birth":{"date":"1987-02-14","place":"Salto","country":"Uruguay"},"nationality":"Uruguay","height":"184 cm","weight":"71 kg","injured":false,"photo":"https:\/\/media.api-sports.io\/football\/players\/274.png"},"statistics":[{"team":{"id":85,"name":"Paris Saint Germain","logo":"https:\/\/media.api-sports.io\/football\/teams\/85.png"},"league":{"id":61,"name":"Ligue 1","country":"France","logo":"https:\/\/media.api-sports.io\/football\/leagues\/61.png","flag":"https:\/\/media.api-sports.io\/flags\/fr.svg","season":2018},"games":{"appearences":21,"lineups":20,"minutes":1676,"number":null,"position":"Attacker","rating":"7.400000","captain":false},"substitutes":{"in":1,"out":6,"bench":3},"shots":{"total":52,"on":24},"goals":{"total":18,"conceded":null,"assists":5,"saves":null},"passes":{"total":267,"key":13,"accuracy":77},"tackles":{"total":9,"blocks":2,"interceptions":6},"duels":{"total":96,"won":42},"dribbles":{"attempts":20,"success":11,"past":null},"fouls":{"drawn":16,"committed":11},"cards":{"yellow":1,"yellowred":0,"red":0},"penalty":{"won":2,"commited":null,"scored":4,"missed":1,"saved":null}},{"team":{"id":85,"name":"Paris Saint Germain","logo":"https:\/\/media.api-sports.io\/football\/teams\/85.png"},"league":{"id":65,"name":"Coupe de la Ligue","country":"France","logo":"https:\/\/media.api-sports.io\/football\/leagues\/65.png","flag":"https:\/\/media.api-sports.io\/flags\/fr.svg","season":2018},"games":{"appearences":2,"lineups":1,"minutes":134,"number":null,"position":"Attacker","rating":null,"captain":false},"substitutes":{"in":1,"out":0,"bench":1},"shots":{"total":null,"on":null},"goals":{"total":1,"conceded":null,"assists":null,"saves":null},"passes":{"total":null,"key":null,"accuracy":null},"tackles":{"total":null,"blocks":null,"interceptions":null},"duels":{"total":null,"won":null},"dribbles":{"attempts":null,"success":null,"past":null},"fouls":{"drawn":null,"committed":null},"cards":{"yellow":1,"yellowred":0,"red":0},"penalty":{"won":null,"commited":null,"scored":null,"missed":null,"saved":null}},{"team":{"id":85,"name":"Paris Saint Germain","logo":"https:\/\/media.api-sports.io\/football\/teams\/85.png"},"league":{"id":66,"name":"Coupe de France","country":"France","logo":"https:\/\/media.api-sports.io\/football\/leagues\/66.png","flag":"https:\/\/media.api-sports.io\/flags\/fr.svg","season":2018},"games":{"appearences":3,"lineups":1,"minutes":161,"number":null,"position":"Attacker","rating":null,"captain":false},"substitutes":{"in":2,"out":0,"bench":2},"shots":{"total":null,"on":null},"goals":{"total":2,"conceded":null,"assists":null,"saves":null},"passes":{"total":null,"key":null,"accuracy":null},"tackles":{"total":null,"blocks":null,"interceptions":null},"duels":{"total":null,"won":null},"dribbles":{"attempts":null,"success":null,"past":null},"fouls":{"drawn":null,"committed":null},"cards":{"yellow":1,"yellowred":0,"red":0},"penalty":{"won":null,"commited":null,"scored":null,"missed":null,"saved":null}},{"team":{"id":85,"name":"Paris Saint Germain","logo":"https:\/\/media.api-sports.io\/football\/teams\/85.png"},"league":{"id":2,"name":"UEFA Champions League","country":"World","logo":"https:\/\/media.api-sports.io\/football\/leagues\/2.png","flag":null,"season":2018},"games":{"appearences":7,"lineups":5,"minutes":414,"number":null,"position":"Attacker","rating":"7.016666","captain":false},"substitutes":{"in":2,"out":3,"bench":2},"shots":{"total":12,"on":6},"goals":{"total":2,"conceded":null,"assists":1,"saves":null},"passes":{"total":59,"key":3,"accuracy":84},"tackles":{"total":null,"blocks":0,"interceptions":4},"duels":{"total":13,"won":4},"dribbles":{"attempts":3,"success":2,"past":null},"fouls":{"drawn":1,"committed":3},"cards":{"yellow":0,"yellowred":0,"red":0},"penalty":{"won":null,"commited":null,"scored":0,"missed":0,"saved":null}}]}]} Rendering layout layouts/application.html.erb Rendering players/search.html.erb within layouts/application Rendered players/search.html.erb within layouts/application (Duration: 7.5ms | Allocations: 1307) [Webpacker] Everything's up-to-date. Nothing to do Rendered shared/_header.html.erb (Duration: 11.3ms | Allocations: 1202) Rendered shared/_footer.html.erb (Duration: 0.2ms | Allocations: 39) Rendered layout layouts/application.html.erb (Duration: 86.3ms | Allocations: 11466) Completed 200 OK in 5049ms (Views: 88.3ms | ActiveRecord: 1369.3ms | Allocations: 27433) ``` 上記のようにレスポンスが返っきましたが、viewに検索結果が表示されません。 どのように改善すれば良いか、アドバイスお願い致します。
winterboum

2022/12/04 23:03

JSON.parse(response.body) を JSON.parse(response.read_body) するとどうなります? read_body というのは 初見です、、、

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。