ROM::SQL
RDBMS suport for Ruby Object Mapper.
Installation
Add this line to your application's Gemfile:
gem 'rom-sql'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rom-sql
Setup
ROM uses Sequel under the hood and exposes its Dataset API in relation objects. For schema migrations you can use its Migration API which is available via repositories.
setup = ROM.setup(sqlite: "sqlite::memory")
setup.sqlite.connection.create_table(:users) do
primary_key :id
String :name
Boolean :admin
end
setup.sqlite.connection.create_table(:tasks) do
primary_key :id
Integer :user_id
String :title
end
Relations
ROM doesn't have a relationship concept like in ActiveRecord or Sequel. Instead it provides a convenient interface for building joined relations that can be mapped to aggregate objects.
There's no lazy-loading, eager-loading or any other magic happening behind the scenes. You're in full control of how data are fetched from the database and it's an explicit operation.
setup.relation(:tasks)
setup.relation(:users) do
one_to_many :tasks, key: :user_id
def by_name(name)
where(name: name)
end
def with_tasks
association_join(:tasks)
end
end
rom = setup.finalize
users = rom.relations.users
tasks = rom.relations.tasks
users.insert(id: 1, name: "Piotr")
tasks.insert(user_id: 1, title: "Be happy")
puts users.by_name("Piotr").with_tasks.to_a.inspect
# => [{:id=>1, :name=>"Piotr", :user_id=>1, :title=>"Be happy"}]
Mapping
Mapping joined relations can be simplified using wrap and group in-memory
operations:
setup.relation(:tasks)
setup.relation(:users) do
one_to_many :tasks, key: :user_id
def by_name(name)
where(name: name)
end
def with_tasks
in_memory { group(association_join(:tasks), tasks: [:title]) }
end
end
setup.mappers do
define(:users) do
model name: 'User'
group tasks: [:title]
end
end
rom = setup.finalize
users = rom.relations.users
tasks = rom.relations.tasks
users.insert(id: 1, name: "Piotr")
tasks.insert(user_id: 1, title: "Be happy")
rom.read(:users).with_tasks.by_name("Piotr").to_a
# => [#<User:0x007fb31542a098 @id=1, @name="Piotr", @tasks=[{:title=>"Be happy"}]>]
ROADMAP
On a very high level:
- Make it dead simple to join relations and support all types of joins
- Make it dead simple to select and alias column names
- Discover conventions for typical query scenarios and make common things trivial, less common things simple and super rare cases possible
- Make mapper interface smart enough to figure out when columns are aliased
For details please refer to issues.
License
See LICENSE file.
