Forked from aiaio/interface_for_procs_with_papreclip.rb
Last active
August 29, 2015 14:22
-
-
Save jcarhuazv/d46886a366f429ca27bd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Adds behavior for getting, setting, and validating | |
# images for any given model. Relies on RAILS_ROOT/config/image_definitions.rb | |
module ImageHandling | |
def self.included(base) | |
base.class_eval do | |
# Defines accessor names: if the class is Book, | |
# names will be #book_images and #book_images= | |
image_accessor_name = self.to_s.underscore + "_images" | |
# Define a getter method for all images. | |
define_method(image_accessor_name) do | |
self.images | |
end | |
# Define a setter methods for images. | |
define_method(image_accessor_name + "=") do |attrs| | |
attrs.each do |attr_set| | |
if attr_set['id'].blank? | |
self.images.create(attr_set) | |
else | |
image = self.images.find(attr_set['id']) | |
image.update_attributes(attr_set) | |
end | |
end | |
end | |
# Note: Uses the conditional validation plugin to determine whether | |
# to run the validation. | |
validation_check_name = "should_validate_#{image_accessor_name}?".to_sym | |
validate :validate_required_images, :if => validation_check_name | |
after_validation :filter_image_errors | |
end | |
base.extend(ClassMethods) | |
base.send(:include, InstanceMethods) | |
end | |
module ClassMethods | |
# Gets the image definitions from RAILS_ROOT/config/image_definitions.rb. | |
# Expects a constant named class_name + ImageDefinition. | |
# If you only want an array of one of the definitions' attributes, | |
# pass in the attribute's name as a symbol (e.g., :label). | |
def image_definitions(attr=nil) | |
image_definition_const = const_get(self.to_s + "ImageDefinition") | |
return image_definition_const if attr.nil? | |
image_definition_const.map {|image| image[attr]} | |
end | |
end | |
module InstanceMethods | |
# Return available images by label. | |
# If no label is given, return all available images. | |
def available_images(label=nil) | |
if label.nil? | |
all_images = self.images | |
self.class.image_definitions(:label).map do |label| | |
image_with_label = all_images.detect {|image| image.label == label} | |
image_with_label || self.images.new(:label => label) | |
end | |
else | |
self.images.find(:first, :conditions => {:label => label}) | |
end | |
end | |
private | |
# Validates the presence of all images marked as | |
# required in the class's image definition. | |
def validate_required_images | |
missing_images = [] | |
self.class.image_definitions.each do |definition| | |
if definition[:required] | |
if (image = self.available_images(definition[:label])).nil? || image.new_record? | |
missing_images << definition[:label] | |
end | |
end | |
end | |
return true if missing_images.blank? | |
self.errors.add(:base, "The following required images are missing: #{missing_images.to_sentence}") | |
end | |
# HACK: Problem here is that ActiveRecord | |
# automatically invokes a validates_associated callback | |
# on new has_many relations, which produces some ugly and | |
# unhelpful error messages. This filter removes those messages. | |
# TODO: Remove this when a better fix is discovered. | |
def filter_image_errors | |
copy = self.errors.map do |attr, message| | |
[attr, message] | |
end | |
self.errors.clear | |
copy.each do |error| | |
unless error.first =~ /image/i | |
error.last.each do |e| | |
self.errors.add(error.first, e) | |
end | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment