{@thread.name}

Eduardo B. Alexandre
2023-06-03

Eduardo B. Alexandre:

In my system, I have 2 contexts/apis that uses the same table and have a field in common.

The first is the User resource inside the Accounts api:

defmodule Accounts.User do
  attributes do
    attribute :referral_code, :uuid do
      allow_nil? false

      generated? true
    end
  end

  postgres do
    table "users"

    migration_defaults referral_code: "fragment(\"uuid_generate_v4()\")"

    repo TeacherCompanion.Repo
  end
end

As you can see, I have a migration_defaults function call where I specify that an uuid need to be automatically generated for the referral_code field.

I also have another resource called Referrer which is inside my Referrals api:

defmodule Referrals.Referrer do
  attributes do
    ...

    attribute :referral_code, :uuid do
      allow_nil? false

      writable? false
    end
  end

  postgres do
    table "users"

    repo TeacherCompanion.Repo
  end
end

This resource also has the referral_code field, but it is only a “read-only” field. the thing is that in this resource I’m not specifying the migration_defaults function call since it would be redundant as I already did that in the other resource and I would just be duplicating code and making maintenance more bothersome.

The problem is that since Referrer don’t have the migration_defaults function call, when I generate the migration for both resources, Ash will simply ignore the Usermigration_defaults and not add any default for the users table referral_code field.

I’m not sure if this is by design, but it feels very odd to me since I was expecting that Ash would simply “merge” both resource configurations into the users table.

The only workaround I found was to duplicate the migration_defaults function call in both resources, but that kinda of eliminates the benefits of breaking a table into subsets (contexts) since in the end I need to duplicate a lot of code that shouldn’t be needed in the first place.

\ ឵឵឵:

In the case there is one canonical resource that contains all the attributes (+ defaults, etc.) necessary to generate the migration, which it looks like might be the case for you with User , you could simply exclude the other resources from the migration generator with migrate? false .

Eduardo B. Alexandre:

Actual, Referrer has new fields that the User don´t have. It has a new relationship:

  relationships do
    alias Referrals.Referred

    has_many :referreds, Referred do
      destination_attribute :referred_by_id
    end
  end

zachdaniel:

There is an option to ignore specific fields on migrations

zachdaniel:

It’s something like migration_ignore_fields

zachdaniel:

You could put that in the migrations who aren’t in charge of those columns potentially

Eduardo B. Alexandre:

Thanks <@197905764424089601> adding migration_ignore_attributes [:referral_code] did the trick!