googleapis/google-api-ruby-client

YouTube Data API v3 update_video fails with ArgumentError

ekortright opened this issue · 1 comments

Environment

  • OS: MacOS 11.5.2
  • Ruby version: 2.7.6
  • Gem name and version: google-apis-youtube_v3-0.22.0

Steps to reproduce

  1. Instantiate service object and call update_video method with part = 'id,snippet,status' and a video object specifying the video ID, snippet and status, following instructions in the method documentation.

Code example

require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'google-apis-youtube_v3'

REDIRECT_URI = 'http://localhost'
APPLICATION_NAME = '...'
API_KEY = '...'

SCOPE = Google::Apis::YoutubeV3::AUTH_YOUTUBE_FORCE_SSL

def authorize
  client_id = Google::Auth::ClientId.from_file('secrets/client_secret.json')
  token_store = Google::Auth::Stores::FileTokenStore.new(file: "secrets/youtube-creds.yml")
  authorizer = Google::Auth::UserAuthorizer.new(client_id, SCOPE, token_store)
  user_id = 'default'
  credentials = authorizer.get_credentials(user_id)
  if credentials.nil?
    url = authorizer.get_authorization_url(base_url: REDIRECT_URI)
    puts "Open the following URL in the browser and enter the resulting code after authorization"
    puts url
    code = gets
    credentials = authorizer.get_and_store_credentials_from_code(user_id: user_id, code: code, base_url: REDIRECT_URI)
  end
  credentials
end

def get_service
  service = Google::Apis::YoutubeV3::YouTubeService.new
  service.key = API_KEY
  service.client_options.application_name = APPLICATION_NAME
  service.authorization = authorize
  service
end

o = {
  "id": 'XYZ123',
  "snippet": {
    "category_id": "27",
    "default_language": "en",
    "description": "Testing updating description and title.",
    "tags": [
      "tag1",
      "tag2",
      "tag3"
    ],
    "title": "Test video upload using Ruby SDK"
  },
  "status": {
    "privacy_status": "private"
  }
}
resp = s.update_video('id,snippet,status', o)

Result

ArgumentError (unknown keywords: :id, :snippet, :status)

Note that the video object is almost identical to the one used to create the video in the first place. The only change, apart from trivial modifications of the video title and description, was the addition of the id attribute to identify the video.

The key to this mystery was given by @jimgay at StackOverflow.

It turns out that because the second argument video_object defaults to nil, Ruby is taking the last argument in the method call as a collection of key-value pairs to be passed to the method separately as keyword arguments, instead of passing one object as the value of the second parameter.

One solution is to instantiate an object of class Google::Apis::YoutubeV3::Video (which requires instantiating snippet and status objects) and pass that as the second argument.

Another possibility would be first to get the video by calling list_videos and passing back the returned object after making the desired modifications to the metadata.

Finally, it is also possible to use the plain hash as originally desired, as long as it is clear to Ruby that it is to be passed in as the second argument and not as key-value pairs. For example:

resp = s.update_video('id,snippet,status', o, options: nil)