media_magick 0.1.0 → 0.1.1

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.
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 %>