Rails Event Store in Ruby— Introduction

Altimetrik Poland Tech Blog
4 min readJun 26, 2023
Source: https://blog.arkency.com/ruby-event-store-use-without-rails/

Domain Driven Design is starting to make big waves in software engineering. As programmers, we always try to make our code easy to read and maintain. The problem arises when our project expands and can easily get out of control. There have been many answers to this problem: Object Oriented Design, SOLID, new frameworks like Trailblazer, functional programming. One idea is also to start thinking of our application as one driven by events.

In this guide, I’ll look at a simple use of the Rails Event Store, a gem created by the Arkency agency, which can be your engine for developing DDD applications. But before we can run, we need to walk first…

Rails Event Store

Rails Event Store is a gem that is an implementation of the Event Store in Ruby for use in a Rails application — you can also use it outside the Rails framework.

To install, add the following line to the Gemfile in your Rails project:

gem "rails_event_store"

Then run the following commands in the terminal. This will generate an event_store table in your database. It will contain all the data needed to publish events, retrieve them and handle them using subscriptions.

rails generate rails_event_store_active_record:migration --data-type=jsonb
rails db:migrate

Blog Post example

For the purpose of our article, let’s focus on the infamous Blog application example. We will have one Post model that will respond to the creation of a new blog post. Let’s see how we can create our first event.

However, before we start creating events, we need a quick configuration in application.rb

module Blog
class Application < Rails::Application
config.to_prepare do
Rails.configuration.event_store = RailsEventStore::Client.new
end
end
end

The code above will help us initialize our event store client, which can be used throughout our application.

Creating code for an event can be as simple as inheriting from RailsEventStore::Event

class PostCreated < RailsEventStore::Event
end

Publish event

To create a new event we will need to name our stream and create the event data (title and content of the blog post).

stream_name = "post_1"
event_data = {title: "Hello World", content: "This is my first blog post..." }
event = PostCreated.new(data: event_data)
client.publish(event, stream_name: stream_name)

We can also use a version with optimistic locking if we have a distributed application and want to avoid race conditions. To do this, we add the expected version to the code fragment.

stream_name = "post_1"
event_data = {title: "Hello World", content: "This is my first blog post..." }
event = PostCreated.new(data: event_data)
client.publish(event, stream_name: stream_name, expected_version: 1)

Publishing an event will commit our event in the database.

Reading events

The Rails event store comes out with an API for retrieving events from the database and many useful helper methods. Let’s look at some of them in the context of our code.

In my opinion, the most useful one is reading events from streams by latest.

scope = client.read.stream('post_1').backward.limit(100).to_a

Searching for events by time can be done using the newer_than method and passing a date as a param.

client.read.stream('post_1').newer_than('2023-02-14').to_a

We can also query events by time range.

client.read.stream('post_1').between(10.days.ago..3.days.ago).to_a 

Deleting events

You can delete all events through the stream. This should be avoided in most cases, as it can corrupt the application state.

stream_name = "post_1"
client.delete_stream(stream_name)

Subscription

Finally, I would like to write about subscriptions, as understanding the publish subscribe mechanism can be helpful in the land of Domain Driven Design. Subscriptions respond to publish events using handlers.

In the code example below, we will react with our subscribe handler to the creation of a new post. When this happens, we want to save the post using our ActiveRecord model and we want to notify our subscribers by email that a new post has just been created.

class PostReadModel
def call(event)
if event_type == 'PostCreated'
post = create_new_post(event)
notify_subscribers(post)
end
end


private

def create_new_post
Post.create(event.data)
end

def notify_subscribers(post)
puts "subscribers notified"
Subscriber.each do |subscriber|
BlogMailer.new_post_notification(subscriber.email, post).deliver_now
end
end
end

Now we need to link our handler to the event store, it is as simple as adding this line to our configuration.

client.subscribe(PostReadModel.new, to: [PostCreated])

What’s next?

That would be all in terms of an introduction to the Rails Event Store. We have gone through publishing, subscribing and reading events, but there is a lot more that the framework has to offer like Event Sourcing, Projections, Command Bus. There is also a book on Domain Driven Design using the Rails Event Store from Arkency.

You can find more information in the resources below.

Resources

Words by Przemysław Mroczek, Senior Engineer

Editing by Kinga Kuśnierz, Content Writer

https://www.linkedin.com/in/kingakusnierz/

--

--

Altimetrik Poland Tech Blog

This is a Technical Blog of Altimetrik Poland team. We focus on subjects like: Java, Data, Mobile, Blockchain and Recruitment. Waiting for your feedback!