Custom Repository

Installation with Bundler

By default RailsEventStore will use the ActiveRecord event repository. If you want to use another event repository without loading unnecessary ActiveRecord dependency, you'll need to do:

gem 'rails_event_store', require: 'rails_event_store/all'
gem 'your_custom_repository'

After running bundle install, Rails Event Store should be ready to be used. See custom repository README to learn how to setup its data store.

Configure custom repository

Rails.application.configure do
  config.to_prepare do
    Rails.configuration.event_store = RailsEventStore::Client.new(
      repository: YourCustomRepository.new
    )
  end
end

Community event repositories

Those repositories were written by community members and are not guaranteed to be up to date with latest Rails event store.

Writing your own repository

If you want to write your own repository, we provide a suite of tests that you can re-use. Just require and include it in your repository spec. Make sure to meditate on which exepcted_version option you are going to support and how.

Using RubyEventStore::InMemoryRepository for faster tests

RubyEventStore comes with RubyEventStore::InMemoryRepository that you can use in tests instead of the default one. InMemoryRepository does not persist events but offers the same characteristics as RailsEventStoreActiveRecord::EventRepository. It is tested with the same test suite and raises identical exceptions.

RSpec.configure do |c|
  c.around(:each)
    Rails.configuration.event_store = RailsEventStore::Client.new(
      repository: RubyEventStore::InMemoryRepository.new
    )
    # add subscribers here
  end
end

If you want even faster tests you can additionally skip event's serialization.

RSpec.configure do |c|
  c.around(:each)
    Rails.configuration.event_store = RailsEventStore::Client.new(
      repository: RubyEventStore::InMemoryRepository.new,
      mapper: RubyEventStore::Mappers::NullMapper.new,
    )
    # add subscribers here
  end
end

We don't recommend using InMemoryRepository in production even if you don't need to persist events because the repository keeps all published events in memory. This is acceptable in testing because you can throw the instance away for every test and garbage collector reclaims the memory. In production, your memory would keep growing until you restart the application server.

Using Ruby Object Mapper (ROM) for SQL without ActiveRecord or Rails

RubyEventStore comes with RubyEventStore::ROM::EventRepository that you can use with a SQL database without requiring ActiveRecord or when not using Rails altogether. It is tested with the same test suite as the ActiveRecord implementation and raises identical exceptions.

Basic ROM setup

You simply need to configure your ROM container and then store it globally on RubyEventStore::ROM.env or pass it to the repository constructor.

require 'ruby_event_store/rom/sql'

# Use the `setup` helper to configure repositories and mappers.
# Then store an Env instance to get access to the ROM container.
RubyEventStore::ROM.env = RubyEventStore::ROM.setup(:sql, ENV['DATABASE_URL'])

# Use the repository the same as with ActiveRecord
client = RubyEventStore::Client.new(
  repository: RubyEventStore::ROM::EventRepository.new
)

Advanced ROM setup

You can use a specific ROM container per repository to customize it more extensively. This example illustrates how to get at the ROM configuration and even run the latest migrations.

require 'ruby_event_store/rom/sql'

config = ROM::Configuration.new(:sql, ENV['DATABASE_URL'])

# Run migrations if you need to (optional)
config.default.run_migrations

# Use the `setup` helper to configure the ROM container
env = RubyEventStore::ROM.setup(config)

# Use the repository the same as with ActiveRecord
client = RubyEventStore::Client.new(
  repository: RubyEventStore::ROM::EventRepository.new(rom: env)
)

# P.S. Access the ROM container
container = env.container

This advanced option provides flexibility if you are using a separate database for RES or have other needs that require more granular configurations.

ROM migrations

SQL schema migrations can be copied to your project using Rake tasks. (The ROM migrations use Sequel under the hood.)

Add the tasks to your Rakefile to import them into your project:

# In your project Rakefile
require 'ruby_event_store/rom/adapters/sql/rake_task'

Then run Rake tasks to get your database setup:

# Copies the migrations to your project (in db/migrate)
DATABASE_URL=postgres://localhost/database bundle exec rake db:migrations:copy
# <= migration file created db/migrate/20180417201709_create_ruby_event_store_tables.rb

# Run the migrations in your project (in db/migrate)
DATABASE_URL=postgres://localhost/database bundle exec rake db:migrate
# <= db:migrate executed

You can run bundle exec rake -T to get a list of all available tasks. You can also programmatically run migrations (see examples above).

NOTE: Make sure the database connection in your app doesn't try to connect and setup RES before the migrations have run.