Skip to content

Instantly share code, notes, and snippets.

@mackermedia
Created January 22, 2014 21:28
Show Gist options
  • Save mackermedia/8567677 to your computer and use it in GitHub Desktop.
Save mackermedia/8567677 to your computer and use it in GitHub Desktop.
Meta override column setter to support Rich Picker submitting images as path strings rather than File objects.
# lib/rich/carrier_wave_sanitizer.rb
module Rich
class CarrierWaveSanitizer
def initialize(ar_object, column, path_string)
@ar_object = ar_object
@column = column
@path_string = path_string
end
def sanitize_and_set
return if @path_string.blank? || same_filename_as_persisted?
set_file_from_path_string
end
private
def same_filename_as_persisted?
@path_string == @ar_object.send(@column).file.try(:filename)
end
def set_file_from_path_string
if CarrierWave::Uploader::Base.storage == CarrierWave::Storage::File
file_storage_set_upload
elsif CarrierWave::Uploader::Base.storage == CarrierWave::Storage::Fog
fog_storage_set_upload
end
end
def file_storage_set_upload
if File.exists?(absolute_image_path)
@ar_object.send("#{@column}_without_sanitization=", File.open(absolute_image_path))
end
end
def fog_storage_set_upload
@ar_object.send("remote_#{@column}_url=", @path_string)
end
def absolute_image_path
@absolute_image_path ||= File.join(resource_base_path, @path_string)
end
def resource_base_path
Rails.env.test? ? "" : Rails.root.join("public")
end
end
end
# spec/lib/rich/carrier_wave_sanitizer_spec.rb
require 'spec_helper'
describe Rich::CarrierWaveSanitizer do
def image_path(filename)
Rails.root.join("spec", "fixtures", "images", filename).to_s
end
let(:image_filename) { "serve_hero.png" }
let(:image_file) { File.new(image_path(image_filename)) }
let!(:subject) { create(:hero_image_component, :image => image_file) }
describe "#sanitize_and_set" do
it "does not modify the AR object if value is blank" do
lambda {
subject.image = ""
}.should_not change(subject, :image)
end
it "does not modify the AR object value is set to same filename as persisted" do
lambda {
subject.image = image_filename
}.should_not change(subject, :image)
end
context "with a new non-blank value" do
it "changes changed status on AR object if value is valid" do
lambda {
subject.image = image_path("housing_property.jpg")
}.should change(subject, :changed).from([]).to(["image"])
end
context "when storage is File" do
before { CarrierWave::Uploader::Base.storage = CarrierWave::Storage::File }
after { CarrierWave::Uploader::Base.storage = CarrierWave::Storage::File }
it "stores the new file when storage type is File" do
subject.image.file.filename.should == "serve_hero.png"
subject.image = image_path("housing_property.jpg")
subject.image.file.filename.should == "housing_property.jpg"
end
end
context "when storage is Fog" do
before { CarrierWave::Uploader::Base.storage = CarrierWave::Storage::Fog }
after { CarrierWave::Uploader::Base.storage = CarrierWave::Storage::File }
it "sets the remote column url when storage type is Fog" do
subject.image.file.filename.should == "serve_hero.png"
subject.should_receive("remote_image_url=").with(image_path("housing_property.jpg"))
subject.image = image_path("housing_property.jpg")
end
end
end
end
end
# config/initializers/rich_picker_field.rb
# modifies the column setter to convert a path as string
# into a File object like multi-part forms submit.
# This is needed to work with CarrierWave uploaders
#
# Example:
# mount_uploader :image
# rich_picker_field :image
unless ActiveRecord::Base.respond_to?(:rich_picker_field)
module RichPickerField
def rich_picker_field(column)
define_method "#{column}_with_sanitization=" do |path_string|
rich_sanitizer = Rich::CarrierWaveSanitizer.new(self, column, path_string)
rich_sanitizer.sanitize_and_set
end
self.send(:alias_method_chain, :"#{column}=", :sanitization)
end
end
ActiveRecord::Base.extend(RichPickerField)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment