Ruby Code Samples

The following code samples, which use the Google APIs Client Library for Ruby , are available for the YouTube Data API . You can download these code samples from the ruby folder of the YouTube APIs code sample repository on GitHub .

Add a channel subscription

This sample calls the API's subscriptions.insert method to add a subscription to a specified channel.

 #!/usr/bin/ruby 
 require 
  
 'rubygems' 
 gem 
  
 'google-api-client' 
 , 
  
 '>0.7' 
 require 
  
 'google/api_client' 
 require 
  
 'google/api_client/client_secrets' 
 require 
  
 'google/api_client/auth/file_storage' 
 require 
  
 'google/api_client/auth/installed_app' 
 require 
  
 'trollop' 
 # This OAuth 2.0 access scope allows for full read/write access to the 
 # authenticated user's account. 
 YOUTUBE_SCOPE 
  
 = 
  
 'https://www.googleapis.com/auth/youtube' 
 YOUTUBE_API_SERVICE_NAME 
  
 = 
  
 'youtube' 
 YOUTUBE_API_VERSION 
  
 = 
  
 'v3' 
 def 
  
 get_authenticated_service 
  
 client 
  
 = 
  
 Google 
 :: 
 APIClient 
 . 
 new 
 ( 
  
 :application_name 
  
 = 
>  
 $PROGRAM_NAME 
 , 
  
 :application_version 
  
 = 
>  
 '1.0.0' 
  
 ) 
  
 youtube 
  
 = 
  
 client 
 . 
 discovered_api 
 ( 
 YOUTUBE_API_SERVICE_NAME 
 , 
  
 YOUTUBE_API_VERSION 
 ) 
  
 file_storage 
  
 = 
  
 Google 
 :: 
 APIClient 
 :: 
 FileStorage 
 . 
 new 
 ( 
 " 
 #{ 
 $PROGRAM_NAME 
 } 
 -oauth2.json" 
 ) 
  
 if 
  
 file_storage 
 . 
 authorization 
 . 
 nil? 
  
 client_secrets 
  
 = 
  
 Google 
 :: 
 APIClient 
 :: 
 ClientSecrets 
 . 
 load 
  
 flow 
  
 = 
  
 Google 
 :: 
 APIClient 
 :: 
 InstalledAppFlow 
 . 
 new 
 ( 
  
 :client_id 
  
 = 
>  
 client_secrets 
 . 
 client_id 
 , 
  
 :client_secret 
  
 = 
>  
 client_secrets 
 . 
 client_secret 
 , 
  
 :scope 
  
 = 
>  
 [ 
 YOUTUBE_SCOPE 
 ] 
  
 ) 
  
 client 
 . 
 authorization 
  
 = 
  
 flow 
 . 
 authorize 
 ( 
 file_storage 
 ) 
  
 else 
  
 client 
 . 
 authorization 
  
 = 
  
 file_storage 
 . 
 authorization 
  
 end 
  
 return 
  
 client 
 , 
  
 youtube 
 end 
 def 
  
 main 
  
 opts 
  
 = 
  
 Trollop 
 :: 
 options 
  
 do 
  
 opt 
  
 :channel_id 
 , 
  
 'ID of the channel to subscribe to.' 
 , 
  
 :type 
  
 = 
>  
 String 
 , 
  
 :default 
  
 = 
>  
 'UCtVd0c0tGXuTSbU5d8cSBUg' 
  
 end 
  
 client 
 , 
  
 youtube 
  
 = 
  
 get_authenticated_service 
  
 begin 
  
 body 
  
 = 
  
 { 
  
 :snippet 
  
 = 
>  
 { 
  
 :resourceId 
  
 = 
>  
 { 
  
 :channelId 
  
 = 
>  
 opts 
 [ 
 :channel_id 
 ] 
  
 } 
  
 } 
  
 } 
  
 # Call the API's youtube.subscriptions.insert method to add the subscription 
  
 # to the specified channel. 
  
 subscriptions_response 
  
 = 
  
 client 
 . 
 execute! 
 ( 
  
 :api_method 
  
 = 
>  
 youtube 
 . 
 subscriptions 
 . 
 insert 
 , 
  
 :parameters 
  
 = 
>  
 { 
  
 :part 
  
 = 
>  
 body 
 . 
 keys 
 . 
 join 
 ( 
 ',' 
 ) 
  
 }, 
  
 :body_object 
  
 = 
>  
 body 
  
 ) 
  
 puts 
  
 "A subscription to ' 
 #{ 
 subscriptions_response 
 . 
 data 
 . 
 snippet 
 . 
 title 
 } 
 ' was added." 
  
 rescue 
  
 Google 
 :: 
 APIClient 
 :: 
 TransmissionError 
  
 = 
>  
 e 
  
 puts 
  
 e 
 . 
 result 
 . 
 body 
  
 end 
 end 
 main 
  

Authorize a request

The following code sample performs OAuth 2.0 authorization by checking for the presence of a local file that contains authorization credentials. If the file is not present, the script opens a browser and waits for a response, then saves the returned credentials locally.

 require 
  
 'google/api_client' 
 require 
  
 'google/api_client/client_secrets' 
 require 
  
 'json' 
 require 
  
 'launchy' 
 require 
  
 'thin' 
 RESPONSE_HTML 
  
 = 
  
<< stop 
< html 
>  
< head 
>  
< title>OAuth 
  
 2 
  
 Flow 
  
 Complete 
< / 
 title 
>  
< /head 
> <body> 
 You have successfully completed the OAuth 2 flow. Please close this browser window and return to your program. 
 </ 
 body 
>
< /html 
> stop 
 FILE_POSTFIX = '-oauth2.json' 
 # Small helper for the sample apps for performing OAuth 2.0 flows from the command 
 # line. Starts an embedded server to handle redirects. 
 class CommandLineOAuthHelper 
 def initialize(scope) 
 credentials = Google::APIClient::ClientSecrets.load 
 @authorization = Signet::OAuth2::Client.new( 
 :authorization_uri => credentials.authorization_uri, 
 :token_credential_uri => credentials.token_credential_uri, 
 :client_id => credentials.client_id, 
 :client_secret => credentials.client_secret, 
 :redirect_uri => credentials.redirect_uris.first, 
 :scope => scope 
 ) 
 end 
 # Request authorization. Checks to see if a local file with credentials is present, and uses that. 
 # Otherwise, opens a browser and waits for response, then saves the credentials locally. 
 def authorize 
 credentialsFile = $0 + FILE_POSTFIX 
 if File.exist? credentialsFile 
 File.open(credentialsFile, 'r') do |file| 
 credentials = JSON.load(file) 
 @authorization.access_token = credentials['access_token'] 
 @authorization.client_id = credentials['client_id'] 
 @authorization.client_secret = credentials['client_secret'] 
 @authorization.refresh_token = credentials['refresh_token'] 
 @authorization.expires_in = (Time.parse(credentials['token_expiry']) - Time.now).ceil 
 if @authorization.expired? 
 @authorization.fetch_access_token! 
 save(credentialsFile) 
 end 
 end 
 else 
 auth = @authorization 
 url = @authorization.authorization_uri().to_s 
 server = Thin::Server.new('0.0.0.0', 8080) do 
 run lambda { |env| 
 # Exchange the auth code & quit 
 req = Rack::Request.new(env) 
 auth.code = req['code'] 
 auth.fetch_access_token! 
 server.stop() 
 [200, {'Content-Type' => 'text/ 
 html 
 '}, RESPONSE_HTML] 
 } 
 end 
 Launchy.open(url) 
 server.start() 
 save(credentialsFile) 
 end 
 return @authorization 
 end 
 def save(credentialsFile) 
 File.open(credentialsFile, ' 
 w 
 ', 0600) do |file| 
 json = JSON.dump({ 
 :access_token => @authorization.access_token, 
 :client_id => @authorization.client_id, 
 :client_secret => @authorization.client_secret, 
 :refresh_token => @authorization.refresh_token, 
 :token_expiry => @authorization.expires_at 
 }) 
 file.write(json) 
 end 
 end 
 end 
  

Retrieve my uploads

This sample calls the API's playlistItems.list method to retrieve a list of videos uploaded to the channel associated with the request. The code also calls the channels.list method with the mine parameter set to true to retrieve the playlist ID that identifies the channel's uploaded videos.

 #!/usr/bin/ruby 
 require 
  
 'rubygems' 
 gem 
  
 'google-api-client' 
 , 
  
 '>0.7' 
 require 
  
 'google/api_client' 
 require 
  
 'google/api_client/client_secrets' 
 require 
  
 'google/api_client/auth/file_storage' 
 require 
  
 'google/api_client/auth/installed_app' 
 # This OAuth 2.0 access scope allows for read-only access to the authenticated 
 # user's account, but not other types of account access. 
 YOUTUBE_READONLY_SCOPE 
  
 = 
  
 'https://www.googleapis.com/auth/youtube.readonly' 
 YOUTUBE_API_SERVICE_NAME 
  
 = 
  
 'youtube' 
 YOUTUBE_API_VERSION 
  
 = 
  
 'v3' 
 def 
  
 get_authenticated_service 
  
 client 
  
 = 
  
 Google 
 :: 
 APIClient 
 . 
 new 
 ( 
  
 :application_name 
  
 = 
>  
 $PROGRAM_NAME 
 , 
  
 :application_version 
  
 = 
>  
 '1.0.0' 
  
 ) 
  
 youtube 
  
 = 
  
 client 
 . 
 discovered_api 
 ( 
 YOUTUBE_API_SERVICE_NAME 
 , 
  
 YOUTUBE_API_VERSION 
 ) 
  
 file_storage 
  
 = 
  
 Google 
 :: 
 APIClient 
 :: 
 FileStorage 
 . 
 new 
 ( 
 " 
 #{ 
 $PROGRAM_NAME 
 } 
 -oauth2.json" 
 ) 
  
 if 
  
 file_storage 
 . 
 authorization 
 . 
 nil? 
  
 client_secrets 
  
 = 
  
 Google 
 :: 
 APIClient 
 :: 
 ClientSecrets 
 . 
 load 
  
 flow 
  
 = 
  
 Google 
 :: 
 APIClient 
 :: 
 InstalledAppFlow 
 . 
 new 
 ( 
  
 :client_id 
  
 = 
>  
 client_secrets 
 . 
 client_id 
 , 
  
 :client_secret 
  
 = 
>  
 client_secrets 
 . 
 client_secret 
 , 
  
 :scope 
  
 = 
>  
 [ 
 YOUTUBE_READONLY_SCOPE 
 ] 
  
 ) 
  
 client 
 . 
 authorization 
  
 = 
  
 flow 
 . 
 authorize 
 ( 
 file_storage 
 ) 
  
 else 
  
 client 
 . 
 authorization 
  
 = 
  
 file_storage 
 . 
 authorization 
  
 end 
  
 return 
  
 client 
 , 
  
 youtube 
 end 
 def 
  
 main 
  
 client 
 , 
  
 youtube 
  
 = 
  
 get_authenticated_service 
  
 begin 
  
 # Retrieve the "contentDetails" part of the channel resource for the 
  
 # authenticated user's channel. 
  
 channels_response 
  
 = 
  
 client 
 . 
 execute! 
 ( 
  
 :api_method 
  
 = 
>  
 youtube 
 . 
 channels 
 . 
 list 
 , 
  
 :parameters 
  
 = 
>  
 { 
  
 :mine 
  
 = 
>  
 true 
 , 
  
 :part 
  
 = 
>  
 'contentDetails' 
  
 } 
  
 ) 
  
 channels_response 
 . 
 data 
 . 
 items 
 . 
 each 
  
 do 
  
 | 
 channel 
 | 
  
 # From the API response, extract the playlist ID that identifies the list 
  
 # of videos uploaded to the authenticated user's channel. 
  
 uploads_list_id 
  
 = 
  
 channel 
 [ 
 'contentDetails' 
 ][ 
 'relatedPlaylists' 
 ][ 
 'uploads' 
 ] 
  
 # Retrieve the list of videos uploaded to the authenticated user's channel. 
  
 next_page_token 
  
 = 
  
 '' 
  
 until 
  
 next_page_token 
 . 
 nil? 
  
 playlistitems_response 
  
 = 
  
 client 
 . 
 execute! 
 ( 
  
 :api_method 
  
 = 
>  
 youtube 
 . 
 playlist_items 
 . 
 list 
 , 
  
 :parameters 
  
 = 
>  
 { 
  
 :playlistId 
  
 = 
>  
 uploads_list_id 
 , 
  
 :part 
  
 = 
>  
 'snippet' 
 , 
  
 :maxResults 
  
 = 
>  
 50 
 , 
  
 :pageToken 
  
 = 
>  
 next_page_token 
  
 } 
  
 ) 
  
 puts 
  
 "Videos in list 
 #{ 
 uploads_list_id 
 } 
 " 
  
 # Print information about each video. 
  
 playlistitems_response 
 . 
 data 
 . 
 items 
 . 
 each 
  
 do 
  
 | 
 playlist_item 
 | 
  
 title 
  
 = 
  
 playlist_item 
 [ 
 'snippet' 
 ][ 
 'title' 
 ] 
  
 video_id 
  
 = 
  
 playlist_item 
 [ 
 'snippet' 
 ][ 
 'resourceId' 
 ][ 
 'videoId' 
 ] 
  
 puts 
  
 " 
 #{ 
 title 
 } 
 ( 
 #{ 
 video_id 
 } 
 )" 
  
 end 
  
 next_page_token 
  
 = 
  
 playlistitems_response 
 . 
 next_page_token 
  
 end 
  
 puts 
  
 end 
  
 rescue 
  
 Google 
 :: 
 APIClient 
 :: 
 TransmissionError 
  
 = 
>  
 e 
  
 puts 
  
 e 
 . 
 result 
 . 
 body 
  
 end 
 end 
 main 
  

Search by keyword

This sample calls the API's search.list method to retrieve search results associated with a particular keyword.

 #!/usr/bin/ruby 
 require 
  
 'rubygems' 
 gem 
  
 'google-api-client' 
 , 
  
 '>0.7' 
 require 
  
 'google/api_client' 
 require 
  
 'trollop' 
 # Set DEVELOPER_KEY to the API key value from the APIs & auth > Credentials 
 # tab of 
 # {{ Google Cloud Console }} <{{ https://cloud.google.com/console }} 
> # Please ensure that you have enabled the YouTube Data API for your project. 
 DEVELOPER_KEY 
  
 = 
  
 'REPLACE_ME' 
 YOUTUBE_API_SERVICE_NAME 
  
 = 
  
 'youtube' 
 YOUTUBE_API_VERSION 
  
 = 
  
 'v3' 
 def 
  
 get_service 
  
 client 
  
 = 
  
 Google 
 :: 
 APIClient 
 . 
 new 
 ( 
  
 :key 
  
 = 
>  
 DEVELOPER_KEY 
 , 
  
 :authorization 
  
 = 
>  
 nil 
 , 
  
 :application_name 
  
 = 
>  
 $PROGRAM_NAME 
 , 
  
 :application_version 
  
 = 
>  
 '1.0.0' 
  
 ) 
  
 youtube 
  
 = 
  
 client 
 . 
 discovered_api 
 ( 
 YOUTUBE_API_SERVICE_NAME 
 , 
  
 YOUTUBE_API_VERSION 
 ) 
  
 return 
  
 client 
 , 
  
 youtube 
 end 
 def 
  
 main 
  
 opts 
  
 = 
  
 Trollop 
 :: 
 options 
  
 do 
  
 opt 
  
 :q 
 , 
  
 'Search term' 
 , 
  
 :type 
  
 = 
>  
 String 
 , 
  
 :default 
  
 = 
>  
 'Google' 
  
 opt 
  
 :max_results 
 , 
  
 'Max results' 
 , 
  
 :type 
  
 = 
>  
 :int 
 , 
  
 :default 
  
 = 
>  
 25 
  
 end 
  
 client 
 , 
  
 youtube 
  
 = 
  
 get_service 
  
 begin 
  
 # Call the search.list method to retrieve results matching the specified 
  
 # query term. 
  
 search_response 
  
 = 
  
 client 
 . 
 execute! 
 ( 
  
 :api_method 
  
 = 
>  
 youtube 
 . 
 search 
 . 
 list 
 , 
  
 :parameters 
  
 = 
>  
 { 
  
 :part 
  
 = 
>  
 'snippet' 
 , 
  
 :q 
  
 = 
>  
 opts 
 [ 
 :q 
 ] 
 , 
  
 :maxResults 
  
 = 
>  
 opts 
 [ 
 :max_results 
 ] 
  
 } 
  
 ) 
  
 videos 
  
 = 
  
 [] 
  
 channels 
  
 = 
  
 [] 
  
 playlists 
  
 = 
  
 [] 
  
 # Add each result to the appropriate list, and then display the lists of 
  
 # matching videos, channels, and playlists. 
  
 search_response 
 . 
 data 
 . 
 items 
 . 
 each 
  
 do 
  
 | 
 search_result 
 | 
  
 case 
  
 search_result 
 . 
 id 
 . 
 kind 
  
 when 
  
 'youtube#video' 
  
 videos 
 << 
 " 
 #{ 
 search_result 
 . 
 snippet 
 . 
 title 
 } 
 ( 
 #{ 
 search_result 
 . 
 id 
 . 
 videoId 
 } 
 )" 
  
 when 
  
 'youtube#channel' 
  
 channels 
 << 
 " 
 #{ 
 search_result 
 . 
 snippet 
 . 
 title 
 } 
 ( 
 #{ 
 search_result 
 . 
 id 
 . 
 channelId 
 } 
 )" 
  
 when 
  
 'youtube#playlist' 
  
 playlists 
 << 
 " 
 #{ 
 search_result 
 . 
 snippet 
 . 
 title 
 } 
 ( 
 #{ 
 search_result 
 . 
 id 
 . 
 playlistId 
 } 
 )" 
  
 end 
  
 end 
  
 puts 
  
 "Videos: 
 \n 
 " 
 , 
  
 videos 
 , 
  
 " 
 \n 
 " 
  
 puts 
  
 "Channels: 
 \n 
 " 
 , 
  
 channels 
 , 
  
 " 
 \n 
 " 
  
 puts 
  
 "Playlists: 
 \n 
 " 
 , 
  
 playlists 
 , 
  
 " 
 \n 
 " 
  
 rescue 
  
 Google 
 :: 
 APIClient 
 :: 
 TransmissionError 
  
 = 
>  
 e 
  
 puts 
  
 e 
 . 
 result 
 . 
 body 
  
 end 
 end 
 main 
  

Upload a video

This sample calls the API's videos.insert method to upload a video to the channel associated with the request.

 #!/usr/bin/ruby 
 require 
  
 'rubygems' 
 gem 
  
 'google-api-client' 
 , 
  
 '>0.7' 
 require 
  
 'google/api_client' 
 require 
  
 'google/api_client/client_secrets' 
 require 
  
 'google/api_client/auth/file_storage' 
 require 
  
 'google/api_client/auth/installed_app' 
 require 
  
 'trollop' 
 # A limited OAuth 2 access scope that allows for uploading files, but not other 
 # types of account access. 
 YOUTUBE_UPLOAD_SCOPE 
  
 = 
  
 'https://www.googleapis.com/auth/youtube.upload' 
 YOUTUBE_API_SERVICE_NAME 
  
 = 
  
 'youtube' 
 YOUTUBE_API_VERSION 
  
 = 
  
 'v3' 
 def 
  
 get_authenticated_service 
  
 client 
  
 = 
  
 Google 
 :: 
 APIClient 
 . 
 new 
 ( 
  
 :application_name 
  
 = 
>  
 $PROGRAM_NAME 
 , 
  
 :application_version 
  
 = 
>  
 '1.0.0' 
  
 ) 
  
 youtube 
  
 = 
  
 client 
 . 
 discovered_api 
 ( 
 YOUTUBE_API_SERVICE_NAME 
 , 
  
 YOUTUBE_API_VERSION 
 ) 
  
 file_storage 
  
 = 
  
 Google 
 :: 
 APIClient 
 :: 
 FileStorage 
 . 
 new 
 ( 
 " 
 #{ 
 $PROGRAM_NAME 
 } 
 -oauth2.json" 
 ) 
  
 if 
  
 file_storage 
 . 
 authorization 
 . 
 nil? 
  
 client_secrets 
  
 = 
  
 Google 
 :: 
 APIClient 
 :: 
 ClientSecrets 
 . 
 load 
  
 flow 
  
 = 
  
 Google 
 :: 
 APIClient 
 :: 
 InstalledAppFlow 
 . 
 new 
 ( 
  
 :client_id 
  
 = 
>  
 client_secrets 
 . 
 client_id 
 , 
  
 :client_secret 
  
 = 
>  
 client_secrets 
 . 
 client_secret 
 , 
  
 :scope 
  
 = 
>  
 [ 
 YOUTUBE_UPLOAD_SCOPE 
 ] 
  
 ) 
  
 client 
 . 
 authorization 
  
 = 
  
 flow 
 . 
 authorize 
 ( 
 file_storage 
 ) 
  
 else 
  
 client 
 . 
 authorization 
  
 = 
  
 file_storage 
 . 
 authorization 
  
 end 
  
 return 
  
 client 
 , 
  
 youtube 
 end 
 def 
  
 main 
  
 opts 
  
 = 
  
 Trollop 
 :: 
 options 
  
 do 
  
 opt 
  
 :file 
 , 
  
 'Video file to upload' 
 , 
  
 :type 
  
 = 
>  
 String 
  
 opt 
  
 :title 
 , 
  
 'Video title' 
 , 
  
 :default 
  
 = 
>  
 'Test Title' 
 , 
  
 :type 
  
 = 
>  
 String 
  
 opt 
  
 :description 
 , 
  
 'Video description' 
 , 
  
 :default 
  
 = 
>  
 'Test Description' 
 , 
  
 :type 
  
 = 
>  
 String 
  
 opt 
  
 :category_id 
 , 
  
 'Numeric video category. See https://developers.google.com/youtube/v3/docs/videoCategories/list' 
 , 
  
 :default 
  
 = 
>  
 22 
 , 
  
 :type 
  
 = 
>  
 :int 
  
 opt 
  
 :keywords 
 , 
  
 'Video keywords, comma-separated' 
 , 
  
 :default 
  
 = 
>  
 '' 
 , 
  
 :type 
  
 = 
>  
 String 
  
 opt 
  
 :privacy_status 
 , 
  
 'Video privacy status: public, private, or unlisted' 
 , 
  
 :default 
  
 = 
>  
 'public' 
 , 
  
 :type 
  
 = 
>  
 String 
  
 end 
  
 if 
  
 opts 
 [ 
 :file 
 ]. 
 nil? 
  
 or 
  
 not 
  
 File 
 . 
 file? 
 ( 
 opts 
 [ 
 :file 
 ] 
 ) 
  
 Trollop 
 :: 
 die 
  
 :file 
 , 
  
 'does not exist' 
  
 end 
  
 client 
 , 
  
 youtube 
  
 = 
  
 get_authenticated_service 
  
 begin 
  
 body 
  
 = 
  
 { 
  
 :snippet 
  
 = 
>  
 { 
  
 :title 
  
 = 
>  
 opts 
 [ 
 :title 
 ] 
 , 
  
 :description 
  
 = 
>  
 opts 
 [ 
 :description 
 ] 
 , 
  
 :tags 
  
 = 
>  
 opts 
 [ 
 :keywords 
 ]. 
 split 
 ( 
 ',' 
 ), 
  
 :categoryId 
  
 = 
>  
 opts 
 [ 
 :category_id 
 ] 
 , 
  
 }, 
  
 :status 
  
 = 
>  
 { 
  
 :privacyStatus 
  
 = 
>  
 opts 
 [ 
 :privacy_status 
 ] 
  
 } 
  
 } 
  
 videos_insert_response 
  
 = 
  
 client 
 . 
 execute! 
 ( 
  
 :api_method 
  
 = 
>  
 youtube 
 . 
 videos 
 . 
 insert 
 , 
  
 :body_object 
  
 = 
>  
 body 
 , 
  
 :media 
  
 = 
>  
 Google 
 :: 
 APIClient 
 :: 
 UploadIO 
 . 
 new 
 ( 
 opts 
 [ 
 :file 
 ] 
 , 
  
 'video/*' 
 ), 
  
 :parameters 
  
 = 
>  
 { 
  
 :uploadType 
  
 = 
>  
 'resumable' 
 , 
  
 :part 
  
 = 
>  
 body 
 . 
 keys 
 . 
 join 
 ( 
 ',' 
 ) 
  
 } 
  
 ) 
  
 videos_insert_response 
 . 
 resumable_upload 
 . 
 send_all 
 ( 
 client 
 ) 
  
 puts 
  
 "Video id ' 
 #{ 
 videos_insert_response 
 . 
 data 
 . 
 id 
 } 
 ' was successfully uploaded." 
  
 rescue 
  
 Google 
 :: 
 APIClient 
 :: 
 TransmissionError 
  
 = 
>  
 e 
  
 puts 
  
 e 
 . 
 result 
 . 
 body 
  
 end 
 end 
 main 
  
Design a Mobile Site
View Site in Mobile | Classic
Share by: