fogged 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +34 -0
- data/app/controllers/fogged/resources_controller.rb +259 -0
- data/app/jobs/fogged/resources/zencoder_poll_job.rb +39 -0
- data/app/models/fogged/resource.rb +153 -0
- data/app/models/fogged/resources/aws_encoder.rb +64 -0
- data/app/models/fogged/resources/encoder.rb +13 -0
- data/app/serializers/fogged/resource_serializer.rb +35 -0
- data/config/locales/en.yml +6 -0
- data/config/locales/fr.yml +6 -0
- data/config/routes.rb +4 -0
- data/db/migrate/20141103143408_create_fogged_resources.rb +20 -0
- data/lib/fogged.rb +46 -0
- data/lib/fogged/acts_as_having_many_resources.rb +30 -0
- data/lib/fogged/acts_as_having_one_resource.rb +34 -0
- data/lib/fogged/engine.rb +50 -0
- data/lib/fogged/version.rb +3 -0
- data/lib/tasks/fogged_tasks.rake +4 -0
- data/test/controllers/fogged/resources_controller/confirm_test.rb +56 -0
- data/test/controllers/fogged/resources_controller/create_test.rb +56 -0
- data/test/controllers/fogged/resources_controller/destroy_test.rb +29 -0
- data/test/controllers/fogged/resources_controller/show_test.rb +35 -0
- data/test/controllers/fogged/resources_controller/update_test.rb +31 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/images_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/image.rb +3 -0
- data/test/dummy/app/models/movie.rb +4 -0
- data/test/dummy/app/models/movie_fogged_resource.rb +4 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/delayed_job +5 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +78 -0
- data/test/dummy/config/environments/test.rb +39 -0
- data/test/dummy/config/initializers/assets.rb +8 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/fog.rb +1 -0
- data/test/dummy/config/initializers/fogged.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20141104135257_create_images.rb +10 -0
- data/test/dummy/db/migrate/20141104152227_create_movies.rb +9 -0
- data/test/dummy/db/migrate/20141104152345_create_movie_fogged_resources.rb +10 -0
- data/test/dummy/db/migrate/20141105073909_create_delayed_jobs.rb +22 -0
- data/test/dummy/db/schema.rb +72 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +234 -0
- data/test/dummy/log/test.log +20250 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/test/controllers/resources_controller/index_test.rb +56 -0
- data/test/dummy/test/models/image_test.rb +24 -0
- data/test/dummy/test/models/movie_test.rb +26 -0
- data/test/fixtures/fogged/resources.yml +31 -0
- data/test/fixtures/images.yml +5 -0
- data/test/fixtures/movie_fogged_resources.yml +19 -0
- data/test/fixtures/movies.yml +8 -0
- data/test/fogged_test.rb +7 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/jobs/fogged/resources/zencoder_poll_job_test.rb +92 -0
- data/test/models/fogged/resource_test.rb +97 -0
- data/test/models/fogged/resources/aws_encoder_test.rb +54 -0
- data/test/models/fogged/resources/encoder_test.rb +18 -0
- data/test/support/concerns/json_test_helper.rb +43 -0
- data/test/support/concerns/resource_test_helper.rb +28 -0
- data/test/test_helper.rb +59 -0
- metadata +354 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
module Fogged
|
2
|
+
module Resources
|
3
|
+
class AWSEncoder < Struct.new(:resource)
|
4
|
+
def encode!
|
5
|
+
encode_video if resource.video?
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def encode_video
|
11
|
+
fail(ArgumentError, "Zencoder gem needed") unless defined?(Zencoder)
|
12
|
+
fail(ArgumentError, "Delayed Job gem needed") unless defined?(Delayed::Job)
|
13
|
+
|
14
|
+
job = Zencoder::Job.create(
|
15
|
+
:input => resource.url,
|
16
|
+
:region => "europe",
|
17
|
+
:download_connections => 5,
|
18
|
+
:output => output
|
19
|
+
)
|
20
|
+
resource.update!(
|
21
|
+
:encoding_job_id => job.body["id"].to_s,
|
22
|
+
:encoding_progress => 0
|
23
|
+
)
|
24
|
+
|
25
|
+
Delayed::Job.enqueue(ZencoderPollJob.new(resource.id))
|
26
|
+
end
|
27
|
+
|
28
|
+
def output
|
29
|
+
[
|
30
|
+
{
|
31
|
+
:url => "s3://#{bucket}/#{fogged_name_for(:h264)}",
|
32
|
+
:video_codec => "h264",
|
33
|
+
:public => 1,
|
34
|
+
:thumbnails => {
|
35
|
+
:number => 5,
|
36
|
+
:format => "png",
|
37
|
+
:base_url => "s3://#{bucket}",
|
38
|
+
:filename => "#{resource.token}-thumbnail-{{number}}",
|
39
|
+
:public => 1
|
40
|
+
}
|
41
|
+
},
|
42
|
+
{
|
43
|
+
:url => "s3://#{bucket}/#{fogged_name_for(:mpeg)}",
|
44
|
+
:video_codec => "mpeg4",
|
45
|
+
:public => 1
|
46
|
+
},
|
47
|
+
{
|
48
|
+
:url => "s3://#{bucket}/#{fogged_name_for(:webm)}",
|
49
|
+
:video_codec => "vp8",
|
50
|
+
:public => 1
|
51
|
+
}
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
def bucket
|
56
|
+
resource.send(:fogged_file).directory.key
|
57
|
+
end
|
58
|
+
|
59
|
+
def fogged_name_for(type)
|
60
|
+
resource.send(:fogged_name_for, type)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Fogged
|
2
|
+
module Resources
|
3
|
+
class Encoder
|
4
|
+
def self.for(resource)
|
5
|
+
"Fogged::Resources::#{provider_for(resource)}Encoder".constantize.new(resource)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.provider_for(resource)
|
9
|
+
return :AWS if resource.send(:fogged_file).class.to_s.include?("AWS")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Fogged
|
2
|
+
class ResourceSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :name, :upload_url, :url
|
4
|
+
attributes :h264_url, :mpeg_url, :webm_url, :thumbnail_urls
|
5
|
+
attributes :encoding_progress
|
6
|
+
|
7
|
+
def include_upload_url?
|
8
|
+
options[:include_upload_url]
|
9
|
+
end
|
10
|
+
|
11
|
+
def include_h264_url?
|
12
|
+
object.video?
|
13
|
+
end
|
14
|
+
|
15
|
+
def include_mpeg_url?
|
16
|
+
object.video?
|
17
|
+
end
|
18
|
+
|
19
|
+
def include_webm_url?
|
20
|
+
object.video?
|
21
|
+
end
|
22
|
+
|
23
|
+
def include_thumbnail_urls?
|
24
|
+
object.video?
|
25
|
+
end
|
26
|
+
|
27
|
+
def include_encoding_progress?
|
28
|
+
object.video?
|
29
|
+
end
|
30
|
+
|
31
|
+
def encoding_progress
|
32
|
+
object.encoding_progress || 0
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
class CreateFoggedResources < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :fogged_resources do |t|
|
4
|
+
t.string :name, :null => false
|
5
|
+
t.string :token, :null => false
|
6
|
+
t.integer :width
|
7
|
+
t.integer :height
|
8
|
+
t.string :extension, :null => false
|
9
|
+
t.boolean :uploading
|
10
|
+
t.string :content_type, :null => false
|
11
|
+
t.integer :encoding_progress
|
12
|
+
t.string :encoding_job_id
|
13
|
+
t.integer :duration
|
14
|
+
|
15
|
+
t.timestamps
|
16
|
+
end
|
17
|
+
|
18
|
+
add_index :fogged_resources, :token
|
19
|
+
end
|
20
|
+
end
|
data/lib/fogged.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
Gem.loaded_specs["fogged"].dependencies.select { |d| d.type == :runtime }.each do |d|
|
2
|
+
require d.name
|
3
|
+
end
|
4
|
+
|
5
|
+
require "fogged/engine"
|
6
|
+
require "fogged/acts_as_having_one_resource"
|
7
|
+
require "fogged/acts_as_having_many_resources"
|
8
|
+
|
9
|
+
module Fogged
|
10
|
+
mattr_accessor :provider
|
11
|
+
@@provider = nil
|
12
|
+
|
13
|
+
mattr_accessor :resources
|
14
|
+
@@resources = nil
|
15
|
+
|
16
|
+
mattr_accessor :test_enabled
|
17
|
+
@@test_enabled = false
|
18
|
+
|
19
|
+
# controller
|
20
|
+
mattr_accessor :parent_controller
|
21
|
+
@@parent_controller = "ApplicationController"
|
22
|
+
|
23
|
+
# aws
|
24
|
+
mattr_accessor :aws_key
|
25
|
+
@@aws_key = nil
|
26
|
+
mattr_accessor :aws_secret
|
27
|
+
@@aws_secret = nil
|
28
|
+
mattr_accessor :aws_bucket
|
29
|
+
@@aws_bucket = nil
|
30
|
+
mattr_accessor :aws_region
|
31
|
+
@@aws_region = nil
|
32
|
+
|
33
|
+
# zencoder
|
34
|
+
mattr_accessor :zencoder_enabled
|
35
|
+
@@zencoder_enabled = false
|
36
|
+
mattr_accessor :zencoder_polling_frequency
|
37
|
+
@@zencoder_polling_frequency = 10
|
38
|
+
|
39
|
+
def self.configure
|
40
|
+
yield self
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.test_mode!
|
44
|
+
self.test_enabled = true
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Fogged
|
2
|
+
module ActsAsHavingManyResources
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
DEFAULT_OPTIONS = {
|
7
|
+
:dependent => :destroy,
|
8
|
+
:class_name => "Fogged::Resource"
|
9
|
+
}
|
10
|
+
|
11
|
+
def acts_as_having_many_resources(*args)
|
12
|
+
options = args.extract_options!
|
13
|
+
unless options.include?(:through)
|
14
|
+
fail(ArgumentError, ":through option is mandatory")
|
15
|
+
end
|
16
|
+
has_many :resources, DEFAULT_OPTIONS.merge(options)
|
17
|
+
validate :_check_resources, :unless => "resources.empty?"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def _check_resources
|
24
|
+
return if resources.to_a.select(&:uploading).empty?
|
25
|
+
errors.add(:resources, I18n.t("fogged.resources.still_uploading"))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
ActiveRecord::Base.send(:include, Fogged::ActsAsHavingManyResources)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Fogged
|
2
|
+
module ActsAsHavingOneResource
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
DEFAULT_OPTIONS = {
|
7
|
+
:dependent => :destroy,
|
8
|
+
:class_name => "Fogged::Resource"
|
9
|
+
}
|
10
|
+
|
11
|
+
def acts_as_having_one_resource(*args)
|
12
|
+
belongs_to :resource, DEFAULT_OPTIONS.merge(args.extract_options!)
|
13
|
+
validate :_check_resource, :unless => "resource.blank?"
|
14
|
+
|
15
|
+
define_method(:resource_id) do
|
16
|
+
resource.try(:id)
|
17
|
+
end
|
18
|
+
|
19
|
+
define_method(:resource_id=) do |id|
|
20
|
+
self.resource = id.blank? ? nil : Resource.find(id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def _check_resource
|
28
|
+
return unless resource.uploading
|
29
|
+
errors.add(:resource, I18n.t("fogged.resource.still_uploading"))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
ActiveRecord::Base.send(:include, Fogged::ActsAsHavingOneResource)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Fogged
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace Fogged
|
4
|
+
config.fogged = Fogged
|
5
|
+
|
6
|
+
initializer "fogged.detect_zencoder" do
|
7
|
+
if defined?(Zencoder) && defined?(Delayed::Job)
|
8
|
+
Fogged.zencoder_enabled = true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
initializer "fogged.resources" do
|
13
|
+
unless Fogged.test_enabled
|
14
|
+
case Fogged.provider
|
15
|
+
when :aws
|
16
|
+
fail(ArgumentError, "AWS key is mandatory") unless Fogged.aws_key
|
17
|
+
fail(ArgumentError, "AWS secret is mandatory") unless Fogged.aws_secret
|
18
|
+
fail(ArgumentError, "AWS bucket is mandatory") unless Fogged.aws_bucket
|
19
|
+
storage_options = {
|
20
|
+
:provider => "AWS",
|
21
|
+
:aws_access_key_id => Fogged.aws_key,
|
22
|
+
:aws_secret_access_key => Fogged.aws_secret
|
23
|
+
}
|
24
|
+
storage_options.merge!(:region => Fogged.aws_region) if Fogged.aws_region
|
25
|
+
storage = Fog::Storage.new(storage_options)
|
26
|
+
|
27
|
+
Fogged.resources = storage.directories.get(Fogged.aws_bucket)
|
28
|
+
if Rails.env.test?
|
29
|
+
Fog.mock!
|
30
|
+
Fogged.resources = storage.directories.create(:key => Fogged.aws_bucket)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
fail(ArgumentError, "Provider #{Fogged.config.provider} is not available!")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
initializer "fogged.resources.test" do
|
39
|
+
if Fogged.test_enabled
|
40
|
+
Fog.mock!
|
41
|
+
storage = Fog::Storage.new(
|
42
|
+
:provider => "AWS",
|
43
|
+
:aws_access_key_id => "1234567890",
|
44
|
+
:aws_secret_access_key => "1234567890"
|
45
|
+
)
|
46
|
+
Fogged.resources = storage.directories.create(:key => "test")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
module Fogged
|
4
|
+
class ResourcesControllerConfirmTest < ActionController::TestCase
|
5
|
+
tests ResourcesController
|
6
|
+
include ResourceTestHelper
|
7
|
+
|
8
|
+
test "should confirm resource" do
|
9
|
+
resource = fogged_resources(:resource_png)
|
10
|
+
FastImage.expects(:size).once.returns([800, 600])
|
11
|
+
|
12
|
+
put :confirm, :id => resource, :use_route => :fogged
|
13
|
+
|
14
|
+
assert_json_resource(resource.reload)
|
15
|
+
assert_equal 800, resource.width
|
16
|
+
assert_equal 600, resource.height
|
17
|
+
refute resource.encoding?
|
18
|
+
end
|
19
|
+
|
20
|
+
test "should confirm video resource with zencoder enabled" do
|
21
|
+
in_a_fork do
|
22
|
+
require "zencoder"
|
23
|
+
require "delayed_job_active_record"
|
24
|
+
|
25
|
+
Fogged.zencoder_enabled = true
|
26
|
+
|
27
|
+
Zencoder::Job.expects(:create).returns(
|
28
|
+
OpenStruct.new(:body => create_output)
|
29
|
+
)
|
30
|
+
resource = fogged_resources(:resource_mov)
|
31
|
+
|
32
|
+
assert_difference("Delayed::Job.count") do
|
33
|
+
put :confirm, :id => resource, :use_route => :fogged
|
34
|
+
end
|
35
|
+
|
36
|
+
assert_json_resource(resource.reload)
|
37
|
+
assert resource.encoding_job_id
|
38
|
+
assert resource.encoding?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
test "should not confirm resource with invalid id" do
|
43
|
+
assert_raise(ActiveRecord::RecordNotFound) do
|
44
|
+
put :confirm, :id => 123456, :use_route => :fogged
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def create_output
|
51
|
+
{
|
52
|
+
:id => 1234567890
|
53
|
+
}.with_indifferent_access
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
module Fogged
|
4
|
+
class ResourcesControllerCreateTest < ActionController::TestCase
|
5
|
+
tests ResourcesController
|
6
|
+
include ResourceTestHelper
|
7
|
+
|
8
|
+
def setup
|
9
|
+
super
|
10
|
+
@resource_params = {
|
11
|
+
:name => "Dummy",
|
12
|
+
:filename => "dummy.png",
|
13
|
+
:content_type => "image/png"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
test "should create resource" do
|
18
|
+
assert_difference("Resource.count") do
|
19
|
+
post :create, :resource => @resource_params, :use_route => :fogged
|
20
|
+
end
|
21
|
+
|
22
|
+
assert_json_resource(Resource.last)
|
23
|
+
assert_equal "png", Resource.last.extension
|
24
|
+
end
|
25
|
+
|
26
|
+
test "should not create resource without resource parameter" do
|
27
|
+
assert_no_difference("Resource.count") do
|
28
|
+
assert_raise(ActionController::ParameterMissing) do
|
29
|
+
post :create, :use_route => :fogged
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
%i(filename content_type name).each do |field|
|
35
|
+
test "should not create resource without #{field}" do
|
36
|
+
assert_no_difference("Resource.count") do
|
37
|
+
assert_raise(ActionController::ParameterMissing) do
|
38
|
+
post :create,
|
39
|
+
:resource => @resource_params.merge(field => ""),
|
40
|
+
:use_route => :fogged
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
test "should not create resource with invalid filename" do
|
47
|
+
assert_no_difference("Resource.count") do
|
48
|
+
assert_raise(ActiveRecord::RecordInvalid) do
|
49
|
+
post :create,
|
50
|
+
:resource => @resource_params.merge(:filename => "bar"),
|
51
|
+
:use_route => :fogged
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|