Skip to content
Browse files

cleaning up the migration, removing support for backward migrations a…

…nd added an upgrade notes file
  • Loading branch information...
1 parent 959cb0f commit 26e79a77ca5d1441a1a9e72f0568786459a7c2d5 Matthew Peychich committed Oct 9, 2009
Showing with 150 additions and 2,980 deletions.
  1. +1 −0 README
  2. +2 −0 UPGRADE_NOTES
  3. +2 −2 app/helpers/photos_helper.rb
  4. +1 −8 app/models/photo.rb
  5. +8 −9 app/models/profile.rb
  6. +1 −1 config/initializers/avatar_sources.rb
  7. +0 −2 config/initializers/file_column_settings.rb
  8. +7 −60 db/migrate/20091006171847_move_to_paperclip.rb
  9. +4 −4 test/functional/profiles_controller_test.rb
  10. +4 −1 vendor/gems/colored-1.1/.specification
  11. +4 −1 vendor/gems/gcnovus-avatar-0.0.7/.specification
  12. +4 −1 vendor/gems/mocha-0.9.3/.specification
  13. +96 −0 vendor/gems/paperclip-2.1.2/.specification
  14. +4 −1 vendor/gems/redgreen-1.2.2/.specification
  15. +4 −1 vendor/gems/uuidtools-1.0.4/.specification
  16. +4 −1 vendor/gems/will_paginate-2.2.2/.specification
  17. +4 −1 vendor/gems/youtube-g-0.4.9.9/.specification
  18. +0 −69 vendor/plugins/file_column/CHANGELOG
  19. +0 −54 vendor/plugins/file_column/README
  20. +0 −36 vendor/plugins/file_column/Rakefile
  21. +0 −6 vendor/plugins/file_column/TODO
  22. +0 −13 vendor/plugins/file_column/init.rb
  23. +0 −720 vendor/plugins/file_column/lib/file_column.rb
  24. +0 −150 vendor/plugins/file_column/lib/file_column_helper.rb
  25. +0 −28 vendor/plugins/file_column/lib/file_compat.rb
  26. +0 −260 vendor/plugins/file_column/lib/magick_file_column.rb
  27. +0 −19 vendor/plugins/file_column/lib/rails_file_column.rb
  28. +0 −124 vendor/plugins/file_column/lib/test_case.rb
  29. +0 −112 vendor/plugins/file_column/lib/validations.rb
  30. +0 −63 vendor/plugins/file_column/test/abstract_unit.rb
  31. +0 −17 vendor/plugins/file_column/test/connection.rb
  32. +0 −97 vendor/plugins/file_column/test/file_column_helper_test.rb
  33. +0 −650 vendor/plugins/file_column/test/file_column_test.rb
  34. +0 −32 vendor/plugins/file_column/test/fixtures/entry.rb
  35. +0 −1 vendor/plugins/file_column/test/fixtures/invalid-image.jpg
  36. BIN vendor/plugins/file_column/test/fixtures/kerb.jpg
  37. +0 −25 vendor/plugins/file_column/test/fixtures/mysql.sql
  38. +0 −10 vendor/plugins/file_column/test/fixtures/schema.rb
  39. BIN vendor/plugins/file_column/test/fixtures/skanthak.png
  40. +0 −380 vendor/plugins/file_column/test/magick_test.rb
  41. +0 −21 vendor/plugins/file_column/test/magick_view_only_test.rb
View
1 README
@@ -1,5 +1,6 @@
How to get LovdByLess up and running
+USERS WHO ARE UPGRADING READ THE UPGRADE NOTES
WINDOWS USERS READ THIS: http://www.gamutworks.net/blog/?p=17
UBUNTO USERS READ THIS: http://groups.google.com/group/lovdbyless/browse_thread/thread/d29043342c47f06?hl=en
View
2 UPGRADE_NOTES
@@ -0,0 +1,2 @@
+2009-10-09 - Upgrading from file_column to paperclip
+This upgrade has no reverse migration provided. It is strongly recommended that production files and databases be backed up prior to upgrading and that this upgrade be tested locally in development before an upgrade is performed on production. If you have modified the default path for file_column, you will need to update the DEFAULT_FILE_COLUMN_PATH found in '20091006171847_move_to_paperclip.rb'. Once the upgrade is complete, delete the old file_column directories.
View
4 app/helpers/photos_helper.rb
@@ -9,8 +9,8 @@ def image photo, size = :square, img_opts = {}
def photo_path photo = nil, size = :square
path = nil
- unless photo.nil? || photo.image.blank?
- path = url_for_file_column(photo, :image, size.to_s) rescue nil
+ unless photo.image.exists?
+ path = photo.image.url(size) rescue nil
end
path = missing_photo_path(size) if path.nil?
return path
View
9 app/models/photo.rb
@@ -18,7 +18,7 @@ class Photo < ActiveRecord::Base
belongs_to :profile
- has_attached_file :image, :styles => { :square => "50x50#", :small => "175x250>"}
+ has_attached_file :image, :styles => { :square => "50x50#", :small => "175x250>"}, :path => ":rails_root/public/system/:attachment/:id/:style/:basename.:extension"
validates_attachment_presence :image
validates_presence_of :profile_id
@@ -28,12 +28,5 @@ def after_create
feed_item = FeedItem.create(:item => self)
([profile] + profile.friends + profile.followers).each{ |p| p.feed_items << feed_item }
end
-
- # file_column :image, :magick => {
- # :versions => {
- # :square => {:crop => "1:1", :size => "50x50", :name => "square"},
- # :small => "175x250>"
- # }
- # }
end
View
17 app/models/profile.rb
@@ -78,15 +78,14 @@ class Profile < ActiveRecord::Base
set_property :min_prefix_len => 3, :morphology => false
end
- has_attached_file :icon, :styles => { :big => "150x150#", :medium => "100x100#", :small => "50x50#" }, :default_url => "/avatar_default_:style.png"
- #
- # file_column :icon, :magick => {
- # :versions => {
- # :big => {:crop => "1:1", :size => "150x150", :name => "big"},
- # :medium => {:crop => "1:1", :size => "100x100", :name => "medium"},
- # :small => {:crop => "1:1", :size => "50x50", :name => "small"}
- # }
- # }
+ has_attached_file :icon,
+ :styles => {
+ :big => "150x150#",
+ :medium => "100x100#",
+ :small => "50x50#"
+ },
+ :default_url => "/avatar_default_:style.png",
+ :path => ":rails_root/public/system/:attachment/:id/:style/:basename.:extension"
cattr_accessor :featured_profile
@@featured_profile = {:date=>Date.today-4, :profile=>nil}
View
2 config/initializers/avatar_sources.rb
@@ -7,7 +7,7 @@
require 'sized_gravatar_source'
# order:
-# 1. FileColumn(Profile#icon)
+# 1. Paperclip(Profile#icon)
# 2. Gravatar(Profile#email), with default
# a RailsAssetSourceWrapper containing
# a StringSubstitutionSourceWrapper containing
View
2 config/initializers/file_column_settings.rb
@@ -1,2 +0,0 @@
-# FileColumn::ClassMethods::DEFAULT_OPTIONS[:root_path] = File.join(RAILS_ROOT, "public", 'system')
-# FileColumn::ClassMethods::DEFAULT_OPTIONS[:web_root] = 'system/'
View
67 db/migrate/20091006171847_move_to_paperclip.rb
@@ -1,4 +1,6 @@
class MoveToPaperclip < ActiveRecord::Migration
+ DEFAULT_FILE_COLUMN_PATH = File.join(RAILS_ROOT, "public", 'system')
+
def self.up
# Profiles
add_column :profiles, :icon_file_name, :string
@@ -7,8 +9,8 @@ def self.up
add_column :profiles, :icon_updated_at, :datetime
Profile.find_each do |profile|
- next unless profile.old_icon
- profile.icon = File.new(profile.old_icon)
+ next unless profile.read_attribute('icon')
+ profile.icon = File.new(File.join(DEFAULT_FILE_COLUMN_PATH, 'profile', 'icon', profile.id.to_s, profile.read_attribute('icon')))
profile.save
end
@@ -21,70 +23,15 @@ def self.up
add_column :photos, :image_updated_at, :datetime
Photo.find_each do |photo|
- next unless photo.old_image
- photo.image = File.new(profile.old_image)
+ next unless photo.read_attribute('image')
+ photo.image = File.new(File.join(DEFAULT_FILE_COLUMN_PATH, 'photo', 'image', photo.id.to_s, photo.read_attribute('image')))
photo.save
end
remove_column :photos, :image
end
def self.down
- # Profiles
- add_column :profiles, :icon, :string
-
- Profile.find_each do |profile|
- next unless profile.icon
- profile.old_icon = File.new(profile.icon.path)
- profile.save
- end
-
- remove_column :profiles, :icon_updated_at
- remove_column :profiles, :icon_file_size
- remove_column :profiles, :icon_content_type
- remove_column :profiles, :icon_file_name
-
- # Photos
- add_column :photos, :image, :string
-
- Photo.find_each do |photo|
- next unless photo.image
- photo.old_image = File.new(photo.image.path)
- photo.save
- end
-
- remove_column :photos, :image_updated_at
- remove_column :photos, :image_file_size
- remove_column :photos, :image_content_type
- remove_column :photos, :image_file_name
+ raise ActiveRecord::IrreversibleMigration.new('The migrations from file_column to paperclip is not reversable')
end
-end
-
-
-# just for redundancy. we want this to be a reverdable migration.
-class Profile < ActiveRecord::Base
- file_column :icon, :magick => {
- :versions => {
- :big => {:crop => "1:1", :size => "150x150", :name => "big"},
- :medium => {:crop => "1:1", :size => "100x100", :name => "medium"},
- :small => {:crop => "1:1", :size => "50x50", :name => "small"}
- }
- }
- alias_method :old_icon=, :icon=
- alias_method :old_icon, :icon
-
- has_attached_file :icon, :styles => { :big => "150x150>", :medium => "100x100>", :small => "50x50>" }
-end
-
-class Photo < ActiveRecord::Base
- file_column :image, :magick => {
- :versions => {
- :square => {:crop => "1:1", :size => "50x50", :name => "square"},
- :small => "175x250>"
- }
- }
- alias_method :old_image=, :image=
- alias_method :old_image, :image
-
- has_attached_file :image, :styles => { :square => "50x50#", :small => "175x250>"}
end
View
8 test/functional/profiles_controller_test.rb
@@ -124,19 +124,19 @@ class ProfilesControllerTest < ActionController::TestCase
#raise (p.send :icon_state).inspect
assert_not_nil p.icon
get :show, {:id => p.id, :public_view => true}, {:user => p.id}
- assert_tag :img, :attributes => { :src => /\/system\/icons\/\d*\/big\/user.png/ }
+ assert_tag :img, :attributes => { :src => /\/icons\/\d*\/big\/user.png/ }
end
should 'use gravatar otherwise' do
p = profiles(:user2)
- assert !p.icon.file?
+ assert !p.icon.exists?
get :show, {:id => p.id}, {:user => p.id, :public_view => true}
assert_tag :img, :attributes => {:src => /www\.gravatar\.com/}
end
should 'send the app\'s internal default as the default to gravatar' do
p = profiles(:user2)
- assert !p.icon.file?
+ assert !p.icon.exists?
get :show, {:id => p.id}, {:user => p.id, :public_view => true}
assert_tag :img, :attributes => { :src => /http...www.gravatar.com\/avatar\/[0-9a-f]+\?size\=50&amp;default\=http...test\.host\/images\/avatar_default_small\.png/ }
end
@@ -148,7 +148,7 @@ class ProfilesControllerTest < ActionController::TestCase
assert_not_nil profiles(:user).icon
post :delete_icon, {:id => profiles(:user).id, :format => 'js'}, {:user => profiles(:user).id}
assert_response :success
- assert !assigns(:p).reload.icon.file?
+ assert !assigns(:p).reload.icon.exists?
end
end
View
5 vendor/gems/colored-1.1/.specification
@@ -27,10 +27,13 @@ files:
- test/colored_test.rb
has_rdoc: false
homepage: http://errtheblog.com/
+licenses: []
+
post_install_message:
rdoc_options: []
require_paths:
+- bin
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
@@ -47,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
requirements: []
rubyforge_project:
-rubygems_version: 1.3.1
+rubygems_version: 1.3.5
signing_key:
specification_version: 2
summary: Add some color to your life.
View
5 vendor/gems/gcnovus-avatar-0.0.7/.specification
@@ -51,6 +51,8 @@ files:
- lib/avatar.rb
has_rdoc: true
homepage: http://github.com/gcnovus/avatar
+licenses: []
+
post_install_message:
rdoc_options:
- --line-numbers
@@ -60,6 +62,7 @@ rdoc_options:
- --charset
- utf-8
require_paths:
+- bin
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
@@ -76,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
requirements: []
rubyforge_project:
-rubygems_version: 1.3.1
+rubygems_version: 1.3.5
signing_key:
specification_version: 2
summary: Multi-source avatar support
View
5 vendor/gems/mocha-0.9.3/.specification
@@ -195,6 +195,8 @@ files:
- RELEASE
has_rdoc: true
homepage: http://mocha.rubyforge.org
+licenses: []
+
post_install_message:
rdoc_options:
- --title
@@ -204,6 +206,7 @@ rdoc_options:
- --line-numbers
require_paths:
- bin
+- bin
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
@@ -220,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
requirements: []
rubyforge_project: mocha
-rubygems_version: 1.3.1
+rubygems_version: 1.3.5
signing_key:
specification_version: 2
summary: Mocking and stubbing library
View
96 vendor/gems/paperclip-2.1.2/.specification
@@ -0,0 +1,96 @@
+--- !ruby/object:Gem::Specification
+name: paperclip
+version: !ruby/object:Gem::Version
+ version: 2.1.2
+platform: ruby
+authors:
+- Jon Yurek
+autorequire:
+bindir: bin
+cert_chain: []
+
+date: 2008-05-13 00:00:00 -04:00
+default_executable:
+dependencies: []
+
+description:
+email: jyurek@thoughtbot.com
+executables: []
+
+extensions: []
+
+extra_rdoc_files:
+- README
+files:
+- README
+- LICENSE
+- Rakefile
+- init.rb
+- generators/paperclip
+- generators/paperclip/paperclip_generator.rb
+- generators/paperclip/templates
+- generators/paperclip/templates/paperclip_migration.rb
+- generators/paperclip/USAGE
+- lib/paperclip
+- lib/paperclip/attachment.rb
+- lib/paperclip/geometry.rb
+- lib/paperclip/iostream.rb
+- lib/paperclip/storage.rb
+- lib/paperclip/thumbnail.rb
+- lib/paperclip/upfile.rb
+- lib/paperclip.rb
+- tasks/paperclip_tasks.rake
+- test/database.yml
+- test/debug.log
+- test/fixtures
+- test/fixtures/12k.png
+- test/fixtures/50x50.png
+- test/fixtures/5k.png
+- test/fixtures/bad.png
+- test/fixtures/text.txt
+- test/helper.rb
+- test/s3.yml
+- test/test_attachment.rb
+- test/test_geometry.rb
+- test/test_integration.rb
+- test/test_iostream.rb
+- test/test_paperclip.rb
+- test/test_storage.rb
+- test/test_thumbnail.rb
+has_rdoc: true
+homepage: http://www.thoughtbot.com/
+licenses: []
+
+post_install_message:
+rdoc_options:
+- --line-numbers
+- --inline-source
+require_paths:
+- lib
+required_ruby_version: !ruby/object:Gem::Requirement
+ requirements:
+ - - ">="
+ - !ruby/object:Gem::Version
+ version: "0"
+ version:
+required_rubygems_version: !ruby/object:Gem::Requirement
+ requirements:
+ - - ">="
+ - !ruby/object:Gem::Version
+ version: "0"
+ version:
+requirements:
+- ImageMagick
+rubyforge_project: paperclip
+rubygems_version: 1.3.5
+signing_key:
+specification_version: 2
+summary: File attachments as attributes for ActiveRecord
+test_files:
+- test/test_attachment.rb
+- test/test_geometry.rb
+- test/test_integration.rb
+- test/test_iostream.rb
+- test/test_paperclip.rb
+- test/test_storage.rb
+- test/test_thumbnail.rb
View
5 vendor/gems/redgreen-1.2.2/.specification
@@ -32,10 +32,13 @@ files:
- test/test_fake.rb
has_rdoc: false
homepage: http://errtheblog.com/post/15, http://on-ruby.blogspot.com/
+licenses: []
+
post_install_message:
rdoc_options: []
require_paths:
+- bin
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
@@ -52,7 +55,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
requirements: []
rubyforge_project:
-rubygems_version: 1.3.1
+rubygems_version: 1.3.5
signing_key:
specification_version: 2
summary: redgreen is an expanded version of Pat Eyler's RedGreen
View
5 vendor/gems/uuidtools-1.0.4/.specification
@@ -65,12 +65,15 @@ files:
- README
has_rdoc: true
homepage: http://uuidtools.rubyforge.org/
+licenses: []
+
post_install_message:
rdoc_options:
- --main
- README
require_paths:
- bin
+- bin
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
@@ -87,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
requirements: []
rubyforge_project: uuidtools
-rubygems_version: 1.3.1
+rubygems_version: 1.3.5
signing_key:
specification_version: 2
summary: UUID generator
View
5 vendor/gems/will_paginate-2.2.2/.specification
@@ -72,10 +72,13 @@ files:
- test/view_test.rb
has_rdoc: true
homepage: http://github.com/mislav/will_paginate
+licenses: []
+
post_install_message:
rdoc_options: []
require_paths:
+- bin
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
@@ -92,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
requirements: []
rubyforge_project: will-paginate
-rubygems_version: 1.3.1
+rubygems_version: 1.3.5
signing_key:
specification_version: 2
summary: Most awesome pagination solution for Rails
View
5 vendor/gems/youtube-g-0.4.9.9/.specification
@@ -56,12 +56,15 @@ files:
- youtube-g.gemspec
has_rdoc: true
homepage: http://youtube-g.rubyforge.org/
+licenses: []
+
post_install_message:
rdoc_options:
- --main
- README.txt
require_paths:
- bin
+- bin
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
@@ -78,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
requirements: []
rubyforge_project:
-rubygems_version: 1.3.1
+rubygems_version: 1.3.5
signing_key:
specification_version: 2
summary: An object-oriented Ruby wrapper for the YouTube GData API
View
69 vendor/plugins/file_column/CHANGELOG
@@ -1,69 +0,0 @@
-*svn*
- * allow for directories in file_column dirs as well
- * use subdirs for versions instead of fiddling with filename
- * url_for_image_column_helper for dynamic resizing of images from views
- * new "crop" feature [Sean Treadway]
- * url_for_file_column helper: do not require model objects to be stored in
- instance variables
- * allow more fined-grained control over :store_dir via callback
- methods [Gerret Apelt]
- * allow assignment of regular file objects
- * validation of file format and file size [Kyle Maxwell]
- * validation of image dimensions [Lee O'Mara]
- * file permissions can be set via :permissions option
- * fixed bug that prevents deleting of file via assigning nil if
- column is declared as NON NULL on some databases
- * don't expand absolute paths. This is necessary for file_column to work
- when your rails app is deployed into a sub-directory via a symbolic link
- * url_for_*_column will no longer return absolute URLs! Instead, although the
- generated URL starts with a slash, it will be relative to your application's
- root URL. This is so, because rails' image_tag helper will automatically
- convert it to an absolute URL. If you need an absolute URL (e.g., to pass
- it to link_to) use url_for_file_column's :absolute => true option.
- * added support for file_column enabled unit tests [Manuel Holtgrewe]
- * support for custom transformation of images [Frederik Fix]
- * allow setting of image attributes (e.g., quality) [Frederik Fix]
- * :magick columns can optionally ignore non-images (i.e., do not try to
- resize them)
-
-0.3.1
- * make object with file_columns serializable
- * use normal require for RMagick, so that it works with gem
- and custom install as well
-
-0.3
- * fixed bug where empty file uploads were not recognized with some browsers
- * fixed bug on windows when "file" utility is not present
- * added option to disable automatic file extension correction
- * Only allow one attribute per call to file_column, so that options only
- apply to one argument
- * try to detect when people forget to set the form encoding to
- 'multipart/form-data'
- * converted to rails plugin
- * easy integration with RMagick
-
-0.2
- * complete rewrite using state pattern
- * fixed sanitize filename [Michael Raidel]
- * fixed bug when no file was uploaded [Michael Raidel]
- * try to fix filename extensions [Michael Raidel]
- * Feed absolute paths through File.expand_path to make them as simple as possible
- * Make file_column_field helper work with auto-ids (e.g., "event[]")
-
-0.1.3
- * test cases with more than 1 file_column
- * fixed bug when file_column was called with several arguments
- * treat empty ("") file_columns as nil
- * support for binary files on windows
-
-0.1.2
- * better rails integration, so that you do not have to include the modules yourself. You
- just have to "require 'rails_file_column'" in your "config/environment.rb"
- * Rakefile for testing and packaging
-
-0.1.1 (2005-08-11)
- * fixed nasty bug in url_for_file_column that made it unusable on Apache
- * prepared for public release
-
-0.1 (2005-08-10)
- * initial release
View
54 vendor/plugins/file_column/README
@@ -1,54 +0,0 @@
-FEATURES
-========
-
-Let's assume an model class named Entry, where we want to define the "image" column
-as a "file_upload" column.
-
-class Entry < ActiveRecord::Base
- file_column :image
-end
-
-* every entry can have one uploaded file, the filename will be stored in the "image" column
-
-* files will be stored in "public/entry/image/<entry.id>/filename.ext"
-
-* Newly uploaded files will be stored in "public/entry/tmp/<random>/filename.ext" so that
- they can be reused in form redisplays (due to validation etc.)
-
-* in a view, "<%= file_column_field 'entry', 'image' %> will create a file upload field as well
- as a hidden field to recover files uploaded before in a case of a form redisplay
-
-* in a view, "<%= url_for_file_column 'entry', 'image' %> will create an URL to access the
- uploaded file. Note that you need an Entry object in the instance variable @entry for this
- to work.
-
-* easy integration with RMagick to resize images and/or create thumb-nails.
-
-USAGE
-=====
-
-Just drop the whole directory into your application's "vendor/plugins" directory. Starting
-with version 1.0rc of rails, it will be automatically picked for you by rails plugin
-mechanism.
-
-DOCUMENTATION
-=============
-
-Please look at the rdoc-generated documentation in the "doc" directory.
-
-RUNNING UNITTESTS
-=================
-
-There are extensive unittests in the "test" directory. Currently, only MySQL is supported, but
-you should be able to easily fix this by looking at "connection.rb". You have to create a
-database for the tests and put the connection information into "connection.rb". The schema
-for MySQL can be found in "test/fixtures/mysql.sql".
-
-You can run the tests by starting the "*_test.rb" in the directory "test"
-
-BUGS & FEEDBACK
-===============
-
-Bug reports (as well as patches) and feedback are very welcome. Please send it to
-sebastian.kanthak@muehlheim.de
-
View
36 vendor/plugins/file_column/Rakefile
@@ -1,36 +0,0 @@
-task :default => [:test]
-
-PKG_NAME = "file-column"
-PKG_VERSION = "0.3.1"
-
-PKG_DIR = "release/#{PKG_NAME}-#{PKG_VERSION}"
-
-task :clean do
- rm_rf "release"
-end
-
-task :setup_directories do
- mkpath "release"
-end
-
-
-task :checkout_release => :setup_directories do
- rm_rf PKG_DIR
- revision = ENV["REVISION"] || "HEAD"
- sh "svn export -r #{revision} . #{PKG_DIR}"
-end
-
-task :release_docs => :checkout_release do
- sh "cd #{PKG_DIR}; rdoc lib"
-end
-
-task :package => [:checkout_release, :release_docs] do
- sh "cd release; tar czf #{PKG_NAME}-#{PKG_VERSION}.tar.gz #{PKG_NAME}-#{PKG_VERSION}"
-end
-
-task :test do
- sh "cd test; ruby file_column_test.rb"
- sh "cd test; ruby file_column_helper_test.rb"
- sh "cd test; ruby magick_test.rb"
- sh "cd test; ruby magick_view_only_test.rb"
-end
View
6 vendor/plugins/file_column/TODO
@@ -1,6 +0,0 @@
-* document configuration options better
-* support setting of permissions
-* validation methods for file format/size
-* delete stale files from tmp directories
-
-* ensure valid URLs are created even when deployed at sub-path (compute_public_url?)
View
13 vendor/plugins/file_column/init.rb
@@ -1,13 +0,0 @@
-# plugin init file for rails
-# this file will be picked up by rails automatically and
-# add the file_column extensions to rails
-
-require 'file_column'
-require 'file_compat'
-require 'file_column_helper'
-require 'validations'
-#require 'test_case' if RAILS_ENV == 'test'
-
-ActiveRecord::Base.send(:include, FileColumn)
-ActionView::Base.send(:include, FileColumnHelper)
-ActiveRecord::Base.send(:include, FileColumn::Validations)
View
720 vendor/plugins/file_column/lib/file_column.rb
@@ -1,720 +0,0 @@
-require 'fileutils'
-require 'tempfile'
-require 'magick_file_column'
-
-module FileColumn # :nodoc:
- def self.append_features(base)
- super
- base.extend(ClassMethods)
- end
-
- def self.create_state(instance,attr)
- filename = instance[attr]
- if filename.nil? or filename.empty?
- NoUploadedFile.new(instance,attr)
- else
- PermanentUploadedFile.new(instance,attr)
- end
- end
-
- def self.init_options(defaults, model, attr)
- options = defaults.dup
- options[:store_dir] ||= File.join(options[:root_path], model, attr)
- unless options[:store_dir].is_a?(Symbol)
- options[:tmp_base_dir] ||= File.join(options[:store_dir], "tmp")
- end
- options[:base_url] ||= options[:web_root] + File.join(model, attr)
-
- [:store_dir, :tmp_base_dir].each do |dir_sym|
- if options[dir_sym].is_a?(String) and !File.exists?(options[dir_sym])
- FileUtils.mkpath(options[dir_sym])
- end
- end
-
- options
- end
-
- class BaseUploadedFile # :nodoc:
-
- def initialize(instance,attr)
- @instance, @attr = instance, attr
- @options_method = "#{attr}_options".to_sym
- end
-
-
- def assign(file)
- if file.is_a? File
- # this did not come in via a CGI request. However,
- # assigning files directly may be useful, so we
- # make just this file object similar enough to an uploaded
- # file that we can handle it.
- file.extend FileColumn::FileCompat
- end
-
- if file.nil?
- delete
- else
- if file.size == 0
- # user did not submit a file, so we
- # can simply ignore this
- self
- else
- if file.is_a?(String)
- # if file is a non-empty string it is most probably
- # the filename and the user forgot to set the encoding
- # to multipart/form-data. Since we would raise an exception
- # because of the missing "original_filename" method anyways,
- # we raise a more meaningful exception rightaway.
- raise TypeError.new("Do not know how to handle a string with value '#{file}' that was passed to a file_column. Check if the form's encoding has been set to 'multipart/form-data'.")
- end
- upload(file)
- end
- end
- end
-
- def just_uploaded?
- @just_uploaded
- end
-
- def on_save(&blk)
- @on_save ||= []
- @on_save << Proc.new
- end
-
- # the following methods are overriden by sub-classes if needed
-
- def temp_path
- nil
- end
-
- def absolute_dir
- if absolute_path then File.dirname(absolute_path) else nil end
- end
-
- def relative_dir
- if relative_path then File.dirname(relative_path) else nil end
- end
-
- def after_save
- @on_save.each { |blk| blk.call } if @on_save
- self
- end
-
- def after_destroy
- end
-
- def options
- @instance.send(@options_method)
- end
-
- private
-
- def store_dir
- if options[:store_dir].is_a? Symbol
- raise ArgumentError.new("'#{options[:store_dir]}' is not an instance method of class #{@instance.class.name}") unless @instance.respond_to?(options[:store_dir])
-
- dir = File.join(options[:root_path], @instance.send(options[:store_dir]))
- FileUtils.mkpath(dir) unless File.exists?(dir)
- dir
- else
- options[:store_dir]
- end
- end
-
- def tmp_base_dir
- if options[:tmp_base_dir]
- options[:tmp_base_dir]
- else
- dir = File.join(store_dir, "tmp")
- FileUtils.mkpath(dir) unless File.exists?(dir)
- dir
- end
- end
-
- def clone_as(klass)
- klass.new(@instance, @attr)
- end
-
- end
-
-
- class NoUploadedFile < BaseUploadedFile # :nodoc:
- def delete
- # we do not have a file so deleting is easy
- self
- end
-
- def upload(file)
- # replace ourselves with a TempUploadedFile
- temp = clone_as TempUploadedFile
- temp.store_upload(file)
- temp
- end
-
- def absolute_path(subdir=nil)
- nil
- end
-
-
- def relative_path(subdir=nil)
- nil
- end
-
- def assign_temp(temp_path)
- return self if temp_path.nil? or temp_path.empty?
- temp = clone_as TempUploadedFile
- temp.parse_temp_path temp_path
- temp
- end
- end
-
- class RealUploadedFile < BaseUploadedFile # :nodoc:
- def absolute_path(subdir=nil)
- if subdir
- File.join(@dir, subdir, @filename)
- else
- File.join(@dir, @filename)
- end
- end
-
- def relative_path(subdir=nil)
- if subdir
- File.join(relative_path_prefix, subdir, @filename)
- else
- File.join(relative_path_prefix, @filename)
- end
- end
-
- private
-
- # regular expressions to try for identifying extensions
- EXT_REGEXPS = [
- /^(.+)\.([^.]+\.[^.]+)$/, # matches "something.tar.gz"
- /^(.+)\.([^.]+)$/ # matches "something.jpg"
- ]
-
- def split_extension(filename,fallback=nil)
- EXT_REGEXPS.each do |regexp|
- if filename =~ regexp
- base,ext = $1, $2
- return [base, ext] if options[:extensions].include?(ext.downcase)
- end
- end
- if fallback and filename =~ EXT_REGEXPS.last
- return [$1, $2]
- end
- [filename, ""]
- end
-
- end
-
- class TempUploadedFile < RealUploadedFile # :nodoc:
-
- def store_upload(file)
- @tmp_dir = FileColumn.generate_temp_name
- @dir = File.join(tmp_base_dir, @tmp_dir)
- FileUtils.mkdir(@dir)
-
- @filename = FileColumn::sanitize_filename(file.original_filename)
- local_file_path = File.join(tmp_base_dir,@tmp_dir,@filename)
-
- # stored uploaded file into local_file_path
- # If it was a Tempfile object, the temporary file will be
- # cleaned up automatically, so we do not have to care for this
- if file.respond_to?(:local_path) and file.local_path and File.exists?(file.local_path)
- FileUtils.copy_file(file.local_path, local_file_path)
- elsif file.respond_to?(:read)
- File.open(local_file_path, "wb") { |f| f.write(file.read) }
- else
- raise ArgumentError.new("Do not know how to handle #{file.inspect}")
- end
- File.chmod(options[:permissions], local_file_path)
-
- if options[:fix_file_extensions]
- # try to determine correct file extension and fix
- # if necessary
- content_type = get_content_type((file.content_type.chomp if file.content_type))
- if content_type and options[:mime_extensions][content_type]
- @filename = correct_extension(@filename,options[:mime_extensions][content_type])
- end
-
- new_local_file_path = File.join(tmp_base_dir,@tmp_dir,@filename)
- File.rename(local_file_path, new_local_file_path) unless new_local_file_path == local_file_path
- local_file_path = new_local_file_path
- end
-
- @instance[@attr] = @filename
- @just_uploaded = true
- end
-
-
- # tries to identify and strip the extension of filename
- # if an regular expresion from EXT_REGEXPS matches and the
- # downcased extension is a known extension (in options[:extensions])
- # we'll strip this extension
- def strip_extension(filename)
- split_extension(filename).first
- end
-
- def correct_extension(filename, ext)
- strip_extension(filename) << ".#{ext}"
- end
-
- def parse_temp_path(temp_path, instance_options=nil)
- raise ArgumentError.new("invalid format of '#{temp_path}'") unless temp_path =~ %r{^((\d+\.)+\d+)/([^/].+)$}
- @tmp_dir, @filename = $1, FileColumn.sanitize_filename($3)
- @dir = File.join(tmp_base_dir, @tmp_dir)
-
- @instance[@attr] = @filename unless instance_options == :ignore_instance
- end
-
- def upload(file)
- # store new file
- temp = clone_as TempUploadedFile
- temp.store_upload(file)
-
- # delete old copy
- delete_files
-
- # and return new TempUploadedFile object
- temp
- end
-
- def delete
- delete_files
- @instance[@attr] = ""
- clone_as NoUploadedFile
- end
-
- def assign_temp(temp_path)
- return self if temp_path.nil? or temp_path.empty?
- # we can ignore this since we've already received a newly uploaded file
-
- # however, we delete the old temporary files
- temp = clone_as TempUploadedFile
- temp.parse_temp_path(temp_path, :ignore_instance)
- temp.delete_files
-
- self
- end
-
- def temp_path
- File.join(@tmp_dir, @filename)
- end
-
- def after_save
- super
-
- # we have a newly uploaded image, move it to the correct location
- file = clone_as PermanentUploadedFile
- file.move_from(File.join(tmp_base_dir, @tmp_dir), @just_uploaded)
-
- # delete temporary files
- delete_files
-
- # replace with the new PermanentUploadedFile object
- file
- end
-
- def delete_files
- FileUtils.rm_rf(File.join(tmp_base_dir, @tmp_dir))
- end
-
- def get_content_type(fallback=nil)
- if options[:file_exec]
- begin
- content_type = `#{options[:file_exec]} -bi "#{File.join(@dir,@filename)}"`.chomp
- content_type = fallback unless $?.success?
- content_type.gsub!(/;.+$/,"") if content_type
- content_type
- rescue
- fallback
- end
- else
- fallback
- end
- end
-
- private
-
- def relative_path_prefix
- File.join("tmp", @tmp_dir)
- end
- end
-
-
- class PermanentUploadedFile < RealUploadedFile # :nodoc:
- def initialize(*args)
- super *args
- @dir = File.join(store_dir, relative_path_prefix)
- @filename = @instance[@attr]
- @filename = nil if @filename.empty?
- end
-
- def move_from(local_dir, just_uploaded)
- # remove old permament dir first
- # this creates a short moment, where neither the old nor
- # the new files exist but we can't do much about this as
- # filesystems aren't transactional.
- FileUtils.rm_rf @dir
-
- FileUtils.mv local_dir, @dir
-
- @just_uploaded = just_uploaded
- end
-
- def upload(file)
- temp = clone_as TempUploadedFile
- temp.store_upload(file)
- temp
- end
-
- def delete
- file = clone_as NoUploadedFile
- @instance[@attr] = ""
- file.on_save { delete_files }
- file
- end
-
- def assign_temp(temp_path)
- return nil if temp_path.nil? or temp_path.empty?
-
- temp = clone_as TempUploadedFile
- temp.parse_temp_path(temp_path)
- temp
- end
-
- def after_destroy
- delete_files
- end
-
- def delete_files
- FileUtils.rm_rf @dir
- end
-
- private
-
- def relative_path_prefix
- raise RuntimeError.new("Trying to access file_column, but primary key got lost.") if @instance.id.to_s.empty?
- @instance.id.to_s
- end
- end
-
- # The FileColumn module allows you to easily handle file uploads. You can designate
- # one or more columns of your model's table as "file columns" like this:
- #
- # class Entry < ActiveRecord::Base
- #
- # file_column :image
- # end
- #
- # Now, by default, an uploaded file "test.png" for an entry object with primary key 42 will
- # be stored in in "public/entry/image/42/test.png". The filename "test.png" will be stored
- # in the record's "image" column. The "entries" table should have a +VARCHAR+ column
- # named "image".
- #
- # The methods of this module are automatically included into <tt>ActiveRecord::Base</tt>
- # as class methods, so that you can use them in your models.
- #
- # == Generated Methods
- #
- # After calling "<tt>file_column :image</tt>" as in the example above, a number of instance methods
- # will automatically be generated, all prefixed by "image":
- #
- # * <tt>Entry#image=(uploaded_file)</tt>: this will handle a newly uploaded file
- # (see below). Note that
- # you can simply call your upload field "entry[image]" in your view (or use the
- # helper).
- # * <tt>Entry#image(subdir=nil)</tt>: This will return an absolute path (as a
- # string) to the currently uploaded file
- # or nil if no file has been uploaded
- # * <tt>Entry#image_relative_path(subdir=nil)</tt>: This will return a path relative to
- # this file column's base directory
- # as a string or nil if no file has been uploaded. This would be "42/test.png" in the example.
- # * <tt>Entry#image_just_uploaded?</tt>: Returns true if a new file has been uploaded to this instance.
- # You can use this in your code to perform certain actions (e. g., validation,
- # custom post-processing) only on newly uploaded files.
- #
- # You can access the raw value of the "image" column (which will contain the filename) via the
- # <tt>ActiveRecord::Base#attributes</tt> or <tt>ActiveRecord::Base#[]</tt> methods like this:
- #
- # entry['image'] # e.g."test.png"
- #
- # == Storage of uploaded files
- #
- # For a model class +Entry+ and a column +image+, all files will be stored under
- # "public/entry/image". A sub-directory named after the primary key of the object will
- # be created, so that files can be stored using their real filename. For example, a file
- # "test.png" stored in an Entry object with id 42 will be stored in
- #
- # public/entry/image/42/test.png
- #
- # Files will be moved to this location in an +after_save+ callback. They will be stored in
- # a temporary location previously as explained in the next section.
- #
- # By default, files will be created with unix permissions of <tt>0644</tt> (i. e., owner has
- # read/write access, group and others only have read access). You can customize
- # this by passing the desired mode as a <tt>:permissions</tt> options. The value
- # you give here is passed directly to <tt>File::chmod</tt>, so on Unix you should
- # give some octal value like 0644, for example.
- #
- # == Handling of form redisplay
- #
- # Suppose you have a form for creating a new object where the user can upload an image. The form may
- # have to be re-displayed because of validation errors. The uploaded file has to be stored somewhere so
- # that the user does not have to upload it again. FileColumn will store these in a temporary directory
- # (called "tmp" and located under the column's base directory by default) so that it can be moved to
- # the final location if the object is successfully created. If the form is never completed, though, you
- # can easily remove all the images in this "tmp" directory once per day or so.
- #
- # So in the example above, the image "test.png" would first be stored in
- # "public/entry/image/tmp/<some_random_key>/test.png" and be moved to
- # "public/entry/image/<primary_key>/test.png".
- #
- # This temporary location of newly uploaded files has another advantage when updating objects. If the
- # update fails for some reasons (e.g. due to validations), the existing image will not be overwritten, so
- # it has a kind of "transactional behaviour".
- #
- # == Additional Files and Directories
- #
- # FileColumn allows you to keep more than one file in a directory and will move/delete
- # all the files and directories it finds in a model object's directory when necessary.
- #
- # As a convenience you can access files stored in sub-directories via the +subdir+
- # parameter if they have the same filename.
- #
- # Suppose your uploaded file is named "vancouver.jpg" and you want to create a
- # thumb-nail and store it in the "thumb" directory. If you call
- # <tt>image("thumb")</tt>, you
- # will receive an absolute path for the file "thumb/vancouver.jpg" in the same
- # directory "vancouver.jpg" is stored. Look at the documentation of FileColumn::Magick
- # for more examples and how to create these thumb-nails automatically.
- #
- # == File Extensions
- #
- # FileColumn will try to fix the file extension of uploaded files, so that
- # the files are served with the correct mime-type by your web-server. Most
- # web-servers are setting the mime-type based on the file's extension. You
- # can disable this behaviour by passing the <tt>:fix_file_extensions</tt> option
- # with a value of +nil+ to +file_column+.
- #
- # In order to set the correct extension, FileColumn tries to determine
- # the files mime-type first. It then uses the +MIME_EXTENSIONS+ hash to
- # choose the corresponding file extension. You can override this hash
- # by passing in a <tt>:mime_extensions</tt> option to +file_column+.
- #
- # The mime-type of the uploaded file is determined with the following steps:
- #
- # 1. Run the external "file" utility. You can specify the full path to
- # the executable in the <tt>:file_exec</tt> option or set this option
- # to +nil+ to disable this step
- #
- # 2. If the file utility couldn't determine the mime-type or the utility was not
- # present, the content-type provided by the user's browser is used
- # as a fallback.
- #
- # == Custom Storage Directories
- #
- # FileColumn's storage location is determined in the following way. All
- # files are saved below the so-called "root_path" directory, which defaults to
- # "RAILS_ROOT/public". For every file_column, you can set a separte "store_dir"
- # option. It defaults to "model_name/attribute_name".
- #
- # Files will always be stored in sub-directories of the store_dir path. The
- # subdirectory is named after the instance's +id+ attribute for a saved model,
- # or "tmp/<randomkey>" for unsaved models.
- #
- # You can specify a custom root_path by setting the <tt>:root_path</tt> option.
- #
- # You can specify a custom storage_dir by setting the <tt>:storage_dir</tt> option.
- #
- # For setting a static storage_dir that doesn't change with respect to a particular
- # instance, you assign <tt>:storage_dir</tt> a String representing a directory
- # as an absolute path.
- #
- # If you need more fine-grained control over the storage directory, you
- # can use the name of a callback-method as a symbol for the
- # <tt>:store_dir</tt> option. This method has to be defined as an
- # instance method in your model. It will be called without any arguments
- # whenever the storage directory for an uploaded file is needed. It should return
- # a String representing a directory relativeo to root_path.
- #
- # Uploaded files for unsaved models objects will be stored in a temporary
- # directory. By default this directory will be a "tmp" directory in
- # your <tt>:store_dir</tt>. You can override this via the
- # <tt>:tmp_base_dir</tt> option.
- module ClassMethods
-
- # default mapping of mime-types to file extensions. FileColumn will try to
- # rename a file to the correct extension if it detects a known mime-type
- MIME_EXTENSIONS = {
- "image/gif" => "gif",
- "image/jpeg" => "jpg",
- "image/pjpeg" => "jpg",
- "image/x-png" => "png",
- "image/jpg" => "jpg",
- "image/png" => "png",
- "application/x-shockwave-flash" => "swf",
- "application/pdf" => "pdf",
- "application/pgp-signature" => "sig",
- "application/futuresplash" => "spl",
- "application/msword" => "doc",
- "application/postscript" => "ps",
- "application/x-bittorrent" => "torrent",
- "application/x-dvi" => "dvi",
- "application/x-gzip" => "gz",
- "application/x-ns-proxy-autoconfig" => "pac",
- "application/x-shockwave-flash" => "swf",
- "application/x-tgz" => "tar.gz",
- "application/x-tar" => "tar",
- "application/zip" => "zip",
- "audio/mpeg" => "mp3",
- "audio/x-mpegurl" => "m3u",
- "audio/x-ms-wma" => "wma",
- "audio/x-ms-wax" => "wax",
- "audio/x-wav" => "wav",
- "image/x-xbitmap" => "xbm",
- "image/x-xpixmap" => "xpm",
- "image/x-xwindowdump" => "xwd",
- "text/css" => "css",
- "text/html" => "html",
- "text/javascript" => "js",
- "text/plain" => "txt",
- "text/xml" => "xml",
- "video/mpeg" => "mpeg",
- "video/quicktime" => "mov",
- "video/x-msvideo" => "avi",
- "video/x-ms-asf" => "asf",
- "video/x-ms-wmv" => "wmv"
- }
-
- EXTENSIONS = Set.new MIME_EXTENSIONS.values
- EXTENSIONS.merge %w(jpeg)
-
- # default options. You can override these with +file_column+'s +options+ parameter
- DEFAULT_OPTIONS = {
- :root_path => File.join(RAILS_ROOT, "public"),
- :web_root => "",
- :mime_extensions => MIME_EXTENSIONS,
- :extensions => EXTENSIONS,
- :fix_file_extensions => true,
- :permissions => 0644,
-
- # path to the unix "file" executbale for
- # guessing the content-type of files
- :file_exec => "file"
- }
-
- # handle the +attr+ attribute as a "file-upload" column, generating additional methods as explained
- # above. You should pass the attribute's name as a symbol, like this:
- #
- # file_column :image
- #
- # You can pass in an options hash that overrides the options
- # in +DEFAULT_OPTIONS+.
- def file_column(attr, options={})
- options = DEFAULT_OPTIONS.merge(options) if options
-
- my_options = FileColumn::init_options(options,
- ActiveSupport::Inflector.underscore(self.name).to_s,
- attr.to_s)
-
- state_attr = "@#{attr}_state".to_sym
- state_method = "#{attr}_state".to_sym
-
- define_method state_method do
- result = instance_variable_get state_attr
- if result.nil?
- result = FileColumn::create_state(self, attr.to_s)
- instance_variable_set state_attr, result
- end
- result
- end
-
- private state_method
-
- define_method attr do |*args|
- send(state_method).absolute_path *args
- end
-
- define_method "#{attr}_relative_path" do |*args|
- send(state_method).relative_path *args
- end
-
- define_method "#{attr}_dir" do
- send(state_method).absolute_dir
- end
-
- define_method "#{attr}_relative_dir" do
- send(state_method).relative_dir
- end
-
- define_method "#{attr}=" do |file|
- state = send(state_method).assign(file)
- instance_variable_set state_attr, state
- if state.options[:after_upload] and state.just_uploaded?
- state.options[:after_upload].each do |sym|
- self.send sym
- end
- end
- end
-
- define_method "#{attr}_temp" do
- send(state_method).temp_path
- end
-
- define_method "#{attr}_temp=" do |temp_path|
- instance_variable_set state_attr, send(state_method).assign_temp(temp_path)
- end
-
- after_save_method = "#{attr}_after_save".to_sym
-
- define_method after_save_method do
- instance_variable_set state_attr, send(state_method).after_save
- end
-
- after_save after_save_method
-
- after_destroy_method = "#{attr}_after_destroy".to_sym
-
- define_method after_destroy_method do
- send(state_method).after_destroy
- end
- after_destroy after_destroy_method
-
- define_method "#{attr}_just_uploaded?" do
- send(state_method).just_uploaded?
- end
-
- # this creates a closure keeping a reference to my_options
- # right now that's the only way we store the options. We
- # might use a class attribute as well
- define_method "#{attr}_options" do
- my_options
- end
-
- private after_save_method, after_destroy_method
-
- FileColumn::MagickExtension::file_column(self, attr, my_options) if options[:magick]
- end
-
- end
-
- private
-
- def self.generate_temp_name
- now = Time.now
- "#{now.to_i}.#{now.usec}.#{Process.pid}"
- end
-
- def self.sanitize_filename(filename)
- filename = File.basename(filename.gsub("\\", "/")) # work-around for IE
- filename.gsub!(/[^a-zA-Z0-9\.\-\+_]/,"_")
- filename = "_#{filename}" if filename =~ /^\.+$/
- filename = "unnamed" if filename.size == 0
- filename
- end
-
-end
-
-
View
150 vendor/plugins/file_column/lib/file_column_helper.rb
@@ -1,150 +0,0 @@
-# This module contains helper methods for displaying and uploading files
-# for attributes created by +FileColumn+'s +file_column+ method. It will be
-# automatically included into ActionView::Base, thereby making this module's
-# methods available in all your views.
-module FileColumnHelper
-
- # Use this helper to create an upload field for a file_column attribute. This will generate
- # an additional hidden field to keep uploaded files during form-redisplays. For example,
- # when called with
- #
- # <%= file_column_field("entry", "image") %>
- #
- # the following HTML will be generated (assuming the form is redisplayed and something has
- # already been uploaded):
- #
- # <input type="hidden" name="entry[image_temp]" value="..." />
- # <input type="file" name="entry[image]" />
- #
- # You can use the +option+ argument to pass additional options to the file-field tag.
- #
- # Be sure to set the enclosing form's encoding to 'multipart/form-data', by
- # using something like this:
- #
- # <%= form_tag {:action => "create", ...}, :multipart => true %>
- def file_column_field(object, method, options={})
- result = ActionView::Helpers::InstanceTag.new(object.dup, method.to_s+"_temp", self).to_input_field_tag("hidden", {})
- result << ActionView::Helpers::InstanceTag.new(object.dup, method, self).to_input_field_tag("file", options)
- end
-
- # Creates an URL where an uploaded file can be accessed. When called for an Entry object with
- # id 42 (stored in <tt>@entry</tt>) like this
- #
- # <%= url_for_file_column(@entry, "image")
- #
- # the following URL will be produced, assuming the file "test.png" has been stored in
- # the "image"-column of an Entry object stored in <tt>@entry</tt>:
- #
- # /entry/image/42/test.png
- #
- # This will produce a valid URL even for temporary uploaded files, e.g. files where the object
- # they are belonging to has not been saved in the database yet.
- #
- # The URL produces, although starting with a slash, will be relative
- # to your app's root. If you pass it to one rails' +image_tag+
- # helper, rails will properly convert it to an absolute
- # URL. However, this will not be the case, if you create a link with
- # the +link_to+ helper. In this case, you can pass <tt>:absolute =>
- # true</tt> to +options+, which will make sure, the generated URL is
- # absolute on your server. Examples:
- #
- # <%= image_tag url_for_file_column(@entry, "image") %>
- # <%= link_to "Download", url_for_file_column(@entry, "image", :absolute => true) %>
- #
- # If there is currently no uploaded file stored in the object's column this method will
- # return +nil+.
- def url_for_file_column(object, method, options=nil)
- case object
- when String, Symbol
- object = instance_variable_get("@#{object.to_s}")
- end
-
- # parse options
- subdir = nil
- absolute = false
- if options
- case options
- when Hash
- subdir = options[:subdir]
- absolute = options[:absolute]
- when String, Symbol
- subdir = options
- end
- end
-
- relative_path = object.send("#{method}_relative_path", subdir)
- return nil unless relative_path
-
- url = ""
- url << request.relative_url_root.to_s if absolute
- url << "/"
- url << object.send("#{method}_options")[:base_url] << "/"
- url << relative_path
- end
-
- # Same as +url_for_file_colum+ but allows you to access different versions
- # of the image that have been processed by RMagick.
- #
- # If your +options+ parameter is non-nil this will
- # access a different version of an image that will be produced by
- # RMagick. You can use the following types for +options+:
- #
- # * a <tt>:symbol</tt> will select a version defined in the model
- # via FileColumn::Magick's <tt>:versions</tt> feature.
- # * a <tt>geometry_string</tt> will dynamically create an
- # image resized as specified by <tt>geometry_string</tt>. The image will
- # be stored so that it does not have to be recomputed the next time the
- # same version string is used.
- # * <tt>some_hash</tt> will dynamically create an image
- # that is created according to the options in <tt>some_hash</tt>. This
- # accepts exactly the same options as Magick's version feature.
- #
- # The version produced by RMagick will be stored in a special sub-directory.
- # The directory's name will be derived from the options you specified
- # (via a hash function) but if you want
- # to set it yourself, you can use the <tt>:name => name</tt> option.
- #
- # Examples:
- #
- # <%= url_for_image_column @entry, "image", "640x480" %>
- #
- # will produce an URL like this
- #
- # /entry/image/42/bdn19n/filename.jpg
- # # "640x480".hash.abs.to_s(36) == "bdn19n"
- #
- # and
- #
- # <%= url_for_image_column @entry, "image",
- # :size => "50x50", :crop => "1:1", :name => "thumb" %>
- #
- # will produce something like this:
- #
- # /entry/image/42/thumb/filename.jpg
- #
- # Hint: If you are using the same geometry string / options hash multiple times, you should
- # define it in a helper to stay with DRY. Another option is to define it in the model via
- # FileColumn::Magick's <tt>:versions</tt> feature and then refer to it via a symbol.
- #
- # The URL produced by this method is relative to your application's root URL,
- # although it will start with a slash.
- # If you pass this URL to rails' +image_tag+ helper, it will be converted to an
- # absolute URL automatically.
- # If there is currently no image uploaded, or there is a problem while loading
- # the image this method will return +nil+.
- def url_for_image_column(object, method, options=nil)
- case object
- when String, Symbol
- object = instance_variable_get("@#{object.to_s}")
- end
- subdir = nil
- if options
- subdir = object.send("#{method}_state").create_magick_version_if_needed(options)
- end
- if subdir.nil?
- nil
- else
- url_for_file_column(object, method, subdir)
- end
- end
-end
View
28 vendor/plugins/file_column/lib/file_compat.rb
@@ -1,28 +0,0 @@
-module FileColumn
-
- # This bit of code allows you to pass regular old files to
- # file_column. file_column depends on a few extra methods that the
- # CGI uploaded file class adds. We will add the equivalent methods
- # to file objects if necessary by extending them with this module. This
- # avoids opening up the standard File class which might result in
- # naming conflicts.
-
- module FileCompat # :nodoc:
- def original_filename
- File.basename(path)
- end
-
- def size
- File.size(path)
- end
-
- def local_path
- path
- end
-
- def content_type
- nil
- end
- end
-end
-
View
260 vendor/plugins/file_column/lib/magick_file_column.rb
@@ -1,260 +0,0 @@
-module FileColumn # :nodoc:
-
- class BaseUploadedFile # :nodoc:
- def transform_with_magick
- if needs_transform?
- begin
- img = ::Magick::Image::read(absolute_path).first
- rescue ::Magick::ImageMagickError
- if options[:magick][:image_required]
- @magick_errors ||= []
- @magick_errors << "invalid image"
- end
- return
- end
-
- if options[:magick][:versions]
- options[:magick][:versions].each_pair do |version, version_options|
- next if version_options[:lazy]
- dirname = version_options[:name]
- FileUtils.mkdir File.join(@dir, dirname)
- transform_image(img, version_options, absolute_path(dirname))
- end
- end
- if options[:magick][:size] or options[:magick][:crop] or options[:magick][:transformation] or options[:magick][:attributes]
- transform_image(img, options[:magick], absolute_path)
- end
-
- GC.start
- end
- end
-
- def create_magick_version_if_needed(version)
- # RMagick might not have been loaded so far.
- # We do not want to require it on every call of this method
- # as this might be fairly expensive, so we just try if ::Magick
- # exists and require it if not.
- begin
- ::Magick
- rescue NameError
- require 'RMagick'
- end
-
- if version.is_a?(Symbol)
- version_options = options[:magick][:versions][version]
- else
- version_options = MagickExtension::process_options(version)
- end
-
- unless File.exists?(absolute_path(version_options[:name]))
- begin
- img = ::Magick::Image::read(absolute_path).first
- rescue ::Magick::ImageMagickError
- # we might be called directly from the view here
- # so we just return nil if we cannot load the image
- return nil
- end
- dirname = version_options[:name]
- FileUtils.mkdir File.join(@dir, dirname)
- transform_image(img, version_options, absolute_path(dirname))
- end
-
- version_options[:name]
- end
-
- attr_reader :magick_errors
-
- def has_magick_errors?
- @magick_errors and !@magick_errors.empty?
- end
-
- private
-
- def needs_transform?
- options[:magick] and just_uploaded? and
- (options[:magick][:size] or options[:magick][:versions] or options[:magick][:transformation] or options[:magick][:attributes])
- end
-
- def transform_image(img, img_options, dest_path)
- begin
- if img_options[:transformation]
- if img_options[:transformation].is_a?(Symbol)
- img = @instance.send(img_options[:transformation], img)
- else
- img = img_options[:transformation].call(img)
- end
- end
- if img_options[:crop]
- dx, dy = img_options[:crop].split(':').map { |x| x.to_f }
- w, h = (img.rows * dx / dy), (img.columns * dy / dx)
- img = img.crop(::Magick::CenterGravity, [img.columns, w].min,
- [img.rows, h].min, true)
- end
-
- if img_options[:size]
- img = img.change_geometry(img_options[:size]) do |c, r, i|
- i.resize(c, r)
- end
- end
- ensure
- img.write(dest_path) do
- if img_options[:attributes]
- img_options[:attributes].each_pair do |property, value|
- self.send "#{property}=", value
- end
- end
- end
- File.chmod options[:permissions], dest_path
- end
- end
- end
-
- # If you are using file_column to upload images, you can
- # directly process the images with RMagick,
- # a ruby extension
- # for accessing the popular imagemagick libraries. You can find
- # more information about RMagick at http://rmagick.rubyforge.org.
- #
- # You can control what to do by adding a <tt>:magick</tt> option
- # to your options hash. All operations are performed immediately
- # after a new file is assigned to the file_column attribute (i.e.,
- # when a new file has been uploaded).
- #
- # == Resizing images
- #
- # To resize the uploaded image according to an imagemagick geometry
- # string, just use the <tt>:size</tt> option:
- #
- # file_column :image, :magick => {:size => "800x600>"}
- #
- # If the uploaded file cannot be loaded by RMagick, file_column will
- # signal a validation error for the corresponding attribute. If you
- # want to allow non-image files to be uploaded in a column that uses
- # the <tt>:magick</tt> option, you can set the <tt>:image_required</tt>
- # attribute to +false+:
- #
- # file_column :image, :magick => {:size => "800x600>",
- # :image_required => false }
- #
- # == Multiple versions
- #
- # You can also create additional versions of your image, for example
- # thumb-nails, like this:
- # file_column :image, :magick => {:versions => {
- # :thumb => {:size => "50x50"},
- # :medium => {:size => "640x480>"}
- # }
- #
- # These versions will be stored in separate sub-directories, named like the
- # symbol you used to identify the version. So in the previous example, the
- # image versions will be stored in "thumb", "screen" and "widescreen"
- # directories, resp.
- # A name different from the symbol can be set via the <tt>:name</tt> option.
- #
- # These versions can be accessed via FileColumnHelper's +url_for_image_column+
- # method like this:
- #
- # <%= url_for_image_column "entry", "image", :thumb %>
- #
- # == Cropping images
- #
- # If you wish to crop your images with a size ratio before scaling
- # them according to your version geometry, you can use the :crop directive.
- # file_column :image, :magick => {:versions => {
- # :square => {:crop => "1:1", :size => "50x50", :name => "thumb"},
- # :screen => {:crop => "4:3", :size => "640x480>"},
- # :widescreen => {:crop => "16:9", :size => "640x360!"},
- # }
- # }
- #
- # == Custom attributes
- #
- # To change some of the image properties like compression level before they
- # are saved you can set the <tt>:attributes</tt> option.
- # For a list of available attributes go to http://www.simplesystems.org/RMagick/doc/info.html
- #
- # file_column :image, :magick => { :attributes => { :quality => 30 } }
- #
- # == Custom transformations
- #
- # To perform custom transformations on uploaded images, you can pass a
- # callback to file_column:
- # file_column :image, :magick =>
- # Proc.new { |image| image.quantize(256, Magick::GRAYColorspace) }
- #
- # The callback you give, receives one argument, which is an instance
- # of Magick::Image, the RMagick image class. It should return a transformed
- # image. Instead of passing a <tt>Proc</tt> object, you can also give a
- # <tt>Symbol</tt>, the name of an instance method of your model.
- #
- # Custom transformations can be combined via the standard :size and :crop
- # features, by using the :transformation option:
- # file_column :image, :magick => {
- # :transformation => Proc.new { |image| ... },
- # :size => "640x480"
- # }
- #
- # In this case, the standard resizing operations will be performed after the
- # custom transformation.
- #
- # Of course, custom transformations can be used in versions, as well.
- #
- # <b>Note:</b> You'll need the
- # RMagick extension being installed in order to use file_column's
- # imagemagick integration.
- module MagickExtension
-
- def self.file_column(klass, attr, options) # :nodoc:
- require 'RMagick'
- options[:magick] = process_options(options[:magick],false) if options[:magick]
- if options[:magick][:versions]
- options[:magick][:versions].each_pair do |name, value|
- options[:magick][:versions][name] = process_options(value, name.to_s)
- end
- end
- state_method = "#{attr}_state".to_sym
- after_assign_method = "#{attr}_magick_after_assign".to_sym
-
- klass.send(:define_method, after_assign_method) do
- self.send(state_method).transform_with_magick
- end
-
- options[:after_upload] ||= []
- options[:after_upload] << after_assign_method
-
- klass.validate do |record|
- state = record.send(state_method)
- if state.has_magick_errors?
- state.magick_errors.each do |error|
- record.errors.add attr, error
- end
- end
- end
- end
-
-
- def self.process_options(options,create_name=true)
- case options
- when String then options = {:size => options}
- when Proc, Symbol then options = {:transformation => options }
- end
- if options[:geometry]
- options[:size] = options.delete(:geometry)
- end
- options[:image_required] = true unless options.key?(:image_required)
- if options[:name].nil? and create_name
- if create_name == true
- hash = 0
- for key in [:size, :crop]
- hash = hash ^ options[key].hash if options[key]
- end
- options[:name] = hash.abs.to_s(36)
- else
- options[:name] = create_name
- end
- end
- options
- end
-
- end
-end
View
19 vendor/plugins/file_column/lib/rails_file_column.rb
@@ -1,19 +0,0 @@
-# require this file from your "config/environment.rb" (after rails has been loaded)
-# to integrate the file_column extension into rails.
-
-require 'file_column'
-require 'file_column_helper'
-
-
-module ActiveRecord # :nodoc:
- class Base # :nodoc:
- # make file_column method available in all active record decendants
- include FileColumn
- end
-end
-
-module ActionView # :nodoc:
- class Base # :nodoc:
- include FileColumnHelper
- end
-end
View
124 vendor/plugins/file_column/lib/test_case.rb
@@ -1,124 +0,0 @@
-require 'test/unit'
-
-# Add the methods +upload+, the <tt>setup_file_fixtures</tt> and
-# <tt>teardown_file_fixtures</tt> to the class Test::Unit::TestCase.
-class Test::Unit::TestCase
- # Returns a +Tempfile+ object as it would have been generated on file upload.
- # Use this method to create the parameters when emulating form posts with
- # file fields.
- #
- # === Example:
- #
- # def test_file_column_post
- # entry = { :title => 'foo', :file => upload('/tmp/foo.txt')}
- # post :upload, :entry => entry
- #
- # # ...
- # end
- #
- # === Parameters
- #
- # * <tt>path</tt> The path to the file to upload.
- # * <tt>content_type</tt> The MIME type of the file. If it is <tt>:guess</tt>,
- # the method will try to guess it.
- def upload(path, content_type=:guess, type=:tempfile)
- if content_type == :guess
- case path
- when /\.jpg$/ then content_type = "image/jpeg"
- when /\.png$/ then content_type = "image/png"
- else content_type = nil
- end
- end
- uploaded_file(path, content_type, File.basename(path), type)
- end
-
- # Copies the fixture files from "RAILS_ROOT/test/fixtures/file_column" into
- # the temporary storage directory used for testing
- # ("RAILS_ROOT/test/tmp/file_column"). Call this method in your
- # <tt>setup</tt> methods to get the file fixtures (images, for example) into
- # the directory used by file_column in testing.
- #
- # Note that the files and directories in the "fixtures/file_column" directory
- # must have the same structure as you would expect in your "/public" directory
- # after uploading with FileColumn.
- #
- # For example, the directory structure could look like this:
- #
- # test/fixtures/file_column/
- # `-- container
- # |-- first_image
- # | |-- 1
- # | | `-- image1.jpg
- # | `-- tmp
- # `-- second_image
- # |-- 1
- # | `-- image2.jpg
- # `-- tmp
- #
- # Your fixture file for this one "container" class fixture could look like this:
- #
- # first:
- # id: 1
- # first_image: image1.jpg
- # second_image: image1.jpg
- #
- # A usage example:
- #
- # def setup
- # setup_fixture_files
- #
- # # ...
- # end
- def setup_fixture_files
- tmp_path = File.join(RAILS_ROOT, "test", "tmp", "file_column")
- file_fixtures = Dir.glob File.join(RAILS_ROOT, "test", "fixtures", "file_column", "*")
-
- FileUtils.mkdir_p tmp_path unless File.exists?(tmp_path)
- FileUtils.cp_r file_fixtures, tmp_path
- end
-
- # Removes the directory "RAILS_ROOT/test/tmp/file_column/" so the files
- # copied on test startup are removed. Call this in your unit test's +teardown+
- # method.
- #
- # A usage example:
- #
- # def teardown
- # teardown_fixture_files
- #
- # # ...
- # end
- def teardown_fixture_files
- FileUtils.rm_rf File.join(RAILS_ROOT, "test", "tmp", "file_column")
- end
-
- private
-
- def uploaded_file(path, content_type, filename, type=:tempfile) # :nodoc:
- if type == :tempfile
- t = Tempfile.new(File.basename(filename))
- FileUtils.copy_file(path, t.path)
- else
- if path
- t = StringIO.new(IO.read(path))
- else
- t = StringIO.new
- end
- end
- (class << t; self; end).class_eval do
- alias local_path path if type == :tempfile
- define_method(:local_path) { "" } if type == :stringio
- define_method(:original_filename) {filename}
- define_method(:content_type) {content_type}
- end
- return t
- end
-end
-
-# If we are running in the "test" environment, we overwrite the default
-# settings for FileColumn so that files are not uploaded into "/public/"
-# in tests but rather into the directory "/test/tmp/file_column".
-if RAILS_ENV == "test"
- FileColumn::ClassMethods::DEFAULT_OPTIONS[:root_path] =
- File.join(RAILS_ROOT, "test", "tmp", "file_column")
-end
View
112 vendor/plugins/file_column/lib/validations.rb
@@ -1,112 +0,0 @@
-module FileColumn
- module Validations #:nodoc:
-
- def self.append_features(base)
- super
- base.extend(ClassMethods)
- end
-
- # This module contains methods to create validations of uploaded files. All methods
- # in this module will be included as class methods into <tt>ActiveRecord::Base</tt>
- # so that you can use them in your models like this:
- #
- # class Entry < ActiveRecord::Base
- # file_column :image
- # validates_filesize_of :image, :in => 0..1.megabyte
- # end
- module ClassMethods
- EXT_REGEXP = /\.([A-z0-9]+)$/
-
- # This validates the file type of one or more file_columns. A list of file columns
- # should be given followed by an options hash.
- #
- # Required options:
- # * <tt>:in</tt> => list of extensions or mime types. If mime types are used they
- # will be mapped into an extension via FileColumn::ClassMethods::MIME_EXTENSIONS.
- #
- # Examples:
- # validates_file_format_of :field, :in => ["gif", "png", "jpg"]
- # validates_file_format_of :field, :in => ["image/jpeg"]
- def validates_file_format_of(*attrs)
-
- options = attrs.pop if attrs.last.is_a?Hash
- raise ArgumentError, "Please include the :in option." if !options || !options[:in]
- options[:in] = [options[:in]] if options[:in].is_a?String
- raise ArgumentError, "Invalid value for option :in" unless options[:in].is_a?Array
-
- validates_each(attrs, options) do |record, attr, value|
- unless value.blank?
- mime_extensions = record.send("#{attr}_options")[:mime_extensions]
- extensions = options[:in].map{|o| mime_extensions[o] || o }
- record.errors.add attr, "is not a valid format." unless extensions.include?(value.scan(EXT_REGEXP).flatten.first)
- end
- end
-
- end
-
- # This validates the file size of one or more file_columns. A list of file columns
- # should be given followed by an options hash.
- #
- # Required options:
- # * <tt>:in</tt> => A size range. Note that you can use ActiveSupport's
- # numeric extensions for kilobytes, etc.
- #
- # Examples:
- # validates_filesize_of :field, :in => 0..100.megabytes
- # validates_filesize_of :field, :in => 15.kilobytes..1.megabyte
- def validates_filesize_of(*attrs)
-
- options = attrs.pop if attrs.last.is_a?Hash
- raise ArgumentError, "Please include the :in option." if !options || !options[:in]
- raise ArgumentError, "Invalid value for option :in" unless options[:in].is_a?Range
-
- validates_each(attrs, options) do |record, attr, value|
- unless value.blank?
- size = File.size(value)
- record.errors.add attr, "is smaller than the allowed size range." if size < options[:in].first
- record.errors.add attr, "is larger than the allowed size range." if size > options[:in].last
- end
- end
-
- end
-
- IMAGE_SIZE_REGEXP = /^(\d+)x(\d+)$/
-
- # Validates the image size of one or more file_columns. A list of file columns
- # should be given followed by an options hash. The validation will pass
- # if both image dimensions (rows and columns) are at least as big as
- # given in the <tt>:min</tt> option.
- #
- # Required options:
- # * <tt>:min</tt> => minimum image dimension string, in the format NNxNN
- # (columns x rows).
- #
- # Example:
- # validates_image_size :field, :min => "1200x1800"
- #
- # This validation requires RMagick to be installed on your system
- # to check the image's size.
- def validates_image_size(*attrs)
- options = attrs.pop if attrs.last.is_a?Hash
- raise ArgumentError, "Please include a :min option." if !options || !options[:min]
- minimums = options[:min].scan(IMAGE_SIZE_REGEXP).first.collect{|n| n.to_i} rescue []
- raise ArgumentError, "Invalid value for option :min (should be 'XXxYY')" unless minimums.size == 2
-
- require 'RMagick'
-
- validates_each(attrs, options) do |record, attr, value|
- unless value.blank?
- begin
- img = ::Magick::Image::read(value).first
- record.errors.add('image', "is too small, must be at least #{minimums[0]}x#{minimums[1]}") if ( img.rows < minimums[1] || img.columns < minimums[0] )
- rescue ::Magick::ImageMagickError
- record.errors.add('image', "invalid image")
- end
- img = nil
- GC.start
- end
- end
- end
- end
- end
-end
View
63 vendor/plugins/file_column/test/abstract_unit.rb
@@ -1,63 +0,0 @@
-require 'test/unit'
-require 'rubygems'
-require 'active_support'
-require 'active_record'
-require 'action_view'
-require File.dirname(__FILE__) + '/connection'
-require 'stringio'
-
-RAILS_ROOT = File.dirname(__FILE__)
-RAILS_ENV = ""
-
-$: << "../lib"
-
-require 'file_column'
-require 'file_compat'
-require 'validations'
-require 'test_case'
-
-# do not use the file executable normally in our tests as
-# it may not be present on the machine we are running on
-FileColumn::ClassMethods::DEFAULT_OPTIONS =
- FileColumn::ClassMethods::DEFAULT_OPTIONS.merge({:file_exec => nil})
-
-class ActiveRecord::Base
- include FileColumn
- include FileColumn::Validations
-end
-
-
-class RequestMock
- attr_accessor :relative_url_root
-
- def initialize
- @relative_url_root = ""
- end
-end
-
-class Test::Unit::TestCase
-
- def assert_equal_paths(expected_path, path)
- assert_equal normalize_path(expected_path), normalize_path(path)
- end
-
-
- private
-
- def normalize_path(path)
- Pathname.new(path).realpath
- end
-
- def clear_validations
- [:validate, :validate_on_create, :validate_on_update].each do |attr|
- Entry.write_inheritable_attribute attr, []
- Movie.write_inheritable_attribute attr, []
- end
- end
-
- def file_path(filename)
- File.expand_path("#{File.dirname(__FILE__)}/fixtures/#{filename}")
- end
-
- alias_method :f, :file_path
-end
View
17 vendor/plugins/file_column/test/connection.rb
@@ -1,17 +0,0 @@
-print "Using native MySQL\n"
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-db = 'file_column_test'
-
-ActiveRecord::Base.establish_connection(
- :adapter => "mysql",
- :host => "localhost",
- :username => "rails",
- :password => "",
- :database => db,
- :socket => "/var/run/mysqld/mysqld.sock"
-)
-
-load File.dirname(__FILE__) + "/fixtures/schema.rb"
View
97 vendor/plugins/file_column/test/file_column_helper_test.rb
@@ -1,97 +0,0 @@
-require File.dirname(__FILE__) + '/abstract_unit'
-require File.dirname(__FILE__) + '/fixtures/entry'
-
-class UrlForFileColumnTest < Test::Unit::TestCase
- include FileColumnHelper
-
- def setup
- Entry.file_column :image
- @request = RequestMock.new
- end
-
- def test_url_for_file_column_with_temp_entry
- @e = Entry.new(:image => upload(f("skanthak.png")))
- url = url_for_file_column("e", "image")
- assert_match %r{^/entry/image/tmp/\d+(\.\d+)+/skanthak.png$}, url
- end
-
- def test_url_for_file_column_with_saved_entry
- @e = Entry.new(:image => upload(f("skanthak.png")))
- assert @e.save
-
- url = url_for_file_column("e", "image")
- assert_equal "/entry/image/#{@e.id}/skanthak.png", url
- end
-
- def test_url_for_file_column_works_with_symbol
- @e = Entry.new(:image => upload(f("skanthak.png")))