claire_client 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Matheus E. Muller
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = claire.client
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Matheus E. Muller. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "claire_client"
8
+ gem.summary = "A ruby client for St. Claire."
9
+ gem.description = "This gem is a Ruby client for the St. Claire Media Server, which power power Canção Nova's reach of video and streamming web services."
10
+ gem.email = "hello@memuller.com"
11
+ gem.homepage = "http://github.com/memuller/claire.client"
12
+ gem.authors = ["Matheus E. Muller"]
13
+ gem.add_dependency "activesupport", ">= 2.3.5"
14
+ gem.add_dependency "hashie", ">= 0.2.0"
15
+ gem.add_development_dependency "rspec", ">= 1.2.9"
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+ require 'spec/rake/spectask'
24
+ Spec::Rake::SpecTask.new(:spec) do |spec|
25
+ spec.libs << 'lib' << 'spec'
26
+ spec.spec_files = FileList['spec/**/*_spec.rb']
27
+ end
28
+
29
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
30
+ spec.libs << 'lib' << 'spec'
31
+ spec.pattern = 'spec/**/*_spec.rb'
32
+ spec.rcov = true
33
+ end
34
+
35
+ task :spec => :check_dependencies
36
+
37
+ task :default => :spec
38
+
39
+ require 'rake/rdoctask'
40
+ Rake::RDocTask.new do |rdoc|
41
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
42
+
43
+ rdoc.rdoc_dir = 'rdoc'
44
+ rdoc.title = "claire.client #{version}"
45
+ rdoc.rdoc_files.include('README*')
46
+ rdoc.rdoc_files.include('lib/**/*.rb')
47
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,77 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{claire_client}
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Matheus E. Muller"]
12
+ s.date = %q{2010-04-28}
13
+ s.description = %q{This gem is a Ruby client for the St. Claire Media Server, which power power Canção Nova's reach of video and streamming web services.}
14
+ s.email = %q{hello@memuller.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "claire_client.gemspec",
27
+ "lib/claire_client.rb",
28
+ "lib/claire_client/category.rb",
29
+ "lib/claire_client/item.rb",
30
+ "lib/claire_client/list.rb",
31
+ "lib/claire_client/listable.rb",
32
+ "lib/claire_client/stream.rb",
33
+ "lib/claire_client/video.rb",
34
+ "spec/claire_client/item_spec.rb",
35
+ "spec/claire_client/list_spec.rb",
36
+ "spec/claire_client/listable_spec.rb",
37
+ "spec/claire_client_spec.rb",
38
+ "spec/fixtures/item.xml",
39
+ "spec/fixtures/item_direct.xml",
40
+ "spec/fixtures/item_with_channel.xml",
41
+ "spec/fixtures/list.xml",
42
+ "spec/spec.opts",
43
+ "spec/spec_helper.rb"
44
+ ]
45
+ s.homepage = %q{http://github.com/memuller/claire.client}
46
+ s.rdoc_options = ["--charset=UTF-8"]
47
+ s.require_paths = ["lib"]
48
+ s.rubygems_version = %q{1.3.6}
49
+ s.summary = %q{A ruby client for St. Claire.}
50
+ s.test_files = [
51
+ "spec/claire_client/item_spec.rb",
52
+ "spec/claire_client/list_spec.rb",
53
+ "spec/claire_client/listable_spec.rb",
54
+ "spec/claire_client_spec.rb",
55
+ "spec/spec_helper.rb"
56
+ ]
57
+
58
+ if s.respond_to? :specification_version then
59
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
60
+ s.specification_version = 3
61
+
62
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
63
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.3.5"])
64
+ s.add_runtime_dependency(%q<hashie>, [">= 0.2.0"])
65
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
66
+ else
67
+ s.add_dependency(%q<activesupport>, [">= 2.3.5"])
68
+ s.add_dependency(%q<hashie>, [">= 0.2.0"])
69
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
70
+ end
71
+ else
72
+ s.add_dependency(%q<activesupport>, [">= 2.3.5"])
73
+ s.add_dependency(%q<hashie>, [">= 0.2.0"])
74
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
75
+ end
76
+ end
77
+
@@ -0,0 +1,10 @@
1
+ module Claire
2
+ module Client
3
+ class Category
4
+ include Claire::Client::Item
5
+ include Claire::Client::Listable
6
+
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,92 @@
1
+ module Claire
2
+ module Client
3
+ module Item
4
+
5
+ attr_writer :partial
6
+
7
+ def initialize arg
8
+ if arg.is_a? String
9
+ file = Claire::Client.get("#{self.class.base_url}/#{arg}")
10
+ if Claire::Client.format == 'xml'
11
+ hash = Hashie::Mash.new(Hashie::Mash.from_xml(file))
12
+ else
13
+ hash = Hashie::Mash.new(JSON.parse(file))
14
+ end
15
+ @partial = false
16
+ else
17
+ hash = Hashie::Mash.new(arg) and @partial = true
18
+ end
19
+
20
+ # fetches items from rss, channel, or directly?
21
+ if hash.rss
22
+ hash = hash.rss
23
+ hash = if hash.channel
24
+ then hash.channel
25
+ else hash.item
26
+ end
27
+ end
28
+
29
+ hash.each do |k,v|
30
+
31
+ # skips paging and sub-items.
32
+ next if %w(item next previous).include? k
33
+
34
+ # sets an element's label
35
+ v = v.label if v.respond_to?('merge') and not v.label.nil?
36
+
37
+ # properly fetches the items's link, in case there are more than one link
38
+ v = v.first if k == 'link' and v.respond_to? 'push'
39
+
40
+ class_eval "def #{k}; @#{k}; end"
41
+ instance_variable_set "@#{k}", v
42
+ end
43
+
44
+ # a link is always required.
45
+ raise Claire::Error, "a link is always required" if @link.nil? or @link.empty?
46
+
47
+ end
48
+
49
+ # comparison operator. Sorts by title.
50
+ def <=> arg
51
+ criteria = :title
52
+ return 1 if self.send(criteria) > arg.send(criteria)
53
+ return 0 if self.send(criteria) == arg.send(criteria)
54
+ return -1 if self.send(criteria) < arg.send(criteria)
55
+ end
56
+
57
+ # checks an item's partial status
58
+ def partial?
59
+ @partial
60
+ end
61
+
62
+ module ClassMethods
63
+
64
+ # Returns this class base URI on the server,
65
+ # or guesses it from this class name.
66
+ def base_url
67
+ if defined? @@base_url
68
+ return @@base_url unless @@base_url.nil?
69
+ end
70
+ self.to_s.downcase.pluralize.split('::').last
71
+ end
72
+
73
+ # Manually set this class base URI on the server.
74
+ def base_url= arg
75
+ @@base_url = arg
76
+ end
77
+ end
78
+
79
+ # Extends the class methods above.
80
+ def Item.included base
81
+ base.extend ClassMethods
82
+ (@@children ||= []) << base
83
+ end
84
+
85
+ # Lists all avaliable Claire::Items
86
+ def self.children
87
+ @@children ||= []
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,53 @@
1
+ module Claire
2
+ module Client
3
+ class List
4
+ include Enumerable
5
+
6
+ attr_reader :body, :document
7
+
8
+ # gets, parses, and builds objects.
9
+ def initialize(arg)
10
+ #puts Claire::Client.respond_to? :get
11
+ @body = Claire::Client.get(arg)
12
+ @document = Hashie::Mash.new(Hashie::Mash.from_xml(@body))
13
+ @document = @document.rss if @document.rss
14
+ @document = @document.channel if @document.channel
15
+ if @document.item.nil?
16
+ @items = []
17
+ else
18
+ @items = @document.item
19
+ end
20
+ build_items
21
+ end
22
+
23
+ # Implements an iterator that either
24
+ # - returns an Array of items if no block is given
25
+ # - yields the given block once for each item
26
+ def each &block
27
+ return @objects unless block
28
+ @objects.each do |obj|
29
+ yield(obj)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ # Builds an array of Claire media objects.
36
+ # guesses their classes based on their restfull URI.
37
+ def build_items
38
+ @items.each do |item|
39
+ link = if item.link.is_a? String
40
+ then item.link
41
+ else item.link.first
42
+ end
43
+ klass = ("Claire::Client::" + link.split('/')[-2].classify).constantize
44
+ obj = klass.new(item)
45
+ (@objects||=[]) << obj
46
+
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ module Claire
2
+ module Client
3
+ module Listable
4
+
5
+ module ClassMethods
6
+
7
+ # Returns a Claire::List on its base_url.
8
+ # if passed a block, gets the list, them applies a local
9
+ # filter to the received items, returning an Array.
10
+ def all &block
11
+ list = List.new(self.base_url)
12
+ return list unless block
13
+ items = []
14
+ list.each do |item|
15
+ items << item if yield(item)
16
+ end
17
+ items
18
+
19
+ end
20
+
21
+ end
22
+
23
+ # Extends the class methods above.
24
+ def Listable.included base
25
+ raise Error, "only Claire::Client::Item s can be Listable" unless Item.children.include? base
26
+ base.extend ClassMethods
27
+ (@@children ||= []) << base
28
+ end
29
+
30
+ # Lists all avaliable Claire::Items
31
+ def self.children
32
+ @@children ||= []
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,10 @@
1
+ module Claire
2
+ module Client
3
+ class Stream
4
+ include Claire::Client::Item
5
+ include Claire::Client::Listable
6
+
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Claire
2
+ module Client
3
+ class Video
4
+ include Claire::Client::Item
5
+ include Claire::Client::Listable
6
+
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,85 @@
1
+ #loads global dependencies
2
+ #%w(rubygems mongo mongo_mapper memcache yaml activesupport json).each{|lib| require lib}
3
+
4
+ #loads every ruby file inside those folders
5
+ full_dir = File.expand_path(File.join(File.dirname(__FILE__), 'claire_client'))
6
+ %w(item list listable category video stream).each do |lib|
7
+ load "#{full_dir}/#{lib}.rb"
8
+ end
9
+
10
+ #
11
+ # Dir.new(full_dir).entries.each do |file|
12
+ # load [full_dir, file]*'/' if file.include? '.rb'
13
+ # end
14
+
15
+ #main module here.
16
+ module Claire
17
+ module Client
18
+ %w(rubygems open-uri active_support hashie).each { |lib| require lib }
19
+ @@hostname = "localhost:3000"
20
+ @@api_key = "33c80d2e38e6b1753982500721f76eccaee0d111"
21
+ @@format = 'xml'
22
+
23
+ %w(api_key hostname format).each do |var|
24
+ class_eval <<-METHOD
25
+ def self.#{var}
26
+ @@#{var}
27
+ end
28
+
29
+ def self.#{var}= arg
30
+ @@#{var} = arg
31
+ end
32
+ METHOD
33
+ end
34
+
35
+ # receives all parameters necessary for request-making.
36
+ def self.config args={}
37
+ args.each do |k,v|
38
+ class_variable_set "@@#{k}", v
39
+ end
40
+ end
41
+
42
+ # assembles an URL from an string of params.
43
+ def self.assemble_url url="", params={}
44
+ url = "http://#{@@hostname}/#{url}"
45
+ url += ".#{@@format.downcase}" if @@format
46
+ uri = URI.parse url
47
+ (uri.query ||= "") << "api_key=#{@@api_key}"
48
+ params.each do |k,v|
49
+ uri.query << "&#{k}=#{v}"
50
+ end
51
+ uri
52
+
53
+ end
54
+
55
+ # gets an URL. Assembles it first.
56
+ def self.get url=''
57
+ url = assemble_url(url)
58
+ request = open(url)
59
+ return request.read if request.status.first.to_i == 200
60
+ nil
61
+ rescue Exception => e
62
+
63
+
64
+ raise
65
+ end
66
+
67
+
68
+ end
69
+
70
+
71
+ #here goes the errors.
72
+ class Error < StandardError; end
73
+ class ClientError < Error; end
74
+ class AuthError < Error; end
75
+ class NotFound < Error; end
76
+ class TimeoutError < Error; end
77
+
78
+ module Client
79
+ class Video
80
+ include Claire::Client::Item
81
+ end
82
+ end
83
+
84
+ end
85
+
@@ -0,0 +1,128 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ class Video
4
+ include Claire::Client::Item
5
+ end
6
+
7
+ describe Claire::Client::Item do
8
+ #@session.should_receive(:post).with("url", "data", "headers")
9
+ #@session = mock("session")
10
+ before do
11
+ Claire::Client.stub(:get).with('videos/id').and_return xml :item
12
+ @video = Video.new(hash_from_xml(:item))
13
+ end
14
+
15
+ describe "its initializer" do
16
+
17
+ describe "its base_url class attribute" do
18
+ it "should default to the class name, pluralized" do
19
+ Video.base_url.should == "videos"
20
+ end
21
+
22
+ it "should accept manual overwrite on the class" do
23
+ Video.base_url = "lists"
24
+ Video.base_url.should == "lists"
25
+ Video.base_url = nil
26
+ Video.base_url.should == "videos"
27
+ end
28
+
29
+ it "if the class is in a module, it should get the class name only" do
30
+ eval %(
31
+ module Testing
32
+ class Video
33
+ include Claire::Client::Item
34
+ end
35
+ end
36
+ )
37
+ Testing::Video.base_url.should == "videos"
38
+ end
39
+ end
40
+
41
+ context "upon receiving a Hash" do
42
+ before :each do
43
+ @video = Video.new(hash_from_xml(:item))
44
+ end
45
+
46
+ it "should set partial do true" do
47
+ @video.should be_partial
48
+ end
49
+
50
+ it "should skip the <rss> container if it is present" do
51
+ @video.title.should be_a_kind_of String
52
+ @video.should_not respond_to :rss
53
+ end
54
+
55
+ it "should skip the <channel> container if its present" do
56
+ video = Video.new(hash_from_xml(:item_with_channel))
57
+ video.title.should be_a_kind_of String
58
+ video.should_not respond_to :channel
59
+ end
60
+
61
+ it "should never set 'items' attributes " do
62
+ %w(item item_with_channel).each do |type|
63
+ video = Video.new(hash_from_xml(type))
64
+ video.should_not respond_to :item
65
+ video.title.should be_a_kind_of String
66
+
67
+ end
68
+ end
69
+
70
+ it "should set the link attribute properly (eg ignoring links to other objects/pages)" do
71
+ video = Video.new hash_from_xml :item_with_channel
72
+ video.link.should be_a_kind_of String
73
+ end
74
+
75
+ it "should set its key/values as properties of the element" do
76
+ %w(title link category keywords description).each do |item|
77
+ @video.send(item).should be_a_kind_of String
78
+ end
79
+ %w(thumbnail content).each{ |item| @video.send(item).should be_a_kind_of Array }
80
+ end
81
+ it "should fail if there is not a link attribute" do
82
+ lambda { Video.new( {:rss => {:item => {:name => 'bla'}}} ) }.should raise_error Claire::Error
83
+ end
84
+ end
85
+
86
+ context "upon receiving a String" do
87
+ before { @video = Video.new 'id' }
88
+ it "should open the given string" do
89
+ lambda { Video.new "" }.should raise_error
90
+ lambda { Video.new "id" }.should_not raise_error
91
+ end
92
+ it "should parse the result using the XML parsing rules" do
93
+ @video.title.should be_a_kind_of String
94
+ end
95
+ it "should set partial to false" do
96
+ @video.should_not be_partial
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+
103
+ describe "its comparison (spaceship) operator" do
104
+ it "should be defined" do
105
+ @video.should respond_to '<=>'
106
+ end
107
+
108
+ it "should compare items by title" do
109
+ @video2 = @video.clone
110
+ (@video <=> @video2).should be 0
111
+ end
112
+
113
+ end
114
+
115
+ context "when an undefined method is called" do
116
+ it "it should raise error if partial is false"
117
+ context "if the item is partial" do
118
+ it "should request the full object from server, and replace itself"
119
+ it "should return the asked attribute"
120
+ end
121
+ end
122
+
123
+ it "should have a list of its children as the children class attribute" do
124
+ Claire::Client::Item.children.include?(Video).should be true
125
+ end
126
+
127
+
128
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+
4
+ describe Claire::Client::List do
5
+
6
+ before do
7
+ Claire::Client.stub(:get).with('categories').and_return(xml(:item_with_channel))
8
+ @list = Claire::Client::List.new('categories')
9
+ end
10
+
11
+ describe "its initializing methods & states" do
12
+ it "should require a String" do
13
+ lambda { Claire::Client::List.new }.should raise_error ArgumentError
14
+ lambda { Claire::Client::List.new('categories') }.should_not raise_error
15
+ end
16
+
17
+ it "should make the response accessible thru the body property" do
18
+ @list.body.should be_a_kind_of String
19
+ end
20
+
21
+
22
+ it "should have a parsed document accessible thru the document property" do
23
+ @list.document.should respond_to '[]'
24
+ end
25
+
26
+ end
27
+
28
+ describe "its each method" do
29
+
30
+ it "should return an array" do
31
+ @list.each.should respond_to :first
32
+ end
33
+
34
+ it "should accept a block, yielding once for each object" do
35
+ i = 0 and arr = []
36
+ @list.each do |item|
37
+ item.should_not be_nil
38
+ i += 1
39
+ end
40
+ i.should == 2
41
+ arr.each_slice(2){ |a| a.first.should_not == a.last }
42
+ end
43
+
44
+ it "should contain a list of Claire::Client:Itens-based objects" do
45
+ @list.each do |item|
46
+ Claire::Client::Item.children.include?(item.class).should be true
47
+ end
48
+ end
49
+
50
+ it "the returned objects should be set as partial" do
51
+ @list.each { |item| item.should be_partial }
52
+ end
53
+ end
54
+
55
+ describe "its size method" do
56
+ it "should return the nun_items field if its avaliable"
57
+ it "should count the items if otherwise"
58
+ end
59
+
60
+
61
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ class Video
4
+ include Claire::Client::Item
5
+ include Claire::Client::Listable
6
+ end
7
+
8
+ describe Claire::Client::Listable do
9
+ before do
10
+ Claire::Client.stub(:get).with('videos').and_return xml(:item_with_channel)
11
+ Claire::Client.stub(:get).with('videos/id').and_return xml(:item)
12
+ end
13
+
14
+ describe "initialization" do
15
+ it "should work only on Claire::Items" do
16
+ lambda { eval("
17
+ class NotAVideo
18
+ include Claire::Client::Listable
19
+ end
20
+ ") }.should raise_error Claire::Error
21
+ lambda { Video.new('id')}.should_not raise_error
22
+ end
23
+ end
24
+
25
+ describe "its all method" do
26
+ it "should be defined" do
27
+ Video.should respond_to :all
28
+ end
29
+
30
+ it "should return a Claire::List on the item's base URL" do
31
+ Video.all.should be_a_kind_of Claire::Client::List
32
+ end
33
+ end
34
+
35
+ it "delegate a count property to its all method" # do
36
+ # Video.count.should == 2
37
+ # end
38
+
39
+ it "should have a list of its children" do
40
+ Claire::Client::Listable.children.include?(Video).should be_true
41
+ end
42
+
43
+ it "should accept a block filter" do
44
+ Video.all { |video| video.title }.should_not be_empty
45
+ Video.all { |video| video.title == ''}.should be_empty
46
+ end
47
+
48
+
49
+ end
@@ -0,0 +1,115 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ describe Claire::Client do
3
+ before { Claire::Client.stub(:get).with('categories').and_return(xml(:list)) }
4
+
5
+ it "should have a hostname property" do
6
+ %w(hostname hostname=).each{ |method| Claire::Client.should respond_to method }
7
+ end
8
+ it "should have an API key" do
9
+ %w(api_key api_key=).each{ |method| Claire::Client.should respond_to method }
10
+ end
11
+ it "should have a format property" do
12
+ %w(format format=).each{ |method| Claire::Client.should respond_to method }
13
+ end
14
+
15
+ context "its config method" do
16
+
17
+ it "should exist"do
18
+ Claire::Client.should respond_to "config"
19
+ end
20
+
21
+ it "should accept an hash of init options" do
22
+ lambda{ Claire::Client.config :api_key => "abc", :hostname => "localhost:3000"}.should_not raise_error
23
+ end
24
+
25
+ it "received options must be set" do
26
+ Claire::Client.config :api_key => "abc", :hostname => "localhost:3000"
27
+ Claire::Client.api_key.should == "abc"
28
+ Claire::Client.hostname.should == "localhost:3000"
29
+ end
30
+
31
+ end
32
+
33
+ it "standard errors should be defined" do
34
+ %w(Claire::Error Claire::ClientError Claire::AuthError Claire::NotFound Claire::TimeoutError).each do |err|
35
+ lambda{ eval("#{err}") }.should_not raise_error
36
+ end
37
+ end
38
+
39
+ describe "its assemble_url method" do
40
+
41
+ it "should exist" do
42
+ Claire::Client.should respond_to "assemble_url"
43
+ end
44
+
45
+ it "should receive a string" do
46
+ lambda{ Claire::Client.assemble_url("url") }.should_not raise_error
47
+ end
48
+
49
+ it "should receive an optional parameter hash" do
50
+ lambda{ Claire::Client.assemble_url("url",{:param => 'value'}) }.should_not raise_error
51
+ end
52
+
53
+ it "should return an URI object" do
54
+ Claire::Client.assemble_url.should be_a_kind_of URI
55
+ end
56
+
57
+ context "about the resulting URI" do
58
+ before do
59
+ @response = Claire::Client.assemble_url("categories")
60
+ end
61
+
62
+ it "should have the given hostname" do
63
+ lambda { Claire::Client.hostname.include?(@response.host) }.call.should be true
64
+ end
65
+
66
+ it "should use the API key" do
67
+ @response.query.include?("api_key=#{Claire::Client.api_key}").should be true
68
+ end
69
+
70
+ it "should have the desired format" do
71
+ lambda { @response.to_s.include?(".#{Claire::Client.format.downcase}") }.call.should be true
72
+ end
73
+
74
+ it "should have the desired path" do
75
+ lambda { @response.path.include? "categories" }.call.should be true
76
+ end
77
+
78
+ it "should have the given query" do
79
+ @response = Claire::Client.assemble_url("categories?stuff=true")
80
+ lambda { @response.query.include?("stuff=true") }.call.should be true
81
+ end
82
+
83
+ context "if a param hash was given" do
84
+ before :each do
85
+ @response = Claire::Client.assemble_url("categories", :page => 2, :limit => 10)
86
+ end
87
+
88
+ it "assembles the params in the URI" do
89
+ %w(limit=10 page=2).each do |i|
90
+ @response.query.include?(i).should be true
91
+ end
92
+ end
93
+ end
94
+
95
+ end
96
+
97
+ end
98
+
99
+ describe "its get method" do
100
+ it "should exist" do
101
+ Claire::Client.should respond_to "get"
102
+ end
103
+
104
+ it "should receive a String" do
105
+ lambda { Claire::Client.get "categories" }.should_not raise_error
106
+ end
107
+
108
+ it "should receive aditional params as an hash"
109
+
110
+ it "should make the request and return an body" do
111
+ lambda { Claire::Client.get "categories" }.call.should_not be_empty
112
+ end
113
+
114
+ end
115
+ end
@@ -0,0 +1,23 @@
1
+ <?xml version="1.0" encoding="utf-8" standalone="yes"?>
2
+
3
+ <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss" xmlns:atom="http://www.w3.org/2005/Atom">
4
+ <item>
5
+ <title>new title</title>
6
+ <link>http://localhost:3000/videos/4bbced401637fd736a000004</link>
7
+ <media:content type="video/flv" url="/videos/4bbced401637fd736a000004/flv-h263.flv" duration=""/>
8
+ <media:content type="video/flv" url="/videos/4bbced401637fd736a000004/flv-h264.flv" duration=""/>
9
+ <media:thumbnail width="215" url="/videos/4bbced401637fd736a000004/thumb_thumb_medium.jpg" heigth="120"/>
10
+ <media:thumbnail width="50" url="/videos/4bbced401637fd736a000004/thumb_thumb_square.jpg" heigth="50"/>
11
+ <media:thumbnail width="500" url="/videos/4bbced401637fd736a000004/thumb_thumb_large.jpg" heigth="281"/>
12
+ <media:category label="test"/>
13
+ <media:keywords>many, keywords, here</media:keywords>
14
+ <media:description>asa</media:description>
15
+ <media:community>
16
+ <media:starRating average="0.0"/>
17
+ <media:statistics views="0"/>
18
+ </media:community>
19
+ <related>
20
+ <item title="new title" link="http://localhost:3000/videos/4bbced401637fd736a000004" thumbnail="/videos/4bbced401637fd736a000004/thumb_thumb_square.jpg"/>
21
+ </related>
22
+ </item>
23
+ </rss>
@@ -0,0 +1,19 @@
1
+ <item>
2
+ <title>new title</title>
3
+ <link>http://localhost:3000/videos/4bbced401637fd736a000004</link>
4
+ <media:content type="video/flv" url="/videos/4bbced401637fd736a000004/flv-h263.flv" duration=""/>
5
+ <media:content type="video/flv" url="/videos/4bbced401637fd736a000004/flv-h264.flv" duration=""/>
6
+ <media:thumbnail width="215" url="/videos/4bbced401637fd736a000004/thumb_thumb_medium.jpg" heigth="120"/>
7
+ <media:thumbnail width="50" url="/videos/4bbced401637fd736a000004/thumb_thumb_square.jpg" heigth="50"/>
8
+ <media:thumbnail width="500" url="/videos/4bbced401637fd736a000004/thumb_thumb_large.jpg" heigth="281"/>
9
+ <media:category label="test"/>
10
+ <media:keywords></media:keywords>
11
+ <media:description>asa</media:description>
12
+ <media:community>
13
+ <media:starRating average="0.0"/>
14
+ <media:statistics views="0"/>
15
+ </media:community>
16
+ <related>
17
+ <item title="new title" link="http://localhost:3000/videos/4bbced401637fd736a000004" thumbnail="/videos/4bbced401637fd736a000004/thumb_thumb_square.jpg"/>
18
+ </related>
19
+ </item>
@@ -0,0 +1,53 @@
1
+ <?xml version="1.0" encoding="utf-8" standalone="yes"?>
2
+
3
+ <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss" xmlns:atom="http://www.w3.org/2005/Atom">
4
+
5
+ <channel>
6
+ <title>test</title>
7
+ <description></description>
8
+ <header>/public/categories/4bb48ef61637fd69c1000005/original.jpg</header>
9
+ <num_items>1</num_items>
10
+ <link>http://localhost:3000/categories/4bb48ef61637fd69c1000005</link>
11
+ <item>
12
+ <title>new title</title>
13
+ <link>http://localhost:3000/videos/4bbced401637fd736a000004</link>
14
+ <media:content type="video/flv" duration="" url="/videos/4bbced401637fd736a000004/flv-h263.flv"/>
15
+ <media:content type="video/flv" duration="" url="/videos/4bbced401637fd736a000004/flv-h264.flv"/>
16
+ <media:thumbnail heigth="50" width="50" url="/videos/4bbced401637fd736a000004/thumb_thumb_square.jpg"/>
17
+ <media:thumbnail heigth="120" width="215" url="/videos/4bbced401637fd736a000004/thumb_thumb_medium.jpg"/>
18
+ <media:thumbnail heigth="281" width="500" url="/videos/4bbced401637fd736a000004/thumb_thumb_large.jpg"/>
19
+ <media:category label="testting"/>
20
+ <media:keywords></media:keywords>
21
+ <media:description>asa</media:description>
22
+ <media:community>
23
+ <media:starRating average="0.0"/>
24
+ <media:statistics views="0"/>
25
+ </media:community>
26
+ <related>
27
+ <item thumbnail="/videos/4bbced401637fd736a000004/thumb_thumb_square.jpg" title="new title" link="http://localhost:3000/videos/4bbced401637fd736a000004"/>
28
+ </related>
29
+ </item>
30
+ <item>
31
+ <title>new title 2</title>
32
+ <link>http://localhost:3000/videos/4bbced401637fd736a000004</link>
33
+ <media:content type="video/flv" duration="" url="/videos/4bbced401637fd736a000004/flv-h263.flv"/>
34
+ <media:content type="video/flv" duration="" url="/videos/4bbced401637fd736a000004/flv-h264.flv"/>
35
+ <media:thumbnail heigth="50" width="50" url="/videos/4bbced401637fd736a000004/thumb_thumb_square.jpg"/>
36
+ <media:thumbnail heigth="120" width="215" url="/videos/4bbced401637fd736a000004/thumb_thumb_medium.jpg"/>
37
+ <media:thumbnail heigth="281" width="500" url="/videos/4bbced401637fd736a000004/thumb_thumb_large.jpg"/>
38
+ <media:category label="testting"/>
39
+ <media:keywords></media:keywords>
40
+ <media:description>asa</media:description>
41
+ <media:community>
42
+ <media:starRating average="0.0"/>
43
+ <media:statistics views="0"/>
44
+ </media:community>
45
+ <related>
46
+ <item thumbnail="/videos/4bbced401637fd736a000004/thumb_thumb_square.jpg" title="new title" link="http://localhost:3000/videos/4bbced401637fd736a000004"/>
47
+ </related>
48
+ </item>
49
+ <atom:link rel="next" href="http://localhost:3000/categories/4bb48ef61637fd69c1000005.xml?page=2"/>
50
+ </channel>
51
+
52
+
53
+ </rss>
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="utf-8" standalone="yes"?>
2
+
3
+ <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss" xmlns:atom="http://www.w3.org/2005/Atom">
4
+
5
+ <item>
6
+ <title>test</title>
7
+ <link>http://localhost:3000/categories/4bb48ef61637fd69c1000005</link>
8
+ <num_videos>1</num_videos>
9
+ </item>
10
+ <item>
11
+ <title>none</title>
12
+ <link>http://localhost:3000/categories/4bb881681637fd0513000001</link>
13
+ <description>some</description>
14
+ <num_videos>0</num_videos>
15
+ </item>
16
+ <item>
17
+ <title>name</title>
18
+ <link>http://localhost:3000/categories/4bb882251637fd0513000002</link>
19
+ <description>namae</description>
20
+ <num_videos>0</num_videos>
21
+ </item>
22
+
23
+
24
+ </rss>
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ require 'claire_client'
5
+ require 'spec'
6
+ require 'spec/autorun'
7
+
8
+ $root = File.join(File.dirname(__FILE__), '..')
9
+
10
+ Spec::Runner.configure do |config|
11
+
12
+ end
13
+
14
+ def xml arg
15
+ File.open("#{$root}/spec/fixtures/#{arg}.xml", 'r').read
16
+ end
17
+
18
+ def hash_from_xml arg
19
+ Hashie::Mash.from_xml(xml(arg))
20
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: claire_client
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Matheus E. Muller
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-28 00:00:00 -03:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activesupport
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 3
30
+ - 5
31
+ version: 2.3.5
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: hashie
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 2
44
+ - 0
45
+ version: 0.2.0
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 1
57
+ - 2
58
+ - 9
59
+ version: 1.2.9
60
+ type: :development
61
+ version_requirements: *id003
62
+ description: "This gem is a Ruby client for the St. Claire Media Server, which power power Can\xC3\xA7\xC3\xA3o Nova's reach of video and streamming web services."
63
+ email: hello@memuller.com
64
+ executables: []
65
+
66
+ extensions: []
67
+
68
+ extra_rdoc_files:
69
+ - LICENSE
70
+ - README.rdoc
71
+ files:
72
+ - .document
73
+ - .gitignore
74
+ - LICENSE
75
+ - README.rdoc
76
+ - Rakefile
77
+ - VERSION
78
+ - claire_client.gemspec
79
+ - lib/claire_client.rb
80
+ - lib/claire_client/category.rb
81
+ - lib/claire_client/item.rb
82
+ - lib/claire_client/list.rb
83
+ - lib/claire_client/listable.rb
84
+ - lib/claire_client/stream.rb
85
+ - lib/claire_client/video.rb
86
+ - spec/claire_client/item_spec.rb
87
+ - spec/claire_client/list_spec.rb
88
+ - spec/claire_client/listable_spec.rb
89
+ - spec/claire_client_spec.rb
90
+ - spec/fixtures/item.xml
91
+ - spec/fixtures/item_direct.xml
92
+ - spec/fixtures/item_with_channel.xml
93
+ - spec/fixtures/list.xml
94
+ - spec/spec.opts
95
+ - spec/spec_helper.rb
96
+ has_rdoc: true
97
+ homepage: http://github.com/memuller/claire.client
98
+ licenses: []
99
+
100
+ post_install_message:
101
+ rdoc_options:
102
+ - --charset=UTF-8
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ requirements: []
120
+
121
+ rubyforge_project:
122
+ rubygems_version: 1.3.6
123
+ signing_key:
124
+ specification_version: 3
125
+ summary: A ruby client for St. Claire.
126
+ test_files:
127
+ - spec/claire_client/item_spec.rb
128
+ - spec/claire_client/list_spec.rb
129
+ - spec/claire_client/listable_spec.rb
130
+ - spec/claire_client_spec.rb
131
+ - spec/spec_helper.rb