In my rails app, I'm running delayed jobs with Sucker Punch gem. I'm looping through some phone numbers sending an sms message to each with Twilio.
If there is an error with Twilio sending it, I can capture it with a rescue just fine, but is there a way to notify the user without just raising an exception showing an error page?
Ideally, it would be as a flash message (or other notification) when it happens. Is there some way to do this?
As mentioned in the chat by Nick Veys
, the solution to this will be to create some sort of persistence with the data.
--
Push
I think the functionality you're looking for will be achieved by using some sort of "push" technology, notably Pusher
. This will give you the ability to create a set of files / settings which will provide the ability for the message to appear for the user.
I would personally set up the following:
DelayedJob
processes requests as required- If the message raised an error, store the error
- Send the error message to the user with the push implementation
So I would do this:
#Gemfile
gem 'aasm', '~> 3.3.3'
gem 'pusher', '~> 0.14.1'
#app/models/message.rb
class Message < ActiveRecord::Base
include AASM
aasm do
state :queued, :initial => true
state :sending
state :delivered
state :error
event :sent do
transitions :from => [:queued, :sending], :to => :sent
end
event :raise_error do
transition :from => [:queued, :sending], :to => :error, :on_transition => Proc.new {|obj, *args| obj.set_message(*args) }
end
def set_message(message)
self.update(error: message)
Redis.lpush(self.user.id, self.id)
end
end
end
This means that if you attempt to send the message, you'll be able to update the message as follows:
@message = Message.find params[:id]
if [[message.send_error]]
@message.raise_error(error.message)
end
This means that you'll then be able to append the messages into a Redis instance, which you can then cycle through with Pusher:
--
Pusher
The value of this will be that when you use a front-end notification service such as Pusher, what you're really doing is taking data from your application, and sending it via a websocket, or maybe SSE, to the front-end browser
This is really what you need -- the ability to display the message for the user as / when it happens. To do this, I would use the following:
#app/assets/javascripts/application.js
pusher = new Pusher("**************")
channel = pusher.subscribe("private-user-[[username]]")
channel.bind "error", (data) ->
alert data.message
This will give you the ability to process the Redis queue you made, allowing you to send the requested updates as they are made:
#app/workers/pusher.rb
class PusherQueue
@queue = :pusher
def self.perform(user, message)
# push message here
end
end
This connects with the Pusher service, allowing you to "listen" for the updates you'll receive from the server. This means that if you are able to populate these updates (error messages) using the above code, you'll be able to send the errors to the users as they interact with your app
You read up more about Pusher / push technologies here: