Permalink
Browse files

Tracking new attachment styles with a Rake task to refresh them

  • Loading branch information...
1 parent 7478455 commit 3ae7a3e8cc1d3756465a6e5b3e4148015e62bb64 @murbanski murbanski committed Aug 25, 2011
View
@@ -39,6 +39,7 @@
require 'paperclip/attachment'
require 'paperclip/storage'
require 'paperclip/callback_compatibility'
+require 'paperclip/missing_attachment_styles'
require 'paperclip/railtie'
require 'logger'
require 'cocaine'
@@ -269,6 +270,7 @@ def has_attached_file name, options = {}
end
attachment_definitions[name] = {:validations => []}.merge(options)
+ Paperclip.classes_with_attachments << self
after_save :save_attached_files
before_destroy :destroy_attached_files
@@ -0,0 +1,86 @@
+
+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."
View
@@ -20,7 +20,7 @@
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
@@ -0,0 +1,80 @@
+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

0 comments on commit 3ae7a3e

Please sign in to comment.