Hi folks, TL;DR I’m working on using the Memory adapter to create an in-memory store for testing purposes (mocking an external service) where I’d prefer not to include an external dep like sqlite. I’m having trouble figuring out exactly how I utilize combine and/or how I might compose a set of relations:
Right now I’m modeling a folder and files:
config ||= ROM.container(:memory) do |config|
config.relation(:folders) do
schema(infer: true) do
attribute :id, ROM::Types::String
attribute :parent_id, ROM::Types::String
primary_key :id
associations do
has_many :files, foreign_key: :folder_id
end
end
def by_id(id)
dataset = folders.select { |f| f[:id] == id }
new(dataset)
end
def where(conditions = {})
ds = conditions.reduce(folders) { |acc, (k, v)| acc.select { |a| a[k] == v } }
new(ds)
end
def files_for(id)
folders.combine(files).by_id(id)
end
end
config.relation(:files) do |config|
schema(infer: true) do
attribute :id, ROM::Types::String
attribute :folder_id, ROM::Types::String
primary_key :id
associations do
belongs_to :folders, as: :folder, foreign_key: :folder_id
end
end
def where(conditions = {})
ds = conditions.reduce(files) { |acc, (k, v)| acc.select { |a| a[k] == v } }
new(ds)
end
end
end
class FoldersRepo < ROM::Repository[:folders]
commands :create
end
class FilesRepo < ROM::Repository[:files]
commands :create
end
folders_repo = FoldersRepo.new(config)
files_repo = FilesRepo.new(config)
folders_repo.create(id: "1234", parent_id: "0")
files_repo.create(id: "5678", folder_id: "1234")
files_repo.create(id: "7890", folder_id: "0")
# this works but not sure its how it is designed:
[3] pry(main)> folders_repo.folders.by_id("1234").files.where(folder_id: "1234")
=> #<ROM::Relation[Files] name=ROM::Relation::Name(files) dataset=[{:id=>"5678", :folder_id=>"1234"}]>
# focusing in on the folders relation and the "files_for" method that uses combine
# it seems to pull the right folder
[1] pry(main)> folders_repo.folders.files_for("1234")
=> #<ROM::Relation::Combined root=#<ROM::Relation[Folders] name=ROM::Relation::Name(folders) dataset=[{:id=>"1234", :parent_id=>"0"}]> nodes=[]>
# but I don't understand this, should this not be scoped to only files with the right foreign key?:
[2] pry(main)> folders_repo.folders.files_for("1234").files
=> #<ROM::Relation[Files] name=ROM::Relation::Name(files) dataset=#<ROM::Memory::Dataset data=[{:id=>"5678", :folder_id=>"1234"}, {:id=>"7890", :folder_id=>"0"}]>>
additionally, following some of the documentation around combine, I found that if I redefine the files_for
method as so:
def files_for(id)
folders.combine(:files).by_id(id)
end
When invoked I get: NotImplementedError: NotImplementedError
I admit this might be an edge case for ROM.
I looked into the tutorial to build an adapter from scratch to see if there was something I need to implement. I also looked at memory specific specs in the rom repo. I’m sure I’m not understanding something but not sure where my misunderstanding is happening. Thanks for any feedback!