foodsoft/app/models/message.rb

100 lines
4.2 KiB
Ruby
Raw Normal View History

2009-01-06 11:49:19 +01:00
# A message within the foodsoft.
#
# * sender (User) - the sending User (might be nil if it is a system message)
# * recipient (User) - the receiving User
# * recipients (String) - list of all recipients of this message as User.nick/Group.name
# * subject (string) - message subject
# * body (string) - message body
# * read? (boolean) - message read status
# * email_state (integer) - email state, one of EMAIL_STATE.values
# * created_on (timestamp) - creation timestamp
class Message < ActiveRecord::Base
belongs_to :sender, :class_name => "User", :foreign_key => "sender_id"
belongs_to :recipient, :class_name => "User", :foreign_key => "recipient_id"
attr_accessible :recipient_id, :recipient, :subject, :body, :recipients
# Values for the email_state attribute: :none, :pending, :sent, :failed
EMAIL_STATE = {
:none => 0,
:pending => 1,
:sent => 2,
:failed => 3
}
validates_presence_of :recipient_id
validates_length_of :subject, :in => 1..255
validates_presence_of :recipients
validates_presence_of :body
validates_inclusion_of :email_state, :in => EMAIL_STATE.values
@@pending = false
# Automatically determine if this message should be send as an email.
def before_validation_on_create
if (recipient && recipient.settings["messages.sendAsEmail"] == '1')
self.email_state = EMAIL_STATE[:pending]
else
self.email_state = EMAIL_STATE[:none]
end
end
# Determines if this new message is a pending email.
def after_create
@@pending = @@pending || self.email_state == EMAIL_STATE[:pending]
end
# Returns true if there might be pending emails.
def self.pending?
@@pending
end
# Returns true if this message is a system message, i.e. was sent automatically by the FoodSoft itself.
def system_message?
self.sender_id.nil?
end
# Sends all pending messages that are to be send as emails.
def self.send_emails
transaction do
messages = find(:all, :conditions => ["email_state = ?", EMAIL_STATE[:pending]], :lock => true)
logger.debug("Sending #{messages.size} pending messages as emails...") unless messages.empty?
for message in messages
if (message.recipient && message.recipient.email && !message.recipient.email.empty?)
begin
Mailer.deliver_message(message)
message.update_attribute(:email_state, EMAIL_STATE[:sent])
logger.debug("Delivered message as email: id = #{message.id}, recipient = #{message.recipient.nick}, subject = \"#{message.subject}\"")
rescue => exception
message.update_attribute(:email_state, EMAIL_STATE[:failed])
logger.warn("Failed to deliver message as email: id = #{message.id}, recipient = #{message.recipient.nick}, subject = \"#{message.subject}\", exception = #{exception.message}")
end
else
message.update_attribute(:email_state, EMAIL_STATE[:failed])
logger.warn("Cannot deliver message as email (no user email): id = #{message.id}, recipient = #{message.recipient.nick}, subject = \"#{message.subject}\"")
end
end
logger.debug("Done sending emails.") unless messages.empty?
@@pending = false
end
end
# Returns a new message object created from the attributes specified (recipient, recipients, subject)
# and the body from the given template that can make use of the variables specified.
# The templates are to be stored in app/views/messages, i.e. the template name
# "order_finished" would invoke template file "app/views/messages/order_finished.rhtml".
# Note: you need to set the sender afterwards if this should not be a system message.
#
# Example:
# Message.from_template(
# 'order_finished',
# {:user => user, :group => order_group, :order => self, :results => results, :total => group_order.price},
# {:recipient_id => user.id, :recipients => recipients, :subject => "Bestellung beendet: #{self.name}"}
# ).save!
def self.from_template(template, vars, attributes)
view = ActionView::Base.new(Rails::Configuration.new.view_path, {}, MessagesController.new)
new(attributes.merge(:body => view.render(:file => "messages/#{template}.rhtml", :locals => vars)))
end
end