howcast 0.7.4 → 0.7.15
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +38 -0
- data/{README.markdown → README.md} +44 -13
- data/Rakefile +6 -39
- data/VERSION +1 -1
- data/fixtures/categories.xml +2230 -0
- data/fixtures/category.1585.xml +24 -0
- data/fixtures/homepage.staff_videos.xml +315 -0
- data/fixtures/invalid.api_key.xml +6 -0
- data/fixtures/playlist.4566.xml +484 -0
- data/fixtures/users.someone.profile.videos.xml +440 -0
- data/fixtures/video.233.generated.xml +1563 -0
- data/fixtures/video.233.xml +830 -0
- data/howcast.gemspec +31 -90
- data/lib/howcast.rb +1 -1
- data/lib/howcast/client.rb +1 -1
- data/lib/howcast/client/base.rb +232 -188
- data/lib/howcast/client/category.rb +31 -13
- data/lib/howcast/client/homepage.rb +10 -8
- data/lib/howcast/client/marker.rb +2 -0
- data/lib/howcast/client/playlist.rb +2 -0
- data/lib/howcast/client/search.rb +11 -11
- data/lib/howcast/client/type.rb +48 -0
- data/lib/howcast/client/user.rb +2 -0
- data/lib/howcast/client/utils.rb +53 -0
- data/lib/howcast/client/video.rb +39 -25
- data/lib/howcast/ext/string.rb +8 -0
- data/lib/howcast/hpricot/elements.rb +22 -0
- data/lib/howcast/version.rb +3 -0
- data/script/github-test.rb +24 -0
- data/spec/howcast/client/base_spec.rb +2 -2
- data/spec/howcast/client/category_spec.rb +41 -2
- data/spec/howcast/client/homepage_spec.rb +8 -8
- data/spec/howcast/client/playlist_spec.rb +6 -4
- data/spec/howcast/client/search_spec.rb +7 -8
- data/spec/howcast/client/user_spec.rb +9 -7
- data/spec/howcast/client/video_spec.rb +106 -22
- data/spec/spec_helper.rb +4 -7
- data/spec/xml_fixtures_helper.rb +20 -2895
- metadata +94 -28
- data/CHANGELOG +0 -108
- data/Manifest +0 -19
- data/howcast-0.7.3.gem +0 -0
- data/spec/string_matchers_helper.rb +0 -22
data/howcast.gemspec
CHANGED
@@ -1,97 +1,38 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "howcast/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
9
|
-
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
s.
|
6
|
+
s.name = "howcast"
|
7
|
+
s.version = Howcast::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Jingshen Jimmy Zhang", "Ian Smith-Heisters", "Juris Galang"]
|
10
|
+
s.email = ["support@howcast.com"]
|
11
|
+
s.homepage = "http://api.howcast.com/"
|
12
|
+
s.summary = %q{Ruby-bindings for the Howcast API}
|
13
13
|
s.description = %q{ Howcast offers an Application Programming Interface (API) which allows
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
}
|
23
|
-
s.email = %q{support@howcast.com}
|
24
|
-
s.extra_rdoc_files = [
|
25
|
-
"README.markdown"
|
26
|
-
]
|
27
|
-
s.files = [
|
28
|
-
"CHANGELOG",
|
29
|
-
"License.txt",
|
30
|
-
"Manifest",
|
31
|
-
"README.markdown",
|
32
|
-
"Rakefile",
|
33
|
-
"VERSION",
|
34
|
-
"howcast-0.7.3.gem",
|
35
|
-
"howcast.gemspec",
|
36
|
-
"lib/howcast.rb",
|
37
|
-
"lib/howcast/client.rb",
|
38
|
-
"lib/howcast/client/base.rb",
|
39
|
-
"lib/howcast/client/category.rb",
|
40
|
-
"lib/howcast/client/homepage.rb",
|
41
|
-
"lib/howcast/client/marker.rb",
|
42
|
-
"lib/howcast/client/playlist.rb",
|
43
|
-
"lib/howcast/client/search.rb",
|
44
|
-
"lib/howcast/client/user.rb",
|
45
|
-
"lib/howcast/client/video.rb",
|
46
|
-
"lib/howcast/errors.rb",
|
47
|
-
"lib/howcast/logging.rb",
|
48
|
-
"spec/howcast/client/base_spec.rb",
|
49
|
-
"spec/howcast/client/category_spec.rb",
|
50
|
-
"spec/howcast/client/homepage_spec.rb",
|
51
|
-
"spec/howcast/client/playlist_spec.rb",
|
52
|
-
"spec/howcast/client/search_spec.rb",
|
53
|
-
"spec/howcast/client/user_spec.rb",
|
54
|
-
"spec/howcast/client/video_spec.rb",
|
55
|
-
"spec/output_capture_helper.rb",
|
56
|
-
"spec/spec.opts",
|
57
|
-
"spec/spec_helper.rb",
|
58
|
-
"spec/string_matchers_helper.rb",
|
59
|
-
"spec/xml_fixtures_helper.rb",
|
60
|
-
"tasks/github.rake"
|
61
|
-
]
|
62
|
-
s.homepage = %q{http://github.com/howcast/howcast-gem}
|
63
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
64
|
-
s.require_paths = ["lib"]
|
65
|
-
s.rubygems_version = %q{1.3.6}
|
66
|
-
s.summary = %q{Howcast API Ruby Wrapper}
|
67
|
-
s.test_files = [
|
68
|
-
"spec/howcast/client/base_spec.rb",
|
69
|
-
"spec/howcast/client/category_spec.rb",
|
70
|
-
"spec/howcast/client/homepage_spec.rb",
|
71
|
-
"spec/howcast/client/playlist_spec.rb",
|
72
|
-
"spec/howcast/client/search_spec.rb",
|
73
|
-
"spec/howcast/client/user_spec.rb",
|
74
|
-
"spec/howcast/client/video_spec.rb",
|
75
|
-
"spec/output_capture_helper.rb",
|
76
|
-
"spec/spec_helper.rb",
|
77
|
-
"spec/string_matchers_helper.rb",
|
78
|
-
"spec/xml_fixtures_helper.rb"
|
79
|
-
]
|
14
|
+
developers to build applications that interface with Howcast. The Howcast
|
15
|
+
API is RESTful (REpresentational State Transfer) and users of this API will
|
16
|
+
be able: 1) Retreive detailed information about a single video, including
|
17
|
+
metadata such as title, description, video views, rating etc; 2) Retrieve a
|
18
|
+
list of videos restricted by a set of filters offered by Howcast and sorted
|
19
|
+
using several metrics that you can specify (most recent, most views, etc);
|
20
|
+
3) Search for video; 4) And much more. Note: Before you can use our APIs,
|
21
|
+
you must register an API key, that is submitted with each request.
|
22
|
+
}
|
80
23
|
|
81
|
-
|
82
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
83
|
-
s.specification_version = 3
|
24
|
+
s.rubyforge_project = "howcast"
|
84
25
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
26
|
+
s.files = `git ls-files`.split("\n")
|
27
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
28
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
29
|
+
s.require_paths = ["lib"]
|
30
|
+
|
31
|
+
s.add_runtime_dependency(%q<hpricot>, [">= 0"])
|
32
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
33
|
+
|
34
|
+
#s.add_development_dependency(%q<jeweler>, [">= 0"])
|
35
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
36
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
37
|
+
s.add_development_dependency(%q<ruby-debug>, [">= 0"])
|
96
38
|
end
|
97
|
-
|
data/lib/howcast.rb
CHANGED
data/lib/howcast/client.rb
CHANGED
@@ -2,6 +2,6 @@
|
|
2
2
|
class Howcast::Client
|
3
3
|
end
|
4
4
|
|
5
|
-
%w(client/base client/video client/search client/category client/marker client/user client/homepage client/playlist).each do |dependency|
|
5
|
+
%w(client/utils client/base client/video client/search client/category client/marker client/user client/homepage client/playlist client/type).each do |dependency|
|
6
6
|
require(File.expand_path(File.join(File.dirname(__FILE__), dependency)))
|
7
7
|
end
|
data/lib/howcast/client/base.rb
CHANGED
@@ -22,10 +22,16 @@
|
|
22
22
|
#++
|
23
23
|
|
24
24
|
require 'rubygems'
|
25
|
+
require 'benchmark'
|
26
|
+
require 'timeout'
|
25
27
|
require 'hpricot'
|
28
|
+
require 'nokogiri'
|
26
29
|
require 'open-uri'
|
27
30
|
require 'uri'
|
28
31
|
|
32
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../hpricot/elements'))
|
33
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '../ext/string'))
|
34
|
+
|
29
35
|
class Howcast::Client
|
30
36
|
attr_accessor :key
|
31
37
|
|
@@ -56,210 +62,248 @@ class Howcast::Client
|
|
56
62
|
end
|
57
63
|
|
58
64
|
def base_uri
|
59
|
-
@base_uri ||= URI.parse("http://
|
65
|
+
@base_uri ||= URI.parse("http://api.howcast.com")
|
60
66
|
end
|
61
67
|
end
|
68
|
+
|
62
69
|
protected
|
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
|
-
|
70
|
+
# Establishes a connection with the Howcast API. Will auto append the api key, that was used
|
71
|
+
# to instantiate the Client object, to the URL
|
72
|
+
#
|
73
|
+
# === Inputs
|
74
|
+
#
|
75
|
+
# * <tt>relative_path</tt> -- should be the path after <tt>http://www.howcast.com/</tt>
|
76
|
+
#
|
77
|
+
# === Outputs
|
78
|
+
#
|
79
|
+
# Hpricot object encapsulating the xml returned from the Howcast API
|
80
|
+
#
|
81
|
+
# === Exceptions
|
82
|
+
#
|
83
|
+
# * <tt>Howcast::ApiNotFound</tt> -- raised if the requested +relative_path+ is malformed or not available (404)
|
84
|
+
# * <tt>Howcast::ApiKeyNotFound</tt> -- raised if the +api_key+ is invalid
|
85
|
+
#
|
86
|
+
# === Examples
|
87
|
+
#
|
88
|
+
# Get the Hpricot data for most recent howcast studios videos
|
89
|
+
# establish_connection("videos/most_recent/howcast_studios.xml")
|
90
|
+
def establish_connection(relative_path_and_query)
|
91
|
+
begin
|
92
|
+
uri = self.class.base_uri.dup
|
93
|
+
relative_path_and_query = '/' + relative_path_and_query unless relative_path_and_query[0] == '/'
|
94
|
+
uri.path, uri.query = *relative_path_and_query.split('?')
|
95
|
+
|
96
|
+
doc = nil
|
97
|
+
time = Benchmark.realtime do
|
98
|
+
doc = Hpricot.XML open(attach_api_key uri)
|
99
|
+
end
|
100
|
+
Howcast.log.info "Established connection with: '#{uri.to_s}' after #{time * 1000}ms"
|
101
|
+
|
102
|
+
raise Howcast::ApiKeyNotFound \
|
103
|
+
if doc.at(:err) && doc.at(:err)['msg'].match(/Invalid API Key/)
|
104
|
+
|
105
|
+
doc
|
106
|
+
rescue Timeout::Error
|
107
|
+
raise Howcast::ApiError, "Timed-out after #{time * 1000}ms while attempting to access the API at #{uri.to_s}"
|
91
108
|
rescue URI::InvalidURIError
|
92
|
-
raise Howcast::ApiNotFound
|
93
|
-
rescue OpenURI::HTTPError =>
|
94
|
-
raise Howcast::ApiError
|
109
|
+
raise Howcast::ApiNotFound, "Invalid URL #{uri.to_s} requested."
|
110
|
+
rescue OpenURI::HTTPError => e
|
111
|
+
raise Howcast::ApiError, "HTTP error #{e.message} accessing the API at #{uri.to_s}."
|
95
112
|
end
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
113
|
+
end
|
114
|
+
|
115
|
+
# Parses the xml for a single item from +xml+ and creates a new +klass+ object
|
116
|
+
#
|
117
|
+
# === Inputs
|
118
|
+
#
|
119
|
+
# * <tt>xml</tt> -- See below for a sample xml input
|
120
|
+
# * <tt>klass</tt> -- Class to create - Video | Category supported
|
121
|
+
#
|
122
|
+
# Sample input xml
|
123
|
+
# <video>
|
124
|
+
# <id>1086</id>
|
125
|
+
# <rating>96</rating>
|
126
|
+
# <title>How To Choose a Paintbrush</title>
|
127
|
+
# <category-id>19</category-id>
|
128
|
+
# <description>
|
129
|
+
# <![CDATA[Yes, you could just use your fingers, but selecting the best brushes for your painting might achieve a slightly more grown-up result.]]>
|
130
|
+
# </description>
|
131
|
+
# <views>362</views>
|
132
|
+
# <permalink>http://www.howcast.com/guides/1086-How-To-Choose-a-Paintbrush</permalink>
|
133
|
+
# <username>michaelrsanchez</username>
|
134
|
+
# <created-at>Thu, 20 Dec 2007 14:14:58 -0800</created-at>
|
135
|
+
# </video>
|
136
|
+
#
|
137
|
+
# === Outputs
|
138
|
+
#
|
139
|
+
# +klass+ object with initialized attributes
|
140
|
+
def parse_single_xml(xml, klass)
|
141
|
+
hash = { }
|
142
|
+
klass.attr_accessors.each do |attribute|
|
143
|
+
node_name = attribute.to_s.gsub("_", "-") # xml schema uses hyphens for spaces, but ruby uses underscores
|
144
|
+
if node_name == "category-hierarchy"
|
145
|
+
hash[attribute] = category_hierarchy_for(xml) unless xml.at(node_name).nil?
|
146
|
+
elsif node_name == "playlist-memberships"
|
147
|
+
hash[attribute] = playlist_memberships_for(xml) unless xml.at(node_name).nil?
|
148
|
+
elsif node_name == "ingredients"
|
149
|
+
hash[attribute] = ingredients_for(xml) unless xml.at(node_name).nil?
|
150
|
+
elsif node_name == "markers"
|
151
|
+
hash[attribute] = markers_for(xml) unless xml.at(node_name).nil?
|
152
|
+
elsif node_name == "related-videos"
|
153
|
+
hash[attribute] = related_videos_for(xml) unless xml.at(node_name).nil?
|
154
|
+
elsif node_name == "videos"
|
155
|
+
hash[attribute] = videos_for(xml) unless xml.at(node_name).nil?
|
156
|
+
elsif node_name == "playlist-thumbnail-url"
|
157
|
+
# TODO: Resolve this hack, xml attributes aren't named consistently
|
158
|
+
hash[attribute] = !xml.at(node_name).nil? ? xml.at(node_name).inner_text.strip : xml.at("thumbnail-url").inner_text.strip
|
159
|
+
elsif node_name == "type"
|
160
|
+
hash[attribute] = type_for(xml) unless xml.at(node_name).nil?
|
161
|
+
elsif %w{ ads-allowed mature-content }.include? node_name
|
162
|
+
hash[attribute] = !xml.at(node_name).nil? ? "true" : ""
|
163
|
+
else
|
164
|
+
hash[attribute] = !xml.at(node_name).nil? ? xml.at(node_name).inner_text.strip : ""
|
142
165
|
end
|
143
|
-
hash.values.all?{|v| v==""} ? nil : klass.new(hash)
|
144
|
-
end
|
145
|
-
|
146
|
-
# Creates parameters to append to a uri
|
147
|
-
#
|
148
|
-
# === Inputs
|
149
|
-
#
|
150
|
-
# Options are:
|
151
|
-
# * <tt>:page</tt> -- the page number
|
152
|
-
# * <tt>:use_ampersand</tt> -- boolean to return ampersand (defaults to false)
|
153
|
-
#
|
154
|
-
# === Outputs
|
155
|
-
#
|
156
|
-
# A valid suffix string to append to the end of a url
|
157
|
-
#
|
158
|
-
# === Examples
|
159
|
-
#
|
160
|
-
# "?page=2"
|
161
|
-
# uri_suffix(:page => 2)
|
162
|
-
# "&page=2"
|
163
|
-
# uri_suffix(:page => 3, :use_ampersand => true)
|
164
|
-
def uri_suffix(opts)
|
165
|
-
opts && opts[:page] ? "#{opts[:use_ampersand] ? '&' : '?'}page=#{opts[:page]}" : ""
|
166
166
|
end
|
167
|
+
hash.values.all?{ |v| (v == "") or (v.respond_to?(:empty?) and v.empty?) } ? nil : klass.new(hash)
|
168
|
+
end
|
167
169
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
170
|
+
# Creates parameters to append to a uri
|
171
|
+
#
|
172
|
+
# === Inputs
|
173
|
+
#
|
174
|
+
# Options are:
|
175
|
+
# * <tt>:page</tt> -- the page number
|
176
|
+
# * <tt>:use_ampersand</tt> -- boolean to return ampersand (defaults to false)
|
177
|
+
#
|
178
|
+
# === Outputs
|
179
|
+
#
|
180
|
+
# A valid suffix string to append to the end of a url
|
181
|
+
#
|
182
|
+
# === Examples
|
183
|
+
#
|
184
|
+
# "?page=2"
|
185
|
+
# uri_suffix(:page => 2)
|
186
|
+
# "&page=2"
|
187
|
+
# uri_suffix(:page => 3, :use_ampersand => true)
|
188
|
+
def uri_suffix(opts)
|
189
|
+
opts && opts[:page] ? "#{opts[:use_ampersand] ? '&' : '?'}page=#{opts[:page]}" : ""
|
190
|
+
end
|
191
|
+
|
192
|
+
# Appends the api key to a uri and returns the appended uri
|
193
|
+
#
|
194
|
+
# === Inputs
|
195
|
+
#
|
196
|
+
# * <tt>uri</tt> -- the URI object to append the api_key to
|
197
|
+
#
|
198
|
+
# === Outputs
|
199
|
+
#
|
200
|
+
# The uri with the api_key appended to the query string
|
201
|
+
#
|
202
|
+
# === Examples
|
203
|
+
#
|
204
|
+
# attach_api_key(URI.parse("http://www.howcast.com")).to_s
|
205
|
+
# => "http://www.howcast.com?api_key=APIKEYHERE"
|
206
|
+
#
|
207
|
+
# attach_api_key(URI.parse("http://www.howcast.com/videos/most_recent/all?page=2")).to_s
|
208
|
+
# => "http://www.howcast.com/videos/most_recent/all?page=2&api_key=APIKEYHERE"
|
209
|
+
def attach_api_key(uri)
|
210
|
+
uri = uri.dup
|
211
|
+
key = "api_key=#{self.key}"
|
212
|
+
uri.query = uri.query.to_s.strip != "" ? uri.query+"&"+key : key
|
213
|
+
uri
|
214
|
+
end
|
191
215
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
216
|
+
# From merb/core_ext/hash.rb, line 87
|
217
|
+
def hash_to_params hash
|
218
|
+
params = ''
|
219
|
+
stack = []
|
196
220
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
221
|
+
hash.keys.sort{ |a, b| a.to_s <=> b.to_s }.each do |k|
|
222
|
+
v = hash[k]
|
223
|
+
if v.is_a?(Hash)
|
224
|
+
stack << [k,v]
|
225
|
+
else
|
226
|
+
params << "#{k}=#{v}&"
|
203
227
|
end
|
228
|
+
end
|
204
229
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
end
|
230
|
+
stack.each do |parent, h|
|
231
|
+
h.each do |k, v|
|
232
|
+
if v.is_a?(Hash)
|
233
|
+
stack << ["#{parent}[#{k}]", v]
|
234
|
+
else
|
235
|
+
params << "#{parent}[#{k}]=#{v}&"
|
212
236
|
end
|
213
237
|
end
|
214
|
-
|
215
|
-
params.chop! # trailing &
|
216
|
-
params
|
217
238
|
end
|
239
|
+
|
240
|
+
params.chop! # trailing &
|
241
|
+
params
|
242
|
+
end
|
218
243
|
|
219
244
|
private
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
245
|
+
def category_hierarchy_for(xml)
|
246
|
+
categories = []
|
247
|
+
node = xml.at('category-hierarchy')
|
248
|
+
node.children_of_type('category').each do |child|
|
249
|
+
category = Category.new(:id => child['id'], :parent_id => child['parent_id'], :name => child.inner_text, :permalink => child['permalink'])
|
250
|
+
categories << category
|
251
|
+
end unless node.nil?
|
252
|
+
categories
|
253
|
+
end
|
254
|
+
|
255
|
+
def playlist_memberships_for(xml)
|
256
|
+
memberships = []
|
257
|
+
node = xml.at('playlist-memberships')
|
258
|
+
node.children_of_type('playlist').each do |child|
|
259
|
+
playlist = Playlist.new(:id => child['id'], :title => child.inner_text)
|
260
|
+
memberships << playlist
|
261
|
+
end unless node.nil?
|
262
|
+
memberships
|
263
|
+
end
|
264
|
+
|
265
|
+
def ingredients_for(xml)
|
266
|
+
ingredients = []
|
267
|
+
node = xml.at('ingredients')
|
268
|
+
node.children_of_type('ingredient').each do |child|
|
269
|
+
ingredients << child.inner_text.strip
|
270
|
+
end unless node.nil?
|
271
|
+
ingredients
|
272
|
+
end
|
273
|
+
|
274
|
+
def markers_for(xml)
|
275
|
+
markers = []
|
276
|
+
node = xml.at('markers')
|
277
|
+
node.children_of_type('marker').each do |child|
|
278
|
+
markers << parse_single_xml(child, Marker)
|
279
|
+
end unless node.nil?
|
280
|
+
markers
|
281
|
+
end
|
282
|
+
|
283
|
+
def type_for(xml)
|
284
|
+
node = xml.at('type')
|
285
|
+
if node['status'] && node['class']
|
286
|
+
Type.new(:name => node.inner_text.strip, :kind => node['class'], :status => node['status'])
|
287
|
+
else
|
288
|
+
node.inner_text.strip
|
264
289
|
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def related_videos_for(xml)
|
293
|
+
related = []
|
294
|
+
node = xml.at('related-videos')
|
295
|
+
node.children_of_type('video').each do |child|
|
296
|
+
related << parse_single_xml(child, Video)
|
297
|
+
end unless node.nil?
|
298
|
+
related
|
299
|
+
end
|
300
|
+
|
301
|
+
def videos_for(xml)
|
302
|
+
videos = []
|
303
|
+
node = xml.at('videos')
|
304
|
+
node.children_of_type('video').each do |child|
|
305
|
+
videos << parse_single_xml(child, Video)
|
306
|
+
end unless node.nil?
|
307
|
+
videos
|
308
|
+
end
|
265
309
|
end
|