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,34 @@
1
+ module Panda
2
+ module Builders
3
+
4
+ def self.included(base)
5
+ base.extend(CreateBuilder)
6
+ base.extend(DeleteBuilder)
7
+ end
8
+
9
+ module CreateBuilder
10
+
11
+ def create(attributes)
12
+ if attr_id=(attributes[:id] || attributes['id'])
13
+ raise "Can't create attribute. Already have an id=#{attr_id}"
14
+ end
15
+
16
+ response = connection.post(full_object_url(many_path), attributes)
17
+ Panda::const_get("#{end_class_name}").new(response)
18
+ end
19
+
20
+ def create!(attributes)
21
+ create(attributes) || raise(self.error.first.to_s)
22
+ end
23
+
24
+ end
25
+
26
+ module DeleteBuilder
27
+ def delete(id)
28
+ response = connection.delete(full_object_url(object_url(one_path,{:id =>id})))
29
+ response['deleted'] == 'ok'
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,7 @@
1
+ module Panda
2
+ module CloudConnection
3
+ def connection
4
+ cloud.connection
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,62 @@
1
+ module Panda
2
+ module Finders
3
+
4
+ module FindOne
5
+
6
+ def find(id)
7
+ find_by_path(one_path, {:id => id})
8
+ end
9
+
10
+ def find_object_by_path(url, map={})
11
+ full_url = object_url(url, map)
12
+ params = element_params(url, map)
13
+ self.connection.get(full_url, params)
14
+ end
15
+
16
+ def find_by_path(url, map={})
17
+ object = find_object_by_path(url, map)
18
+ kclass = Panda::const_get("#{end_class_name}")
19
+
20
+ if object.is_a?(Array)
21
+ object.map{|o| kclass.new(o)}
22
+ elsif object["id"]
23
+ kclass.new(object)
24
+ else
25
+ Error.new(object).raise!
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ module FindMany
32
+
33
+ def find_by(map)
34
+ all(map).first
35
+ end
36
+
37
+ def all(map={})
38
+ find_by_path(many_path, map)
39
+ end
40
+
41
+ private
42
+
43
+ def find_all_by_has_many(relation_name, relation_value)
44
+ map = {}
45
+ map[relation_name.to_sym] = relation_value
46
+ has_many_path = build_hash_many_path(many_path, relation_name)
47
+ find_by_path(has_many_path, map)
48
+ end
49
+
50
+ def method_missing(method_symbol, *arguments)
51
+ method_name = method_symbol.to_s
52
+ if method_name =~ /^find_all_by_([_a-zA-Z]\w*)$/
53
+ find_all_by_has_many($1, arguments.pop)
54
+ else
55
+ super
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,55 @@
1
+ module Panda
2
+ module Router
3
+ DEFAULT_FORMAT = "json"
4
+ VAR_PATTERN = /:\w+/
5
+
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ def resource_path
13
+ @url || "/#{end_class_name.downcase}s"
14
+ end
15
+
16
+ def match(url)
17
+ @url = url
18
+ end
19
+
20
+ def many_path
21
+ resource_path
22
+ end
23
+
24
+ def one_path
25
+ resource_path + "/:id"
26
+ end
27
+
28
+ def build_hash_many_path(end_path, relation_attr)
29
+ relation_class_name = relation_attr[0..relation_attr.rindex("_id")-1].capitalize
30
+ prefix_path = Panda::const_get(relation_class_name).resource_path + "/:" + relation_attr
31
+ prefix_path + end_path
32
+ end
33
+
34
+ def object_url(url, map)
35
+ full_object_url(url.clone.gsub(VAR_PATTERN){|key| map[key[1..-1].to_sym] || map[key[1..-1].to_s]})
36
+ end
37
+
38
+ def element_params(url, map)
39
+ params = map.clone
40
+ url.clone.scan(VAR_PATTERN).map{|key| params.reject!{|k,v| k==key[1..-1] } }
41
+ params
42
+ end
43
+
44
+ def full_object_url(url)
45
+ url + ".#{DEFAULT_FORMAT}"
46
+ end
47
+
48
+ end
49
+
50
+ def object_url_map(url)
51
+ self.class.full_object_url(url.clone.gsub(VAR_PATTERN) {|key| send(key[1..-1].to_sym)})
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,13 @@
1
+ module ShortStatus
2
+ def success?
3
+ @attributes['status'] == 'success'
4
+ end
5
+
6
+ def processing?
7
+ @attributes['status'] == 'processing'
8
+ end
9
+
10
+ def fail?
11
+ @attributes['status'] == 'fail'
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ module Panda
2
+ module Updatable
3
+
4
+ def save
5
+ new? ? create : update
6
+ end
7
+
8
+ def save!
9
+ save || raise("Resource invalid")
10
+ end
11
+
12
+ def update_attribute(name, value)
13
+ self.send("#{name}=".to_sym, value)
14
+ self.save
15
+ end
16
+
17
+ def update_attributes(attributes)
18
+ load(attributes) && save
19
+ end
20
+
21
+ def update
22
+ response = connection.put(object_url_map(self.class.one_path), @changed_attributes)
23
+ load_response(response) ? (@changed_attributes = {}; true) : false
24
+ end
25
+
26
+ end
27
+ end
data/lib/panda/panda.rb CHANGED
@@ -1,187 +1,38 @@
1
1
  require 'restclient'
2
+ require 'forwardable'
2
3
  require 'json' unless defined?(ActiveSupport::JSON)
3
4
 
4
- class Panda
5
-
6
- def self.connect!(auth_params, options={})
7
- @@connection = Connection.new(auth_params, options)
8
- end
9
-
10
- def self.get(request_uri, params={})
11
- connection.get(request_uri, params)
12
- end
5
+ module Panda
6
+ class << self
7
+ extend Forwardable
13
8
 
14
- def self.post(request_uri, params={})
15
- connection.post(request_uri, params)
16
- end
9
+ attr_reader :cloud, :clouds
10
+ attr_reader :connection
17
11
 
18
- def self.put(request_uri, params={})
19
- connection.put(request_uri, params)
20
- end
12
+ def_delegators :connection, :get, :post, :put, :delete, :api_url, :setup_bucket, :signed_params
21
13
 
22
- def self.delete(request_uri, params={})
23
- connection.delete(request_uri, params)
24
- end
25
-
26
- def self.setup_bucket(params={})
27
- connection.setup_bucket(params)
28
- end
29
-
30
- def self.authentication_params(*params)
31
- raise "Method deprecated. Please use signed_params instead."
32
- end
33
-
34
- def self.signed_params(verb, request_uri, params = {}, timestamp_str = nil)
35
- connection.signed_params(verb, request_uri, params, timestamp_str)
36
- end
37
-
38
- private
39
-
40
- def self.connection
41
- if defined?(@@connection)
42
- @@connection
43
- else
44
- raise "Not connected. Please connect! first."
45
- end
46
- end
47
-
48
- class Connection
49
- attr_reader :api_host, :api_port, :access_key, :secret_key, :api_version, :format
50
-
51
- DEFAULT_API_PORT=80
52
- DEFAULT_API_HOST="api.pandastream.com"
53
-
54
- def initialize(auth_params, options={})
55
- @api_version = 2
56
- @format = "hash"
57
-
58
- if auth_params.class == String
59
- self.format = options[:format] || options["format"]
60
- init_from_url(auth_params)
61
- else
62
- self.format = auth_params[:format] || auth_params["format"]
63
- init_from_hash(auth_params)
64
- end
65
-
66
- @connection = RestClient::Resource.new(api_url)
67
- end
68
-
69
- def format=(ret_format)
70
- if ret_format
71
- raise "Format unknown" if !["json", "hash"].include?(ret_format.to_s)
72
- @format = ret_format.to_s
73
- end
74
- end
75
-
76
- def get(request_uri, params={})
77
- rescue_restclient_exception do
78
- query = signed_query("GET", request_uri, params)
79
- body_of @connection[request_uri + '?' + query].get
80
- end
81
- end
82
-
83
- def post(request_uri, params={})
84
- rescue_restclient_exception do
85
- body_of @connection[request_uri].post(signed_params("POST", request_uri, params))
86
- end
87
- end
14
+ def configure(auth_params=nil)
15
+ @clouds = {}
88
16
 
89
- def put(request_uri, params={})
90
- rescue_restclient_exception do
91
- body_of @connection[request_uri].put(signed_params("PUT", request_uri, params))
92
- end
93
- end
94
-
95
- def delete(request_uri, params={})
96
- rescue_restclient_exception do
97
- query = signed_query("DELETE", request_uri, params)
98
- body_of @connection[request_uri + '?' + query].delete
17
+ if auth_params
18
+ connect!(auth_params)
19
+ else
20
+ yield @connection = Connection.new
99
21
  end
100
- end
101
22
 
102
- def signed_query(*args)
103
- ApiAuthentication.hash_to_query(signed_params(*args))
23
+ @connection.raise_error=true
24
+ @connection.format = :hash
25
+ @cloud = Cloud::new(:id => @connection.cloud_id)
104
26
  end
105
-
106
- def signed_params(verb, request_uri, params = {}, timestamp_str = nil)
107
- auth_params = stringify_keys(params)
108
- auth_params['cloud_id'] = @cloud_id
109
- auth_params['access_key'] = @access_key
110
- auth_params['timestamp'] = timestamp_str || Time.now.iso8601(6)
111
27
 
112
- params_to_sign = auth_params.reject{|k,v| ['file'].include?(k.to_s)}
113
- auth_params['signature'] = ApiAuthentication.generate_signature(verb, request_uri, @api_host, @secret_key, params_to_sign)
114
- auth_params
28
+ def connect!(auth_params, options={})
29
+ @connection = Connection.new(auth_params, options)
115
30
  end
116
31
 
117
- def api_url
118
- "http://#{@api_host}:#{@api_port}/#{@prefix}"
32
+ def connection
33
+ raise "Not connected. Please connect! first." unless @connection
34
+ @connection
119
35
  end
120
36
 
121
- def setup_bucket(params={})
122
- granting_params = { :s3_videos_bucket => params[:bucket], :user_aws_key => params[:access_key], :user_aws_secret => params[:secret_key] }
123
- put("/clouds/#{@cloud_id}.json", granting_params)
124
- end
125
-
126
- private
127
- def stringify_keys(params)
128
- params.inject({}) do |options, (key, value)|
129
- options[key.to_s] = value
130
- options
131
- end
132
- end
133
-
134
- def rescue_restclient_exception(&block)
135
- begin
136
- yield
137
- rescue RestClient::Exception => e
138
- format_to(e.http_body)
139
- end
140
- end
141
-
142
- # API change on rest-client 1.4
143
- def body_of(response)
144
- json_response = response.respond_to?(:body) ? response.body : response
145
- format_to(json_response)
146
- end
147
-
148
- def format_to(response)
149
- if self.format == "json"
150
- response
151
-
152
- elsif defined?(ActiveSupport::JSON)
153
- ActiveSupport::JSON.decode(response)
154
-
155
- else
156
- JSON.parse(response)
157
- end
158
- end
159
-
160
- def init_from_url(url)
161
- params = url.scan(/http:\/\/([^:@]+):([^:@]+)@([^:@]+)(:[\d]+)?\/([^:@]+)$/).flatten
162
- @access_key = params[0]
163
- @secret_key = params[1]
164
- @cloud_id = params[4]
165
- @api_host = params[2]
166
-
167
- if params[3]
168
- @api_port = params[3][1..-1]
169
- else
170
- @api_port = DEFAULT_API_PORT
171
- end
172
- @prefix = "v#{@api_version}"
173
-
174
- end
175
-
176
- def init_from_hash(hash_params)
177
- params = { :api_host => DEFAULT_API_HOST, :api_port => DEFAULT_API_PORT }.merge(hash_params)
178
-
179
- @cloud_id = params["cloud_id"] || params[:cloud_id]
180
- @access_key = params["access_key"] || params[:access_key]
181
- @secret_key = params["secret_key"] || params[:secret_key]
182
- @api_host = params["api_host"] || params[:api_host]
183
- @api_port = params["api_port"] || params[:api_port]
184
- @prefix = params["prefix_url"] || "v#{@api_version}"
185
- end
186
37
  end
187
38
  end
@@ -0,0 +1,48 @@
1
+ module Panda
2
+ class EncodingScope < Scope
3
+
4
+ def initialize(parent)
5
+ super(parent, Encoding)
6
+ end
7
+
8
+ def non_delegate_methods
9
+ super + [:status, :profile_id, :profile_name, :video, :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 video(this_video_id)
23
+ @scoped_attributes[:video_id] = this_video_id
24
+ self
25
+ end
26
+
27
+ def status(this_status)
28
+ @scoped_attributes[:status] = this_status
29
+ self
30
+ end
31
+
32
+ def profile(this_profile_id)
33
+ @scoped_attributes[:profile_id] = this_profile_id
34
+ self
35
+ end
36
+
37
+ def profile_name(this_profile_name)
38
+ @scoped_attributes[:profile_name] = this_profile_name
39
+ self
40
+ end
41
+
42
+ def find_by_profile_name(this_profile_name)
43
+ @scoped_attributes[:profile_name] = this_profile_name
44
+ trigger_request.first
45
+ end
46
+
47
+ end
48
+ end