Commit 33b2ed44 by Mike Burns

Merge branch 'master' of https://github.com/murbanski/paperclip

parents 281a7553 fc0349d7
......@@ -305,6 +305,56 @@ processors, where a defined `watermark` processor is invoked after the
attr_accessor :watermark
end
Deploy
------
Paperclip is aware of new attachment styles you have added in previous deploy. The only thing you should do after each deployment is to call
`rake paperclip:refresh:missing_styles`. It will store current attachment styles in `RAILS_ROOT/public/system/paperclip_attachments.yml`
by default. You can change it by:
Paperclip.registered_attachments_styles_path = '/tmp/config/paperclip_attachments.yml'
Here is an example for Capistrano:
namespace :deploy do
desc "build missing paperclip styles"
task :build_missing_paperclip_styles, :roles => :app do
run "cd #{release_path}; RAILS_ENV=production bundle exec rake paperclip:refresh:missing_styles"
end
end
after("deploy:update_code", "deploy:build_missing_paperclip_styles")
Now you don't have to remember to refresh thumbnails in production everytime you add new style.
Unfortunately it does not work with dynamic styles - it just ignores them.
If you already have working app and don't want `rake paperclip:refresh:missing_styles` to refresh old pictures, you need to tell
Paperclip about existing styles. Simply create paperclip_attachments.yml file by hand. For example:
class User < ActiveRecord::Base
has_attached_file :avatar, :styles => {:thumb => 'x100', :croppable => '600x600>', :big => '1000x1000>'}
end
class Book < ActiveRecord::Base
has_attached_file :cover, :styles => {:small => 'x100', :large => '1000x1000>'}
has_attached_file :sample, :styles => {:thumb => 'x100'}
end
Then in `RAILS_ROOT/public/system/paperclip_attachments.yml`:
---
:User:
:avatar:
- :thumb
- :croppable
- :big
:Book:
:cover:
- :small
- :large
:sample:
- :thumb
Testing
-------
......
......@@ -39,6 +39,7 @@ require 'paperclip/style'
require 'paperclip/attachment'
require 'paperclip/storage'
require 'paperclip/callback_compatibility'
require 'paperclip/missing_attachment_styles'
require 'paperclip/railtie'
require 'logger'
require 'cocaine'
......@@ -288,6 +289,7 @@ module Paperclip
end
attachment_definitions[name] = {:validations => []}.merge(options)
Paperclip.classes_with_attachments << self
after_save :save_attached_files
before_destroy :prepare_for_destroy
......
require 'set'
module Paperclip
class << self
attr_accessor :classes_with_attachments
attr_writer :registered_attachments_styles_path
def registered_attachments_styles_path
@registered_attachments_styles_path ||= Rails.root.join('public/system/paperclip_attachments.yml').to_s
end
end
self.classes_with_attachments = Set.new
# Get list of styles saved on previous deploy (running rake paperclip:refresh:missing_styles)
def self.get_registered_attachments_styles
YAML.load_file(Paperclip.registered_attachments_styles_path)
rescue Errno::ENOENT
nil
end
private_class_method :get_registered_attachments_styles
def self.save_current_attachments_styles!
File.open(Paperclip.registered_attachments_styles_path, 'w') do |f|
YAML.dump(current_attachments_styles, f)
end
end
# Returns hash with styles for all classes using Paperclip.
# Unfortunately current version does not work with lambda styles:(
# {
# :User => {:avatar => [:small, :big]},
# :Book => {
# :cover => [:thumb, :croppable]},
# :sample => [:thumb, :big]},
# }
# }
def self.current_attachments_styles
Hash.new.tap do |current_styles|
Paperclip.classes_with_attachments.each do |klass|
klass.attachment_definitions.each do |attachment_name, attachment_attributes|
# TODO: is it even possible to take into account Procs?
next if attachment_attributes[:styles].kind_of?(Proc)
attachment_attributes[:styles].try(:keys).try(:each) do |style_name|
klass_sym = klass.to_s.to_sym
current_styles[klass_sym] ||= Hash.new
current_styles[klass_sym][attachment_name.to_sym] ||= Array.new
current_styles[klass_sym][attachment_name.to_sym] << style_name.to_sym
current_styles[klass_sym][attachment_name.to_sym].map!(&:to_s).sort!.map!(&:to_sym).uniq!
end
end
end
end
end
private_class_method :current_attachments_styles
# Returns hash with styles missing from recent run of rake paperclip:refresh:missing_styles
# {
# :User => {:avatar => [:big]},
# :Book => {
# :cover => [:croppable]},
# }
# }
def self.missing_attachments_styles
current_styles = current_attachments_styles
registered_styles = get_registered_attachments_styles
Hash.new.tap do |missing_styles|
current_styles.each do |klass, attachment_definitions|
attachment_definitions.each do |attachment_name, styles|
registered = registered_styles[klass][attachment_name] rescue []
missed = styles - registered
if missed.present?
klass_sym = klass.to_s.to_sym
missing_styles[klass_sym] ||= Hash.new
missing_styles[klass_sym][attachment_name.to_sym] ||= Array.new
missing_styles[klass_sym][attachment_name.to_sym].concat(missed.to_a)
missing_styles[klass_sym][attachment_name.to_sym].map!(&:to_s).sort!.map!(&:to_sym).uniq!
end
end
end
end
end
end
......@@ -60,6 +60,22 @@ namespace :paperclip do
end
end
end
desc "Regenerates missing thumbnail styles for all classes using Paperclip."
task :missing_styles => :environment do
# Force loading all model classes to never miss any has_attached_file declaration:
Dir[Rails.root + 'app/models/**/*.rb'].each { |path| load path }
Paperclip.missing_attachments_styles.each do |klass, attachment_definitions|
attachment_definitions.each do |attachment_name, missing_styles|
puts "Regenerating #{klass} -> #{attachment_name} -> #{missing_styles.inspect}"
ENV['CLASS'] = klass.to_s
ENV['ATTACHMENT'] = attachment_name.to_s
ENV['STYLES'] = missing_styles.join(',')
Rake::Task['paperclip:refresh:thumbnails'].execute
end
end
Paperclip.save_current_attachments_styles!
end
end
desc "Cleans out invalid attachments. Useful after you've added new validations."
......
......@@ -20,7 +20,7 @@ rescue LoadError => e
puts "debugger disabled"
end
ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
ROOT = Pathname(File.expand_path(File.join(File.dirname(__FILE__), '..')))
def silence_warnings
old_verbose, $VERBOSE = $VERBOSE, nil
......
require './test/helper'
class PaperclipMissingAttachmentStylesTest < Test::Unit::TestCase
context "Paperclip" do
setup do
Paperclip.classes_with_attachments = Set.new
end
teardown do
File.unlink(Paperclip.registered_attachments_styles_path) rescue nil
end
should "be able to keep list of models using it" do
assert_kind_of Set, Paperclip.classes_with_attachments
assert Paperclip.classes_with_attachments.empty?, 'list should be empty'
rebuild_model
assert_equal [Dummy].to_set, Paperclip.classes_with_attachments
end
should "enable to get and set path to registered styles file" do
assert_equal ROOT.join('public/system/paperclip_attachments.yml').to_s, Paperclip.registered_attachments_styles_path
Paperclip.registered_attachments_styles_path = '/tmp/config/paperclip_attachments.yml'
assert_equal '/tmp/config/paperclip_attachments.yml', Paperclip.registered_attachments_styles_path
Paperclip.registered_attachments_styles_path = nil
assert_equal ROOT.join('public/system/paperclip_attachments.yml').to_s, Paperclip.registered_attachments_styles_path
end
should "be able to get current attachment styles" do
assert_equal Hash.new, Paperclip.send(:current_attachments_styles)
rebuild_model :styles => {:croppable => '600x600>', :big => '1000x1000>'}
expected_hash = { :Dummy => {:avatar => [:big, :croppable]}}
assert_equal expected_hash, Paperclip.send(:current_attachments_styles)
end
should "be able to save current attachment styles for further comparison" do
rebuild_model :styles => {:croppable => '600x600>', :big => '1000x1000>'}
Paperclip.save_current_attachments_styles!
expected_hash = { :Dummy => {:avatar => [:big, :croppable]}}
assert_equal expected_hash, YAML.load_file(Paperclip.registered_attachments_styles_path)
end
should "be able to read registered attachment styles from file" do
rebuild_model :styles => {:croppable => '600x600>', :big => '1000x1000>'}
Paperclip.save_current_attachments_styles!
expected_hash = { :Dummy => {:avatar => [:big, :croppable]}}
assert_equal expected_hash, Paperclip.send(:get_registered_attachments_styles)
end
should "be able to calculate differences between registered styles and current styles" do
rebuild_model :styles => {:croppable => '600x600>', :big => '1000x1000>'}
Paperclip.save_current_attachments_styles!
rebuild_model :styles => {:thumb => 'x100', :export => 'x400>', :croppable => '600x600>', :big => '1000x1000>'}
expected_hash = { :Dummy => {:avatar => [:export, :thumb]} }
assert_equal expected_hash, Paperclip.missing_attachments_styles
ActiveRecord::Base.connection.create_table :books, :force => true
class ::Book < ActiveRecord::Base
has_attached_file :cover, :styles => {:small => 'x100', :large => '1000x1000>'}
has_attached_file :sample, :styles => {:thumb => 'x100'}
end
expected_hash = {
:Dummy => {:avatar => [:export, :thumb]},
:Book => {:sample => [:thumb], :cover => [:large, :small]}
}
assert_equal expected_hash, Paperclip.missing_attachments_styles
Paperclip.save_current_attachments_styles!
assert_equal Hash.new, Paperclip.missing_attachments_styles
end
# It's impossible to build styles hash without loading from database whole bunch of records
should "skip lambda-styles" do
rebuild_model :styles => lambda{ |attachment| attachment.instance.other == 'a' ? {:thumb => "50x50#"} : {:large => "400x400"} }
assert_equal Hash.new, Paperclip.send(:current_attachments_styles)
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment