Возникли проблемы с доступом к вложенным данным и Nil в Ruby / Rails - PullRequest
0 голосов
/ 21 апреля 2019

Я получаю данные из внешнего API в моем приложении Rails для интерфейса React.Я хотел бы очистить данные до того, как они попадут во внешний интерфейс и попытаться найти вложенные данные в непредсказуемом ответе API.Иногда вложенные данные возвращают что-то, а иногда nil.Это проблема (я думаю).

Я пробовал различные способы защиты с условиями, но, похоже, это не работает.

Вот метод, с которым я работаю:

def song_details
    search = HTTParty.get("https://musicbrainz.org/ws/2/release/#{params[:songId]}?inc=artist-credits+artist-rels+media+recording-level-rels+url-rels+work-level-rels+recording-rels&fmt=json", {
      headers: {"User-Agent" => "Songly/ver 1.0", "Contact" => "demiansims@gmail.com"}
      })


end

Если я вызываю search['relations'][0]['artist']['name'] в Rails Console, я получаю хорошую строку имени обратно.

Если я пытаюсь запустить:

search['relations'].map { |r| r['artist'].each { |a| puts a['name'] }}

Я получаю no method for Nil class on [] ошибку.Я знаю, что это потому, что некоторые значения равны нулю.

Вот полная картина вложенных данных (стоимость одной итерации - их около 20):

{"end"=>nil,
 "attribute-values"=>{},
 "artist"=>
  {"id"=>"70047e57-0153-4117-b0fc-a1d2e322e5ef",
   "name"=>"Donald Fagen",
   "disambiguation"=>"",
   "sort-name"=>"Fagen, Donald"},
 "ended"=>false,
 "direction"=>"backward",
 "type-id"=>"01ce32b0-d873-4baa-8025-714b45c0c754",
 "begin"=>nil,
 "target-type"=>"artist",
 "target-credit"=>"",
 "type"=>"composer",
 "attributes"=>[],
 "attribute-ids"=>{},
 "source-credit"=>""}

Я пытаюсь получить имя из relations -> artist -> name, еслидаже есть «художник» или «имя», и оно не равно нулю.Как мне подойти к этому?Извините, я новичок в Rails и только начинаю бороться со структурами данных.И я полагаю, что я прав, позаботившись о данных в бэкэнде перед отправкой в ​​React?

EDIT

Предложения, приведенные ниже, намного ближе, но я все ещеполучить ошибки при попытке обернуть данные:

  def song_details
    search = HTTParty.get("https://musicbrainz.org/ws/2/release/#{params[:songId]}?inc=artist-credits+artist-rels+media+recording-level-rels+url-rels+work-level-rels+recording-rels&fmt=json", {
      headers: {"User-Agent" => "Songly/ver 1.0", "Contact" => "demiansims@gmail.com"}
      })
      search['relations'].present?
        search['relations'].map do |r|
          r['artist'].present?
          artist = {
            name: r['artist', 'name'],
            role: r['type'].present? && r['type'],
            id: r['artist', 'id'],
            disambiguation: r['artist', 'disambiguation'],
            attributes: r['attributes'] && r['attributes'].each { |a| a }
          }
      end
    artist
  end

Я получаю такие ошибки, как:

app/controllers/api/v1/searches_controller.rb:26:in `[]'
app/controllers/api/v1/searches_controller.rb:26:in `block in song_details'
app/controllers/api/v1/searches_controller.rb:21:in `map'
app/controllers/api/v1/searches_controller.rb:21:in `song_details'

Ответы [ 2 ]

1 голос
/ 21 апреля 2019

Это хороший пример, в котором вы можете использовать Hash#dig

artist_names = search['relations'].map { |r| r.dig('artist', 'name') }
0 голосов
/ 21 апреля 2019

Вы можете использовать метод try в rails. Метод try возвращает nil, если данные не существуют в объекте, обратитесь к этой ссылке для справки. Если это не работает, используйте nil проверки, такие как a.present? или a.blank?

Если вы хотите проверить ноль, то с предоставленным вами образцом и предполагая, что он будет в массиве, вы можете использовать

a.map { |r|  r['artist'] && r['artist']['name'] } //a is array of object you specified

Вы делаете это неправильно r ['artist', 'name'] выдает ошибку

  def song_details
search = HTTParty.get("https://musicbrainz.org/ws/2/release/#{params[:songId]}?inc=artist-credits+artist-rels+media+recording-level-rels+url-rels+work-level-rels+recording-rels&fmt=json", {
  headers: {"User-Agent" => "Songly/ver 1.0", "Contact" => "demiansims@gmail.com"}
  })
  search['relations'].present?
    search['relations'].map do |r|
      r['artist'].present?
      artist = {
        name: r.dig('artist', 'name'),
        role: r['type'],
        id: r.dig('artist', 'id'),
        disambiguation: r.dig('artist', 'disambiguation'),
        attributes: r['attributes'] && r['attributes'].each { |a| a }
      }
  end
artist

конец

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...