panda 0.6.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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