Hey All!
I’m really new to Ash but I think it’s got a lot of potential to save me a ton of time so I’m working through this for a proof-of-concept / MVP I’m creating.
TL;DR is I’m trying to create an app and a multi-tenant database using schema-isolated multi-tenants approach (one schema per organization) - I’ve got it creating tables but I don’t see any schemas being created, so I just have one accounts table and I should be seeing multiple schemas (one per org) with an accounts table in each schema.
Prior to trying to add in multi-tenancy, I was creating the tables “like normal” and was able to work through the relationship creating and attributes creation. I got that all set up in postgres.
When I started switching the resources to be multi-tenant, I noticed that the multi-tenant migrations started being created during codegen (i.e. mix ash.codegen add_multitenancy_to_remaining
) which seemed good and promising, but that’s where I got stuck because I noticed no multiple schemas were getting created. Also, I tried creating an entry in the organizations table to see if that would trigger a new schema. It didn’t. Then I ran mix ecto.migrate again after the new organizations record was added to the database, but no new schemas were added to the database.
and when I do mix ecto.drop, mix ecto.create and mix ecto.migrate --migrations-path priv/repo/tenant_migrations
then I get all the same issues where I only have one accounts table and not multiple schemas - though I’m NOT seeing an organizations table (my only non-multi-tenant resource right now).
When I do normal mix ecto.drop, mix ecto.create and mix ecto.migrate , then I get the organizations table but still not multiple schemas.
Do I need to redo all my migration code with the codegen from scratch? Do you think something got messed up along the way because the resources started out as being non-multi-tenant? Or am I looking at the issue all wrong? if so, please enlighten me
So here’s the code for inspection :
I marked all of them as multi-tenant like this (full code)
defmodule MyApp.MyDomain.Account do
use Ash.Resource,
domain: MyApp.MyDomain,
data_layer: AshPostgres.DataLayer
postgres do
table "accounts"
repo MyApp.Repo
end
multitenancy do
strategy :context
end
actions do
defaults [:read]
create :signup do
accept [:username, :email]
end
end
attributes do
uuid_primary_key :id
attribute :username, :string do
allow_nil? false
public? true
end
attribute :email, :string do
allow_nil? true
public? true
end
end
end
and I created an Organization resource which I believe is set to be non-multi-tenant because there should just be one table of tenants (full code)
defmodule MyApp.MyDomain.Organization do
use Ash.Resource,
domain: MyApp.MyDomain,
data_layer: AshPostgres.DataLayer
postgres do
table "organizations"
repo MyApp.Repo
end
actions do
defaults [:read]
create :create do
accept [:name]
end
end
attributes do
uuid_primary_key :id
attribute :name, :string do
allow_nil? false
public? true
end
end
postgres do
manage_tenant do
template ["org_", :id]
end
end
defimpl Ash.ToTenant do
def to_tenant(%{id: id}, resource) do
if Ash.Resource.Info.data_layer(resource) == AshPostgres.DataLayer
&& Ash.Resource.Info.multitenancy_strategy(resource) == :context do
"org_#{id}"
else
id
end
end
end
end