panda 0.6.4 → 1.0.0

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.
@@ -0,0 +1,7 @@
1
+ module Panda
2
+ class ProfileScope < Scope
3
+ def initialize(parent)
4
+ super(parent, Profile)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ module Panda
2
+ class Proxy
3
+ include Panda::Router::ClassMethods
4
+ include Panda::Finders::FindMany
5
+ include Panda::Finders::FindOne
6
+ include Panda::Builders::CreateBuilder
7
+ include Panda::CloudConnection
8
+
9
+ attr_accessor :parent, :klass
10
+
11
+ def initialize(parent, klass)
12
+ @parent = parent
13
+ @klass = klass
14
+ end
15
+
16
+ def cloud
17
+ @parent.is_a?(Cloud) ? @parent : @parent.cloud
18
+ end
19
+
20
+ def end_class_name
21
+ klass.end_class_name
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,87 @@
1
+ require 'forwardable'
2
+
3
+ module Panda
4
+ class Scope < Proxy
5
+ extend Forwardable
6
+
7
+ def respond_to?(method)
8
+ scoped_methods = [].methods.map{|i| i.to_sym} - non_delegate_methods + [:reload, :non_delegate_methods]
9
+ !(scoped_methods).include?(method.to_sym)
10
+ end
11
+
12
+ def non_delegate_methods
13
+ [:nil?, :send, :object_id, :respond_to?, :class, :find, :find_by, :create, :create!, :all, :cloud, :connection]
14
+ end
15
+
16
+ def initialize(parent, klass)
17
+ super
18
+
19
+ initialize_scope_attributes
20
+ initialize_scopes
21
+ end
22
+
23
+ # Overide the function to set the cloud_id as the same as the scope
24
+ def find_by_path(url, map={})
25
+ object = find_object_by_path(url, map)
26
+
27
+ if object.is_a?(Array)
28
+ object.map{|o| klass.new(o.merge("cloud_id" => cloud.id))}
29
+ elsif object["id"]
30
+ klass.new(object.merge("cloud_id" => cloud.id))
31
+ else
32
+ Error.new(object).raise!
33
+ end
34
+ end
35
+
36
+ def create(attributes)
37
+ scoped_attrs = attributes.merge(@scoped_attributes)
38
+ super(scoped_attrs)
39
+ end
40
+
41
+ def all(attributes={})
42
+ @scoped_attributes.merge!(attributes)
43
+ trigger_request
44
+ end
45
+
46
+ def reload
47
+ @found = trigger_request
48
+ end
49
+
50
+ private
51
+
52
+ def initialize_scope_attributes
53
+ @scoped_attributes={}
54
+ if @parent.is_a?(Panda::Resource)
55
+ @scoped_attributes[parent_relation_name.to_sym] = @parent.id
56
+ end
57
+ end
58
+
59
+ def proxy_found
60
+ @found ||= trigger_request
61
+ end
62
+
63
+ def initialize_scopes
64
+ [].methods.each do |m|
65
+ unless m.to_s =~ /^__/ || non_delegate_methods.include?(m.to_sym)
66
+ self.class.class_eval do
67
+ def_delegators :proxy_found, m.to_sym
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ def trigger_request
74
+ if @parent.is_a?(Resource)
75
+ path = build_hash_many_path(many_path, parent_relation_name)
76
+ else
77
+ path = many_path
78
+ end
79
+
80
+ find_by_path(path, @scoped_attributes)
81
+ end
82
+
83
+ def parent_relation_name
84
+ "#{@parent.class.end_class_name.downcase}_id"
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,28 @@
1
+ module Panda
2
+ class VideoScope < Scope
3
+
4
+ def initialize(parent)
5
+ super(parent, Video)
6
+ end
7
+
8
+ def non_delegate_methods
9
+ super + [:status, :page, :per_page]
10
+ end
11
+
12
+ def page(this_page)
13
+ @scoped_attributes[:page] = this_page
14
+ self
15
+ end
16
+
17
+ def per_page(this_per_page)
18
+ @scoped_attributes[:per_page] = this_per_page
19
+ self
20
+ end
21
+
22
+ def status(this_status)
23
+ @scoped_attributes[:status] = this_status
24
+ self
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,49 @@
1
+ module Panda
2
+ class Cloud < Base
3
+ include Panda::Updatable
4
+ attr_reader :connection
5
+
6
+ def initialize(attributes={})
7
+ super(attributes)
8
+ connection_params = Panda.connection.to_hash.merge!(:cloud_id => id, :format => :hash)
9
+ @connection = Connection.new(connection_params)
10
+ Panda.clouds[id] = self
11
+ end
12
+
13
+ class << self
14
+ include Panda::Finders::FindOne
15
+
16
+ def find(id, options=nil)
17
+ super(id)
18
+ end
19
+
20
+ def connection
21
+ Panda.connection
22
+ end
23
+ end
24
+
25
+ def videos
26
+ VideoScope.new(self)
27
+ end
28
+
29
+ def encodings
30
+ EncodingScope.new(self)
31
+ end
32
+
33
+ def profiles
34
+ ProfileScope.new(self)
35
+ end
36
+
37
+ def method_missing(method_symbol, *arguments)
38
+ lazy_load
39
+ super
40
+ end
41
+
42
+ private
43
+
44
+ def lazy_load
45
+ @found ||= reload
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+ module Panda
2
+ class Encoding < Resource
3
+ include ShortStatus
4
+
5
+ belongs_to :video
6
+ has_one :profile
7
+
8
+ def url
9
+ "http://s3.amazonaws.com/#{cloud.s3_videos_bucket}/#{id}#{extname}"
10
+ end
11
+
12
+ def screenshots
13
+ @screenshots ||=
14
+ if status == 'success'
15
+ (1..7).map do |i|
16
+ "http://s3.amazonaws.com/#{cloud.s3_videos_bucket}/#{id}_#{i}.jpg"
17
+ end
18
+ else
19
+ []
20
+ end
21
+ end
22
+
23
+ class << self
24
+ def first
25
+ EncodingScope.new(self).per_page(1).first
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ module Panda
2
+ class Profile < Resource
3
+ include Panda::Updatable
4
+
5
+ has_many :encodings
6
+
7
+ def preset?
8
+ !preset_name
9
+ end
10
+
11
+ # override attributes command and preset_name
12
+ # to ovoid <method undefined> when profile is a preset or not
13
+ def command
14
+ @attributes['command']
15
+ end
16
+
17
+ def preset_name
18
+ @attributes['preset_name']
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,52 @@
1
+ module Panda
2
+ class Resource < Base
3
+ include Panda::Builders
4
+ include Panda::Associations
5
+ include Panda::CloudConnection
6
+
7
+ def initialize(attributes={})
8
+ super(attributes)
9
+ @attributes['cloud_id'] ||= Panda.cloud.id
10
+ end
11
+
12
+ class << self
13
+ include Panda::Finders::FindMany
14
+ include Panda::CloudConnection
15
+
16
+ def cloud
17
+ Panda.cloud
18
+ end
19
+
20
+ # delegate to the scope if the method exists
21
+ def method_missing(method_symbol, *args, &block)
22
+ scope = Panda::const_get("#{end_class_name}Scope").new(self)
23
+ if scope.respond_to?(method_symbol)
24
+ scope.send(method_symbol, *args, &block)
25
+ else
26
+ super
27
+ end
28
+ end
29
+
30
+ end
31
+
32
+ def cloud
33
+ Panda.clouds[cloud_id]
34
+ end
35
+
36
+ def create
37
+ raise "Can't create attribute. Already have an id=#{attributes['id']}" if attributes['id']
38
+ response = connection.post(object_url_map(self.class.many_path), attributes)
39
+ load_response(response) ? (@changed_attributes = {}; true) : false
40
+ end
41
+
42
+ def create!
43
+ create || errors.last.raise!
44
+ end
45
+
46
+ def reload
47
+ perform_reload("cloud_id" => cloud_id)
48
+ reset_associations
49
+ self
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,13 @@
1
+ module Panda
2
+ class Video < Resource
3
+ include ShortStatus
4
+ has_many :encodings
5
+
6
+ class << self
7
+ def first
8
+ VideoScope.new(self).per_page(1).first
9
+ end
10
+ end
11
+
12
+ end
13
+ end
data/panda.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{panda}
8
- s.version = "0.6.4"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["New Bamboo"]
12
- s.date = %q{2010-07-01}
12
+ s.date = %q{2010-08-05}
13
13
  s.description = %q{Panda Client}
14
14
  s.email = %q{info@pandastream.com}
15
15
  s.extra_rdoc_files = [
@@ -18,18 +18,43 @@ Gem::Specification.new do |s|
18
18
  ]
19
19
  s.files = [
20
20
  ".gitignore",
21
+ "Gemfile",
21
22
  "LICENSE",
22
23
  "README.md",
23
24
  "Rakefile",
24
25
  "VERSION",
25
26
  "lib/panda.rb",
26
27
  "lib/panda/api_authentication.rb",
28
+ "lib/panda/base.rb",
29
+ "lib/panda/connection.rb",
30
+ "lib/panda/error.rb",
31
+ "lib/panda/modules/associations.rb",
32
+ "lib/panda/modules/builders.rb",
33
+ "lib/panda/modules/cloud_connection.rb",
34
+ "lib/panda/modules/finders.rb",
35
+ "lib/panda/modules/router.rb",
36
+ "lib/panda/modules/short_status.rb",
37
+ "lib/panda/modules/updatable.rb",
27
38
  "lib/panda/panda.rb",
28
- "log/debug.log",
39
+ "lib/panda/proxies/encoding_scope.rb",
40
+ "lib/panda/proxies/profile_scope.rb",
41
+ "lib/panda/proxies/proxy.rb",
42
+ "lib/panda/proxies/scope.rb",
43
+ "lib/panda/proxies/video_scope.rb",
44
+ "lib/panda/resources/cloud.rb",
45
+ "lib/panda/resources/encoding.rb",
46
+ "lib/panda/resources/profile.rb",
47
+ "lib/panda/resources/resource.rb",
48
+ "lib/panda/resources/video.rb",
29
49
  "panda.gemspec",
50
+ "spec/cloud_spec.rb",
51
+ "spec/encoding_spec.rb",
52
+ "spec/heroku_spec.rb",
30
53
  "spec/panda_spec.rb",
54
+ "spec/profile_spec.rb",
31
55
  "spec/spec.opts",
32
- "spec/spec_helper.rb"
56
+ "spec/spec_helper.rb",
57
+ "spec/video_spec.rb"
33
58
  ]
34
59
  s.homepage = %q{http://github.com/newbamboo/panda_gem}
35
60
  s.rdoc_options = ["--charset=UTF-8"]
@@ -37,8 +62,13 @@ Gem::Specification.new do |s|
37
62
  s.rubygems_version = %q{1.3.5}
38
63
  s.summary = %q{Panda Client}
39
64
  s.test_files = [
40
- "spec/panda_spec.rb",
41
- "spec/spec_helper.rb"
65
+ "spec/cloud_spec.rb",
66
+ "spec/encoding_spec.rb",
67
+ "spec/heroku_spec.rb",
68
+ "spec/panda_spec.rb",
69
+ "spec/profile_spec.rb",
70
+ "spec/spec_helper.rb",
71
+ "spec/video_spec.rb"
42
72
  ]
43
73
 
44
74
  if s.respond_to? :specification_version then
@@ -46,21 +76,15 @@ Gem::Specification.new do |s|
46
76
  s.specification_version = 3
47
77
 
48
78
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
- s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
50
- s.add_development_dependency(%q<webmock>, [">= 0"])
51
79
  s.add_runtime_dependency(%q<ruby-hmac>, [">= 0.3.2"])
52
80
  s.add_runtime_dependency(%q<rest-client>, [">= 1.4"])
53
81
  s.add_runtime_dependency(%q<json>, [">= 1.2"])
54
82
  else
55
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
56
- s.add_dependency(%q<webmock>, [">= 0"])
57
83
  s.add_dependency(%q<ruby-hmac>, [">= 0.3.2"])
58
84
  s.add_dependency(%q<rest-client>, [">= 1.4"])
59
85
  s.add_dependency(%q<json>, [">= 1.2"])
60
86
  end
61
87
  else
62
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
63
- s.add_dependency(%q<webmock>, [">= 0"])
64
88
  s.add_dependency(%q<ruby-hmac>, [">= 0.3.2"])
65
89
  s.add_dependency(%q<rest-client>, [">= 1.4"])
66
90
  s.add_dependency(%q<json>, [">= 1.2"])
@@ -0,0 +1,80 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Panda::Video do
4
+ describe "Using configure bloc" do
5
+ before(:each) do
6
+ Panda.configure do |c|
7
+ c.access_key = "my_access_key"
8
+ c.secret_key = "my_secret_key"
9
+ c.api_host = "api.example.com"
10
+ c.cloud_id = 'my_cloud_id'
11
+ c.api_port = 85
12
+ end
13
+ end
14
+
15
+ describe "using a cloud" do
16
+ before(:each) do
17
+ cloud_json = "{\"s3_videos_bucket\":\"my_bucket1\",\"id\":\"cloud1\"}"
18
+ stub_http_request(:get, /api.example.com:85\/v2\/clouds\/cloud1.json/).
19
+ to_return(:body => cloud_json)
20
+ @cloud = Panda::Cloud.find "cloud1"
21
+ end
22
+
23
+ it "should find all videos" do
24
+ videos_json = "[{\"source_url\":\"my_source_url\",\"id\":\"123\"}]"
25
+ stub_http_request(:get, /api.example.com:85\/v2\/videos.json/).
26
+ with{|r| r.uri.query =~ /cloud_id=cloud1/}.
27
+ to_return(:body => videos_json)
28
+
29
+ @cloud.videos.first.id.should == "123"
30
+ end
31
+
32
+ it "should find all videos with params" do
33
+ videos_json = "[{\"source_url\":\"my_source_url\",\"id\":\"134\"}]"
34
+ stub_http_request(:get, /api.example.com:85\/v2\/videos.json/).
35
+ with{|r| r.uri.query =~ /status=success/ && r.uri.query =~ /cloud_id=cloud1/}.
36
+ to_return(:body => videos_json)
37
+ videos = @cloud.videos.all(:status => "success")
38
+ videos.first.id.should == "134"
39
+ end
40
+
41
+ it "should find a video by id" do
42
+ video_json = "{\"source_url\":\"my_source_url\",\"id\":\"123\"}"
43
+ stub_http_request(:get, /api.example.com:85\/v2\/videos\/123.json/).
44
+ with{|r| r.uri.query =~ /cloud_id=cloud1/}.
45
+ to_return(:body => video_json)
46
+
47
+ video = @cloud.videos.find "123"
48
+ video.id.should == "123"
49
+ end
50
+
51
+ it "should find all video with params" do
52
+ videos_json = "{\"source_url\":\"my_source_url\",\"id\":\"123\"}"
53
+ stub_http_request(:post, /api.example.com:85\/v2\/videos.json/).
54
+ with{|r| r.body =~ /cloud_id=cloud1/}.
55
+ to_return(:body => videos_json)
56
+ @cloud.videos.create(:source_url => "my_source_url")
57
+ end
58
+ end
59
+
60
+ describe "Using options on find" do
61
+
62
+ it "should find a cloud" do
63
+ cloud_json = "{\"s3_videos_bucket\":\"my_bucket\",\"id\":\"my_cloud_id\"}"
64
+ stub_http_request(:get, /http:\/\/api.example.com:85\/v2\/clouds\/my_cloud_id.json/).
65
+ to_return(:body => cloud_json)
66
+
67
+ @cloud = Panda::Cloud.find "my_cloud_id", {
68
+ "access_key" => "my_access_key",
69
+ "secret_key" => "my_secret_key",
70
+ "api_host" => "api.example.com",
71
+ "api_port" => 85,
72
+ "format" => "json"
73
+ }
74
+
75
+ @cloud.s3_videos_bucket.should == "my_bucket"
76
+ end
77
+ end
78
+
79
+ end
80
+ end