Talks

Realtime Apps with Hotwire & ActionMailbox

Realtime Apps with Hotwire & ActionMailbox

by Chris Oliver

In his talk at RailsConf 2021, Chris Oliver presents how to build real-time applications using Hotwire and Action Mailbox in Ruby on Rails. The presentation centers around creating a customer support app where users can send and reply to emails in real-time.

Key points covered in the talk include:

  • Introduction to Hotwire: Hotwire is a modern framework that enhances the user experience by allowing real-time updates without full page reloads. Developed from Turbo Links, it enables handling of links and forms efficiently.

  • Understanding Action Mailbox: This powerful Rails feature allows applications to process incoming emails, facilitating functionalities like email replies, rich text support, and attachment handling. Action Mailbox can automatically convert incoming emails into structured data for further processing.

  • Building a Customer Support App: Chris outlines the necessary models for the application, including conversations, messages, contacts, and users. Each conversation will contain multiple messages, and there is a clear distinction between customers and internal team members.

  • Leveraging Turbo Streams: The integration of Turbo Streams provides the ability to update the UI in real-time as users interact with their support tickets. The talk includes how to scaffold models and set up broadcasting for new messages using Action Cable, ensuring instantaneous updates in the user interface.

  • Processing Inbound Emails: Chris details how to effectively handle received emails, explaining the structure of an email and how to extract relevant information such as sender and content. The implementation involves saving attachments and processing HTML parts, including inline images using Active Storage.

  • Email Interactivity: The talk also emphasizes how replies to conversations can be managed seamlessly from both the web app and email, generating dynamic email addresses that facilitate responses.

  • Summary of Benefits: Chris concludes that using Action Mailbox and Hotwire significantly simplifies user interactions, allowing for dynamic content updating and improving the overall user experience by minimizing the necessity of switching contexts between applications and email clients.

Chris encourages developers to embrace these tools, noting their potential for enhancing productivity and engagement with applications. The session wraps up with an invitation to explore further Rails resources available through his platforms, including screencasts and open-source projects.

The conclusion drawn is that real-time applications can leverage these features to provide a superior user experience, particularly in customer service settings where speed and responsiveness are paramount.

00:00:05.339 Hey there! I'm Chris Oliver. I work on Rails screencasts, Jumpstart Pro, Hatchbox, and several other Ruby on Rails open-source projects. In this talk, I'm going to discuss how to build real-time applications using Hotwire and Action Mailbox. We're going to be building a customer support app with Rails where you can send inbound emails and replies, and all of this will happen in real-time. It's pretty cool!
00:00:16.260 First things first, let’s talk about Hotwire. This technology came out around Christmas time and is HTML over the wire. The new version of Turbo Links has evolved into Hotwire.
00:00:22.859 Turbo Links used to intercept links on the page, which worked fine for basic navigation, but it struggled when it came to handling forms and other interactions. We were left on our own to manage those scenarios, and that’s where Hotwire comes in. Hotwire is powered by Turbo JS, which intercepts both links and forms, allowing for seamless submission and updates.
00:00:35.399 With Hotwire, you can publish changes from the backend at any time to update the page seamlessly, making it a really powerful tool.
00:00:47.100 The other component we'll be using in this talk is Action Mailbox, a feature of Rails that many find underappreciated. Action Mailbox allows you to process inbound emails to your application. If you've ever used Basecamp or GitHub and replied via email, then you've already interacted with what Action Mailbox enables in Rails.
00:00:58.800 Sending an email to your Rails app involves your email provider, like SendGrid or Postmark, processing the email and converting it into a web hook. This web hook will make a POST request to your Rails app, which is managed by Action Mailbox.
00:01:12.060 The process of storing text from emails and processing them is straightforward. We'll save these entries in Action Text, allowing us to store images and other attachments effectively.
00:01:19.380 With Action Text, we can store rich text, including formatting like bold, italics, and strikethrough, which will be saved as HTML in our database. You can render this rich text back out along with attachments. For instance, an image uploaded through Action Text is processed dynamically, similar to embedding YouTube videos or user mentions in records.
00:01:35.160 Action Mailbox can be used for various purposes, one example being replying by email, as seen in GitHub. If you reply to an email notification from GitHub, it processes the content and adds it as a comment to the respective issue or pull request.
00:02:07.200 Another application of Action Mailbox is creating a blog platform like 'Hey World', where you write an email, and it gets published as a blog post. If you’re a 'Hey' customer, sending an email to [email protected] automatically converts it into a blog post related to your account.
00:02:48.840 A different interesting use is for managing unsubscribe requests. For example, by adding an unsubscribe link or “mailto” in the email headers, users can easily opt-out of notifications. Simplifying this process can significantly enhance user experience, especially in applications that utilize email notifications extensively.
00:03:54.300 For our example application, we will build a customer support system. This will allow us to create conversations with customers, where both parties can reply either through the app or via email. Users can respond through email when they are not logged into the app or when they are on the go.
00:05:14.400 To build this app, we will need a few models. At a basic level, we’ll require a conversation model, messages, and user models. Conversations will be associated with many messages, which we can refer to as posts. Each conversation will belong to a main user that we want to contact.
00:05:40.860 Additionally, we will distinguish between team members and customers with separate user models, where team members are logged into the app, while a contact model will represent our customers or any other contacts within the app.
00:06:00.720 The post model will be polymorphic, allowing us to refer to either a user or a contact as the author. It will include an action text field, maintaining rich text format. Each message will also have a unique message ID, helping us track the emails throughout the message thread.
00:06:51.600 Now, let's talk about streaming our application with Hotwire. You can scaffold all those models or use Devise for user authentication. Using Rails 7 scaffold, Hotwire functionality is ready. We leverage Turbo Streams for real-time data updates.
00:07:51.900 In our controller, we’ll add a Turbo Stream tag referencing the conversation, which will use Action Cable for streaming. Any changes made on the backend will be reflected in real-time on the user interface. When switching between conversations, the previous stream closes, preventing message overlaps from different conversations.
00:08:59.400 To track post updates, I wrapped all posts in a div with an id of 'posts'. This will enable us to manage the DOM efficiently. When creating a new post, it’s automatically appended to this div, updating it live without requiring a full-page refresh.
00:10:07.860 Our post model will utilize broadcasting methods to communicate updates to the client. Turbo will handle the updates seamlessly, allowing us to append, update, or delete posts without writing additional JavaScript.
00:11:24.320 We want to ensure that hotwire broadcasts are defined correctly for Turbo Streams, so they execute the necessary updates in real-time when posts are created or altered.
00:11:55.880 Creating posts with Hotwire involves handling responses correctly within the controller. When a post is successfully created, we can respond with a Turbo Stream format that replaces the form with a new one and adds the new post to the list.
00:12:43.920 This streamlined process allows for real-time interactions, where new messages appear immediately, without users needing to refresh the page. It enhances collaborative experiences, enabling multiple users to engage with the same conversation simultaneously.
00:14:30.300 Now, let’s shift our focus to handling inbound emails. We have a functioning conversation model, but we need to ensure that we can send and receive emails effectively. Understanding the anatomy of an email is essential for this.
00:15:14.040 Emails consist of various components, including text, images, and links. The content of these emails is formatted using HTML, which presents unique challenges when processing inbound emails. Checking the raw version of emails reveals the components involved in crafting a functional email.
00:16:21.300 Processed emails will often contain both plain text and HTML formats, with inline attachments defined using special IDs. When handling these elements, we will have to maintain the integrity of the email's information while ensuring that our application properly integrates with this format.
00:17:42.240 Installing Action Mailbox is straightforward. By running 'rails action_mailbox:install', we can set up necessary migrations and configure an Ingress service for processing inbound emails through web hooks.
00:19:07.080 This setup ensures that our Rails app is safeguarded against potential web hook exploits by requiring credentials. We can then define and process different types of mailboxes—routes for managing the flow of inbound emails appropriately.
00:20:31.560 When setting up these mailboxes, we can leverage regex to sort and analyze incoming emails, extracting necessary ID information for efficient processing. We also can query inbound emails to create corresponding models that reflect their states.
00:21:40.440 By utilizing Action Mailbox, these emails are stored in Active Storage as mail messages, furthering our ability to manage interactions.
00:22:18.600 Let's take a look at the processing methods involved in handling inbound emails. This begins when we receive an email, which we can access directly through the Ingress controller. Each email can then be processed through separate mailboxes depending on defined rules.
00:23:46.920 The processing of the email requires us to extract the subject, identify the author, and determine the body of the message. Gathering all necessary attachments ensures that additional content is managed within our Rails application effectively.
00:24:53.940 When mapping out a solution for extracting attachments, it is essential to parse the HTML using libraries like Nokogiri. This will allow us to effectively find and replace image references with their corresponding Active Storage entries.
00:26:26.520 We’ll also address the various edge cases that may arise based on email multipart configurations, ensuring that whether the email contains text, HTML, or attachments, our solution can adequately accommodate the content.
00:27:43.140 Lastly, we need to address how replies will be handled within our application as well. Each reply should maintain proper formatting and linking to the original conversation.
00:28:56.460 By leveraging unique ID in reply addresses, we enable the necessary routing to send updates back to the conversation. This design pattern facilitates creating a consistent thread of communication throughout the app.
00:30:13.200 Testing and validating emails during development allows us to ensure reliability and user friendly access to our app's features. By creating and managing threads of conversations, we can ensure that these experiences feel cohesive and straightforward.
00:31:14.880 Finally, our mailer setup can handle this process gracefully. With certain consideration for managing instance variables for conversation context, we can readily keep our mailers slick and straightforward. The end goal is clear: create seamless communication experiences between users, whether they are in the app or responding via email.
00:32:58.320 In conclusion, building real-time applications with Hotwire and managing inbound emails with Action Mailbox presents powerful opportunities. By incorporating these technologies, we can greatly enhance user engagement and streamline communication, providing a better experience overall.
00:34:43.680 I hope this talk has provided you with valuable insights into the development of real-time applications using these tools. If you're interested in further exploration, you can find resources, including code examples on GitHub at github.com/exitthree, and you can also check out my screencasts at gorails.com to continue your learning journey.
00:35:54.960 Thank you for attending, and I hope you enjoyed this session!