I have a quiz. and a question.
and relation is.
quiz many_to_many question
question many_to_many quiz
via quiz_question
Now, I want to have an api where I can write Quiz.update_quiz_with_question_ids(existing_quiz,[ qid_1,qid_2,qid_3])
which ends up relating question_id
s and quiz_id
s.
What I tried:
update :update_quiz_with_question_ids do
accept []
argument :question_ids, {:array, :uuid} do
allow_nil? false
end
change manage_relationship(:questions, :question_ids, type: :direct_control)
end
which leaves with the following error
{:error,
%Ash.Error.Invalid{
errors: [
%Ash.Error.Query.Required{
field: :question_id,
type: :argument,
resource: PyqRatta.Databank.Question,
changeset: nil,
query: nil,
error_context: [],
vars: [],
path: [],
stacktrace: #Stacktrace<>,
class: :invalid
}
],
...
So, I tried a little differently.
update :update_quiz_with_question_ids do
accept []
argument :question_ids, {:array, :uuid} do
allow_nil? false
end
change manage_relationship(:questions, :question_ids,
on_match: :ignore,
on_lookup: :relate,
on_no_match: :relate,
# since we are adding more questions to the quiz.
on_missing: :ignore)
end
and same error persists. Finally, did one more tweak.
defmodule Databank.Changes.QuestionsFromQuestionIds do
@moduledoc """
Fetches questions from database to udpate the relationship from questions to quizzes
"""
use Ash.Resource.Change
alias Databank.Quiz
alias Databank.Question
alias Databank.QuizQuestion
def change(changeset, opts, context) do
quiz_id = Ash.Changeset.get_data(changeset, :id)
qids = Ash.Changeset.get_argument(changeset, :question_ids)
questions =
Enum.reduce(qids, [], fn qid, acc ->
{:ok, question} = Question.read(qid)
acc ++ [question]
end)
Ash.Changeset.force_set_argument(changeset, :question_ids, questions)
end
end
along with
update :update_quiz_with_question_ids do
accept []
argument :question_ids, {:array, :uuid} do
allow_nil? false
end
change Databank.Changes.QuestionsFromQuestionIds
change manage_relationship(:question_ids, :questions, type: :direct_control)
end
the changeset is :
#Ash.Changeset<
api: Databank,
action_type: :update,
action: :update_quiz_with_question_id,
attributes: %{},
relationships: %{
questions: [
{[%{id: "39f41254-f959-4f1d-96d4-30500d96d8d1"}],
[
ignore?: false,
on_missing: :destroy,
on_match: :update,
on_lookup: :ignore,
on_no_match: :create,
eager_validate_with: false,
authorize?: true,
meta: [inputs_was_list?: false, id: :question_id],
type: :direct_control
]}
]
},
arguments: %{question_id: "39f41254-f959-4f1d-96d4-30500d96d8d1"},
errors: [
%Ash.Error.Invalid{
errors: [
%Ash.Error.Query.Required{
field: :question_id,
type: :argument,
resource: Databank.Question,
changeset: nil,
query: nil,
error_context: [],
vars: [],
path: [],
stacktrace: #Stacktrace<>,
class: :invalid
}
],
stacktraces?: true,
changeset: nil,
query: #Ash.Query<
resource: Databank.Quiz,
load: [questions: []],
errors: [
%Ash.Error.Invalid{
errors: [
%Ash.Error.Query.Required{
field: :question_id,
type: :argument,
resource: Databank.Question,
changeset: nil,
query: nil,
error_context: [],
vars: [],
path: [],
stacktrace: #Stacktrace<>,
class: :invalid
}
],
stacktraces?: true,
changeset: nil,
query: #Ash.Query<
resource: Databank.Question,
filter: #Ash.Filter<id == nil>,
errors: [
%Ash.Error.Query.Required{
field: :question_id,
type: :argument,
resource: Databank.Question,
changeset: nil,
query: nil,
error_context: [],
vars: [],
path: [],
stacktrace: #Stacktrace<>,
class: :invalid
}
],
select: [:id, :question_text, :question_image, :type,
:correct_answer_text, :correct_answer_image,
:explanation_text, :explanation_image, :short_description,
:long_description, :year, :tags, :created_at, :updated_at]
>,
error_context: [],
vars: [],
path: [],
stacktrace: #Stacktrace<>,
class: :invalid
},
%Ash.Error.Query.Required{
field: :question_id,
type: :argument,
resource: Databank.Question,
changeset: nil,
query: nil,
error_context: [],
vars: [],
path: [],
stacktrace: #Stacktrace<>,
class: :invalid
}
]
>,
error_context: [nil],
vars: [],
path: [],
stacktrace: #Stacktrace<>,
class: :invalid
},
...
The reasoning behind this is : if manage_relationship
can alter the fields via given relationship key. But that doesn’t appear to be the case for many to many
TL;DR
create an Api where
relation is.
quiz many_to_many question
question many_to_many quiz
via quiz_question
Quiz.update_quiz_with_question_ids(existing_quiz,[ qid_1,qid_2,qid_3])
which ends up relating question_id
s and quiz_id
s.