Create a resource including a belongs_to id

I have this resource with the name location:
attributes do
uuid_primary_key :id

attribute :name
attribute :code, :string
attribute :slug, :string
end

relationships do
belongs_to :level, Feriendaten.Geo.Level
end
attributes do
uuid_primary_key :id

attribute :name
attribute :code, :string
attribute :slug, :string
end

relationships do
belongs_to :level, Feriendaten.Geo.Level
end
Now I want to create a new entry for this resource with this code:
level =
Feriendaten.Geo.Level
|> Ash.Query.filter(contains(slug, "land"))
|> Feriendaten.Geo.read!()
|> hd()

Feriendaten.Geo.Location
|> Ash.Changeset.for_create(:create, %{
name: "Germany",
code: "DE",
slug: "germany",
level_id: level.id
})
|> Feriendaten.Geo.create!()
level =
Feriendaten.Geo.Level
|> Ash.Query.filter(contains(slug, "land"))
|> Feriendaten.Geo.read!()
|> hd()

Feriendaten.Geo.Location
|> Ash.Changeset.for_create(:create, %{
name: "Germany",
code: "DE",
slug: "germany",
level_id: level.id
})
|> Feriendaten.Geo.create!()
The recourse Location gets created but the attribute level_id is empty. How can I achieve to create a Location with the belongs_to association?
6 Replies
Rebecca Le
Rebecca Le•3y ago
in your create action definition, you would use manage_relationship to allow the setting of the level_id - let me grab an example In your Location resource:
actions do
create :create do
primary? true
change manage_relationship(:level_id, :level, type: :append_and_remove)
...
actions do
create :create do
primary? true
change manage_relationship(:level_id, :level, type: :append_and_remove)
...
this would allow the level_id attribute to be set when creating a Location, ensuring it's also a valid value etc.
Stefan Wintermeyer
Stefan WintermeyerOP•3y ago
Thanks @Rebecca Le ! For the archive. The function needs an addition line:
actions do
defaults [:read, :update, :destroy]

create(:create) do
argument :level_id, :string
primary? true
change manage_relationship(:level_id, :level, type: :append_and_remove)
end
end
actions do
defaults [:read, :update, :destroy]

create(:create) do
argument :level_id, :string
primary? true
change manage_relationship(:level_id, :level, type: :append_and_remove)
end
end
Withouth the argument :level_id, :string it doesn't work.
ZachDaniel
ZachDaniel•3y ago
You can also set attribute_writable? true on the relationship to make the attribute that it adds writable as a normal attribute.
Stefan Wintermeyer
Stefan WintermeyerOP•3y ago
Much cleaner. Thank you Zach!
ZachDaniel
ZachDaniel•3y ago
There are some differences in their behavior, for instance if you have policies on reading the related resource, manage_relationship will look it up first to make sure you can read it, that kind of thing. but attribute_writable? is simpler generally, yes. manage_relationship would be required for every other type of relationship though since they don't have an associated attribute like belongs_to does.
sevenseacat
sevenseacat•3y ago
TIL also, thanks 😄

Did you find this page helpful?