howcast 0.3.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,20 @@
1
+ == 0.4.1 2008-11-05
2
+
3
+ * Support for finding a category ancestor trail from a category object
4
+
5
+ == 0.4 2008-11-02
6
+
7
+ * Add support for the new category API to get the name and parent ID
8
+ * Added badges and easy_steps methods for video
9
+
10
+ == 0.3.4 2008-08-21
11
+
12
+ * Support for new paging scheme in browse pages - ?page=1 => /1
13
+
14
+ == 0.3.3 2008-07-25
15
+
16
+ * Video dimensions
17
+
1
18
  == 0.3.2 2008-06-03
2
19
 
3
20
  * Clean up with inject
@@ -13,6 +13,7 @@ lib/howcast/client/base.rb
13
13
  lib/howcast/client/video.rb
14
14
  lib/howcast/client/guide.rb
15
15
  lib/howcast/client/search.rb
16
+ lib/howcast/client/category.rb
16
17
  script/destroy
17
18
  script/generate
18
19
  script/txt2html
@@ -23,6 +24,7 @@ spec/howcast/client/base_spec.rb
23
24
  spec/howcast/client/guide_spec.rb
24
25
  spec/howcast/client/video_spec.rb
25
26
  spec/howcast/client/search_spec.rb
27
+ spec/howcast/client/category_spec.rb
26
28
  tasks/deployment.rake
27
29
  tasks/environment.rake
28
30
  tasks/rspec.rake
@@ -6,3 +6,4 @@ require_local('howcast/client/base.rb')
6
6
  require_local('howcast/client/video.rb')
7
7
  require_local('howcast/client/guide.rb')
8
8
  require_local('howcast/client/search.rb')
9
+ require_local('howcast/client/category.rb')
@@ -79,7 +79,7 @@ class Howcast::Client
79
79
  # === Inputs
80
80
  #
81
81
  # * <tt>xml</tt> -- See below for a sample xml input
82
- # * <tt>klass</tt> -- Class to create - Guide | Video supported
82
+ # * <tt>klass</tt> -- Class to create - Guide | Video | Category supported
83
83
  #
84
84
  # Sample input xml
85
85
  # <guide>
@@ -0,0 +1,85 @@
1
+ #--
2
+ # Copyright (c) 2008 Howcast Media Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ class Howcast::Client
25
+ class Category
26
+ extend WatchAttrAccessors
27
+ attr_accessor :id, :name, :parent_id, :parents
28
+
29
+ # Creates a new Category object which is used to encapsulate all the attributes available
30
+ # from the Howcast Category API. The parents attribute will be an array of category
31
+ # ancestors of the form:
32
+ # [{:id => 1, :name => 'root'}, {:id => 2, :name => 'immediate parent'}]
33
+ #
34
+ # === Inputs
35
+ #
36
+ # * <tt>attributes</tt> -- A hash to set the various attributes of the category object
37
+ #
38
+ # === Examples
39
+ #
40
+ # Initialize a category with name "Arts & Crafts"
41
+ # Category.new :name => "Arts & Crafts"
42
+ def initialize(attributes={})
43
+ attributes.each do |k, v|
44
+ self.send("#{k}=", v) if self.respond_to?(k)
45
+ end
46
+ end
47
+ end
48
+
49
+ # Provides access to the Howcast category API.
50
+ #
51
+ # === Inputs
52
+ #
53
+ # * <tt>id</tt> -- The id of the category to lookup
54
+ #
55
+ # === Outputs
56
+ #
57
+ # Category object if the id exists or nil if the id doesn't exist or is malformed
58
+ #
59
+ # === Exceptions
60
+ #
61
+ # * <tt>Howcast::ApiNotFound</tt>
62
+ #
63
+ # === Examples
64
+ #
65
+ # Get the Howcast category with id 2
66
+ # Howcast::Client.new.category(2)
67
+ def category(id)
68
+ response = establish_connection("categories/#{id}.xml")
69
+ parse_single_category_xml(response.at(:category))
70
+ end
71
+
72
+ private
73
+ # Exception here to parse the <parents> tag in a category, will set a category.parents variable
74
+ # which is an array of parent metadata hases
75
+ # [{:id => '123', :name => "root"}, {:id => "1234", :name => "parent"}]
76
+ def parse_single_category_xml(xml)
77
+ hash = {}
78
+ Category.attr_accessors.each do |attribute|
79
+ node_name = attribute.to_s.gsub("_", "-") # xml schema uses hyphens for spaces, but ruby uses underscores
80
+ hash[attribute] = !xml.at(node_name).nil? ? xml.at(node_name).inner_text.strip : ""
81
+ end
82
+ hash[:parents] = (xml.at('parents')/:category).map{ |c| {:id => c['id'], :name => c.inner_html }}
83
+ hash.values.all?{|v| v==""} ? nil : Category.new(hash)
84
+ end
85
+ end
@@ -44,7 +44,6 @@ class Howcast::Client
44
44
  end
45
45
  end
46
46
 
47
- # REFACTOR: Consider combining with videos method
48
47
  # Provides access to the Howcast list guides API.
49
48
  #
50
49
  # === Inputs
@@ -75,11 +74,6 @@ class Howcast::Client
75
74
  def guides_url(options={})
76
75
  defaults = {:page => nil, :sort => "most_recent", :filter => "howcast_written", :category_id => nil}
77
76
  options = defaults.update(options)
78
- if options[:category_id].nil?
79
- uri = "guides/#{options[:sort]}/#{options[:filter]}.xml"
80
- else
81
- uri = "guides/#{options[:sort]}/#{options[:filter]}/#{options[:category_id]}.xml"
82
- end
83
- uri + uri_suffix(options)
77
+ "guides/#{options[:sort]}/#{options[:filter]}#{"/#{options[:category_id]}" if options[:category_id]}#{"/#{options[:page]}" if options[:page]}.xml"
84
78
  end
85
79
  end
@@ -37,7 +37,8 @@ class Howcast::Client
37
37
  class Video
38
38
  extend WatchAttrAccessors
39
39
  attr_accessor :id, :title, :permalink, :thumbnail_url, :category_id,
40
- :views, :username, :duration, :created_at, :rating, :description
40
+ :views, :username, :duration, :created_at, :rating, :description, :width, :height,
41
+ :badges, :easy_steps
41
42
  # Creates a new Video object which is used to encapsulate all the attributes available
42
43
  # from the Howcast Video API
43
44
  #
@@ -54,6 +55,11 @@ class Howcast::Client
54
55
  self.send("#{k}=", v) if self.respond_to?(k)
55
56
  end
56
57
  end
58
+
59
+ # Return true if the video contains easy step by step directions, else false
60
+ def easy_steps?
61
+ easy_steps == "true"
62
+ end
57
63
  end
58
64
 
59
65
  # Provides access to the Howcast video API.
@@ -109,11 +115,6 @@ class Howcast::Client
109
115
  def videos_url(options={})
110
116
  defaults = {:page => nil, :sort => "most_recent", :filter => "howcast_studios", :category_id => nil}
111
117
  options = defaults.update(options)
112
- if options[:category_id].nil?
113
- uri = "videos/#{options[:sort]}/#{options[:filter]}.xml"
114
- else
115
- uri = "videos/#{options[:sort]}/#{options[:filter]}/#{options[:category_id]}.xml"
116
- end
117
- uri + uri_suffix(options)
118
+ "videos/#{options[:sort]}/#{options[:filter]}#{"/#{options[:category_id]}" if options[:category_id]}#{"/#{options[:page]}" if options[:page]}.xml"
118
119
  end
119
120
  end
@@ -1,8 +1,8 @@
1
1
  module Howcast #:nodoc:
2
2
  module Version #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 3
5
- TINY = 2
4
+ MINOR = 4
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  class << self
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Howcast::Client::Category, "initialize" do
4
+ it "should create a category object with all the inputted attributes" do
5
+ category = Howcast::Client::Category.new :name => "category_title"
6
+ category.name.should == 'category_title'
7
+ end
8
+
9
+ it "should ignore inputs which are not category attributes" do
10
+ category = Howcast::Client::Category.new :not_an_attribute => "value", :name => "category_title"
11
+ category.respond_to?(:not_an_attribute).should be_false
12
+ category.name.should == "category_title"
13
+ end
14
+ end
15
+
16
+ describe Howcast::Client, "category" do
17
+ before do
18
+ @hc = Howcast::Client.new(:key => "myapikey")
19
+ @hc.stub!(:open).and_return(category_xml)
20
+ end
21
+
22
+ it "should establish a connection with the correct category url" do
23
+ @hc.should_receive(:open).with("http://www.howcast.com/categories/2.xml?api_key=myapikey").and_return(category_xml)
24
+ @hc.category(2)
25
+ end
26
+
27
+ it "should raise Howcast::ApiKeyNotFound error when the response contains Invalid API Key" do
28
+ lambda {
29
+ @hc.stub!(:open).and_return(invalid_api_key_xml)
30
+ @hc.category(2)
31
+ }.should raise_error(Howcast::ApiKeyNotFound)
32
+ end
33
+
34
+ it "should set the title attribute in the category model response" do
35
+ @hc.category(2).name.should == "General African Travel"
36
+ end
37
+
38
+ it "should set the parent_id attribute in the category model response" do
39
+ @hc.category(2).parent_id.should == "1584"
40
+ end
41
+
42
+ it "should set the parents metadata hash" do
43
+ @hc.category(2).parents.should == [{:id => "1571", :name => "Travel"}, {:id => "1584", :name => "African Travel"}]
44
+ end
45
+ end
@@ -23,8 +23,8 @@ describe Howcast::Client, "guides" do
23
23
  @hc.guides
24
24
  end
25
25
 
26
- it "should establish a connection with guides/most_recent/howcast_written.xml?page=2 when :page => 2" do
27
- @hc.should_receive(:open).with("http://www.howcast.com/guides/most_recent/howcast_written.xml?page=2&api_key=myapikey").and_return(guides_xml)
26
+ it "should establish a connection with guides/most_recent/howcast_written/2.xml when :page => 2" do
27
+ @hc.should_receive(:open).with("http://www.howcast.com/guides/most_recent/howcast_written/2.xml?api_key=myapikey").and_return(guides_xml)
28
28
  @hc.guides(:page => 2)
29
29
  end
30
30
 
@@ -44,6 +44,14 @@ describe Howcast::Client, "video" do
44
44
  @hc.video(2).views.should == "38"
45
45
  end
46
46
 
47
+ it "should set the badges in the video model response" do
48
+ @hc.video(2).badges.should == "Howcast Studios"
49
+ end
50
+
51
+ it "should set the easy_steps boolean in the video model response" do
52
+ @hc.video(2).easy_steps?.should be_true
53
+ end
54
+
47
55
  it "should set the rating attribute in the video model response" do
48
56
  @hc.video(2).rating.should == "2.0"
49
57
  end
@@ -67,8 +75,8 @@ describe Howcast::Client, "videos" do
67
75
  @hc.videos
68
76
  end
69
77
 
70
- it "should establish a connection with videos/most_recent/howcast_studios.xml?page=2 when :page => 2" do
71
- @hc.should_receive(:open).with("http://www.howcast.com/videos/most_recent/howcast_studios.xml?page=2&api_key=myapikey").and_return(videos_xml)
78
+ it "should establish a connection with videos/most_recent/howcast_studios/2.xml when :page => 2" do
79
+ @hc.should_receive(:open).with("http://www.howcast.com/videos/most_recent/howcast_studios/2.xml?api_key=myapikey").and_return(videos_xml)
72
80
  @hc.videos(:page => 2)
73
81
  end
74
82
 
@@ -48,6 +48,41 @@ Spec::Runner.configure do |config|
48
48
  VID
49
49
  end
50
50
 
51
+ def category_xml
52
+ <<-CAT
53
+ <?xml version="1.0" encoding="UTF-8"?>
54
+ <howcast version="0.1">
55
+ <category>
56
+ <id>1255</id>
57
+ <name>General African Travel</name>
58
+ <parent-id>1584</parent-id>
59
+ <parents>
60
+ <category id="1571">Travel</category>
61
+ <category parent_id="1571" id="1584">African Travel</category>
62
+ </parents>
63
+ <subcategories>
64
+ <category>
65
+ <id>1265</id>
66
+ <name>African Travel</name>
67
+ </category>
68
+ <category>
69
+ <id>1289</id>
70
+ <name>European Travel</name>
71
+ </category>
72
+ <category>
73
+ <id>1256</id>
74
+ <name>General Travel</name>
75
+ </category>
76
+ <category>
77
+ <id>1311</id>
78
+ <name>General U.S. Travel</name>
79
+ </category>
80
+ </subcategories>
81
+ </category>
82
+ </howcast>
83
+ CAT
84
+ end
85
+
51
86
  def video_xml
52
87
  <<-VID
53
88
  <?xml version="1.0" encoding="UTF-8"?>
@@ -56,6 +91,8 @@ Spec::Runner.configure do |config|
56
91
  <category-id>2</category-id>
57
92
  <duration>22</duration>
58
93
  <id>233</id>
94
+ <easy-steps>true</easy-steps>
95
+ <badges>Howcast Studios</badges>
59
96
  <title>How To Do a Noble Pose</title>
60
97
  <description>
61
98
  <![CDATA[You recognize the Noble Pose as the dreaded "sit-and-reach" from your childhood gym class. A sample <a href="howcast.com">link</a>]]>
@@ -5,7 +5,7 @@
5
5
  <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
6
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
7
  <title>
8
- Howcast
8
+
9
9
  </title>
10
10
  <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
11
  <style>
@@ -30,15 +30,18 @@
30
30
  <body>
31
31
  <div id="main">
32
32
 
33
- <h1>Howcast</h1>
33
+ <h1></h1>
34
34
  <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/howcast"; return false'>
35
35
  <p>Get Version</p>
36
- <a href="http://rubyforge.org/projects/howcast" class="numbers">0.3.2</a>
36
+ <a href="http://rubyforge.org/projects/howcast" class="numbers">0.4.1</a>
37
37
  </div>
38
- <h2>What</h2>
38
+ <h2>Howcast <span class="caps">API</span> Rubygem</h2>
39
39
 
40
40
 
41
- <p>Howcast RubyGem is a Ruby library for interacting with the <a href="http://groups.google.com/group/howcast-developers">Howcast <span class="caps">API</span></a></p>
41
+ <h2>What</h2>
42
+
43
+
44
+ <p>Howcast Rubygem is a Ruby library for interacting with the <a href="http://groups.google.com/group/howcast-developers">Howcast <span class="caps">API</span></a></p>
42
45
 
43
46
 
44
47
  <h2>Installing</h2>
@@ -1,8 +1,9 @@
1
- h1. Howcast
1
+
2
+ h2. Howcast API Rubygem
2
3
 
3
4
  h2. What
4
5
 
5
- Howcast RubyGem is a Ruby library for interacting with the "Howcast API":http://groups.google.com/group/howcast-developers
6
+ Howcast Rubygem is a Ruby library for interacting with the "Howcast API":http://groups.google.com/group/howcast-developers
6
7
 
7
8
 
8
9
  h2. Installing
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: howcast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Murray
@@ -9,11 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-06-03 00:00:00 -07:00
12
+ date: 2008-11-06 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: hpricot
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
@@ -21,6 +22,16 @@ dependencies:
21
22
  - !ruby/object:Gem::Version
22
23
  version: "0.6"
23
24
  version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hoe
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.2
34
+ version:
24
35
  description: Howcast API Ruby Wrapper
25
36
  email:
26
37
  - michael+gem@howcast.com
@@ -50,6 +61,7 @@ files:
50
61
  - lib/howcast/client/video.rb
51
62
  - lib/howcast/client/guide.rb
52
63
  - lib/howcast/client/search.rb
64
+ - lib/howcast/client/category.rb
53
65
  - script/destroy
54
66
  - script/generate
55
67
  - script/txt2html
@@ -60,6 +72,7 @@ files:
60
72
  - spec/howcast/client/guide_spec.rb
61
73
  - spec/howcast/client/video_spec.rb
62
74
  - spec/howcast/client/search_spec.rb
75
+ - spec/howcast/client/category_spec.rb
63
76
  - tasks/deployment.rake
64
77
  - tasks/environment.rake
65
78
  - tasks/rspec.rake
@@ -92,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
105
  requirements: []
93
106
 
94
107
  rubyforge_project: howcast
95
- rubygems_version: 1.1.0
108
+ rubygems_version: 1.2.0
96
109
  signing_key:
97
110
  specification_version: 2
98
111
  summary: Howcast API Ruby Wrapper