Using an ActiveRecord class method within an ActionMailer object


#1

This is a little convoluted and I’m new to Rails, so please bear with
me…

My application needs to receive both SMS and emails. I have a
controller that has a sms_in method, which receives SMS messages via a
HTTP POST request from an SMS gateway. That controller then calls the
IncomingMessage.process(args) method to go through a number of
validations and create the incoming message in the database as well as
various other database entries that are required with each incoming
message. This works fine.

However, I’m having trouble getting it to work for emails. In my
MailProcessor (ActionMailer) receive method, I’m trying to pass
similar arguments to the IncomingMessage.process(args) class method.
However, for some reason this isn’t working…I can’t seem to call a
class method for an ActiveRecord object from within the ActionMailer
object, and I have no idea why!

Any help would be greatly appreciated!
-Gavin


#2

On 8 Oct 2008, at 16:34, gaveeno wrote:

message. This works fine.

However, I’m having trouble getting it to work for emails. In my
MailProcessor (ActionMailer) receive method, I’m trying to pass
similar arguments to the IncomingMessage.process(args) class method.
However, for some reason this isn’t working…I can’t seem to call a
class method for an ActiveRecord object from within the ActionMailer
object, and I have no idea why!

That should work. Show what you’re doing (and describe what you
actually mean by “isn’t working”)

Fred


#3

I’m using the Fetcher plugin which daemonizes polling the server for
emails. When it pulls in an email, it passes it (the Net::Imap
object) to the receive method of MailProcessor < ActionMailer::Base.
The receive method then calls the process_message class method of
IncomingMessage < ActiveRecord::Base, which should store the incoming
message to the database as well as do a number of other things.
However, this method does not seem to be getting executed for incoming
emails. On the other hand, when this method is called from the
controller containing the sms_in action, the message gets processed/
stored correctly. These are the methods in question:

class MailProcessor < ActionMailer::Base
def receive(mail)
IncomingMessage.process_message({ :sender => mail.from,
:subject => mail.subject,
:channel => “email”,
:person_search_field => “email”,
:date => mail.date,
:body => mail.body,
:delivery_point => mail.to })
end

class MessengerController < ApplicationController
def sms_in
@incoming_message, @opt_or_feedback_object,@processing_notes =
IncomingMessage.process_message({ :sender => params[:smsfrom],
:subject => params[:smsmsg],
:channel => “sms”,
:gateway_id => params[:smsid],
:person_search_field => “mobile_phone”,
:date => params[:smsdate],
:carrier => params[:network],
:delivery_point => params[:smsto] })
end

class IncomingMessage < ActiveRecord::Base
protected
def self.process_message(msg_hash)
@incoming_message = create_incoming_message
#more code to process the message…I didn’t paste it here
because it calls
#a number of other class methods and they would be too much to
paste
end

def self.create_incoming_message
IncomingMessage.create(:subject => @msg_hash[:subject],
:person_id => “#{@person.id}”,
:body => @msg_hash[:body],
:channel => @msg_hash[:channel],
:gateway_id => @msg_hash[:gateway_id],
:carrier => @msg_hash[:carrier],
:date => @msg_hash[:date],
:delivery_point_id => @delivery_point_id)
end

On Oct 8, 11:51 am, Frederick C. removed_email_address@domain.invalid


#4

On Oct 10, 5:32 pm, gaveeno removed_email_address@domain.invalid wrote:

Anybody know why this isn’t working for me?

Well you haven’t said exactly what is happening, eg if you put a
breakpoint in create_incoming_message is it hit? have you tried
stepping through the code and seeing when it fails?
Could it be that creation of the incoming_message fails because of
validation? Do you really mean to be creating class instance
variables ?

Fred


#5

Anybody know why this isn’t working for me?


#6

What SMS gateway are you using if you don’t mind me asking? Is it
open source or are you paying per message?


#7

We are using a shared shortcode provided by another company, so nope
it’s not open source. As far as I’m aware, open source SMS gateways
such as Kannel still require that you have a shortcode leased and
registered with the various carriers, which is really expensive.
There’s really doesn’t seem to be any way to avoid a per-message cost
for outgoing messages (many mobile gateway providers don’t charge for
incoming messages).


#8

I have installed and am using SMS-Fu:
http://brendanlim.com/2008/2/28/send-text-messages-from-rails-with-sms-fu,
which appears to be free to send sms messages. Maybe there is a limit
with this, I am not sure, I read somewhere 500 max in any given 3 day
period but maybe it varies for different carriers? What I would
really like is to be able to receive SMS for free, but it doesnt look
like its in the cards.


#9

When you ask if I really mean to be creating class instance variables,
I assume you’re referring to @incoming_message,
@opt_or_feedback_object, @processing_notes =
IncomingMessage.process_message()…correct? The reason I set class
instance variables is because the view for this action needs to
display details from the incoming message, the object created from the
the incoming message, and the notes that are generated during
processing (including the validation results mostly). I didn’t paste
the last line of the IncomingMessage.process_message() method above,
but FYI it is “return
@incoming_message,@opt_or_feedback_object,@processed_msg_array[0]”.

No, the reason is not that it’s failing because of validations within
the IncomingMessage.process_message() method, because the terminal
window shows now SQL being executed, and also there are items
persisted to the DB regardless of whether validation succeeds or
fails. I took your tip and used breakpoints to see what’s happening
here (this is my first Rails app and I stupidly didn’t think to look
into the Rails debug tools). When a SMS comes in, the breakpoint at
the start of the IncomingMessage.process_message() method is hit.
However, when an email comes in, not breakpoints are hit, regardless
of where they are. I.e. in the MailProcesser.receive() method, I put
the following 2 lines:
1 puts “debug”
2 debugger
The terminal window where I executed the script displays “debug”, but
processing does not stop at the breakpoint.

This might help…it’s the fetcher script that is daemonized (and I
can post more of the code from the Fetcher plugin if you think that
it’d be helpful):

#!/usr/bin/env ruby
require File.dirname(FILE) + ‘/…/config/environment.rb’

class MailFetcherDaemon < Daemon::Base

@config = YAML.load_file("#{RAILS_ROOT}/config/mail.yml")
@config = @config[RAILS_ENV].to_options

@sleep_time = @config.delete(:sleep_time) || 60
def self.start
puts “Starting MailFetcherDaemon”
@fetcher = Fetcher.create({:receiver =>
MailProcessor}.merge(@config))

loop do
  @fetcher.fetch
  sleep(@sleep_time)
end

end

def self.stop
puts “Stopping MailFetcherDaemon”
end

end

MailFetcherDaemon.daemonize

Thanks for your help!
-Gavin

On Oct 10, 12:41 pm, Frederick C. removed_email_address@domain.invalid