require "act_as_releasable/version" require "act_as_releasable/models" module ActAsReleasable module ClassMethods def act_as_releasable(options = {}) send :include, InstanceMethods class_attribute :releasable_collections self.releasable_collections = (options[:collections] || []) has_one :releasable_candidate, :as => :item unless self.releasable_collections.empty? has_many :releasable_candidate_items, :as => :item end end end module InstanceMethods def release_version! # Clean-up of the official record self.releasable_collections.each do |collection| send(collection).destroy_all end # Updating attributes self.attributes = releasable_candidate.candidate_attributes releasable_candidate_items.each do |candidate_item| send(candidate_item.collection_name).build candidate_item.candidate_attributes end # Destroying prototype data releasable_candidate.destroy if releasable_candidate.present? releasable_candidate_items.destroy_all save! end def release_candidate clone.tap do self.releasable_collections.each do |collection| send(collection).clear end self.attributes = releasable_candidate.try(:candidate_attributes) || {} releasable_candidate_items.each do |candidate_item| send(candidate_item.collection_name).build candidate_item.candidate_attributes end end end def generate_new_candidate if valid? # Destroying prototype data releasable_candidate.destroy if releasable_candidate.present? releasable_candidate_items.destroy_all # Creating new prototype data create_releasable_candidate! :candidate_attributes => attributes self.releasable_collections.each do |collection| send(collection).each do |collection_item| unless collection_item.marked_for_destruction? releasable_candidate_items.create! ({:candidate_attributes => collection_item.attributes, :collection_name => collection}) end end end end end end def self.included(receiver) receiver.extend ClassMethods end end ActiveSupport.on_load(:active_record) do include ActAsReleasable end