Skip to content

Instantly share code, notes, and snippets.

@reedlaw
Created October 20, 2017 23:09
Show Gist options
  • Save reedlaw/a5c886ca8867c11a348cf8cda7d6d209 to your computer and use it in GitHub Desktop.
Save reedlaw/a5c886ca8867c11a348cf8cda7d6d209 to your computer and use it in GitHub Desktop.
ROM associations example
#!/usr/bin/ruby
require "rom"
require "rom/memory"
class Users < ROM::Relation[:memory]
schema do
attribute :id, Types::Int
attribute :name, Types::String
associations do
has_many :tasks, combine_key: :user_id, override: true, view: :for_users
end
end
end
class Tasks < ROM::Relation[:memory]
schema do
attribute :id, Types::Int
attribute :user_id, Types::Int
attribute :title, Types::String
end
def for_users(_assoc, users)
restrict(user_id: users.map { |u| u[:id] })
end
end
rom = ROM.container(:memory) do |config|
config.register_relation(Users, Tasks)
end
users = rom.relations[:users]
tasks = rom.relations[:tasks]
[{ id: 1, name: "Jane" }, { id: 2, name: "John" }].each { |tuple| users << tuple }
[{ id: 1, user_id: 1, title: "Jane's task" }, { id: 2, user_id: 2, title: "John's task" }].each { |tuple| tasks << tuple }
# load all tasks for all users
puts tasks.for_users(users.associations[:tasks], users).to_a
# [{:id=>1, :user_id=>1, :title=>"Jane's task"}, {:id=>2, :user_id=>2, :title=>"John's task"}]
# load tasks for particular users
puts tasks.for_users(users.associations[:tasks], users.restrict(name: "John")).to_a
# [{:id=>2, :user_id=>2, :title=>"John's task"}]
# when we use `combine`, our `for_users` will be called behind the scenes
puts users.restrict(name: "John").combine(:tasks).to_a
# {:id=>2, :name=>"John", :tasks=>[{:id=>2, :user_id=>2, :title=>"John's task"}]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment