This article is about consuming YouTube API in your Ruby/Rails project using ActiveResource. Moreover, this article is an example of how to extend ActiveResource to consume non rest-style API.
Benefits of using our extension to ActiveResource :
- ActiveResource provides a ActiveRecord style interface.
- You can modify our extension according to your interface requirement.
- No not need to use and rely on Ruby library for YouTube REST API.
This article is about consuming YouTube API in your Ruby/Rails project using ActiveResource. Moreover, this article is an example of how to extend ActiveResource to consume non rest-style API.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
require 'rubygems'
require 'activeresource'
class ActiveYouTube < ActiveResource::Base
class << self
## Remove format from the url.
def element_path(id, prefix_options = {}, query_options = nil)
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
"#{prefix(prefix_options)}#{collection_name}/#{id}#{query_string(query_options)}"
end
## Remove format from the url.
def collection_path(prefix_options = {}, query_options = nil)
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
"#{prefix(prefix_options)}#{collection_name}#{query_string(query_options)}"
end
## For a collection call, ActiveResource formatting is not
## compliant with YouTube's output.
def instantiate_collection(collection, prefix_options = {})
unless collection.kind_of? Array
[instantiate_record(collection, prefix_options)]
else
collection.collect! { |record| instantiate_record(record, prefix_options) }
end
end
## To convert output into proper standard.
## If single element is present in output then entry is not an array.
## So this method will ensure entry is always an array.
alias :old_find :find
def find(*args)
output=old_find(*args)
if output.respond_to?:entry and !(output.entry.kind_of? Array)
output.entry=[output.entry]
end
output
end
## When using ActiveResource::CustomMethods, ActiveResource first tries to retrieve the id using find()
## and then makes a get() call using that id.
## But, youtube returns the url of this item as id, which we don't want. This method overrides the behavior.
## Example: comments = Video.find_custom("ZTUVgYoeN_o").get(:comments)
def find_custom(arg)
object = self.new
object.id = arg
object
end
## Following method from ActiveResource::CustomMethods extends the capabilities of activeresource for non-standard urls ;-)
## The objects returned from this method are not automatically converted into ActiveResource instances - they are ordinary Hashes.
## Modifications below ensures that you get ActiveResource instances.
def get(method_name, options = {})
object_array = connection.get(custom_method_collection_url(method_name, options), headers)
if object_array.class.to_s=="Array"
object_array.collect! {|record| self.class.new.load(record)}
else
self.class.new.load(object_array)
end
end
end
## Instance Methods: (modifying the ActiveRecord::CustomMethods).
## This modification is same as defined in above method
def get(method_name, options = {})
self.class.new.load(connection.get(custom_method_element_url(method_name, options), self.class.headers))
end
## Modifying the url formation to make it Youtube API complaint
def custom_method_element_url(method_name, options = {})
"#{self.class.prefix(prefix_options)}#{self.class.collection_name}/#{id}/" +
"#{method_name}#{self.class.send!(:query_string, options)}"
end
end |
- When using the ActiveResource::CustomMethods (get/post) make sure you are using "find_custom" and not "find"
- Disable the logging of ActiveResource, since the following line leads to exception if logger is enabled.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
#### Create classes for YouTube resources.
class Video < ActiveYouTube
self.site = "http://gdata.youtube.com/feeds/api"
## To search by categories and tags
def self.search_by_tags (*options)
from_urls = []
if options.last.is_a? Hash
excludes = options.slice!(options.length-1)
if excludes[:exclude].kind_of? Array
from_urls << excludes[:exclude].map{|keyword| "-"+keyword}.join("/")
else
from_urls << "-"+excludes[:exclude]
end
end
from_urls << options.find_all{|keyword| keyword =~ /^[a-z]/}.join("/")
from_urls << options.find_all{|category| category =~ /^[A-Z]/}.join("%7C")
from_urls.delete_if {|x| x.empty?}
self.find(:all,:from=>"/feeds/api/videos/-/"+from_urls.reverse.join("/"))
end
end
class User < ActiveYouTube
self.site = "http://gdata.youtube.com/feeds/api"
end
class Standardfeed < ActiveYouTube
self.site = "http://gdata.youtube.com/feeds/api"
end
class Playlist < ActiveYouTube
self.site = "http://gdata.youtube.com/feeds/api"
end
##### Examples #######
#### VIDEO
## search for videos
search = Video.find(:first, :params => {:vq => 'ruby', :"max-results" => '5'})
puts search.entry.length
## video information of id = ZTUVgYoeN_o
vid = Video.find("ZTUVgYoeN_o")
puts vid.group.content[0].url
## video comments
comments = Video.find_custom("ZTUVgYoeN_o").get(:comments)
puts comments.entry[0].link[2].href
## searching with category/tags
results = Video.search_by_tags("Comedy")
puts results[0].entry[0].title
# more examples:
# Video.search_by_tags("Comedy", "dog")
# Video.search_by_tags("News","Sports","football", :exclude=>["Comedy","soccer"])
# Video.search_by_tags("News","Sports","football", :exclude=>"soccer")
#### STANDARDFEED
## retrieving standard feeds
most_viewed = Standardfeed.find(:most_viewed, :params => {:time => 'today'})
puts most_viewed.entry[0].group.content[0].url
#### USER
## user's profile - guthrie
user_profile = User.find("guthrie")
puts user_profile.link[1].href
## user's playlist - john
user_playlist = User.find_custom("john").get(:playlists)
puts user_playlist.link[1].href
## user's upload or favorites
rick_video = User.find_custom("rick").get(:uploads)
puts rick_video.entry[0].group.content[0].url
## user's subscription
user_subscriptions = User.find_custom("guthrie").get(:subscriptions)
puts user_subscriptions.to_yaml
#### PLAYLIST
## get playlist - multiple elements in playlist
playlist = Playlist.find("EBF5D6DC4589D7B7")
puts playlist.entry[0].group.content[0].url
## get playlist - single element in playlist
playlist = Playlist.find("45C563323B344971")
puts playlist.entry[0].group.content[0].url |