fogged 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +34 -0
  4. data/app/controllers/fogged/resources_controller.rb +259 -0
  5. data/app/jobs/fogged/resources/zencoder_poll_job.rb +39 -0
  6. data/app/models/fogged/resource.rb +153 -0
  7. data/app/models/fogged/resources/aws_encoder.rb +64 -0
  8. data/app/models/fogged/resources/encoder.rb +13 -0
  9. data/app/serializers/fogged/resource_serializer.rb +35 -0
  10. data/config/locales/en.yml +6 -0
  11. data/config/locales/fr.yml +6 -0
  12. data/config/routes.rb +4 -0
  13. data/db/migrate/20141103143408_create_fogged_resources.rb +20 -0
  14. data/lib/fogged.rb +46 -0
  15. data/lib/fogged/acts_as_having_many_resources.rb +30 -0
  16. data/lib/fogged/acts_as_having_one_resource.rb +34 -0
  17. data/lib/fogged/engine.rb +50 -0
  18. data/lib/fogged/version.rb +3 -0
  19. data/lib/tasks/fogged_tasks.rake +4 -0
  20. data/test/controllers/fogged/resources_controller/confirm_test.rb +56 -0
  21. data/test/controllers/fogged/resources_controller/create_test.rb +56 -0
  22. data/test/controllers/fogged/resources_controller/destroy_test.rb +29 -0
  23. data/test/controllers/fogged/resources_controller/show_test.rb +35 -0
  24. data/test/controllers/fogged/resources_controller/update_test.rb +31 -0
  25. data/test/dummy/Rakefile +6 -0
  26. data/test/dummy/app/assets/javascripts/application.js +13 -0
  27. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  28. data/test/dummy/app/controllers/application_controller.rb +5 -0
  29. data/test/dummy/app/controllers/images_controller.rb +5 -0
  30. data/test/dummy/app/helpers/application_helper.rb +2 -0
  31. data/test/dummy/app/models/image.rb +3 -0
  32. data/test/dummy/app/models/movie.rb +4 -0
  33. data/test/dummy/app/models/movie_fogged_resource.rb +4 -0
  34. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  35. data/test/dummy/bin/bundle +3 -0
  36. data/test/dummy/bin/delayed_job +5 -0
  37. data/test/dummy/bin/rails +4 -0
  38. data/test/dummy/bin/rake +4 -0
  39. data/test/dummy/config.ru +4 -0
  40. data/test/dummy/config/application.rb +23 -0
  41. data/test/dummy/config/boot.rb +5 -0
  42. data/test/dummy/config/database.yml +25 -0
  43. data/test/dummy/config/environment.rb +5 -0
  44. data/test/dummy/config/environments/development.rb +37 -0
  45. data/test/dummy/config/environments/production.rb +78 -0
  46. data/test/dummy/config/environments/test.rb +39 -0
  47. data/test/dummy/config/initializers/assets.rb +8 -0
  48. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  49. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  50. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  51. data/test/dummy/config/initializers/fog.rb +1 -0
  52. data/test/dummy/config/initializers/fogged.rb +7 -0
  53. data/test/dummy/config/initializers/inflections.rb +16 -0
  54. data/test/dummy/config/initializers/mime_types.rb +4 -0
  55. data/test/dummy/config/initializers/session_store.rb +3 -0
  56. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  57. data/test/dummy/config/locales/en.yml +23 -0
  58. data/test/dummy/config/routes.rb +4 -0
  59. data/test/dummy/config/secrets.yml +22 -0
  60. data/test/dummy/db/development.sqlite3 +0 -0
  61. data/test/dummy/db/migrate/20141104135257_create_images.rb +10 -0
  62. data/test/dummy/db/migrate/20141104152227_create_movies.rb +9 -0
  63. data/test/dummy/db/migrate/20141104152345_create_movie_fogged_resources.rb +10 -0
  64. data/test/dummy/db/migrate/20141105073909_create_delayed_jobs.rb +22 -0
  65. data/test/dummy/db/schema.rb +72 -0
  66. data/test/dummy/db/test.sqlite3 +0 -0
  67. data/test/dummy/log/development.log +234 -0
  68. data/test/dummy/log/test.log +20250 -0
  69. data/test/dummy/public/404.html +67 -0
  70. data/test/dummy/public/422.html +67 -0
  71. data/test/dummy/public/500.html +66 -0
  72. data/test/dummy/public/favicon.ico +0 -0
  73. data/test/dummy/test/controllers/resources_controller/index_test.rb +56 -0
  74. data/test/dummy/test/models/image_test.rb +24 -0
  75. data/test/dummy/test/models/movie_test.rb +26 -0
  76. data/test/fixtures/fogged/resources.yml +31 -0
  77. data/test/fixtures/images.yml +5 -0
  78. data/test/fixtures/movie_fogged_resources.yml +19 -0
  79. data/test/fixtures/movies.yml +8 -0
  80. data/test/fogged_test.rb +7 -0
  81. data/test/integration/navigation_test.rb +10 -0
  82. data/test/jobs/fogged/resources/zencoder_poll_job_test.rb +92 -0
  83. data/test/models/fogged/resource_test.rb +97 -0
  84. data/test/models/fogged/resources/aws_encoder_test.rb +54 -0
  85. data/test/models/fogged/resources/encoder_test.rb +18 -0
  86. data/test/support/concerns/json_test_helper.rb +43 -0
  87. data/test/support/concerns/resource_test_helper.rb +28 -0
  88. data/test/test_helper.rb +59 -0
  89. 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
@@ -0,0 +1,6 @@
1
+ en:
2
+ fogged:
3
+ resource:
4
+ still_uploading: is still uploading, please confirm it first
5
+ resources:
6
+ still_uploading: are still uploading, please confirm them first
@@ -0,0 +1,6 @@
1
+ en:
2
+ fogged:
3
+ resource:
4
+ still_uploading: est en cours d'upload, confirmez la resource!
5
+ resources:
6
+ still_uploading: sont en cours d'upload, confirmez les resources!
@@ -0,0 +1,4 @@
1
+ Fogged::Engine.routes.draw do
2
+ resources :resources
3
+ put "resources/:id/confirm" => "resources#confirm"
4
+ end
@@ -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
@@ -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,3 @@
1
+ module Fogged
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :fogged do
3
+ # # Task goes here
4
+ # 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