many_to_many in ash

defmodule Consola.Database.ShortUrl do
use Ash.Resource, domain: Consola.Database, data_layer: AshPostgres.DataLayer

postgres do
table "short_urls"
repo Consola.Repo
end



actions do
default_accept :*
defaults [:create, :read, :update, :destroy]

create :create_with_full_url do
default_accept [:related_full_urls, :short_url, :expires_at]
end

end

attributes do
uuid_primary_key :id

attribute :short_url, :string do
allow_nil? false
public? true
end


attribute :expires_at, :string do
allow_nil? false
public? true
end

create_timestamp :created_at
update_timestamp :updated_at
end

relationships do
many_to_many :related_full_urls, Consola.Database.FullUrl do

through Consola.Database.UrlMapping

public? true
writable? true

source_attribute :id
source_attribute_on_join_resource :short_url_id

destination_attribute :id
destination_attribute_on_join_resource :full_url_id

end

end
end
defmodule Consola.Database.ShortUrl do
use Ash.Resource, domain: Consola.Database, data_layer: AshPostgres.DataLayer

postgres do
table "short_urls"
repo Consola.Repo
end



actions do
default_accept :*
defaults [:create, :read, :update, :destroy]

create :create_with_full_url do
default_accept [:related_full_urls, :short_url, :expires_at]
end

end

attributes do
uuid_primary_key :id

attribute :short_url, :string do
allow_nil? false
public? true
end


attribute :expires_at, :string do
allow_nil? false
public? true
end

create_timestamp :created_at
update_timestamp :updated_at
end

relationships do
many_to_many :related_full_urls, Consola.Database.FullUrl do

through Consola.Database.UrlMapping

public? true
writable? true

source_attribute :id
source_attribute_on_join_resource :short_url_id

destination_attribute :id
destination_attribute_on_join_resource :full_url_id

end

end
end
Aim:
params = %{
short_url: "https://shorturl-example-4.com",
expires_at: "2025-05-16T10:54:16Z",
related_full_urls: [%{url: "https://fullurl-example-4.com"}]
}

# to make this API work!

Consola.Database.ShortUrl|> Ash.Changeset.for_create(:create_with_full_url, params)|> Ash.create!()
params = %{
short_url: "https://shorturl-example-4.com",
expires_at: "2025-05-16T10:54:16Z",
related_full_urls: [%{url: "https://fullurl-example-4.com"}]
}

# to make this API work!

Consola.Database.ShortUrl|> Ash.Changeset.for_create(:create_with_full_url, params)|> Ash.create!()
What are the different ways to handle creating many_to_many relationship while creating the resource itself? Few notable things are 1. many_to_many has writable? true my understanding is that this should enable me to create the mapping (related_full_urls in the 'through' table) if I pass it as params.
1 Reply
abeeshake456
abeeshake456OP3w ago
I guess I have to write manage_relationship.
actions do
default_accept :*
defaults [:create, :read, :update, :destroy]

create :create_with_full_url do
default_accept [:short_url, :expires_at]

argument :related_full_urls, {:array, :map}, allow_nil?: true

change manage_relationship(:related_full_urls, type: :create)
end
end
actions do
default_accept :*
defaults [:create, :read, :update, :destroy]

create :create_with_full_url do
default_accept [:short_url, :expires_at]

argument :related_full_urls, {:array, :map}, allow_nil?: true

change manage_relationship(:related_full_urls, type: :create)
end
end
This did the trick!

Did you find this page helpful?