digitalplaywright/mail-control

View on GitHub
lib/mail-control/logged_email.rb

Summary

Maintainability
C
7 hrs
Test Coverage
module MailControl
  module LoggedEmail
    extend ActiveSupport::Concern

    included do

      store :options

      belongs_to :actor,      :polymorphic => true
      belongs_to :act_object, :polymorphic => true
      belongs_to :act_target, :polymorphic => true

      validates_presence_of :actor_id, :actor_type, :verb
    end

    module ClassMethods

      def poll_for_changes()
        #if block_given?

        ::LoggedEmail.where('state = ? AND send_after <= ?', 'initial', Time.now).select(:act_target_id).uniq.each do |cur_target|
          target_id =  cur_target['act_target_id']

          ::LoggedEmail.where('state = ? AND act_target_id = ? AND send_after <= ?', 'initial', target_id, Time.now).select(:verb).uniq.each do |verb|

            changes_for_target =  ::LoggedEmail.where(:act_target_id => target_id, :state => 'initial', :verb => verb['verb'].to_s)

            yield  verb, changes_for_target

            changes_for_target.each do |cft|
              cft.update_attributes(:state => 'complete')
            end



          end


        end
      end


      # Defines a new LoggedEmail2 type and registers a definition
      #
      # @param [ String ] name The name of the mailing
      #
      # @example Define a new mailing
      #   mailing(:enquiry) do
      #     actor :user, :cache => [:full_name]
      #     act_object :enquiry, :cache => [:subject]
      #     act_target :listing, :cache => [:title]
      #   end
      #
      # @return [Definition] Returns the registered definition
      def mailing(name, &block)
        definition = MailControl::DefinitionDSL.new(name)
        definition.instance_eval(&block)
        MailControl::Definition.register(definition)
      end

      # Publishes an mailing using an mailing name and data
      #
      # @param [ String ] verb The verb of the mailing
      # @param [ Hash ] data The data to initialize the mailing with.
      #
      # @return [MailControl::LoggedEmail2] An LoggedEmail instance with data
      def send_email(verb, data)
        new.send_email({:verb => verb}.merge(data))
      end

    end



    # Publishes the mailing to the receivers
    #
    # @param [ Hash ] options The options to send_email with.
    #
    def send_email(data = {})
      assign_properties(data)

      self
    end


    def refresh_data
      save(:validate => false)
    end

    protected

    def assign_properties(data = {})

      self.verb      = data.delete(:verb)


      write_attribute(:send_after, data[:send_after])
      data.delete(:send_after)

      write_attribute(:send_before, data[:send_before])
      data.delete(:send_before)

      self.state = 'initial'

      [:actor, :act_object, :act_target].each do |type|

        cur_object = data[type]

        unless cur_object
          if definition.send(type.to_sym)
            raise verb.to_json
            #raise MailControl::InvalidData.new(type)
          else
            next

          end
        end

        class_sym = cur_object.class.name.to_sym

        raise MailControl::InvalidData.new(class_sym) unless definition.send(type) == class_sym

        case type
          when :actor
            self.actor = cur_object
          when :act_object
            self.act_object = cur_object
          when :act_target
            self.act_target = cur_object
          else
            raise "unknown type"
        end

        data.delete(type)

      end

      [:grouped_actor].each do |group|


        grp_object = data[group]

        if grp_object == nil
          if definition.send(group.to_sym)
            raise verb.to_json
            #raise MailControl::InvalidData.new(group)
          else
            next

          end
        end

        grp_object.each do |cur_obj|
          raise MailControl::InvalidData.new(class_sym) unless definition.send(group) == cur_obj.class.name.to_sym

          self.grouped_actors << cur_obj

        end

        data.delete(group)

      end

      cur_bond_type = definition.send(:bond_type)

      if cur_bond_type
        write_attribute( :bond_type, cur_bond_type.to_s )
      end

      if definition.send(:unsubscribe_by)
        write_attribute(:unsubscribe_by, definition.send(:unsubscribe_by))
      else
        raise "definition must define unsubscribe_by option"
      end

      if self.act_target.is_unsubscribed_to?(self)
        self.state = 'unsubscribed'
      end

      def_options = definition.send(:options)
      def_options.each do |cur_option|
        cur_object = data[cur_option]

        if cur_object

          if cur_option == :description
            self.description = cur_object
          else
            options[cur_option] = cur_object
          end
          data.delete(cur_option)

        else
          #all options defined must be used
          raise Streama::InvalidData.new(cur_object[0])
        end
      end

      if data.size > 0
        raise "unexpected arguments: " + data.to_json
      end



      self.save


    end

    def definition
      @definition ||= MailControl::Definition.find(verb)
    end


  end
end