rom-rb: Ruby object mapping for SQL and NoSQL without constraining database access
Data mapping and persistence toolkit for Ruby
At a glance
- What is it?
- rom-rb is a data mapping and persistence toolkit for Ruby that aims to give full access to the underlying database while keeping domain objects separate from storage mechanics. Three components handle adapters, changesets, and repository abstraction, each housed in its own subdirectory.
- Who is it for?
- rom-rb suits Ruby applications where the domain model should remain independent of how data is stored and fetched. The repository pattern and changeset abstraction make persistence explicit rather than wired into model classes.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly Ruby, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 6, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Object mapping without hiding the database: what rom-rb is for
Ruby Object Mapper, published as the rom gem, is a data mapping and persistence toolkit for Ruby. Its stated goal is to give full access to object mapping without constraining what the database can express. Domain objects should not carry database-level concerns or be coupled to table structure; that is the design position rom takes.
Project topics cover both sql and nosql backends alongside ddd (domain-driven design) and data-access-layer patterns. rom is not limited to relational storage: whether the backend is a SQL database or a NoSQL store, the adapter layer handles the data side while the domain model works with plain Ruby objects that have no knowledge of where they were fetched from.
This separation has a concrete implication for query complexity. ActiveRecord constrains what SQL can look like because the ORM generates the statement; rom's stated goal is to remove that constraint. Applications with complex, database-specific queries do not need to work around an abstraction layer that cannot express what they need.
The gem is MIT-licensed, v5.4.3 was published on 2025-11-20, and the last push to the repository was on 2026-10-05.
Three components: core adapters, changeset objects, and repository abstraction
rom bundles three components, each in its own subdirectory with its own README.
core, in core/, provides the Core and Adapter APIs. Adapters form the bridge between rom's object-mapping layer and individual storage backends, and core defines the contract that all adapters must satisfy. Without an adapter, rom has no way to talk to a specific database.
changeset, in changeset/, handles the lifecycle of modifications to data integrated with rom-core. Changesets provide an object-oriented model for data changes rather than placing mutation logic directly on the domain object, keeping the modification concern separate from both the storage and the domain layers.
repository, in repository/, adds a repository abstraction on top of rom-core. A repository pattern separates the logic of how data is fetched and stored from the domain objects that consume it, which is the direct implementation of the domain-driven design orientation the ddd topic tag indicates.
Each component has a link to its own README from the main repository page. rom-rb.org/learn/repository/5.2/quick-start documents how the three layers connect in a working project, with code examples the main README does not carry.
Installing rom and the docker-compose development environment
The gem is published as rom on RubyGems at rubygems.org/gems/rom. A quick-start is at rom-rb.org/learn/repository/5.2/quick-start and an introduction to the concepts is at rom-rb.org/learn/introduction.
For contributors or teams running the full test suite, the repository provides a Docker development environment. The docker-compose.yml at the repository root sets up a postgres service and an application container:
version: '2'
services:
db:
image: postgres:latest
ports:
- 5432:5432
environment:
POSTGRES_DB: rom_repository
app:
build: .
command: ./docker_start.sh
environment:
BASE_DB_URI: postgres@db/rom_repository
volumes:
- .:/opt/rom
- bundle_box:/opt/bundle_box
links:
- db
volumes:
bundle_box:The app container starts by running `docker_start.sh` and connects to postgres via the `BASE_DB_URI` variable, set to `postgres@db/rom_repository`. The `rom_repository` database is created automatically when the db container starts. The app code is mounted at /opt/rom.
The Dockerfile installs libsqlite3-dev alongside ruby:latest
Dockerfile builds the application image from ruby:latest and installs libsqlite3-dev:
FROM ruby:latest
RUN apt-get update -qq && apt-get install -y libsqlite3-dev
ENV rom /opt/rom/
ENV bundle_path /opt/box
ENV BUNDLE_PATH $bundle_path`libsqlite3-dev` appearing in a docker-compose setup that runs only postgres is worth noting. postgres handles integration-level testing, but `libsqlite3-dev` supports lighter-weight development and test runs that do not need the full postgres service active. This dual-backend approach is consistent with rom's adapter design: the same domain and repository code can run against different adapters without touching the domain layer.
All container operations run as a non-root user named user. Application code lands at /opt/rom, defined by the rom environment variable, and bundled gems go to /opt/box via `BUNDLE_PATH`. WORKDIR is /opt/rom, and files are copied with --chown=user:user to keep non-root ownership through the image build. A `bundle_box` volume in docker-compose.yml persists gems across container restarts.
rom-rb vs ActiveRecord: who owns the query
ActiveRecord, which ships with Rails, uses the Active Record pattern: each model class corresponds to a table, and queries are expressed as method chains on the model class. The model both represents a domain object and carries the persistence mechanics. For applications where query complexity fits within the ORM's abstraction, this is convenient. For applications where the domain logic and query logic need to stay separate, coupling them into one class creates friction.
rom's stated goal is to provide object mapping without limiting the full power of the database. The repository component handles data retrieval separately from the objects it returns. The changeset component handles modification separately from the objects it modifies. Domain objects have no ActiveRecord-style callbacks, timestamps, or association macros. The application side works with plain Ruby objects; the persistence side works with adapters.
For a small team comfortable with Rails conventions, switching to rom adds configuration cost without clear benefit. The Quick Start guide at rom-rb.org/learn/repository/5.2/quick-start is the right first read before deciding; it shows the wiring between adapters, relations, and repositories in a working example.
Where the documentation stops: sub-READMEs and rom-rb.org
rom's main README is intentionally brief. It names the three components and links to their component-level READMEs inside core/, changeset/ and repository/. Usage examples, adapter configuration, and relation definitions are not in the top-level README.
Substantive documentation lives at rom-rb.org. Introduction content is at rom-rb.org/learn/introduction and the repository quick-start is at rom-rb.org/learn/repository/5.2/quick-start. Both URLs appear in the README, but the content is external to the repository itself.
This means the repository alone cannot answer how to configure an adapter, write a mapper, or define relations between data sources. For engineers evaluating adoption, rom-rb.org is the primary resource, not the GitHub repository. CONTRIBUTING.md and CODE_OF_CONDUCT.md at the repository root document the contribution process. A Gemfile.devtools alongside the main Gemfile separates development-only dependencies from the gem's runtime requirements, which keeps the runtime dependency set clean.
Patch publishing cadence and the Zulip chat community
Patch version data from the repository shows a pattern worth reading carefully. Versions v5.4.2 and v5.4.1 were published on the same date, 2025-01-19, with v5.4.1 at 14:41:05Z and v5.4.2 at 14:41:24Z, a gap of nineteen seconds. An interval of nineteen seconds means a correction was applied within seconds of the initial patch going out; v5.4.3 followed on 2025-11-20 as the current version.
Community discussion runs on Zulip at rom-rb.zulipchat.com, with a badge and link in the README header. For questions about adoption or contribution, Zulip is the documented contact point.
Funding goes through OpenCollective at opencollective.com/rom, with individual backers and organizational sponsors listed in the README with avatars and site links. GitHub Actions handles CI and Codacy handles code quality and coverage analysis, both linked from the README header badges.
Editorial conclusion
rom-rb suits Ruby applications where the domain model should remain independent of how data is stored and fetched. The repository pattern and changeset abstraction make persistence explicit rather than wired into model classes. Teams building straightforward CRUD applications on Rails will find that ActiveRecord handles their needs without the configuration overhead rom requires. Teams building domain-driven applications with complex query requirements, or applications that span SQL and NoSQL backends, are a better fit. Before adopting, verify the application's database usage can be expressed through rom adapters and read rom-rb.org/learn/repository/5.2/quick-start as a starting point.
Frequently asked questions
How do I install the rom-rb gem?
The gem is published as rom on RubyGems at rubygems.org/gems/rom. A quick-start guide for the repository component is at rom-rb.org/learn/repository/5.2/quick-start.
What databases does rom-rb support?
The repository topics list both sql and nosql, and the Docker development environment uses postgres. The Dockerfile also installs libsqlite3-dev, indicating SQLite support for testing. Specific adapter documentation is at rom-rb.org.
What is the difference between rom-rb and ActiveRecord?
rom-rb separates domain objects from persistence mechanics using the repository and changeset components. ActiveRecord couples the domain model to the table. The rom-rb goal is to avoid limiting database access; ActiveRecord abstracts it.
Where is the rom-rb documentation?
The main documentation is at rom-rb.org. The introduction is at rom-rb.org/learn/introduction and the repository quick-start is at rom-rb.org/learn/repository/5.2/quick-start. Each sub-component (core, changeset, repository) has its own README in the repository.
Is rom-rb actively maintained?
The last push to the repository was on 2026-10-05, and v5.4.3 was published on 2025-11-20. Community discussion is on Zulip at rom-rb.zulipchat.com.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hanakai-rb-rom)