I am developing a Ruby on Rails web application that requires text notification.
A User (a model) creates a Task (another model) and assigns it to a Recipient (another model). The User schedules the text notification for the Task and identifies a specific Recipient. I used Associations in each of the Rails Models to establish the relationships between the User, the Task and the Recipient.
Twilio – Creating Text Messages
I used Twilio to deliver the text notifications and leveraged their APIs to integrate the functionality into my Rails app
Twilio is a popular messaging service used by major companies such as AirBnB and Hulu. They provide voice and SMS application services.
I installed the Twilio Ruby gem to communicate with the Twilio API and generate the TwilML.
Delayed::Job – Scheduling Text Messages
I need to leverage a Ruby gem to manage scheduling text messages in the future. After looking at a few gems, I decided to use Delayed::Job. An alternative to consider is the Resque gem. Several developers suggested that gem to me while I was developing my app but I was too deep into my code development (and the Delayed::Job was working fine) to change horses mid way through the race.
Other Ruby Gems
The Daemons gem was used to enable the Delayed::Job gem.
I also used the Figaro gem to protect my Twilio account credentials.
Integrating Twilio into Rails 4
After some trial and error and much fumbling through online documentation, I managed to get the text notification functionality integrated into my Rails app.
Here is a quick summary of the steps I took to get the Twilio API working. I hope that this document will help other developers navigate through the setup process much quicker than I did.
Step 1 – Create a Twilio Dev Account
You will need a Twilio test account to test your application. There is no charge for the test account and you get a free number to validate your voice or texting application.
The account setup process is very straightforward and is explained very well in this video. The speaker does a thorough job walking you through the setup.
You can choose the area code for your test number (and avoid long distance charges). You can even choose a number based on a set of letters.
You will get an API SID and authorization token to configure your account in your Rails application. I used the Figaro gem to protect the data. Figaro places your credentials inside the application.yml file and keeps that file from being posted on GitHub.
You can also control the Request URL and set the http GET and POST settings for the number. This is done inside your Twilio account under Numbers -> Twilio Numbers,
Step 2 – Texting Out With Twilio From the App
My app allows a User (one model) to notify a Recipient (another model), via text message, that they are responsible for a specific Task (the last model). All of the tasks are recorded in the Task table in Rails.
When the User initiates a Task and selects a Recipient, the app needs to fire off a text to the Recipient letting them know that they are responsible for completing the Task.
I placed the code to send the text in the Task Model inside Rails and not in the Task Controller.
I created a method called send_text_message to send the text message to the Recipent. The majority of the code came from the Twilio Ruby gem documentation. I customized it to work with Figaro (note the assignment settings for the twilio_sid, twilio_token, and twilio_phone_number variables in the code).
The send_text_message is fired inside the Task Model after the create method is called in my Task Controller (from the Task New View). After a few tries and a bit of debugging, I was able to send text messages from my app to my phone. It was nice feeling to get my app and Twilio talking (or rather, texting). However, once I got that working, I had to work on the next step: allowing the User to schedule texting Tasks in the future.
Step 3 – Scheduling Texts
I used the Delayed::Job gem to schedule the tasks created in the Task model. I installed the Delayed::Job gem and generated its database table with rails generate and rake db:migrate.
I had to create a relationship between the Task model and the Delayed::Job table.
I could not use a Rail Association so I created a delayed_job_id in my Task table that correlated to the job.id in the Delayed::Job table. I also created a method inside the Task Model, called schedule_sending_text:
The schedule_sending_text method accomplished two things:
- Assigned the schedule_time value (from the Task database) to the run_at value in the Delayed::Job database. I called the send_text_message method inside this piece of code.
- Updated the delayed_job_id in the Task table to be the value in the job.id in the Delayed::Job table.
The Daemons gem is required to get the Delayecd::Job gem firing instances. Once that is installed remember to run the following terminal command inside your application project directory:
$ bin/delayed_job start
You can check the status of the Delayed::Job with the following terminal command:
$ bin/delayed_job status
Remember to synchronize the clock settings inside your Rails app – found in the config -> locales -> application.rb.
You will need to modify your new.html.erb file to include new fields where the User sets the scheduled text time.
Once the User is able to schedule texts for a specific Task, he will need to be able to edit an upcoming Task in cases where he changes his mind.
Step 4 – Changing Scheduled Texts
The Rail app needs to allow a User to edit a scheduled Task and perhaps change the scheduled run time for the text.
When the User accesses an exiting Task (via a View), they can easily change variables such as the Recipient and the text body. However, changing the schedule_time value in the Task database does not automatically change the run_at value in the Delayed::Job table.
I had to write a method inside the Task Model, called change_run_at, that checked to see of the schedule_time has been changed before the Task is saved. If it has been changed (by the User), then update the run_at value in Delayed::Job to reflect the new schedule_time value.
Step 5 – Receive Twilio Texts Into Your Rails App (Optional)
I wanted to allow my app to receive text responses back from the original Recipients so that the Recipient could tell the User (via text message) that the Task was complete. I managed to get this working in my development environment but I am not convinced about the usability of this feature.
Most smart phones have a continuous dialogue stream in the texting app. If the User assigns multiple Tasks to a single Recipient, how will the Recipient indicate that one of the Tasks was completed in the text response?
The Twilio API sends TwilML data back that includes a number of pieces of data including the message_body value. I decided I could leverage that but the Recipient would have to indicate a unique ID inside the message_body associated with a particular Task (the Task.id).
This means that the User would have to include the Task.id in the original message (awkward) and the Recipient would have to send that back in his response text. The app would have to parse the message body, find the Task.id and update the status variable (completed) to indicate that the Task was fulfilled.
I created a receive_text method inside the task Controller that read the params from the incoming Twilio text and updated the @task.completed to value ‘true’.
The Rails app is locally developed. However, Twilio does not send data to a local host. I used ngrok to tunnel the data back to my Rails app on my local host. I found this service easy to set up and use.
You can integrate Twilio texting into your Rails app with some clever coding, the Twilio Ruby gem, and a number of other gems.
This article is part of my Web Development guide.