media_magick 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/.travis.yml +7 -3
- data/CHANGELOG.md +92 -1
- data/README.md +1 -1
- data/app/assets/javascripts/media_magick/plupload_it.js +30 -9
- data/app/controllers/media_magick/attach_controller.rb +16 -28
- data/app/helpers/media_magick/application_helper.rb +46 -5
- data/app/views/_file.html.erb +2 -2
- data/app/views/_image.html.erb +3 -3
- data/app/views/_upload.html.erb +3 -10
- data/app/views/_video.html.erb +8 -0
- data/gemfiles/mongoid-3.0.gemfile +7 -0
- data/lib/media_magick.rb +1 -5
- data/lib/media_magick/controller/helpers.rb +20 -0
- data/lib/media_magick/engine.rb +1 -1
- data/lib/media_magick/model.rb +41 -48
- data/lib/media_magick/version.rb +1 -1
- data/lib/media_magick/video/parser.rb +62 -0
- data/media_magick.gemspec +8 -4
- data/spec/controllers/media_magick/attach_controller_spec.rb +12 -11
- data/spec/dummy/app/assets/javascripts/application.js +5 -0
- data/spec/dummy/app/assets/javascripts/posts.js +2 -0
- data/spec/dummy/app/assets/stylesheets/posts.css +4 -0
- data/spec/dummy/app/controllers/posts_controller.rb +83 -0
- data/spec/dummy/app/helpers/posts_helper.rb +2 -0
- data/spec/dummy/app/models/album.rb +3 -1
- data/spec/dummy/app/models/post.rb +10 -0
- data/spec/dummy/app/models/track.rb +1 -0
- data/spec/dummy/app/uploaders/post_uploader.rb +17 -0
- data/spec/dummy/app/views/posts/_form.html.erb +47 -0
- data/spec/dummy/app/views/posts/edit.html.erb +6 -0
- data/spec/dummy/app/views/posts/index.html.erb +25 -0
- data/spec/dummy/app/views/posts/new.html.erb +5 -0
- data/spec/dummy/app/views/posts/show.html.erb +15 -0
- data/spec/dummy/app/views/users/index.html.erb +1 -1
- data/spec/dummy/config/mongoid.yml +65 -17
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/helpers/media_magick/application_helper_spec.rb +90 -27
- data/spec/integration/images_spec.rb +1 -1
- data/spec/lib/media_magick/controller/helper_spec.rb +37 -0
- data/spec/lib/media_magick/model_spec.rb +41 -9
- data/spec/lib/media_magick/video/parser_spec.rb +67 -0
- data/spec/spec_helper.rb +11 -8
- data/spec/views/_upload.html.erb_spec.rb +26 -0
- metadata +76 -21
- data/.rvmrc +0 -1
- data/spec/dummy/app/helpers/users_helper.rb +0 -2
data/lib/media_magick/model.rb
CHANGED
@@ -1,84 +1,77 @@
|
|
1
1
|
require 'active_support/concern'
|
2
2
|
require 'carrierwave/mongoid'
|
3
3
|
require 'media_magick/attachment_uploader'
|
4
|
+
require 'media_magick/video/parser'
|
4
5
|
|
5
6
|
module MediaMagick
|
6
7
|
module Model
|
7
8
|
extend ActiveSupport::Concern
|
8
9
|
|
9
10
|
module ClassMethods
|
10
|
-
def
|
11
|
-
|
12
|
-
attaches_many(name, options, &block)
|
13
|
-
end
|
11
|
+
def attaches_many(name, options = {})
|
12
|
+
attaches_block = block_given? ? Proc.new : nil
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
# * refactor these methods to remove duplication
|
18
|
-
#
|
19
|
-
def attaches_many(name, options = {}, &block)
|
20
|
-
klass = Class.new do
|
21
|
-
include Mongoid::Document
|
22
|
-
extend CarrierWave::Mount
|
14
|
+
name_camelcase = create_attaches_class(name, options, attaches_block) do
|
15
|
+
create_video_methods(name) if options[:allow_videos]
|
23
16
|
|
24
17
|
field :priority, type: Integer, default: 0
|
18
|
+
|
25
19
|
default_scope asc(:priority)
|
26
20
|
|
27
|
-
|
28
|
-
|
29
|
-
else
|
30
|
-
embedded_in :attachmentable, polymorphic: true
|
31
|
-
end
|
21
|
+
embedded_in(:attachmentable, polymorphic: true)
|
22
|
+
end
|
32
23
|
|
33
|
-
|
24
|
+
embeds_many(name, :as => :attachmentable, class_name: "#{self}#{name_camelcase}")
|
25
|
+
end
|
34
26
|
|
35
|
-
|
36
|
-
|
27
|
+
def attaches_one(name, options = {})
|
28
|
+
attaches_block = block_given? ? Proc.new : nil
|
37
29
|
|
38
|
-
|
30
|
+
name_camelcase = create_attaches_class(name, options, attaches_block) do
|
31
|
+
create_video_methods(name) if options[:allow_videos]
|
39
32
|
|
40
|
-
|
41
|
-
return self.send(self.class::ATTACHMENT).file.filename if method == :filename
|
42
|
-
self.send(self.class::ATTACHMENT).send(method)
|
43
|
-
end
|
33
|
+
embedded_in(name)
|
44
34
|
end
|
45
35
|
|
46
|
-
name_camelcase
|
47
|
-
|
36
|
+
embeds_one(name, class_name: "#{self}#{name_camelcase}", cascade_callbacks: true)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
48
40
|
|
49
|
-
|
50
|
-
|
41
|
+
def create_attaches_class(name, options, attaches_block, &block)
|
42
|
+
klass = Class.new do
|
43
|
+
include Mongoid::Document
|
44
|
+
extend CarrierWave::Mount
|
51
45
|
|
52
|
-
|
46
|
+
field :type, type: String, default: options[:as] || 'image'
|
53
47
|
|
54
|
-
|
48
|
+
def self.create_video_methods(name)
|
49
|
+
field :video, type: String
|
50
|
+
|
51
|
+
def video=(url)
|
52
|
+
self.type = 'video'
|
53
|
+
super
|
54
|
+
|
55
|
+
video = MediaMagick::Video::Parser.new(url)
|
56
|
+
|
57
|
+
send(self.class::ATTACHMENT).store!(video.to_image) if video.valid?
|
58
|
+
end
|
55
59
|
|
56
|
-
|
57
|
-
|
60
|
+
def source(options = {})
|
61
|
+
video = MediaMagick::Video::Parser.new(self.video)
|
58
62
|
|
59
|
-
|
60
|
-
"#{self.class}#{name_camelcase}".constantize.find(id).update_attributes(attachmentable: self)
|
63
|
+
video.to_html(options) if video.valid?
|
61
64
|
end
|
62
65
|
end
|
63
|
-
else
|
64
|
-
embeds_many(name, :as => :attachmentable, class_name: "#{self}#{name_camelcase}")
|
65
|
-
end
|
66
|
-
end
|
67
66
|
|
68
|
-
|
69
|
-
klass = Class.new do
|
70
|
-
include Mongoid::Document
|
71
|
-
extend CarrierWave::Mount
|
67
|
+
class_eval(&block) if block_given?
|
72
68
|
|
73
|
-
embedded_in name
|
74
69
|
mount_uploader name.to_s.singularize, (options[:uploader] || AttachmentUploader)
|
75
70
|
|
76
|
-
accepts_nested_attributes_for name.to_s.singularize
|
77
|
-
|
78
71
|
self.const_set "TYPE", options[:type] || :image
|
79
72
|
self.const_set "ATTACHMENT", name.to_s.singularize
|
80
73
|
|
81
|
-
class_eval(&
|
74
|
+
class_eval(&attaches_block) if attaches_block
|
82
75
|
|
83
76
|
def method_missing(method, args = nil)
|
84
77
|
return self.send(self.class::ATTACHMENT).file.filename if method == :filename
|
@@ -89,7 +82,7 @@ module MediaMagick
|
|
89
82
|
name_camelcase = name.to_s.camelcase
|
90
83
|
Object.const_set "#{self}#{name_camelcase}", klass
|
91
84
|
|
92
|
-
|
85
|
+
return name_camelcase
|
93
86
|
end
|
94
87
|
end
|
95
88
|
end
|
data/lib/media_magick/version.rb
CHANGED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'net/http'
|
3
|
+
|
4
|
+
module MediaMagick
|
5
|
+
module Video
|
6
|
+
class Parser
|
7
|
+
def initialize(url)
|
8
|
+
@url = url
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
youtube_regex = /((https?)?:\/\/)?(www.)?(youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/watch\?feature=player_embedded&v=)([A-Za-z0-9_-]*)(\&\S+)?(\S)*/
|
13
|
+
vimeo_regex = /((https?):\/\/)?(www.)?vimeo\.com\/([A-Za-z0-9._%-]*)((\?|#)\S+)?/
|
14
|
+
|
15
|
+
if @url.match(youtube_regex)
|
16
|
+
@id = @url.match(youtube_regex)[5]
|
17
|
+
@service = 'youtube'
|
18
|
+
true
|
19
|
+
else
|
20
|
+
if @url.match(vimeo_regex)
|
21
|
+
@id = @url.match(vimeo_regex)[4]
|
22
|
+
@service = 'vimeo'
|
23
|
+
true
|
24
|
+
else
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_image
|
31
|
+
id = @id if valid?
|
32
|
+
|
33
|
+
case @service
|
34
|
+
when 'youtube'
|
35
|
+
image_url = "http://img.youtube.com/vi/#{id}/0.jpg"
|
36
|
+
when 'vimeo'
|
37
|
+
uri = URI.parse("http://vimeo.com/api/v2/video/#{id}.json")
|
38
|
+
resp = Net::HTTP.get_response(uri)
|
39
|
+
image_url = JSON.parse(resp.body)[0]["thumbnail_large"]
|
40
|
+
end
|
41
|
+
|
42
|
+
uri = URI.parse(image_url)
|
43
|
+
response = Net::HTTP.get_response(uri)
|
44
|
+
|
45
|
+
File.new("/tmp/#{id}.jpg", "w+").tap do |file|
|
46
|
+
file.write(response.body.force_encoding('UTF-8'))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_html(options = {})
|
51
|
+
valid?
|
52
|
+
|
53
|
+
case @service
|
54
|
+
when 'youtube'
|
55
|
+
"<iframe width=\"#{ options[:width] || 560}\" height=\"#{ options[:height] || 315 }\" src=\"http://www.youtube.com/embed/#{@id}\" frameborder=\"0\" allowfullscreen></iframe>"
|
56
|
+
when 'vimeo'
|
57
|
+
"<iframe src=\"http://player.vimeo.com/video/#{@id}?title=0&byline=0&portrait=0#{ "&#{options[:url_options]}" if options[:url_options] }#{ "&player_id=#{ options[:player_id] }" if options[:player_id] }\" width=\"#{ options[:width] || 500 }\" height=\"#{ options[:height] || 341 }\" frameborder=\"0\" #{ "id=\"#{ options[:player_id] }\"" if options[:player_id] }webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/media_magick.gemspec
CHANGED
@@ -16,13 +16,17 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = MediaMagick::VERSION
|
17
17
|
|
18
18
|
gem.add_dependency 'carrierwave', '~> 0.6.0'
|
19
|
-
gem.add_dependency 'mongoid', '
|
19
|
+
gem.add_dependency 'mongoid', '>= 2.4'
|
20
20
|
gem.add_dependency 'plupload-rails', '~> 1.0.6'
|
21
21
|
gem.add_dependency 'rails', '~> 3.2.0'
|
22
22
|
|
23
|
-
gem.add_development_dependency 'bson_ext', '~> 1.
|
23
|
+
gem.add_development_dependency 'bson_ext', '~> 1.7.0'
|
24
24
|
gem.add_development_dependency 'mini_magick', '~> 3.4'
|
25
25
|
gem.add_development_dependency 'rake', '~> 0.9'
|
26
|
-
gem.add_development_dependency 'rspec-rails', '~> 2.
|
27
|
-
gem.add_development_dependency 'simplecov', '~> 0.
|
26
|
+
gem.add_development_dependency 'rspec-rails', '~> 2.11.0'
|
27
|
+
gem.add_development_dependency 'simplecov', '~> 0.7.0'
|
28
|
+
|
29
|
+
#gems for code analyses
|
30
|
+
gem.add_development_dependency 'flog', '~> 3.0.0.b2'
|
31
|
+
gem.add_development_dependency 'flay', '~> 2.0.0.b1'
|
28
32
|
end
|
@@ -17,6 +17,18 @@ describe MediaMagick::AttachController do
|
|
17
17
|
response.body.should =~ /nu.jpg/m
|
18
18
|
end
|
19
19
|
|
20
|
+
it "creates a new video" do
|
21
|
+
album = Album.create
|
22
|
+
|
23
|
+
expect {
|
24
|
+
post :create, { model: 'Album', id: album.id, relation: 'photos_and_videos', video: 'youtube.com/watch?v=FfUHkPf9D9k' }
|
25
|
+
}.to change { album.reload.photos_and_videos.count }.by(1)
|
26
|
+
|
27
|
+
response.should render_template('_image')
|
28
|
+
|
29
|
+
response.body.should =~ /FfUHkPf9D9k/m
|
30
|
+
end
|
31
|
+
|
20
32
|
it "creates a new photo for embedded models" do
|
21
33
|
album = Album.create
|
22
34
|
track = album.tracks.create
|
@@ -35,17 +47,6 @@ describe MediaMagick::AttachController do
|
|
35
47
|
post :create, { model: 'Album', id: album.id, relation: 'photos', partial: 'albums/photo', file: fixture_file_upload("#{File.expand_path('../../..', __FILE__)}/support/fixtures/nu.jpg") }
|
36
48
|
response.should render_template('albums/_photo')
|
37
49
|
end
|
38
|
-
|
39
|
-
it 'creates a new photo without parent' do
|
40
|
-
album = Album.new
|
41
|
-
album_files = AlbumFiles.create(file: File.new("#{File.expand_path('../../..', __FILE__)}/support/fixtures/nu.jpg"))
|
42
|
-
|
43
|
-
AlbumFiles.should_receive(:create!).and_return(album_files)
|
44
|
-
|
45
|
-
post :create, { model: 'Album', id: album.id, relation: 'files', file: fixture_file_upload("#{File.expand_path('../../..', __FILE__)}/support/fixtures/nu.jpg") }
|
46
|
-
|
47
|
-
response.body.should =~ /nu.jpg/m
|
48
|
-
end
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
class PostsController < ApplicationController
|
2
|
+
# GET /posts
|
3
|
+
# GET /posts.json
|
4
|
+
def index
|
5
|
+
@posts = Post.all
|
6
|
+
|
7
|
+
respond_to do |format|
|
8
|
+
format.html # index.html.erb
|
9
|
+
format.json { render json: @posts }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# GET /posts/1
|
14
|
+
# GET /posts/1.json
|
15
|
+
def show
|
16
|
+
@post = Post.find(params[:id])
|
17
|
+
|
18
|
+
respond_to do |format|
|
19
|
+
format.html # show.html.erb
|
20
|
+
format.json { render json: @post }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# GET /posts/new
|
25
|
+
# GET /posts/new.json
|
26
|
+
def new
|
27
|
+
@post = Post.new
|
28
|
+
|
29
|
+
respond_to do |format|
|
30
|
+
format.html # new.html.erb
|
31
|
+
format.json { render json: @post }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# GET /posts/1/edit
|
36
|
+
def edit
|
37
|
+
@post = Post.find(params[:id])
|
38
|
+
end
|
39
|
+
|
40
|
+
# POST /posts
|
41
|
+
# POST /posts.json
|
42
|
+
def create
|
43
|
+
@post = Post.new(params[:post])
|
44
|
+
|
45
|
+
respond_to do |format|
|
46
|
+
if @post.save
|
47
|
+
format.html { redirect_to @post, notice: 'Post was successfully created.' }
|
48
|
+
format.json { render json: @post, status: :created, location: @post }
|
49
|
+
else
|
50
|
+
format.html { render action: "new" }
|
51
|
+
format.json { render json: @post.errors, status: :unprocessable_entity }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# PUT /posts/1
|
57
|
+
# PUT /posts/1.json
|
58
|
+
def update
|
59
|
+
@post = Post.find(params[:id])
|
60
|
+
|
61
|
+
respond_to do |format|
|
62
|
+
if @post.update_attributes(params[:post])
|
63
|
+
format.html { redirect_to @post, notice: 'Post was successfully updated.' }
|
64
|
+
format.json { head :no_content }
|
65
|
+
else
|
66
|
+
format.html { render action: "edit" }
|
67
|
+
format.json { render json: @post.errors, status: :unprocessable_entity }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# DELETE /posts/1
|
73
|
+
# DELETE /posts/1.json
|
74
|
+
def destroy
|
75
|
+
@post = Post.find(params[:id])
|
76
|
+
@post.destroy
|
77
|
+
|
78
|
+
respond_to do |format|
|
79
|
+
format.html { redirect_to posts_url }
|
80
|
+
format.json { head :no_content }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -5,7 +5,7 @@ class Album
|
|
5
5
|
embeds_many :tracks
|
6
6
|
|
7
7
|
attaches_many :photos
|
8
|
-
attaches_many :files, :relation => :referenced
|
8
|
+
attaches_many :files, :relation => :referenced, type: 'file'
|
9
9
|
attaches_many :compound_name_files
|
10
10
|
|
11
11
|
attaches_many :images do
|
@@ -13,4 +13,6 @@ class Album
|
|
13
13
|
end
|
14
14
|
|
15
15
|
attaches_many :pictures, uploader: PictureUploader
|
16
|
+
|
17
|
+
attaches_many :photos_and_videos, as: 'photo', uploader: PictureUploader, allow_videos: true
|
16
18
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Post
|
2
|
+
include Mongoid::Document
|
3
|
+
include MediaMagick::Model
|
4
|
+
|
5
|
+
field :title, :type => String
|
6
|
+
field :text, :type => String
|
7
|
+
|
8
|
+
attaches_many :files, :type => 'file'
|
9
|
+
attaches_many :images, :type => 'image', :uploader => PostUploader, :allow_videos => true
|
10
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class PostUploader < CarrierWave::Uploader::Base
|
4
|
+
include CarrierWave::MiniMagick
|
5
|
+
|
6
|
+
storage :file
|
7
|
+
|
8
|
+
def store_dir
|
9
|
+
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
10
|
+
end
|
11
|
+
|
12
|
+
process :resize_to_fill => [50, 50]
|
13
|
+
version :thumb do
|
14
|
+
process :resize_to_fit => [300, 300]
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<%= form_for(@post) do |f| %>
|
2
|
+
<% if @post.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<% @post.errors.full_messages.each do |msg| %>
|
8
|
+
<li><%= msg %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<div class="field">
|
15
|
+
<%= f.label :title %><br />
|
16
|
+
<%= f.text_field :title %>
|
17
|
+
</div>
|
18
|
+
<div class="field">
|
19
|
+
<%= f.label :text %><br />
|
20
|
+
<%= f.text_area :text %>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<h3>uploads</h3>
|
24
|
+
<div class="field" style="overflow: hidden;">
|
25
|
+
<label>imagens and videos</label>
|
26
|
+
<%- if @post.new_record? -%>
|
27
|
+
create first
|
28
|
+
<%- else -%>
|
29
|
+
<%= attachment_container_for_video(@post, :images) %>
|
30
|
+
<br /><br />
|
31
|
+
<%= attachment_container @post, :images %>
|
32
|
+
<%- end -%>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div class="field">
|
36
|
+
<label>files</label>
|
37
|
+
<%- if @post.new_record? -%>
|
38
|
+
create first
|
39
|
+
<%- else -%>
|
40
|
+
<%= attachment_container @post, :files, :as => "file" %>
|
41
|
+
<%- end -%>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<div class="actions">
|
45
|
+
<%= f.submit %>
|
46
|
+
</div>
|
47
|
+
<% end %>
|