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 docs

Separate your logic with repositories

Repositories handle data access. Structs hold your data. Your business logic just works with plain Ruby objects.

View repositories guide
class ArticleRepo < ROM::Repository
  struct_namespace MyApp::Structs

  def published
    articles.where(status: 'published').to_a
  end

  def by_author(author_id)
    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
class Articles < ROM::Relation[:sql]
  schema :articles, infer: true

  def published
    where(status: "published")
  end

  def popular
    where { view_count > 1000 }
  end
end

class ArticleRepo < ROM::Repository
  def trending_by_author(author_id)
    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
class CreateArticleChangeset < ROM::Changeset::Create
  map do |tuple|
    tuple.merge(slug: slugify(tuple[:title]))
  end

  def slugify(title)
    # ...
  end
end

class ArticleRepo < ROM::Repository
  def create(attrs)
    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
class Organizations < ROM::Relation[: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.
Explore the Rom docs

Built on community

For people who bring kindness, curiosity, and care

Photograph of cute people being cute

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