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.
Files changed (47) hide show
  1. data/.gitignore +2 -1
  2. data/.travis.yml +7 -3
  3. data/CHANGELOG.md +92 -1
  4. data/README.md +1 -1
  5. data/app/assets/javascripts/media_magick/plupload_it.js +30 -9
  6. data/app/controllers/media_magick/attach_controller.rb +16 -28
  7. data/app/helpers/media_magick/application_helper.rb +46 -5
  8. data/app/views/_file.html.erb +2 -2
  9. data/app/views/_image.html.erb +3 -3
  10. data/app/views/_upload.html.erb +3 -10
  11. data/app/views/_video.html.erb +8 -0
  12. data/gemfiles/mongoid-3.0.gemfile +7 -0
  13. data/lib/media_magick.rb +1 -5
  14. data/lib/media_magick/controller/helpers.rb +20 -0
  15. data/lib/media_magick/engine.rb +1 -1
  16. data/lib/media_magick/model.rb +41 -48
  17. data/lib/media_magick/version.rb +1 -1
  18. data/lib/media_magick/video/parser.rb +62 -0
  19. data/media_magick.gemspec +8 -4
  20. data/spec/controllers/media_magick/attach_controller_spec.rb +12 -11
  21. data/spec/dummy/app/assets/javascripts/application.js +5 -0
  22. data/spec/dummy/app/assets/javascripts/posts.js +2 -0
  23. data/spec/dummy/app/assets/stylesheets/posts.css +4 -0
  24. data/spec/dummy/app/controllers/posts_controller.rb +83 -0
  25. data/spec/dummy/app/helpers/posts_helper.rb +2 -0
  26. data/spec/dummy/app/models/album.rb +3 -1
  27. data/spec/dummy/app/models/post.rb +10 -0
  28. data/spec/dummy/app/models/track.rb +1 -0
  29. data/spec/dummy/app/uploaders/post_uploader.rb +17 -0
  30. data/spec/dummy/app/views/posts/_form.html.erb +47 -0
  31. data/spec/dummy/app/views/posts/edit.html.erb +6 -0
  32. data/spec/dummy/app/views/posts/index.html.erb +25 -0
  33. data/spec/dummy/app/views/posts/new.html.erb +5 -0
  34. data/spec/dummy/app/views/posts/show.html.erb +15 -0
  35. data/spec/dummy/app/views/users/index.html.erb +1 -1
  36. data/spec/dummy/config/mongoid.yml +65 -17
  37. data/spec/dummy/config/routes.rb +3 -0
  38. data/spec/helpers/media_magick/application_helper_spec.rb +90 -27
  39. data/spec/integration/images_spec.rb +1 -1
  40. data/spec/lib/media_magick/controller/helper_spec.rb +37 -0
  41. data/spec/lib/media_magick/model_spec.rb +41 -9
  42. data/spec/lib/media_magick/video/parser_spec.rb +67 -0
  43. data/spec/spec_helper.rb +11 -8
  44. data/spec/views/_upload.html.erb_spec.rb +26 -0
  45. metadata +76 -21
  46. data/.rvmrc +0 -1
  47. data/spec/dummy/app/helpers/users_helper.rb +0 -2
@@ -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 attachs_many(name, options = {}, &block)
11
- warn "[DEPRECATION] `attachs_many` is deprecated. Please use `attaches_many` instead."
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
- # TODO
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
- if options[:relation] == :referenced
28
- belongs_to :attachmentable, polymorphic: true
29
- else
30
- embedded_in :attachmentable, polymorphic: true
31
- end
21
+ embedded_in(:attachmentable, polymorphic: true)
22
+ end
32
23
 
33
- mount_uploader name.to_s.singularize, (options[:uploader] || AttachmentUploader)
24
+ embeds_many(name, :as => :attachmentable, class_name: "#{self}#{name_camelcase}")
25
+ end
34
26
 
35
- self.const_set "TYPE", options[:type] || :image
36
- self.const_set "ATTACHMENT", name.to_s.singularize
27
+ def attaches_one(name, options = {})
28
+ attaches_block = block_given? ? Proc.new : nil
37
29
 
38
- class_eval(&block) if block_given?
30
+ name_camelcase = create_attaches_class(name, options, attaches_block) do
31
+ create_video_methods(name) if options[:allow_videos]
39
32
 
40
- def method_missing(method, args = nil)
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 = name.to_s.camelcase
47
- Object.const_set "#{self}#{name_camelcase}", klass
36
+ embeds_one(name, class_name: "#{self}#{name_camelcase}", cascade_callbacks: true)
37
+ end
38
+
39
+ private
48
40
 
49
- if options[:relation] == :referenced
50
- klass.collection_name = "#{self.name}_#{name.to_s.camelcase}".parameterize
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
- has_many(name, :as => :attachmentable, class_name: "#{self}#{name_camelcase}")
46
+ field :type, type: String, default: options[:as] || 'image'
53
47
 
54
- field "#{name.to_s.singularize}_ids", type: Array
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
- before_create do
57
- ids = self.send("#{name.to_s.singularize}_ids") || []
60
+ def source(options = {})
61
+ video = MediaMagick::Video::Parser.new(self.video)
58
62
 
59
- ids.each do |id|
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
- def attaches_one(name, options = {}, &block)
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(&block) if block_given?
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
- embeds_one name, class_name: "#{self}#{name_camelcase}", cascade_callbacks: true
85
+ return name_camelcase
93
86
  end
94
87
  end
95
88
  end
@@ -1,3 +1,3 @@
1
1
  module MediaMagick
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
@@ -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', '~> 2.4.0'
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.6.0'
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.10.1'
27
- gem.add_development_dependency 'simplecov', '~> 0.6.1'
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
 
@@ -12,4 +12,9 @@
12
12
  //
13
13
  //= require jquery
14
14
  //= require jquery_ujs
15
+ //= require media_magick/plupload_it
15
16
  //= require_tree .
17
+
18
+ $(document).ready(function () {
19
+ $(".attachmentUploader").pluploadIt();
20
+ });
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -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
@@ -0,0 +1,2 @@
1
+ module PostsHelper
2
+ 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
@@ -5,4 +5,5 @@ class Track
5
5
  embedded_in :album
6
6
 
7
7
  attaches_many :files
8
+ attaches_many :photos_and_videos, as: 'photo', uploader: PictureUploader, allow_videos: true
8
9
  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 %>