ROM 2.0.0 Released

We’re happy to announce the release of rom 2.0 with a big list of improvements and new features! This release is a huge milestone for the project as its infrastructure is now complete - this means that all core APIs and high-level extensions are in place, and from now on it’s a matter of expanding functionality with new features.

Let’s take a quick look at the release highlights!

Relation Schemas

This new feature allows you to define a relation schema with attribute names and types.

By defining a relation schema you establish the canonical representation of the data provided by a relation. This gives you type-safe commands out-of-the-box and allows you to define custom types for low-level database coercions.

On top of that, every adapter can extend Schema API with its own features, and that’s how the new version of rom-sql adds support for defining associations.

Here’s an example:

class Users < ROM::Relation[:users]
  schema do
    attribute :id, Types::Serial
    attribute :name, Types::String

    associations do
      has_many :tasks
      belongs_to :group
    end
  end
end

You can learn more about relation schemas in the user documentation. For more information about associations check out SQL docs.

Command support in repositories

The new version of rom-repository adds support for database commands. This is a convenient API for common create/update/delete operations. It means there’s no need to define custom command classes for common operations anymore. Here’s an example:

class UserRepo < ROM::Repository[:users]
  commands :create, update: :by_pk, delete: :by_pk
end

# create
user = user_repo.create(name: "Jane")

# update
user_repo.update(user.id, name: "Jane Doe")

# delete
user_repo.delete(user.id)

Check out the user documentation for more information.

Repository changesets

Another new feature is the Changeset API, provided by rom-repository. This is a new way to handle data changesets via repository commands, similar to Elixir’s Ecto.

Changesets can be created via the Repository#changeset interface, here’s an example of “an update changeset”:

class UserRepo < ROM::Repository[:users]
  commands :create, update: :by_pk
end

user = user_repo.create(name: 'Jane', email: 'jane@doe.org')

changeset = user_repo.changeset(user.id, name: 'Jane Doe')

changeset.diff? # true
changeset.diff # {name=>"Jane Doe"}

user_repo.update(user.id, changeset)

This is a very fresh addition, please try it out and let us know what you think! You can learn more about it in the user documentation.

Native Upsert support for PostgreSQL >= 9.5

We added a new command type to rom-sql called Postgres::Upsert, this allows you to use native upsert statements on PostgreSQL. The repositories don't support it yet, but you can register commands manually and they will be available within the repositories.

Here's a full example of a setup with an Upsert command:

require 'rom-repository'
require 'rom-sql'
require 'rom/sql/commands/postgres'

conf = ROM::Configuration.new(:sql, 'postgres://localhost/rom_example')

conf.default.connection.create_table? :quotes do
  primary_key :id
  String :quote, unique: true, null: false
  Integer :likes, default: 1
end

class UpsertQuote < ROM::SQL::Commands::Postgres::Upsert
  relation :quotes
  register_as :create_or_update
  result :one

  conflict_target :quote
  update_statement likes: Sequel.+(:quotes__likes, 1)
end

conf.register_command(UpsertQuote)

class QuoteRepo < ROM::Repository[:quotes]
  def create_or_update(quote)
    command(:quotes)[:create_or_update].call(quote)
  end
end

rom = ROM.container(conf)

quote_repo = QuoteRepo.new(rom)

quote = quote_repo.create_or_update(quote: 'Such quote')

puts quote.inspect
# {:id=>1, :quote=>"Such quote", :likes=>1}

quote = quote_repo.create_or_update(quote: 'Such quote')

puts quote.inspect
# {:id=>1, :quote=>"Such quote", :likes=>2}

New website design & new documentation

Thanks to the awesome work of Angelo Ashmore, we’ve got a shiny new website design. We also updated the user docs and improved API docs coverage for most important rom gems.

We’re looking for help with adding guides, please check out the issues if you’re interested in contributing a guide.

Hanami and Trailblazer co-operation!

We started working closely with the Hanami and Trailblazer communities, looking into how our projects can help each other. As a result, we’ll be working on a rom-based backend for hanami-model, and integrating rom with Reform from Trailblazer.

These are really exciting times, we believe our co-operation will help us build a stronger ruby ecosystem!

What happens next?

We’d like to finish stable versions of rom-sql and rom-repository later this year. The core rom gem is already at version 2.0, but the main adapter and repositories are still unstable. There will be a lot of effort going into improving the query DSL in rom-sql, there are a lot of Sequel features that we could leverage and make the adapter even more powerful.

Depending on the feedback, we’ll also focus on expanding functionality of existing features and bug-fixing. Please report any issues on GitHub for individual rom projects that you use.

Gem updates summary

Please see the upgrade guide for more information about upgrading.

As part of this release following gems have been released: