I am working on a multi tenant app, so I need some relations to be filtered by tentant.
So some of them will have a tenant_id and right now I have a method in the relation for_tenant that I need to chain to all calls.
Is there a way to make this filtering default? so that the tenant filtering applies to all queries for a relation. Something like dataset but the tenant_id is request scoped.
I’m not sure if I understand well your question, but rom itself won’t help you with anything related to the http layer, because it is not its responsibility and it would be a smell of a bad design breaking a clean architecture. The web interface is at the outermost part of the typical architecture circle, so you have to look it in the other way. You have to find a way to instruct the persistence layer from the request layer (or any other below).
As you said, for default datasets you can use dataset on your relation. But from there you have no way, and you should not, access your request layer. You need to provide something from the request layer to the persistence layer, and not having the persistence layer taking something from the request layer. Soon or later this coupling would cause you troubles when dealing with your layers in the middle.
Just try to deal with it in its context. For example, if your repository function requires the argument you won’t never forget to provide it from your controller. Maybe you can also rely on some sort of custom made relation plugin to add a consistent behaviour.
Thanks for the reply, I ended up with a slightly different solution.
I’ve added a module:
module Organizational
extend ActiveSupport::Concern
included do
def for_organization
organization_id.nil? ? self : where(self[:organization_id] => organization_id)
end
private
def organization_id
Api::Container['organization_id']
end
end
end
Then in a base repository I overwrite root and check the module inclusion
class Repository < ROM::Repository::Root
include Import.args['persistence.rom']
def root
super.respond_to?(:for_organization) ? super.for_organization : super
end
end
This means that I can simply use root in the repo now and it will filter by default.
NOTE: One improvement is that I can use a little meta programming to overwrite the relation name also and do a similar check like for root