R o m
Data persistence, your way
Rom is a Ruby data mapping toolkit that gives you full control over how you read and write your data.
Compose the queries you need, work with records as plain old objects, and enjoy the benefits that come from keeping persistence separate from your domain logic.
View the Rom docsSeparate your logic with repositories
Repositories handle data access. Structs hold your data. Your business logic just works with plain Ruby objects.
View repositories guide
struct_namespace MyApp::Structs
articles.where(status: 'published').to_a
end
articles.where(author_id: author_id).to_a
end
end
# In your app
articles = article_repo.published
# => [#<MyApp::Structs::Article id=1 title="..." status="published">, ...]
Compose any kind of query
You can leverage the full power of your database through a composable query API, from simple lookups to complex multi-table queries.
View relations guide[:sql]
schema :articles, infer: true
where(status: "published")
end
where { view_count > 1000 }
end
end
articles
.published
.popular
.combine(:author)
.where(author_id: author_id)
.order(view_count: :desc)
.to_a
end
end
Organize persistence into clear layers
Relations read data, repositories compose queries, changesets prepare changes, commands write to the database, transformers work on results, and plugins enhance each step.
Every layer handles one job well, and you can use as many or as few as you need.
View changesets guide
map do
tuple.merge(slug: slugify(tuple[:title]))
end
# ...
end
end
articles.changeset(CreateArticleChangeset, attrs).commit
end
end
Work with any data store
Rom is more than just an SQL toolkit. Work with document databases, search engines, HTTP APIs, local data files and more.
Combine results from multiple data stores, and switch adapters without changing your domain logic.
View adapters guide[:http]
# Load GitHub orgs
schema :orgs do
attribute :id, Types::Integer
attribute :name, Types::String
attribute :created_at, Types::JSON::Time
end
end
# Using :http adapter with this config:
# uri: "https://api.github.com", handlers: :json
rom.relations[:orgs].by_name("rom-rb").one
# => {:id=>4589832, :name=>"rom-rb", :created_at=>2013-06-01 22:03:54 UTC}
…and more!
We’ve just scratched the surface with Rom. There’s a lot more to love:
- Fast by design. Rom’s focus on simple data transformations means less overhead and better performance than traditional ORMs.
- Clear and predictable. Know exactly which queries run and when. You’ll never be surprised again by an N+1 lurking in the corner.
- Immutable by default. Results are plain data objects you can pass around with confidence. No state changes, no unexpected queries.
- Framework agnostic. Use rom with Rails, Hanami, Roda, or any kind of Ruby app. It’s a toolkit, not a framework.
- Proven in production. Built on over a decade of refinement and real-world use, Rom is a proven solution you can depend on for the long-term.
Built on community
For people who bring kindness, curiosity, and care
The Hanakai community is a place where people of all backgrounds and experience levels can feel respected, and can share and grow. A place for people to be proud of, and feel safe within.
We do not tolerate nazis, transphobes, racists, or any kind of bigotry. See our Code of Conduct for more.
Supported by
Hanakai is made possible by our wonderful sponsors
We’re also supported by our many community patrons.
Become a Hanakai sponsor or patron today, and help us build a diverse future for Ruby.
Support the Hanakai project