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!