BryanJBryce
Custom action using manage_relationship when relationship is many_to_many
Resources involved are Employee, Shift, and EmployeeShift
Employee and shift are related many_to_many, through EmployeeShift, however, since an employee can clock in and out multiple times during an shift EmployeeShift has it’s own id and isn’t unique by pairs of Employee and Shift ids:
attributes do
uuid_primary_key :id
attribute :in_at, :utc_datetime_usec, allow_nil?: false
attribute :out_at, :utc_datetime_usec
create_timestamp :created_at
update_timestamp :updated_at
end
relationships do
belongs_to :employee, PointOfSale.Accounts.Employee do
api PointOfSale.Accounts
allow_nil? false
attribute_writable? true
end
belongs_to :shift, PointOfSale.Stores.Shift do
allow_nil? false
attribute_writable? true
end
end
Additionally EmployeeShifts have a custom primary create action called start that takes arguments of employ_id and shift_id and set’s the start time:
create :start do
primary? true
accept [:employee_id, :shift_id]
argument :employee_id, :uuid, allow_nil?: false
argument :shift_id, :uuid, allow_nil?: false
change set_attribute(:in_at, DateTime.utc_now())
change set_attribute(:employee_id, arg(:employee_id))
change set_attribute(:shift_id, arg(:shift_id))
end
When I start a new Shift I want to be able to pass an array of Employee ids to manage_relationship so that the custom start create function is called on EmployeeShift so that the included employees are clocked in automatically as the shift starts:
Shift
has_many :employee_shifts, PointOfSale.Stores.EmployeeShift
many_to_many :employees, PointOfSale.Accounts.Employee do
api PointOfSale.Accounts
through PointOfSale.Stores.EmployeeShift
join_relationship :employee_shifts
end
create :start do
accept [:till_id, :employee_ids]
argument :till_id, :uuid, allow_nil?: false
argument :employee_ids, {:array, :uuid}, allow_nil?: false
change set_attribute(:start_at, DateTime.utc_now())
change set_attribute(:till_id, arg(:till_id))
change manage_relationship(:employee_ids, :employee_shifts, type: create)
end
However, when I attempt to create a new Shift via this action I get an error saying that the required arguments of shift_id and employee_id for EmployeeShift are missing.
The shift_id should come from the shift that is created just before running the manage relationship. And I thought I would be accepting employee_ids via the manage_relationship function.
I see that I can pass a map instead of a list of ids, and maybe that is the way, but that doesn’t solve the passing in of the shift_id that I don’t have since it get’s created.
Marked As Solved
zachdaniel
You’ll need to point it at a different create action and/or make those arguments optional (because manage_relationship writes to the attributes, it doesn’t set arguments).
Also Liked
zachdaniel
The action is specified by modifying the underlying keys for manage_relationship.
type: :create maps to
[
on_no_match: :create,
on_match: :ignore
]
The docs for it are here: Ash.Changeset — ash v3.29.3
So you’d say:
type: :create,
on_match: {:create, :action_name, :join_table_action_name, []}
zachdaniel
ah, okay interesting. Sorry, didn’t notice this until now.
Try this:
change manage_relationship(:employee_ids, :employee_shifts, type: :create, value_is_key: :employee_id)
BryanJBryce
That solves the employee_id ![]()
But not the shift_id
** (Ash.Error.Invalid) Input Invalid
* argument shift_id is required at employee_ids, 0
(ash 2.18.2) lib/ash/api/api.ex:2711: Ash.Api.unwrap_or_raise!/3
iex:4: (file)
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









