require 'polygallery' module Polygallery module HasPolygallery extend ActiveSupport::Concern module ClassMethods def has_polygallery(title='gallery', options={}) if title.is_a? Hash options = title title = 'gallery' end defaults = DEFAULT_SETTINGS if options[:association_names].nil? && title.to_s != 'gallery' options[:association_names] = { :gallery => :"#{title}", :photos => :"#{title.to_s.gsub('_gallery', '')}_photos" } end settings = defaults.deep_merge(options) cattr_accessor "#{title}_settings".to_sym send("#{title}_settings=".to_sym, settings) attr_accessor :"#{title}_attributes", :galleries_built has_one title.to_sym, -> { where(title: title.to_s) }, settings[:associations][:gallery] has_many settings[:association_names][:photos], :through => :"#{title}", :source => :photos, # settings[:association_names][:photos], :class_name => settings[:associations][:photos][:class_name] accepts_nested_attributes_for settings[:association_names][:gallery], settings[:nested_attributes][:gallery] accepts_nested_attributes_for settings[:association_names][:photos], settings[:nested_attributes][:photos] after_initialize :if => :new_record? do # puts "GA: #{self.gallery_attributes.inspect}" if self.gallery_attributes.nil? # puts 'BUILDING FIRST PHOTOS ON INIT!' build_gallery_associations build_first_photos end end # puts instance.inspect # instance.new_record? && !instance.has_polygallery? } before_validation do # , :on => :update # , :unless => :new_record? # puts 'BUILDING GALLERIES ON VALIDATION' # unless self.galleries_built? build_gallery_associations # end prune_empty_photos end before_save :ensure_galleryable_set include HasPolygallery::LocalInstanceMethods end def polygalleries self.reflect_on_all_associations(:has_one) .select{|a| a.foreign_key == 'galleryable_id'}.map(&:name) end def has_polygallery?(gallery_title=nil) return polygalleries.any? if gallery_title.nil? polygalleries.include?(gallery_title) end end module LocalInstanceMethods def polygalleries self.class.polygalleries.each do |pg_name| gallery_opts = self.send(:"#{pg_name}_settings") gallery_classname = gallery_opts[:associations][:gallery][:class_name] gallery_class = Object.const_get gallery_classname table_name = gallery_class.table_name gallery_class.select("#{table_name}.title") .where(:galleryable => self) .group("#{table_name}.title") .map(&:title) end end def has_polygallery?(gallery_title=nil) return polygalleries.any? if gallery_title.nil? polygalleries.include?(gallery_title) end def build_gallery_associations return [] unless self.class.has_polygallery? gallery_associations = self.class.polygalleries.map{|pg| self.build_gallery_association pg } self.galleries_built = true gallery_associations end def build_gallery_association(gallery_name=:gallery) gallery_association = send gallery_name attrs_for_this_gallery = send(:"#{gallery_name}_attributes") || {} if gallery_association.present? # if attrs_for_this_gallery.empty? # gallery_association.photos.each do |p| # if p.photo_to_upload.present? # p.photo = File.new p.photo_to_upload # p.photo_to_upload = nil # end # relevant_changes = p.changed - # %w(galleryable_type galleryable_id gallery_title) # if relevant_changes.any? # attrs_for_this_photo = Hash[*relevant_changes.map{|column| # [ column, p.send(column) ] }.flatten] # attrs_for_this_gallery[:photos_attributes] ||= {} # attrs_for_this_gallery[:photos_attributes][(p.id || # attrs_for_this_gallery[:photos_attributes].length).to_s] = attrs_for_this_photo # end # end # # return gallery_association # end if attrs_for_this_gallery.empty? # puts 'Returning due to empty attrs!' return gallery_association end if gallery_association.persisted? # puts 'Updating an existing gallery!' gallery_association.update_attributes attrs_for_this_gallery else attrs_for_this_gallery.each{|k, v| gallery_association.send :"#{k}=", v } end return gallery_association end settings_for_this_gallery = send :"#{gallery_name}_settings" attrs_for_this_gallery[:polygallery_options] = settings_for_this_gallery # puts "Building a new gallery: #{gallery_name}" built_gallery = send :"build_#{gallery_name}", attrs_for_this_gallery gallery_association = send :"#{gallery_name}=", built_gallery gallery_association.galleryable ||= self gallery_association end def build_first_photos return unless self.class.has_polygallery? # self.class.polygalleries.each{|pg| # build_gallery_association pg # send(pg.to_sym).build_first_photo } build_gallery_associations.map(&:build_first_photo) end def first_polyphoto(ga_name=nil) return Photo.new unless gallery_associations.any? ga = if ga_name.present? then send(ga_name) else gallery_associations.to_a.find{|pg| pg.photos.any? } end return Photo.new if ga.nil? ga.first_photo end def first_photo(ga_name=nil); first_polyphoto(ga_name).photo end def ensure_galleryable_set gallery_associations.each do |ga| ga.galleryable ||= self ga.polygallery_photos.each{|pp| pp.galleryable ||= self } end end def gallery_associations self.class.polygalleries.map{|pg| send(pg) } end def galleries_built?; self.galleries_built.present? end def prune_empty_photos gallery_associations.each(&:prune_empty_photos) end def remote_urls_for_polyphotos(style=nil) gallery_associations.map{|ga| ga.remote_urls(style) }.flatten end def thumb_url; first_polyphoto.thumb_url end end end end # ActiveRecord::Base.send :include, Polygallery::HasPolygallery