# 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
1
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
1
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
1
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
1
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
1
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
1
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?
1
2
3
4
5
6
7
8
9