Displays thumbnails of attached images of the issue view (#1006).
This behaviour can be turned on/off in Settings -> Display (off by default). Thumbnail size can be configured there too. git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@9933 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
b0bd506201
commit
a0c495b953
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
class AttachmentsController < ApplicationController
|
class AttachmentsController < ApplicationController
|
||||||
before_filter :find_project, :except => :upload
|
before_filter :find_project, :except => :upload
|
||||||
before_filter :file_readable, :read_authorize, :only => [:show, :download]
|
before_filter :file_readable, :read_authorize, :only => [:show, :download, :thumbnail]
|
||||||
before_filter :delete_authorize, :only => :destroy
|
before_filter :delete_authorize, :only => :destroy
|
||||||
before_filter :authorize_global, :only => :upload
|
before_filter :authorize_global, :only => :upload
|
||||||
|
|
||||||
|
@ -59,6 +59,18 @@ class AttachmentsController < ApplicationController
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def thumbnail
|
||||||
|
if @attachment.thumbnailable? && Setting.thumbnails_enabled? && thumbnail = @attachment.thumbnail
|
||||||
|
send_file thumbnail,
|
||||||
|
:filename => filename_for_content_disposition(@attachment.filename),
|
||||||
|
:type => detect_content_type(@attachment),
|
||||||
|
:disposition => 'inline'
|
||||||
|
else
|
||||||
|
# No thumbnail for the attachment or thumbnail could not be created
|
||||||
|
render :nothing => true, :status => 404
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def upload
|
def upload
|
||||||
# Make sure that API users get used to set this content type
|
# Make sure that API users get used to set this content type
|
||||||
# as it won't trigger Rails' automatic parsing of the request body for parameters
|
# as it won't trigger Rails' automatic parsing of the request body for parameters
|
||||||
|
|
|
@ -153,6 +153,12 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def thumbnail_tag(attachment)
|
||||||
|
link_to image_tag(url_for(:controller => 'attachments', :action => 'thumbnail', :id => attachment)),
|
||||||
|
{:controller => 'attachments', :action => 'show', :id => attachment, :filename => attachment.filename},
|
||||||
|
:title => attachment.filename
|
||||||
|
end
|
||||||
|
|
||||||
def toggle_link(name, id, options={})
|
def toggle_link(name, id, options={})
|
||||||
onclick = "Element.toggle('#{id}'); "
|
onclick = "Element.toggle('#{id}'); "
|
||||||
onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
|
onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
|
||||||
|
|
|
@ -21,12 +21,14 @@ module AttachmentsHelper
|
||||||
# Displays view/delete links to the attachments of the given object
|
# Displays view/delete links to the attachments of the given object
|
||||||
# Options:
|
# Options:
|
||||||
# :author -- author names are not displayed if set to false
|
# :author -- author names are not displayed if set to false
|
||||||
|
# :thumbails -- display thumbnails if enabled in settings
|
||||||
def link_to_attachments(container, options = {})
|
def link_to_attachments(container, options = {})
|
||||||
options.assert_valid_keys(:author)
|
options.assert_valid_keys(:author, :thumbnails)
|
||||||
|
|
||||||
if container.attachments.any?
|
if container.attachments.any?
|
||||||
options = {:deletable => container.attachments_deletable?, :author => true}.merge(options)
|
options = {:deletable => container.attachments_deletable?, :author => true}.merge(options)
|
||||||
render :partial => 'attachments/links', :locals => {:attachments => container.attachments, :options => options}
|
render :partial => 'attachments/links',
|
||||||
|
:locals => {:attachments => container.attachments, :options => options, :thumbnails => (options[:thumbnails] && Setting.thumbnails_enabled?)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,9 @@ class Attachment < ActiveRecord::Base
|
||||||
cattr_accessor :storage_path
|
cattr_accessor :storage_path
|
||||||
@@storage_path = Redmine::Configuration['attachments_storage_path'] || File.join(Rails.root, "files")
|
@@storage_path = Redmine::Configuration['attachments_storage_path'] || File.join(Rails.root, "files")
|
||||||
|
|
||||||
|
cattr_accessor :thumbnails_storage_path
|
||||||
|
@@thumbnails_storage_path = File.join(Rails.root, "tmp", "thumbnails")
|
||||||
|
|
||||||
before_save :files_to_final_location
|
before_save :files_to_final_location
|
||||||
after_destroy :delete_from_disk
|
after_destroy :delete_from_disk
|
||||||
|
|
||||||
|
@ -150,7 +153,35 @@ class Attachment < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def image?
|
def image?
|
||||||
self.filename =~ /\.(bmp|gif|jpg|jpe|jpeg|png)$/i
|
!!(self.filename =~ /\.(bmp|gif|jpg|jpe|jpeg|png)$/i)
|
||||||
|
end
|
||||||
|
|
||||||
|
def thumbnailable?
|
||||||
|
image?
|
||||||
|
end
|
||||||
|
|
||||||
|
# Returns the full path the attachment thumbnail, or nil
|
||||||
|
# if the thumbnail cannot be generated.
|
||||||
|
def thumbnail
|
||||||
|
if thumbnailable? && readable?
|
||||||
|
size = Setting.thumbnails_size.to_i
|
||||||
|
size = 100 unless size > 0
|
||||||
|
target = File.join(self.class.thumbnails_storage_path, "#{id}_#{digest}_#{size}.thumb")
|
||||||
|
|
||||||
|
begin
|
||||||
|
Redmine::Thumbnail.generate(self.diskfile, target, size)
|
||||||
|
rescue => e
|
||||||
|
logger.error "An error occured while generating thumbnail for #{disk_filename} to #{target}\nException was: #{e.message}" if logger
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Deletes all thumbnails
|
||||||
|
def self.clear_thumbnails
|
||||||
|
Dir.glob(File.join(thumbnails_storage_path, "*.thumb")).each do |file|
|
||||||
|
File.delete file
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_text?
|
def is_text?
|
||||||
|
|
|
@ -20,4 +20,14 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% if defined?(thumbnails) && thumbnails %>
|
||||||
|
<% images = attachments.select(&:thumbnailable?) %>
|
||||||
|
<% if images.any? %>
|
||||||
|
<div class="thumbnails">
|
||||||
|
<% images.each do |attachment| %>
|
||||||
|
<div><%= thumbnail_tag(attachment) %></div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -81,7 +81,7 @@ end %>
|
||||||
<%= textilizable @issue, :description, :attachments => @issue.attachments %>
|
<%= textilizable @issue, :description, :attachments => @issue.attachments %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= link_to_attachments @issue %>
|
<%= link_to_attachments @issue, :thumbnails => true %>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
||||||
<%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %>
|
<%= call_hook(:view_issues_show_description_bottom, :issue => @issue) %>
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
<p><%= setting_check_box :gravatar_enabled %></p>
|
<p><%= setting_check_box :gravatar_enabled %></p>
|
||||||
|
|
||||||
<p><%= setting_select :gravatar_default, [["Wavatars", 'wavatar'], ["Identicons", 'identicon'], ["Monster ids", 'monsterid'], ["Retro", 'retro'], ["Mystery man", 'mm']], :blank => :label_none %></p>
|
<p><%= setting_select :gravatar_default, [["Wavatars", 'wavatar'], ["Identicons", 'identicon'], ["Monster ids", 'monsterid'], ["Retro", 'retro'], ["Mystery man", 'mm']], :blank => :label_none %></p>
|
||||||
|
|
||||||
|
<p><%= setting_check_box :thumbnails_enabled %></p>
|
||||||
|
|
||||||
|
<p><%= setting_text_field :thumbnails_size, :size => 6 %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= submit_tag l(:button_save) %>
|
<%= submit_tag l(:button_save) %>
|
||||||
|
|
|
@ -163,6 +163,10 @@ default:
|
||||||
# same secret token on each machine.
|
# same secret token on each machine.
|
||||||
#secret_token: 'change it to a long random string'
|
#secret_token: 'change it to a long random string'
|
||||||
|
|
||||||
|
# Absolute path (e.g. /usr/bin/convert, c:/im/convert.exe) to
|
||||||
|
# the ImageMagick's `convert` binary. Used to generate attachment thumbnails.
|
||||||
|
#imagemagick_convert_command:
|
||||||
|
|
||||||
# specific configuration options for production environment
|
# specific configuration options for production environment
|
||||||
# that overrides the default ones
|
# that overrides the default ones
|
||||||
production:
|
production:
|
||||||
|
|
|
@ -394,6 +394,8 @@ en:
|
||||||
setting_unsubscribe: Allow users to delete their own account
|
setting_unsubscribe: Allow users to delete their own account
|
||||||
setting_session_lifetime: Session maximum lifetime
|
setting_session_lifetime: Session maximum lifetime
|
||||||
setting_session_timeout: Session inactivity timeout
|
setting_session_timeout: Session inactivity timeout
|
||||||
|
setting_thumbnails_enabled: Display attachment thumbnails
|
||||||
|
setting_thumbnails_size: Thumbnails size (in pixels)
|
||||||
|
|
||||||
permission_add_project: Create project
|
permission_add_project: Create project
|
||||||
permission_add_subprojects: Create subprojects
|
permission_add_subprojects: Create subprojects
|
||||||
|
|
|
@ -390,6 +390,8 @@ fr:
|
||||||
setting_unsubscribe: Permettre aux utilisateurs de supprimer leur propre compte
|
setting_unsubscribe: Permettre aux utilisateurs de supprimer leur propre compte
|
||||||
setting_session_lifetime: Durée de vie maximale des sessions
|
setting_session_lifetime: Durée de vie maximale des sessions
|
||||||
setting_session_timeout: Durée maximale d'inactivité
|
setting_session_timeout: Durée maximale d'inactivité
|
||||||
|
setting_thumbnails_enabled: Afficher les vignettes des images
|
||||||
|
setting_thumbnails_size: Taille des vignettes (en pixels)
|
||||||
|
|
||||||
permission_add_project: Créer un projet
|
permission_add_project: Créer un projet
|
||||||
permission_add_subprojects: Créer des sous-projets
|
permission_add_subprojects: Créer des sous-projets
|
||||||
|
|
|
@ -264,6 +264,7 @@ RedmineApp::Application.routes.draw do
|
||||||
match 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/, :via => :get
|
match 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/, :via => :get
|
||||||
match 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/, :via => :get
|
match 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/, :via => :get
|
||||||
match 'attachments/download/:id', :controller => 'attachments', :action => 'download', :id => /\d+/, :via => :get
|
match 'attachments/download/:id', :controller => 'attachments', :action => 'download', :id => /\d+/, :via => :get
|
||||||
|
match 'attachments/thumbnail/:id', :controller => 'attachments', :action => 'thumbnail', :id => /\d+/, :via => :get
|
||||||
resources :attachments, :only => [:show, :destroy]
|
resources :attachments, :only => [:show, :destroy]
|
||||||
|
|
||||||
resources :groups do
|
resources :groups do
|
||||||
|
|
|
@ -212,3 +212,8 @@ default_notification_option:
|
||||||
default: 'only_my_events'
|
default: 'only_my_events'
|
||||||
emails_header:
|
emails_header:
|
||||||
default: ''
|
default: ''
|
||||||
|
thumbnails_enabled:
|
||||||
|
default: 0
|
||||||
|
thumbnails_size:
|
||||||
|
format: int
|
||||||
|
default: 100
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Redmine - project management software
|
||||||
|
# Copyright (C) 2006-2012 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
require 'fileutils'
|
||||||
|
|
||||||
|
module Redmine
|
||||||
|
module Thumbnail
|
||||||
|
extend Redmine::Utils::Shell
|
||||||
|
|
||||||
|
# Generates a thumbnail for the source image to target
|
||||||
|
def self.generate(source, target, size)
|
||||||
|
unless File.exists?(target)
|
||||||
|
directory = File.dirname(target)
|
||||||
|
unless File.exists?(directory)
|
||||||
|
FileUtils.mkdir_p directory
|
||||||
|
end
|
||||||
|
bin = Redmine::Configuration['imagemagick_convert_command'] || 'convert'
|
||||||
|
size_option = "#{size}x#{size}>"
|
||||||
|
cmd = "#{shell_quote bin} #{shell_quote source} -thumbnail #{shell_quote size_option} #{shell_quote target}"
|
||||||
|
unless system(cmd)
|
||||||
|
logger.error("Creating thumbnail failed (#{$?}):\nCommand: #{cmd}")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
target
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.logger
|
||||||
|
Rails.logger
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -41,5 +41,15 @@ module Redmine
|
||||||
SecureRandom.hex(n)
|
SecureRandom.hex(n)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Shell
|
||||||
|
def shell_quote(str)
|
||||||
|
if Redmine::Platform.mswin?
|
||||||
|
'"' + str.gsub(/"/, '\\"') + '"'
|
||||||
|
else
|
||||||
|
"'" + str.gsub(/'/, "'\"'\"'") + "'"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -516,6 +516,10 @@ div.attachments p { margin:4px 0 2px 0; }
|
||||||
div.attachments img { vertical-align: middle; }
|
div.attachments img { vertical-align: middle; }
|
||||||
div.attachments span.author { font-size: 0.9em; color: #888; }
|
div.attachments span.author { font-size: 0.9em; color: #888; }
|
||||||
|
|
||||||
|
div.thumbnails {margin-top:0.6em;}
|
||||||
|
div.thumbnails div {background:#fff;border:2px solid #ddd;display:inline-block;margin-right:2px;}
|
||||||
|
div.thumbnails img {margin: 3px;}
|
||||||
|
|
||||||
p.other-formats { text-align: right; font-size:0.9em; color: #666; }
|
p.other-formats { text-align: right; font-size:0.9em; color: #666; }
|
||||||
.other-formats span + span:before { content: "| "; }
|
.other-formats span + span:before { content: "| "; }
|
||||||
|
|
||||||
|
|
|
@ -252,12 +252,58 @@ class AttachmentsControllerTest < ActionController::TestCase
|
||||||
set_tmp_attachments_directory
|
set_tmp_attachments_directory
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_anonymous_on_private_private
|
def test_download_should_be_denied_without_permission
|
||||||
get :download, :id => 7
|
get :download, :id => 7
|
||||||
assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fdownload%2F7'
|
assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fdownload%2F7'
|
||||||
set_tmp_attachments_directory
|
set_tmp_attachments_directory
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if convert_installed?
|
||||||
|
def test_thumbnail
|
||||||
|
Attachment.clear_thumbnails
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
with_settings :thumbnails_enabled => '1' do
|
||||||
|
get :thumbnail, :id => 16
|
||||||
|
assert_response :success
|
||||||
|
assert_equal 'image/png', response.content_type
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_thumbnail_should_return_404_for_non_image_attachment
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
with_settings :thumbnails_enabled => '1' do
|
||||||
|
get :thumbnail, :id => 15
|
||||||
|
assert_response 404
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_thumbnail_should_return_404_if_thumbnails_not_enabled
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
with_settings :thumbnails_enabled => '0' do
|
||||||
|
get :thumbnail, :id => 16
|
||||||
|
assert_response 404
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_thumbnail_should_return_404_if_thumbnail_generation_failed
|
||||||
|
Attachment.any_instance.stubs(:thumbnail).returns(nil)
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
with_settings :thumbnails_enabled => '1' do
|
||||||
|
get :thumbnail, :id => 16
|
||||||
|
assert_response 404
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_thumbnail_should_be_denied_without_permission
|
||||||
|
with_settings :thumbnails_enabled => '1' do
|
||||||
|
get :thumbnail, :id => 16
|
||||||
|
assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fthumbnail%2F16'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts '(ImageMagick convert not available)'
|
||||||
|
end
|
||||||
|
|
||||||
def test_destroy_issue_attachment
|
def test_destroy_issue_attachment
|
||||||
set_tmp_attachments_directory
|
set_tmp_attachments_directory
|
||||||
issue = Issue.find(3)
|
issue = Issue.find(3)
|
||||||
|
|
|
@ -1155,7 +1155,33 @@ class IssuesControllerTest < ActionController::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_show_with_thumbnails_enabled_should_display_thumbnails
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
|
||||||
|
with_settings :thumbnails_enabled => '1' do
|
||||||
|
get :show, :id => 14
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_select 'div.thumbnails' do
|
||||||
|
assert_select 'a[href=/attachments/16/testfile.png]' do
|
||||||
|
assert_select 'img[src=/attachments/thumbnail/16]'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_show_with_thumbnails_disabled_should_not_display_thumbnails
|
||||||
|
@request.session[:user_id] = 2
|
||||||
|
|
||||||
|
with_settings :thumbnails_enabled => '0' do
|
||||||
|
get :show, :id => 14
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_select 'div.thumbnails', 0
|
||||||
|
end
|
||||||
|
|
||||||
def test_show_with_multi_custom_field
|
def test_show_with_multi_custom_field
|
||||||
field = CustomField.find(1)
|
field = CustomField.find(1)
|
||||||
field.update_attribute :multiple, true
|
field.update_attribute :multiple, true
|
||||||
|
|
|
@ -45,6 +45,10 @@ class RoutingAttachmentsTest < ActionController::IntegrationTest
|
||||||
{ :controller => 'attachments', :action => 'download', :id => '1',
|
{ :controller => 'attachments', :action => 'download', :id => '1',
|
||||||
:filename => 'filename.ext' }
|
:filename => 'filename.ext' }
|
||||||
)
|
)
|
||||||
|
assert_routing(
|
||||||
|
{ :method => 'get', :path => "/attachments/thumbnail/1" },
|
||||||
|
{ :controller => 'attachments', :action => 'thumbnail', :id => '1' }
|
||||||
|
)
|
||||||
assert_routing(
|
assert_routing(
|
||||||
{ :method => 'delete', :path => "/attachments/1" },
|
{ :method => 'delete', :path => "/attachments/1" },
|
||||||
{ :controller => 'attachments', :action => 'destroy', :id => '1' }
|
{ :controller => 'attachments', :action => 'destroy', :id => '1' }
|
||||||
|
|
|
@ -128,6 +128,13 @@ class ActiveSupport::TestCase
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.convert_installed?
|
||||||
|
bin = Redmine::Configuration['imagemagick_convert_command'] || 'convert'
|
||||||
|
system("#{bin} -version")
|
||||||
|
rescue
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
# Returns the path to the test +vendor+ repository
|
# Returns the path to the test +vendor+ repository
|
||||||
def self.repository_path(vendor)
|
def self.repository_path(vendor)
|
||||||
Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
|
Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
|
||||||
|
|
|
@ -214,4 +214,28 @@ class AttachmentTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
set_tmp_attachments_directory
|
set_tmp_attachments_directory
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_thumbnailable_should_be_true_for_images
|
||||||
|
assert_equal true, Attachment.new(:filename => 'test.jpg').thumbnailable?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_thumbnailable_should_be_true_for_non_images
|
||||||
|
assert_equal false, Attachment.new(:filename => 'test.txt').thumbnailable?
|
||||||
|
end
|
||||||
|
|
||||||
|
if convert_installed?
|
||||||
|
def test_thumbnail_should_generate_the_thumbnail
|
||||||
|
set_fixtures_attachments_directory
|
||||||
|
attachment = Attachment.find(16)
|
||||||
|
Attachment.clear_thumbnails
|
||||||
|
|
||||||
|
assert_difference "Dir.glob(File.join(Attachment.thumbnails_storage_path, '*.thumb')).size" do
|
||||||
|
thumbnail = attachment.thumbnail
|
||||||
|
assert_equal "16_8e0294de2441577c529f170b6fb8f638_100.thumb", File.basename(thumbnail)
|
||||||
|
assert File.exists?(thumbnail)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts '(ImageMagick convert not available)'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue