panda 0.6.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -0
- data/README.md +388 -21
- data/Rakefile +4 -17
- data/VERSION +1 -1
- data/lib/panda.rb +21 -1
- data/lib/panda/api_authentication.rb +4 -4
- data/lib/panda/base.rb +102 -0
- data/lib/panda/connection.rb +189 -0
- data/lib/panda/error.rb +29 -0
- data/lib/panda/modules/associations.rb +55 -0
- data/lib/panda/modules/builders.rb +34 -0
- data/lib/panda/modules/cloud_connection.rb +7 -0
- data/lib/panda/modules/finders.rb +62 -0
- data/lib/panda/modules/router.rb +55 -0
- data/lib/panda/modules/short_status.rb +13 -0
- data/lib/panda/modules/updatable.rb +27 -0
- data/lib/panda/panda.rb +21 -170
- data/lib/panda/proxies/encoding_scope.rb +48 -0
- data/lib/panda/proxies/profile_scope.rb +7 -0
- data/lib/panda/proxies/proxy.rb +25 -0
- data/lib/panda/proxies/scope.rb +87 -0
- data/lib/panda/proxies/video_scope.rb +28 -0
- data/lib/panda/resources/cloud.rb +49 -0
- data/lib/panda/resources/encoding.rb +30 -0
- data/lib/panda/resources/profile.rb +22 -0
- data/lib/panda/resources/resource.rb +52 -0
- data/lib/panda/resources/video.rb +13 -0
- data/panda.gemspec +36 -12
- data/spec/cloud_spec.rb +80 -0
- data/spec/encoding_spec.rb +232 -0
- data/spec/heroku_spec.rb +22 -0
- data/spec/panda_spec.rb +17 -4
- data/spec/profile_spec.rb +117 -0
- data/spec/spec_helper.rb +8 -1
- data/spec/video_spec.rb +305 -0
- metadata +33 -23
- data/log/debug.log +0 -0
@@ -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
|
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.
|
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-
|
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
|
-
"
|
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/
|
41
|
-
"spec/
|
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"])
|
data/spec/cloud_spec.rb
ADDED
@@ -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
|