# ROM.rb features
WARNING
Not all ROM.rb features supported! Hanami::Repository
class hides and cut-out a lot of things like chnagesets, commands etc.
Also Hanami 1.2 depends on ROM 3.0 (while current version is 4.0) - be carefull reading ROM docs, pay attention to version!
# Association modifiers
class PostRepository < Hanami::Repository
associations do
belongs_to :user, as: :author
end
...
def get_all_posts
aggregate(author).as(Post)
end
end
2
3
4
5
6
7
8
9
# Nested aggregation
class UserRepository < Hanami::Repository
associations do
has_many :posts
has_one :user_profile
end
end
2
3
4
5
6
class PostRepository < Hanami::Repository
associations do
belongs_to :user, as: :author
end
...
def get_all_posts
aggregate(author: :user_profile).as(Post)
end
end
2
3
4
5
6
7
8
9
# Raw SQL command
Imagine we need to do a very complicated and DB specific query.
Our posts
table has jsonb tags
column and we want to find all tags by query.
class PostRepository < Hanami::Repository
def find_tags(query)
posts.read("SELECT un_tags AS tags FROM posts, unnest(tags) un_tags WHERE un_tags LIKE #{posts.dataset.literal('%'+query+'%')}")
.limit(5).pluck(:tags).to_a
end
end
2
3
4
5
6
We need to call read
methos on a relation (posts
in this case) and pass SQL string.
The good thing - query composition is still supported (via .limit(5)
etc.)
The bad thing - you need to escape query
manually (here it is done via Sequel's dataset.literal
method)
# JOIN and aggregate
Kind-a comple example, but with ROM join
does not work on aggregate
.
Imagine we has such a structure of Users + UserProfle and Follow relations. As a result we want to get Followers of user (array of User
objects) with aggregated UserProfiles
class UserRepository < Hanami::Repository
associations do
has_one :user_profile
has_many :follows, as: :followers, foreign_key: :follower_id
end
#...
end
class FollowRepository < Hanami::Repository
relations :user_profiles
associations do
belongs_to :user, as: :follower_user, foreign_key: :follower_id
end
def get_followers(user_id)
users.combine(:user_profile).join(:followers).where(follows[:user_id].is(user_id)).as(User).order(:id)
end
#...
end
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Add custom chainable query methods
This is how we can add for example full_join
or not_deleted
where-like method
/lib/common/sql_relation_reading_extension.rb
module ROM::SQL::Relation::Reading
def full_join(*args, &block)
__join__(__method__, *args, &block)
end
def not_deleted
new(dataset.where(deleted_at: nil))
end
end
2
3
4
5
6
7
8
9
10
11
TIP
Don't forget to require this file somewhere in environment.rb
now it could be used in Repo methods like
class PostRepository < Hanami::Repository
def find_by_uuid(uuid)
posts.where(uuid: uuid).not_deleted.one
end
``
---
TODO: More ROM usage example?
2
3
4
5
6
7
8
9
← Enum Sequel features →