flixcloud-flix_cloud-gem 0.5.3
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/LICENSE +20 -0
- data/README.markdown +104 -0
- data/Rakefile +59 -0
- data/VERSION.yml +4 -0
- data/lib/flix_cloud/exceptions.rb +6 -0
- data/lib/flix_cloud/extensions/hash.rb +22 -0
- data/lib/flix_cloud/file.rb +21 -0
- data/lib/flix_cloud/file_locations.rb +33 -0
- data/lib/flix_cloud/job.rb +150 -0
- data/lib/flix_cloud/notification.rb +32 -0
- data/lib/flix_cloud/parameters.rb +19 -0
- data/lib/flix_cloud/record.rb +46 -0
- data/lib/flix_cloud/response.rb +26 -0
- data/lib/flix_cloud.rb +10 -0
- data/test/flix_cloud/file_locations_test.rb +45 -0
- data/test/flix_cloud/file_test.rb +29 -0
- data/test/flix_cloud/job_test.rb +532 -0
- data/test/flix_cloud/notification_test.rb +213 -0
- data/test/flix_cloud/parameters_test.rb +20 -0
- data/test/flix_cloud/record_test.rb +50 -0
- data/test/flix_cloud/response_test.rb +56 -0
- data/test/test_helper.rb +15 -0
- metadata +111 -0
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2009 Zencoder
|
|
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.markdown
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
FlixCloud Gem
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
The gem for interacting with the API on [FlixCloud](http://flixcloud.com).
|
|
5
|
+
|
|
6
|
+
See [http://flixcloud.com/api](http://flixcloud.com/api) for more details on the API.
|
|
7
|
+
|
|
8
|
+
Examples
|
|
9
|
+
========
|
|
10
|
+
|
|
11
|
+
Rails
|
|
12
|
+
-----
|
|
13
|
+
|
|
14
|
+
If you're using rails, you can add the following to your environment.rb:
|
|
15
|
+
|
|
16
|
+
config.gem 'flixcloud-flix_cloud-gem', :lib => 'flix_cloud', :source => 'http://gems.github.com'
|
|
17
|
+
config.gem 'sevenwire-http_client', :lib => 'http_client', :source => 'http://gems.github.com'
|
|
18
|
+
config.gem 'crack'
|
|
19
|
+
|
|
20
|
+
Then you can run:
|
|
21
|
+
|
|
22
|
+
rake gems:install
|
|
23
|
+
rake gems:unpack
|
|
24
|
+
|
|
25
|
+
Ruby or Other Frameworks
|
|
26
|
+
------------------------
|
|
27
|
+
|
|
28
|
+
Install the gems (sudo may be necessary):
|
|
29
|
+
|
|
30
|
+
gem install flixcloud-flix_cloud-gem --source http://gems.github.com
|
|
31
|
+
gem install sevenwire-http_client --source http://gems.github.com
|
|
32
|
+
gem install crack
|
|
33
|
+
|
|
34
|
+
Then in your code you can just require the FlixCloud gem:
|
|
35
|
+
|
|
36
|
+
require 'rubygems'
|
|
37
|
+
require 'flix_cloud'
|
|
38
|
+
|
|
39
|
+
Creating Jobs
|
|
40
|
+
-------------
|
|
41
|
+
|
|
42
|
+
You can create jobs using the Job class:
|
|
43
|
+
|
|
44
|
+
job = FlixCloud::Job.new(:api_key => 'your-api-key-here',
|
|
45
|
+
:recipe_id => 1,
|
|
46
|
+
:input_url => 'http://url/to/your/input/file',
|
|
47
|
+
:output_url => 'ftp://url/to/your/output/file',
|
|
48
|
+
:output_user => 'username-for-ftp-here',
|
|
49
|
+
:output_password => 'password-for-ftp-here',
|
|
50
|
+
:watermark_url => 's3://url/to/your/watermark/file')
|
|
51
|
+
job.valid? # true or false
|
|
52
|
+
job.save # true or false
|
|
53
|
+
job.id # returns the id of the saved job, or nil if it failed to save
|
|
54
|
+
job.initialized_at # returns the time the job was created, or nil if it failed to save
|
|
55
|
+
|
|
56
|
+
Job is modeled after ActiveRecord, so create, create!, save, save!, etc all work.
|
|
57
|
+
|
|
58
|
+
See [this](http://flixcloud.com/api#sending_jobs_to_flix_cloud) for more information.
|
|
59
|
+
|
|
60
|
+
Job Notifications
|
|
61
|
+
-----------------
|
|
62
|
+
|
|
63
|
+
When you receive a notification from FlixCloud, you can process it using the Notification class:
|
|
64
|
+
|
|
65
|
+
job = FlixCloud::Notification.new(notification_xml_or_hash)
|
|
66
|
+
job.successful? # true if the state is 'successful_job', false if not
|
|
67
|
+
job.failed? # true if the state is 'failed_job', false if not
|
|
68
|
+
job.cancelled? # true if the state is 'cancelled_job', false if not
|
|
69
|
+
job.id # the id of the job that finished
|
|
70
|
+
job.finished_job_at # the time the job finished at
|
|
71
|
+
job.initialized_job_at # the time the job was created at
|
|
72
|
+
job.recipe_name # the name of the recipe used to process the job
|
|
73
|
+
job.recipe_id # the id of the recipe used to process the job
|
|
74
|
+
job.state # the state of the finished job. 'successful_job', 'failed_job', or 'cancelled_job'
|
|
75
|
+
job.error_message # the error message given for the job if it failed to process
|
|
76
|
+
job.input_media_file.url # url of the input file
|
|
77
|
+
job.input_media_file.width # width of the input file in pixels
|
|
78
|
+
job.input_media_file.height # height of the input file in pixels
|
|
79
|
+
job.input_media_file.size # size of the input file in bytes
|
|
80
|
+
job.input_media_file.duration # duration of the input file in milliseconds
|
|
81
|
+
job.input_media_file.cost # cost of the input file in millicents (1/1000th of a cent)
|
|
82
|
+
job.output_media_file.url # url of the output file
|
|
83
|
+
job.output_media_file.width # width of the output file in pixels
|
|
84
|
+
job.output_media_file.height # height of the output file in pixels
|
|
85
|
+
job.output_media_file.size # size of the output file in bytes
|
|
86
|
+
job.output_media_file.duration # duration of the output file in milliseconds
|
|
87
|
+
job.output_media_file.cost # cost of the output file in millicents (1/1000th of a cent)
|
|
88
|
+
job.watermark_file.url # url of the watermark file
|
|
89
|
+
job.watermark_file.size # size of the watermark file in bytes
|
|
90
|
+
job.watermark_file.cost # cost of the watermark file in millicents (1/1000th of a cent)
|
|
91
|
+
|
|
92
|
+
See [this](http://flixcloud.com/api#job_notifications) for more information.
|
|
93
|
+
|
|
94
|
+
Note
|
|
95
|
+
----
|
|
96
|
+
|
|
97
|
+
Creating jobs sends HTTP requests to FlixCloud, which may take some time. It's
|
|
98
|
+
best to do this asynchronously in your application.
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
COPYRIGHT
|
|
102
|
+
=========
|
|
103
|
+
|
|
104
|
+
Copyright (c) 2009 Zencoder. See LICENSE for details.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'jeweler'
|
|
6
|
+
Jeweler::Tasks.new do |gem|
|
|
7
|
+
gem.name = "flix_cloud-gem"
|
|
8
|
+
gem.summary = %{Gem for integrating with http://flixcloud.com}
|
|
9
|
+
gem.email = "nate@sevenwire.com"
|
|
10
|
+
gem.homepage = "http://github.com/zencoder/flix_cloud-gem"
|
|
11
|
+
gem.authors = ["Nathan Sutton"]
|
|
12
|
+
gem.add_dependency('builder', '>= 2.1.2')
|
|
13
|
+
gem.add_dependency('crack', '>= 0.1.1')
|
|
14
|
+
gem.add_dependency('sevenwire-http_client', '>= 0.1.0')
|
|
15
|
+
|
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
|
17
|
+
end
|
|
18
|
+
rescue LoadError
|
|
19
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
require 'rake/testtask'
|
|
23
|
+
Rake::TestTask.new(:test) do |test|
|
|
24
|
+
test.libs << 'lib' << 'test'
|
|
25
|
+
test.pattern = 'test/**/*_test.rb'
|
|
26
|
+
test.verbose = true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
begin
|
|
30
|
+
require 'rcov/rcovtask'
|
|
31
|
+
Rcov::RcovTask.new do |test|
|
|
32
|
+
test.libs << 'test'
|
|
33
|
+
test.pattern = 'test/**/*_test.rb'
|
|
34
|
+
test.verbose = true
|
|
35
|
+
end
|
|
36
|
+
rescue LoadError
|
|
37
|
+
task :rcov do
|
|
38
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
task :default => :test
|
|
44
|
+
|
|
45
|
+
require 'rake/rdoctask'
|
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
|
47
|
+
if File.exist?('VERSION.yml')
|
|
48
|
+
config = YAML.load(File.read('VERSION.yml'))
|
|
49
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
|
50
|
+
else
|
|
51
|
+
version = ""
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
55
|
+
rdoc.title = "flix_cloud-gem #{version}"
|
|
56
|
+
rdoc.rdoc_files.include('README*')
|
|
57
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
58
|
+
end
|
|
59
|
+
|
data/VERSION.yml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
class FlixCloud::Error < StandardError; end
|
|
2
|
+
class FlixCloud::SaveError < FlixCloud::Error; end
|
|
3
|
+
class FlixCloud::CreateError < FlixCloud::Error; end
|
|
4
|
+
class FlixCloud::ServerBrokeConnection < FlixCloud::Error; end
|
|
5
|
+
class FlixCloud::RequestTimeout < FlixCloud::Error; end
|
|
6
|
+
class FlixCloud::ConnectionRefused < FlixCloud::Error; end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module FlixCloud
|
|
2
|
+
module Extensions
|
|
3
|
+
# Both methods ripped directly out of rails
|
|
4
|
+
module Hash
|
|
5
|
+
def deep_merge(other_hash)
|
|
6
|
+
self.merge(other_hash) do |key, oldval, newval|
|
|
7
|
+
oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
|
|
8
|
+
newval = newval.to_hash if newval.respond_to?(:to_hash)
|
|
9
|
+
oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? oldval.deep_merge(newval) : newval
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
|
14
|
+
# Modifies the receiver in place.
|
|
15
|
+
def deep_merge!(other_hash)
|
|
16
|
+
replace(deep_merge(other_hash))
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
Hash.send(:include, FlixCloud::Extensions::Hash) unless Hash.instance_methods.include?('deep_merge')
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class FlixCloud::File < FlixCloud::Record
|
|
2
|
+
|
|
3
|
+
attr_accessor :url, :size, :width, :height, :duration, :cost
|
|
4
|
+
|
|
5
|
+
record_column :parameters, 'Parameters'
|
|
6
|
+
|
|
7
|
+
def valid?
|
|
8
|
+
self.errors = []
|
|
9
|
+
|
|
10
|
+
unless url
|
|
11
|
+
self.errors << "url is required"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
if parameters && !parameters.valid?
|
|
15
|
+
self.errors << {:parameters => parameters.errors}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
errors.empty?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class FlixCloud::FileLocations < FlixCloud::Record
|
|
2
|
+
|
|
3
|
+
record_column :input, 'File'
|
|
4
|
+
record_column :output, 'File'
|
|
5
|
+
record_column :watermark, 'File'
|
|
6
|
+
|
|
7
|
+
def valid?
|
|
8
|
+
self.errors = []
|
|
9
|
+
|
|
10
|
+
if input
|
|
11
|
+
unless input.valid?
|
|
12
|
+
self.errors << {:input => input.errors}
|
|
13
|
+
end
|
|
14
|
+
else
|
|
15
|
+
self.errors << "input is required"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
if output
|
|
19
|
+
unless output.valid?
|
|
20
|
+
self.errors << {:output => output.errors}
|
|
21
|
+
end
|
|
22
|
+
else
|
|
23
|
+
self.errors << "output is required"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if watermark && !watermark.valid?
|
|
27
|
+
self.errors << {:watermark => watermark.errors}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
errors.empty?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
class FlixCloud::Job < FlixCloud::Record
|
|
2
|
+
|
|
3
|
+
attr_accessor :id, :initialized_at, :api_key, :recipe_id, :recipe_name, :response
|
|
4
|
+
|
|
5
|
+
record_column :file_locations, 'FileLocations'
|
|
6
|
+
|
|
7
|
+
def initialize(attrs={})
|
|
8
|
+
super
|
|
9
|
+
self.shortcut_attributes = attrs
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def valid?
|
|
13
|
+
self.errors = []
|
|
14
|
+
|
|
15
|
+
if file_locations
|
|
16
|
+
unless file_locations.valid?
|
|
17
|
+
self.errors << {:file_locations => file_locations.errors}
|
|
18
|
+
end
|
|
19
|
+
else
|
|
20
|
+
self.errors << "file_locations is required"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if recipe_id || recipe_name
|
|
24
|
+
if recipe_id && recipe_name
|
|
25
|
+
self.errors << "recipe_id and recipe_name cannot both be used"
|
|
26
|
+
end
|
|
27
|
+
else
|
|
28
|
+
self.errors << "recipe_id or recipe_name is required"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
unless api_key
|
|
32
|
+
self.errors << "api_key is required"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
errors.empty?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def save
|
|
39
|
+
return false unless valid?
|
|
40
|
+
|
|
41
|
+
self.response = post('jobs', to_xml)
|
|
42
|
+
|
|
43
|
+
if response.success?
|
|
44
|
+
self.id = response.body_as_hash['job']['id']
|
|
45
|
+
self.initialized_at = response.body_as_hash['job']['initialized_job_at']
|
|
46
|
+
else
|
|
47
|
+
self.errors = response.errors
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
response.success?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def save!
|
|
54
|
+
raise FlixCloud::SaveError unless save
|
|
55
|
+
true
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.create(attrs={})
|
|
59
|
+
job = new(attrs)
|
|
60
|
+
job.save
|
|
61
|
+
job
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self.create!(attrs={})
|
|
65
|
+
job = create(attrs)
|
|
66
|
+
raise FlixCloud::CreateError unless job.id
|
|
67
|
+
job
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def to_xml
|
|
71
|
+
xml = Builder::XmlMarkup.new
|
|
72
|
+
|
|
73
|
+
xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8"
|
|
74
|
+
|
|
75
|
+
xml.tag!("api-request") do
|
|
76
|
+
xml.tag!("api-key", api_key)
|
|
77
|
+
|
|
78
|
+
if recipe_name
|
|
79
|
+
xml.tag!("recipe-name", recipe_name)
|
|
80
|
+
else
|
|
81
|
+
xml.tag!("recipe-id", recipe_id)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if file_locations
|
|
85
|
+
xml.tag!("file-locations") do
|
|
86
|
+
if file_locations.input
|
|
87
|
+
xml.input do
|
|
88
|
+
xml.url(file_locations.input.url)
|
|
89
|
+
if file_locations.input.parameters
|
|
90
|
+
xml.parameters do
|
|
91
|
+
xml.user(file_locations.input.parameters.user)
|
|
92
|
+
xml.password(file_locations.input.parameters.password)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if file_locations.output
|
|
99
|
+
xml.output do
|
|
100
|
+
xml.url(file_locations.output.url)
|
|
101
|
+
if file_locations.output.parameters
|
|
102
|
+
xml.parameters do
|
|
103
|
+
xml.user(file_locations.output.parameters.user)
|
|
104
|
+
xml.password(file_locations.output.parameters.password)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
if file_locations.watermark
|
|
111
|
+
xml.watermark do
|
|
112
|
+
xml.url(file_locations.watermark.url)
|
|
113
|
+
if file_locations.watermark.parameters
|
|
114
|
+
xml.parameters do
|
|
115
|
+
xml.user(file_locations.watermark.parameters.user)
|
|
116
|
+
xml.password(file_locations.watermark.parameters.password)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
xml.target!
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
protected
|
|
130
|
+
|
|
131
|
+
def shortcut_attributes=(attrs)
|
|
132
|
+
translated_attributes = {}
|
|
133
|
+
|
|
134
|
+
attrs.each do |key, value|
|
|
135
|
+
if match = key.to_s.match(/^(input|output|watermark)_(url|user|password)$/)
|
|
136
|
+
file_type = match[1].to_sym
|
|
137
|
+
parameter_type = match[2].to_sym
|
|
138
|
+
|
|
139
|
+
if parameter_type == :url
|
|
140
|
+
translated_attributes.deep_merge!(:file_locations => { file_type => { :url => value}})
|
|
141
|
+
else
|
|
142
|
+
translated_attributes.deep_merge!(:file_locations => { file_type => { :parameters => { parameter_type => value}}})
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
self.attributes = translated_attributes unless translated_attributes.empty?
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
class FlixCloud::Notification < FlixCloud::Record
|
|
2
|
+
attr_accessor :xml, :id, :finished_job_at, :initialized_job_at,
|
|
3
|
+
:recipe_name, :recipe_id, :state, :error_message
|
|
4
|
+
|
|
5
|
+
record_column :input_media_file, 'File'
|
|
6
|
+
record_column :output_media_file, 'File'
|
|
7
|
+
record_column :watermark_file, 'File'
|
|
8
|
+
|
|
9
|
+
def initialize(attrs={})
|
|
10
|
+
if attrs.is_a?(String)
|
|
11
|
+
self.xml = attrs
|
|
12
|
+
attrs = Crack::XML.parse(attrs)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attrs = attrs['job'] if attrs['job']
|
|
16
|
+
|
|
17
|
+
super(attrs)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def successful?
|
|
21
|
+
state == 'successful_job'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def failed?
|
|
25
|
+
state == 'failed_job'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def cancelled?
|
|
29
|
+
state == 'cancelled_job'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class FlixCloud::Parameters < FlixCloud::File
|
|
2
|
+
|
|
3
|
+
attr_accessor :user, :password
|
|
4
|
+
|
|
5
|
+
def valid?
|
|
6
|
+
self.errors = []
|
|
7
|
+
|
|
8
|
+
unless user
|
|
9
|
+
self.errors << "user is required"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
unless password
|
|
13
|
+
self.errors << "password is required"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
errors.empty?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class FlixCloud::Record
|
|
2
|
+
|
|
3
|
+
attr_accessor :errors
|
|
4
|
+
|
|
5
|
+
def initialize(attrs={})
|
|
6
|
+
self.errors = []
|
|
7
|
+
self.attributes = attrs
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def attributes=(attrs)
|
|
11
|
+
attrs.each do |key, value|
|
|
12
|
+
send("#{key}=", value) if respond_to?("#{key}=")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.record_column(attribute, klass)
|
|
17
|
+
eval %{
|
|
18
|
+
attr_reader :#{attribute}
|
|
19
|
+
|
|
20
|
+
def #{attribute}=(value)
|
|
21
|
+
if @#{attribute}
|
|
22
|
+
@#{attribute}.attributes = value
|
|
23
|
+
else
|
|
24
|
+
@#{attribute} = FlixCloud::#{klass}.new(value)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
protected
|
|
32
|
+
|
|
33
|
+
def post(path, body)
|
|
34
|
+
begin
|
|
35
|
+
FlixCloud::Response.new(HttpClient::Resource.new("https://flixcloud.com/#{path}",
|
|
36
|
+
:verify_ssl => OpenSSL::SSL::VERIFY_PEER).post(body, :content_type => 'application/xml', :accept => 'application/xml'))
|
|
37
|
+
rescue HttpClient::ServerBrokeConnection
|
|
38
|
+
raise FlixCloud::ServerBrokeConnection, $!.message
|
|
39
|
+
rescue HttpClient::RequestTimeout
|
|
40
|
+
raise FlixCloud::RequestTimeout, $!.message
|
|
41
|
+
rescue HttpClient::ConnectionRefused
|
|
42
|
+
raise FlixCloud::ConnectionRefused, $!.message
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class FlixCloud::Response
|
|
2
|
+
|
|
3
|
+
attr_accessor :code, :body, :errors, :body_as_hash
|
|
4
|
+
|
|
5
|
+
def initialize(response)
|
|
6
|
+
self.code = response.code
|
|
7
|
+
self.body = response.to_s
|
|
8
|
+
self.body_as_hash = Crack::XML.parse(response.to_s)
|
|
9
|
+
self.errors = []
|
|
10
|
+
process_response_xml
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def success?
|
|
14
|
+
201 == code.to_i
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
protected
|
|
19
|
+
|
|
20
|
+
def process_response_xml
|
|
21
|
+
if body_as_hash['errors'] && body_as_hash['errors'].is_a?(Hash) && body_as_hash['errors']['error']
|
|
22
|
+
self.errors = Array(body_as_hash['errors']['error'])
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
data/lib/flix_cloud.rb
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require 'builder'
|
|
2
|
+
require 'http_client'
|
|
3
|
+
require 'crack/xml'
|
|
4
|
+
|
|
5
|
+
module FlixCloud; end
|
|
6
|
+
|
|
7
|
+
%w(record job file_locations file parameters response extensions/hash
|
|
8
|
+
exceptions notification).each do |file|
|
|
9
|
+
require File.dirname(__FILE__) + "/flix_cloud/#{file}"
|
|
10
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class FlixCloud::FileLocationsTest < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
context "When validationg a file locations object with no attributes set" do
|
|
6
|
+
setup do
|
|
7
|
+
@file_locations = FlixCloud::FileLocations.new
|
|
8
|
+
@file_locations.valid?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
should "require input" do
|
|
12
|
+
assert_match /input is required/, @file_locations.errors.to_s
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
should "require output" do
|
|
16
|
+
assert_match /output is required/, @file_locations.errors.to_s
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "When validating a file locations object with input, output, and watermark objects that are invalid" do
|
|
21
|
+
setup do
|
|
22
|
+
@file_locations = FlixCloud::FileLocations.new(:input => {}, :output => {}, :watermark => {})
|
|
23
|
+
@file_locations.valid?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
should "inherit the input object's errors" do
|
|
27
|
+
assert @file_locations.errors.any?{|error|
|
|
28
|
+
error.is_a?(Hash) && error[:input] && !error[:input].empty?
|
|
29
|
+
}, "Did not inherit input object's errors"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
should "inherit the output object's errors" do
|
|
33
|
+
assert @file_locations.errors.any?{|error|
|
|
34
|
+
error.is_a?(Hash) && error[:output] && !error[:output].empty?
|
|
35
|
+
}, "Did not inherit output object's errors"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
should "inherit the watermark object's errors" do
|
|
39
|
+
assert @file_locations.errors.any?{|error|
|
|
40
|
+
error.is_a?(Hash) && error[:watermark] && !error[:watermark].empty?
|
|
41
|
+
}, "Did not inherit watermark object's errors"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class FlixCloud::FileTest < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
context "When validating a file object with no attributes set" do
|
|
6
|
+
setup do
|
|
7
|
+
@file = FlixCloud::File.new
|
|
8
|
+
@file.valid?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
should "require url" do
|
|
12
|
+
assert_match /url is required/, @file.errors.to_s
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "When validating a file object with a parameters object that is invalid" do
|
|
17
|
+
setup do
|
|
18
|
+
@file = FlixCloud::File.new(:parameters => {})
|
|
19
|
+
@file.valid?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
should "inherit the parameters object's errors" do
|
|
23
|
+
assert @file.errors.any?{|error|
|
|
24
|
+
error.is_a?(Hash) && error[:parameters] && !error[:parameters].empty?
|
|
25
|
+
}, "Did not inherit parameters object's errors"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|