Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'flash-embed-tag' of git://github.com/gerrit/paperclippe…

…d into gerrit
  • Loading branch information...
commit 08581bd3d79b80e7c174ea5288316bf45a80d995 2 parents b545acd + d3316ab
@kbingman kbingman authored
View
147 app/models/asset.rb
@@ -1,24 +1,73 @@
+require 'mime_type_ext'
+
class Asset < ActiveRecord::Base
-
+ Mime::Type.register 'image/png', :image, %w[image/png image/x-png image/jpeg image/pjpeg image/jpg image/gif]
+ Mime::Type.register 'video/mpeg', :video, %w[video/mpeg video/mp4 video/ogg video/quicktime video/x-ms-wmv video/x-flv]
+ Mime::Type.register 'audio/mpeg', :audio, %w[audio/mpeg audio/ogg application/ogg audio/x-ms-wma audio/vnd.rn-realaudio audio/x-wav]
+ Mime::Type.register 'application/x-shockwave-flash', :swf
+ Mime::Type.register 'application/pdf', :pdf
+ # A “movie” can be a swf or a video file (retained for back-compat)
+ Mime::Type.register Mime::SWF.to_s, :movie, Mime::VIDEO.all_types
+
+ def self.known_types
+ [:image, :video, :audio, :swf, :pdf, :movie]
+ end
+
class << self
- def image?(asset_content_type)
- image_content_types.include?(asset_content_type)
- end
-
- def movie?(asset_content_type)
- asset_content_type.to_s =~ /^video/ || extra_content_types[:movie].include?(asset_content_type)
- end
-
- def audio?(asset_content_type)
- asset_content_type.to_s =~ /^audio/ || extra_content_types[:audio].include?(asset_content_type)
+ Asset.known_types.each do |type|
+ define_method "#{type}?" do |asset_content_type|
+ Mime::Type.lookup_by_extension(type.to_s) == asset_content_type.to_s
+ end
+
+ define_method "#{type}_condition" do
+ types = Mime::Type.lookup_by_extension(type.to_s).all_types
+ # use #send due to a ruby 1.8.2 issue
+ send(:sanitize_sql, ['asset_content_type IN (?)', types])
+ end
end
def other?(asset_content_type)
- ![:image, :movie, :audio].any? { |a| send("#{a}?", asset_content_type) }
+ !known_types.any? { |type| send("#{type}?", asset_content_type) }
end
+
+ def other_condition
+ excluded_types = Mime::IMAGE.all_types + Mime::AUDIO.all_types + Mime::MOVIE.all_types
+ # use #send due to a ruby 1.8.2 issue
+ send(:sanitize_sql, ['asset_content_type NOT IN (?)', excluded_types])
+ end
+ end
+ (known_types + [:other]).each do |type|
+ named_scope type.to_s.pluralize.intern, :conditions => self.send("#{type}_condition".intern)
+ end
+
+ class << self
+ def search(search, filter, page)
+ unless search.blank?
- def pdf?(asset_content_type)
- extra_content_types[:pdf].include? asset_content_type
+ search_cond_sql = []
+ search_cond_sql << 'LOWER(asset_file_name) LIKE (:term)'
+ search_cond_sql << 'LOWER(title) LIKE (:term)'
+ search_cond_sql << 'LOWER(caption) LIKE (:term)'
+
+ cond_sql = search_cond_sql.join(" or ")
+
+ @conditions = [cond_sql, {:term => "%#{search.downcase}%" }]
+ else
+ @conditions = []
+ end
+
+ options = { :conditions => @conditions,
+ :order => 'created_at DESC',
+ :page => page,
+ :per_page => 10 }
+
+ @file_types = filter.blank? ? [] : filter.keys
+ if not @file_types.empty?
+ options[:total_entries] = count_by_conditions
+ Asset.paginate_by_content_types(@file_types, :all, options )
+ else
+ Asset.paginate(:all, options)
+ end
end
def find_all_by_content_types(types, *args)
@@ -28,7 +77,12 @@ def find_all_by_content_types(types, *args)
def with_content_types(types, &block)
with_scope(:find => { :conditions => types_to_conditions(types).join(' OR ') }, &block)
end
-
+
+ def count_by_conditions
+ type_conditions = @file_types.blank? ? nil : Asset.types_to_conditions(@file_types.dup).join(" OR ")
+ @count_by_conditions ||= @conditions.empty? ? Asset.count(:all, :conditions => type_conditions) : Asset.count(:all, :conditions => @conditions)
+ end
+
def types_to_conditions(types)
types.collect! { |t| '(' + send("#{t}_condition") + ')' }
end
@@ -83,9 +137,12 @@ def additional_thumbnails
before_save :assign_title
def thumbnail(size='original')
+ return asset.url if size == 'original'
case
when self.pdf? : "/images/assets/pdf_#{size.to_s}.png"
when self.movie? : "/images/assets/movie_#{size.to_s}.png"
+ when self.video? : "/images/assets/movie_#{size.to_s}.png"
+ when self.swf? : "/images/assets/movie_#{size.to_s}.png" #TODO: special icon for swf-files
when self.audio? : "/images/assets/audio_#{size.to_s}.png"
when self.other? : "/images/assets/doc_#{size.to_s}.png"
else
@@ -111,10 +168,6 @@ def extension
asset_file_name.split('.').last.downcase if asset_file_name
end
- [:movie, :audio, :image, :other, :pdf].each do |content|
- define_method("#{content}?") { self.class.send("#{content}?", asset_content_type) }
- end
-
def dimensions(size='original')
@dimensions ||= {}
@dimensions[size] ||= image? && begin
@@ -133,60 +186,10 @@ def width(size='original')
def height(size='original')
image? && self.dimensions(size)[1]
end
-
- def self.search(search, filter, page)
- unless search.blank?
-
- search_cond_sql = []
- search_cond_sql << 'LOWER(asset_file_name) LIKE (:term)'
- search_cond_sql << 'LOWER(title) LIKE (:term)'
- search_cond_sql << 'LOWER(caption) LIKE (:term)'
-
- cond_sql = search_cond_sql.join(" or ")
-
- @conditions = [cond_sql, {:term => "%#{search.downcase}%" }]
- else
- @conditions = []
- end
-
- options = { :conditions => @conditions,
- :order => 'created_at DESC',
- :page => page,
- :per_page => 10 }
-
- @file_types = filter.blank? ? [] : filter.keys
- if not @file_types.empty?
- options[:total_entries] = count_by_conditions
- Asset.paginate_by_content_types(@file_types, :all, options )
- else
- Asset.paginate(:all, options)
- end
- end
-
- def self.count_by_conditions()
- type_conditions = @file_types.blank? ? nil : Asset.types_to_conditions(@file_types.dup).join(" OR ")
- @count_by_conditions ||= @conditions.empty? ? Asset.count(:all, :conditions => type_conditions) : Asset.count(:all, :conditions => @conditions)
- end
-
- # used for extra mime types that do not follow the convention
- @@image_content_types = ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png', 'image/jpg']
- @@extra_content_types = { :audio => ['application/ogg'],
- :movie => ['application/x-shockwave-flash'],
- :pdf => ['application/pdf'] }.freeze
- cattr_reader :extra_content_types, :image_content_types
- # use #send due to a ruby 1.8.2 issue
- @@image_condition = send(:sanitize_sql, ['asset_content_type IN (?)', image_content_types]).freeze
- @@movie_condition = send(:sanitize_sql, ['asset_content_type LIKE ? OR asset_content_type IN (?)', 'video%', extra_content_types[:movie]]).freeze
- @@audio_condition = send(:sanitize_sql, ['asset_content_type LIKE ? OR asset_content_type IN (?)', 'audio%', extra_content_types[:audio]]).freeze
-
- @@other_condition = send(:sanitize_sql, [
- 'asset_content_type NOT LIKE ? AND asset_content_type NOT LIKE ? AND asset_content_type NOT IN (?)',
- 'audio%', 'video%', (extra_content_types[:movie] + extra_content_types[:audio] + image_content_types)]).freeze
- cattr_reader *%w(movie audio image other).collect! { |t| "#{t}_condition".to_sym }
-
- %w(movie audio image other).each do |type|
- named_scope type.pluralize.intern, :conditions => self.send("#{type}_condition".intern)
+ #delegating methods like image? to class
+ (known_types+[:other]).each do |type|
+ define_method("#{type}?") { self.class.send("#{type}?", asset_content_type) }
end
private
View
39 app/models/asset_tags.rb
@@ -189,6 +189,45 @@ class TagError < StandardError; end
raise TagError, "Asset is not an image"
end
end
+ desc %{
+ Embeds a flash-movie in a cross-browser-compatible fashion using only HTML
+
+ *Usage:*
+ <pre><code><r:assets:flash [title="asset_title"] [width="100"] [height="100"]>Fallback content</flash></code></pre>
+
+ *Example with text fallback:*
+ <pre><code>
+ <r:assets:flash title="flash_movie" width="300"] height="200">
+ Sorry, you need to have flash installed, <a href="http://adobe.com/flash">get it here</a>
+ </flash>
+ </code></pre>
+
+ *Example with image fallback:*
+ <pre><code>
+ <r:assets:flash title="flash_movie" width="300"] height="200">
+ <r:assets:image title="flash_screenshot" />
+ </flash>
+ </code></pre>
+ }
+ tag 'assets:flash' do |tag|
+ asset = find_asset(tag, tag.attr.dup)
+ raise TagError, 'Must be flash' unless asset.swf?
+ dimensions = %w[width height].inject('') do |attrs, dimension|
+ attrs << %{#{dimension}="#{tag.attr[dimension]}" } if tag.attr[dimension]
+ attrs
+ end.strip
+ url = asset.thumbnail('original')
+ %{<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" #{dimensions}>
+ <param name="movie" value="#{url}" />
+ <!--[if !IE]>-->
+ <object type="application/x-shockwave-flash" data="#{url}" #{dimensions}>
+ <!--<![endif]-->
+ #{tag.expand}
+ <!--[if !IE]>-->
+ </object>
+ <!--<![endif]-->
+ </object>}
+ end
tag 'assets:thumbnail' do |tag|
options = tag.attr.dup
View
7 lib/mime_type_ext.rb
@@ -0,0 +1,7 @@
+class Mime::Type
+ attr_reader :synonyms
+
+ def all_types
+ ([self.to_s] + synonyms).uniq
+ end
+end
View
15 spec/blueprints.rb
@@ -1,15 +0,0 @@
-require 'faker'
-
-Sham.define do
- title { Faker::Lorem.words(5).join(' ') }
- caption { Faker::Lorem.words(15).join(' ') }
- asset_file_name { Faker::Name.name + '.jpg' }
-end
-
-Asset.blueprint do
- title
- caption
- asset_file_name 'asset.jpg'
- asset_content_type 'image/jpeg'
- asset_file_size '46248'
-end
View
201 spec/models/asset_spec.rb
@@ -1,11 +1,204 @@
require File.dirname(__FILE__) + '/../spec_helper'
describe Asset do
- before(:each) do
- @asset = Asset.make
+ def default_attributes
+ {
+ :asset_file_name => 'asset.jpg',
+ :asset_content_type => 'image/jpeg',
+ :asset_file_size => '46248'
+ }
end
+ def new_asset(overrides={})
+ Asset.new default_attributes.merge(overrides)
+ end
+ def create_asset(overrides={})
+ Asset.create! default_attributes.merge(overrides)
+ end
+
+ it 'should be valid when instantiated' do
+ new_asset.should be_valid
+ end
+
+ it 'should be valid when saved' do
+ create_asset.should be_valid
+ end
+
+ describe 'content types' do
+ describe 'images' do
+ ['image/jpeg', 'image/pjpeg', 'image/gif', 'image/png', 'image/x-png', 'image/jpg'].each do |mime|
+ it "should be an image if it has a content type of #{mime}" do
+ new_asset(:asset_content_type => mime).should be_image
+ end
+ (Asset.known_types - [:image]).each do |other|
+ it "should not be #{other}" do
+ new_asset(:asset_content_type => mime).send("#{other}?").should_not be_true
+ end
+ end
+ end
+
+ describe 'scope' do
+ it 'should only return image assets' do
+ jpeg = create_asset :asset_content_type => 'image/jpeg'
+ gif = create_asset :asset_content_type => 'image/gif'
+ pdf = create_asset :asset_content_type => 'application/pdf'
+ Asset.images.should == [jpeg, gif]
+ end
+ end
+ end
+
+ describe 'audio' do
+ it 'should be audio when its an mp3' do
+ new_asset(:asset_content_type => 'audio/mpeg').should be_audio
+ end
- it "should be valid" do
- @asset.should be_valid
+ it 'should be audio when its a windows media audio file' do
+ new_asset(:asset_content_type => 'audio/x-ms-wma').should be_audio
+ end
+
+ it 'should be audio when its an ogg file' do
+ new_asset(:asset_content_type => 'application/ogg').should be_audio
+ end
+
+ describe 'scope' do
+ it 'should only return audio files' do
+ qt = create_asset :asset_content_type => 'video/quicktime'
+ mp3 = create_asset :asset_content_type => 'audio/mpeg'
+ ogg = create_asset :asset_content_type => 'application/ogg'
+ pdf = create_asset :asset_content_type => 'application/pdf'
+ Asset.audios.should == [mp3, ogg]
+ end
+ end
+ end
+
+ describe 'movies' do
+ it 'should be movie when it has video/* content-type' do
+ new_asset(:asset_content_type => 'video/quicktime').should be_movie
+ end
+ it 'should be movie when it has flash content type' do
+ new_asset(:asset_content_type => 'application/x-shockwave-flash').should be_movie
+ end
+ describe 'scope' do
+ it 'should return swf and video assets, not others' do
+ create_asset :asset_content_type => 'audio/mpeg'
+ qt = create_asset :asset_content_type => 'video/quicktime'
+ create_asset :asset_content_type => 'application/pdf'
+ swf = create_asset :asset_content_type => 'application/x-shockwave-flash'
+ Asset.movies.should == [qt, swf]
+ end
+ end
+ end
+
+ describe 'flash' do
+ it 'should be swf when it has flash content type' do
+ new_asset(:asset_content_type => 'application/x-shockwave-flash').should be_swf
+ end
+
+ describe 'scope' do
+ it 'should only return swf assets' do
+ gif = create_asset :asset_content_type => 'image/gif'
+ pdf = create_asset :asset_content_type => 'application/pdf'
+ swf = create_asset :asset_content_type => 'application/x-shockwave-flash'
+ Asset.swfs.should == [swf]
+ end
+ end
+ end
+
+ describe 'video' do
+ it 'should be video when it has a quicktime content-type' do
+ new_asset(:asset_content_type => 'video/quicktime').should be_video
+ end
+
+ describe 'scope' do
+ it 'should only return video assets' do
+ qt = create_asset :asset_content_type => 'video/quicktime'
+ pdf = create_asset :asset_content_type => 'application/pdf'
+ swf = create_asset :asset_content_type => 'application/x-shockwave-flash'
+ Asset.videos.should == [qt]
+ end
+ end
+ end
+
+ describe 'pdf' do
+ it 'should be pdf when it has pdf content-type' do
+ new_asset(:asset_content_type => 'application/pdf').should be_pdf
+ end
+
+ describe 'scope' do
+ it 'should only return pdf assets' do
+ gif = create_asset :asset_content_type => 'image/gif'
+ pdf = create_asset :asset_content_type => 'application/pdf'
+ swf = create_asset :asset_content_type => 'application/x-shockwave-flash'
+ Asset.pdfs.should == [pdf]
+ end
+ end
+ end
+
+ describe 'other' do
+ it 'text document should be other' do
+ new_asset(:asset_content_type => 'text/plain').should be_other
+ end
+
+ it 'binary should be other' do
+ new_asset(:asset_content_type => 'application/octet-stream').should be_other
+ end
+
+ describe 'scope' do
+ it 'should only return types not covered by other scopes' do
+ # create_asset :asset_content_type => 'application/pdf'
+ create_asset :asset_content_type => 'application/x-shockwave-flash'
+ txt = create_asset :asset_content_type => 'text/plain'
+ create_asset :asset_content_type => 'image/gif'
+ create_asset :asset_content_type => 'video/quicktime'
+ create_asset :asset_content_type => 'audio/mpeg'
+ bin = create_asset :asset_content_type => 'application/octet-stream'
+ create_asset :asset_content_type => 'application/ogg'
+
+ Asset.others.should == [txt, bin]
+ end
+ end
+ end
+ end
+
+ describe '#thumbnail' do
+ describe 'without argument' do
+ it 'should return paperclip asset url for image' do
+ image = new_asset :asset_content_type => 'image/jpeg'
+ image.stub! :asset => mock('asset', :url => '/y/z/e.jpg')
+ image.thumbnail.should == '/y/z/e.jpg'
+ end
+
+ it 'should return paperclip asset url for non-image' do
+ asset = new_asset :asset_content_type => 'application/pdf'
+ asset.stub! :asset => mock('asset', :url => '/y/z/e.pdf')
+ asset.thumbnail.should == '/y/z/e.pdf'
+ end
+ end
+
+ describe 'with size=original' do
+ it 'should return paperclip asset url for image' do
+ image = new_asset :asset_content_type => 'image/jpeg'
+ image.stub! :asset => mock('asset', :url => '/y/z/e.jpg')
+ image.thumbnail('original').should == '/y/z/e.jpg'
+ end
+
+ it 'should return paperclip asset url for non-image' do
+ asset = new_asset :asset_content_type => 'application/pdf'
+ asset.stub! :asset => mock('asset', :url => '/y/z/e.pdf')
+ asset.thumbnail('original').should == '/y/z/e.pdf'
+ end
+ end
+
+ it 'should return resized image for images when given size' do
+ image = new_asset :asset_content_type => 'image/jpeg'
+ image.stub! :asset => mock('asset')
+ image.asset.stub!(:url).with(:thumbnail).and_return('/re/sized/image_thumbnail.jpg')
+ image.thumbnail('thumbnail').should == '/re/sized/image_thumbnail.jpg'
+ end
+
+ it 'should return icon for non-image with a given size' do
+ image = new_asset :asset_content_type => 'application/pdf'
+ image.thumbnail('thumbnail').should == "/images/assets/pdf_thumbnail.png"
+ end
end
+
end
View
4 spec/spec_helper.rb
@@ -6,10 +6,10 @@
require 'spec/rails'
-require File.expand_path(File.dirname(__FILE__) + "/blueprints")
+# require File.expand_path(File.dirname(__FILE__) + "/blueprints")
Spec::Runner.configure do |config|
- # config.use_transactional_fixtures = true
+ config.use_transactional_fixtures = true
# config.use_instantiated_fixtures = false
# config.fixture_path = RAILS_ROOT + '/spec/fixtures'
Please sign in to comment.
Something went wrong with that request. Please try again.