为什么它有时会得到“未定义的方法`videoId'”?

时间:2015-06-28 16:06:12

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-4 youtube youtube-api

我正在尝试使用其API加载Youtube的搜索结果 到目前为止看起来工作得很好但有时会出现此错误

srand(stored_seed)

我只是想知道YouTube是否会在某些特定情况下不提供其视频?

我该如何避免这个问题?

CONTROLLER

ActionView::Template::Error (undefined method `videoId' for #<Google::APIClient::Schema::Youtube::V3::ResourceId:0x000000072afcb8>):

查看

. 
.
.
@search_response = client.execute!(
  :api_method => youtube.search.list,
  :parameters => {
    :part => 'snippet',
    :q => 'cat',
    :maxResults => 10,
    :order => 'date',
    :pageToken => pageToken
  }
)
.
.
.

调试输出

<% @search_response.data.items.each do |video| %>
    ID: <%= video.id.videoId %><br />
    Title: <%= video.snippet.title %><br />
    Description: <%= video.snippet.description %><br />
    <img src="<%= video.snippet.thumbnails.high.url %>" with="480" height="360"><br />
    <br />
    <br />
<% end %>


<%= debug @search_response.data.items %>

2 个答案:

答案 0 :(得分:1)

可能只是因为搜索结果没有返回视频。

这意味着它返回的搜索结果kind可能是youtube#playlistyoutube#channel而不是youtube#video。在这种情况下,您可能需要检查playlistIdchannelId

答案 1 :(得分:1)

清楚地概述这里出现问题的一种方法是Law of Demeter

  
      
  • 每个单位应该对其他单位的知识有限:只有单位&#34;密切关注&#34;与当前单位有关。
  •   
  • 每个单位只应与其朋友交谈;不要和陌生人说话。
  •   
  • 只与您的直接朋友交谈。
  •   

您不需要盲目服从,但经常可以告诉您系统何时出现问题。

所以,当你执行video.snippet.thumbnails.high.url时,你不仅违反了得墨忒耳法则 - 你还要用卡车重复操作它。

所以让我们改写它:

@search_response = client.execute!(
  :api_method => youtube.search.list,
  :parameters => {
    :part => 'snippet',
    :q => 'cat',
    :maxResults => 10,
    :order => 'date',
    :pageToken => pageToken
  }
)

data = @search_response.data
@videos = @search_response.data.try(:items) || []

在你看来

<% @videos.each do |video| %>
    <%- snippet = video.snippet -%>
    <%- if video.id -%>
    ID: <%= video.id.try(:videoId) %><br />
    <%- end ->
    <%- if snippet -%>
    Title: <%= snippet.title %><br />
    Description: <%= snippet.description %><br />
    <%- end -%> 
    <% 
    thumbnails = snippet.thumbnails
    if thumbnails %>
    <img src="<%= thumbnails.high.url %>" with="480" height="360">    
    <% end %>
    <br />
    <br />
    <br />
<% end %>

然而,为避免造成这样的混乱,您经常需要规范化从API获得的响应:

class Video
  include ActiveModel::Model
  attr_accessor :id
  attr_accessor :thumbnails
  attr_accessor :snippet
  attr_accessor :description
  attr_accessor :title

  def initialize(hash = {})
    @id = hash.try[:id].try(:videoId),
    @snippet = hash.try(:snippet),
    @thumbnails = hash.try(:snippet).try(:thumbnails),
    @description = hash.try(:snippet).try(:description)
    @title = hash.try(:snippet).try(:title)
  end
end

所以你会这样做

@videos = @videos.map { |v| Video.new(v) }

并重写你的观点:

<% @videos.each do |video| %>
    ID: <%= video.id %><br />
    Title: <%= video.title %><br />
    Description: <%= video.description %><br />
    <% thumbnail = video.thumbnails.try(:high).try(:url) %>
    <% if thumbnail %>
    <img src="<%= thumbnail %>" with="480" height="360"><br />
    <% end %>
    <br />
    <br />
<% end %>