module Stex::Acts::Messagable::InstanceMethods

Public Instance Methods

messagable_accessor(request) click to toggle source

Accessor for acts_as_messagable options and helpers

@param [String, Symbol] request

Requested option or helper, available values are:
- +:sender_name+ Returns a formatted representation of +self+
  which is used in message sender display fields

- +:recipient_name+ Returns a formatted representation of +self+
  which is used in message recipient display fields

- +:forward_to+ Returns the recipient(s) a message should be forwarded
  to instead of being delivered to +self+ or +nil+ if not defined (see #acts_as_messagable)

- +:optional_recipients+ Returns an Array of Array<Symbol, *Messagable, String>,
  for more details see #acts_as_messagable

- +:store_additional_recipients+ Returns true|false, depending on the given option
  in #acts_as_messagable
# File lib/stex/acts/messagable.rb, line 225
def messagable_accessor(request)
  @cached_accessors ||= {}
  options           = self.class.acts_as_messagable_options

  @cached_accessors[request.to_sym] ||= case request.to_sym
                                          when :sender_name
                                            Stex::Acts::Messagable.run_method(self, options[:sender_name])
                                          when :recipient_name
                                            Stex::Acts::Messagable.run_method(self, options[:recipient_name])
                                          when :forward_to
                                            Stex::Acts::Messagable.run_method(self, options[:forward_to])
                                          when :optional_recipients
                                            Array(options[:optional_recipients]).map do |identifier, proc, name|
                                              recipient_name = name.is_a?(String) ? name : Stex::Acts::Messagable.run_method(self, name)
                                              [identifier, Stex::Acts::Messagable.run_method(self, proc), recipient_name]
                                            end
                                          when :store_additional_recipients
                                            Stex::Acts::Messagable.run_method(self, options[:store_additional_recipients],
                                                                              options[:store_additional_recipients])
                                          else
                                            raise ArgumentError.new('Invalid Request Argument: ' + request.to_s)
                                        end
end
send_message(recipients, subject, content, options = {}) click to toggle source

Sends a message from self to the given list of recipients The whole sending happens in a transaction, so if one message creation fails, none of them are sent.

@param [Array<Messagable>|Array<Hash>|Messagable] recipients

The message recipient(s), all have to be +messagable+
The value will be handled as an Array in every case, so if you only
have one recipient, you don't have to put it in brackets.
The array elements may either be +messagable+ objects or arrays,
mapping +messagable+ to Array<optional recipient identifiers>, see example.

@param [String] subject

The message message's subject

@param [String] content

The message message

@example Recipient with optional recipient (see acts_as_messagable)

my_user.send_message([[my_group, [:tutors]]], 'Subject', 'Body')
# File lib/stex/acts/messagable.rb, line 270
def send_message(recipients, subject, content, options = {})
  recipients_with_cause = []
  all_recipients        = []

  #Create a new list of recipients together with the original recipients
  #that caused their existance in this list.
  #Also, determine whether additional recipients should be saved or not
  Array(recipients).each do |recipient_or_array|
    local_recipients = Stex::Acts::Messagable.determine_message_recipients([recipient_or_array])
    recipient        = recipient_or_array.is_a?(Array) ? recipient_or_array.first : recipient_or_array

    all_recipients += local_recipients

    recipients_with_cause << {:cause             => recipient,
                              :store_additionals => recipient.class.acts_as_messagable_options[:store_additional_recipients] && local_recipients.size > 1,
                              :recipients        => local_recipients.uniq}

  end

  all_recipients.uniq!
  processed_recipients = []

  Stex::Acts::Messagable.message_class.transaction do
    recipients_with_cause.each do |recipient_data|
      recipient_data[:recipients].each do |recipient|

        next if processed_recipients.include?(recipient)
        processed_recipients << recipient

        message                       = options.clone
        message[:subject]             = subject
        message[:content]             = content
        message[:original_recipients] = Array(recipients)

        #If the original recipient was set to store additional recipients, we store
        #all recipients that were caused by the same original recipient
        if recipient_data[:store_additionals]
          message[:additional_recipients] = recipient_data[:recipients] - [recipient]
          # If the recipient itself was set to store additional recipients, we store
          # all recipients this message is sent to, regardless of the original recipients
        elsif recipient.class.acts_as_messagable_options[:store_additional_recipients] && final_recipients.size > 1
          message[:additional_recipients] = all_recipients - [recipient]
        end

        #It might happen that a messagable does not actually want to
        #receive messages, but instead do something different.
        if recipient.class.acts_as_messagable_options[:handler]
          recipient.class.acts_as_messagable_options[:handler].call(self, message)
        else
          #Otherwise, a new message is created and sent to the given recipient
          Stex::Acts::Messagable.message_class.create!(message.merge({:sender => self, :recipient => recipient}))
        end
      end
    end

    #Create a copy of the message for the sender
    Stex::Acts::Messagable.message_class.create!(:subject               => subject,
                                                 :content               => content,
                                                 :original_recipients   => Array(recipients),
                                                 :additional_recipients => all_recipients,
                                                 :sender                => self,
                                                 :recipient             => self,
                                                 :sender_copy           => true)
  end
end