TwistingTwists

TwistingTwists

Managing many to many relationships

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_ids and quiz_ids.

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_ids and quiz_ids.

Marked As Solved

zachdaniel

zachdaniel

Creator of Ash

Ah, never mind, you do :slight_smile:

This is the issue:

    read :read do
      argument :question_id, :uuid do
        allow_nil? false
      end

      # to indicate that only one record will be returned
      get? true
      primary? true

      filter expr(id == ^arg(:question_id))
    end

Your primary read action should not have required arguments. If it does, anything that tries to use it (like manage_relationship won’t know what to supply as the argument value.

Also Liked

TwistingTwists

TwistingTwists

Would never have guessed this error :stuck_out_tongue:

Thank you so much ! :slight_smile: That works.

Last Post!

TwistingTwists

TwistingTwists

Would never have guessed this error :stuck_out_tongue:

Thank you so much ! :slight_smile: That works.

Where Next?

Popular in Questions Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

Other popular topics Top

grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 54006 488
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New

We're in Beta

About us Mission Statement