How to remove/delete a many-to-many relationhip?

I’m relatively new to Elixir/Phoenix (I have much more familiarity with RoR) but I’ve made it quite far in my new application by following tutorials and the documentation.

I am building a sort of one-stop shop for user accounts, where users can be created, and given permissions to one or more web sites (AKA resources) that I work on. Users can have many resources they belong to, and resources have many users that belong to it, so I went with a many-to-many relationship.

I created the user_resources table in the database as a full table with an auto-generated ID. Since a user can’t belong to a resource twice (or vice versa), I’ve created what I believe is a good unique index.

defmodule MyApp.Repo.Migrations.CreateUserResources do
  use Ecto.Migration

  def change do
    create table(:user_resources) do
      add :user_id, references(:users)
      add :resource_id, references(:resources)
      add :inserted_by, :integer
      add :updated_by, :integer

      timestamps()
    end

    create unique_index(:user_resources, [:user_id, :resource_id])
  end
end

I also set up a schema for this relationship. I much prefer my relationships to be as fully fleshed out as possible, so that’s what I’ve done here.

defmodule MyApp.Account.UserResource do
  use Ecto.Schema
  import Ecto.Changeset


  schema "user_resources" do
    field :resource_id, :integer
    field :user_id, :integer
    field :inserted_by, :integer
    field :updated_by, :integer

    timestamps()
  end

  @doc false
  def changeset(user_resource, attrs) do
    user_resource
    |> cast(attrs, [:user_id, :resource_id, :inserted_by, :updated_by])
    |> validate_required([:user_id, :resource_id, :inserted_by, :updated_by])
  end
end

I can successfully add a User to a Resource in my controller like this:

  def add_user(conn, %{"resource_id" => resource_id, "user_id" => user_id}) do
    resource = Domain.get_resource!(resource_id)
    user = Account.get_user!(user_id)
    Domain.add_user(resource, user)

    conn
    |> put_flash(:info, "User added to resource successfully.")
    |> redirect(to: resource_path(conn, :show, resource_id))
  end

Which calls add_user in the Domain Context, which does the real work:

  def add_user(%Resource{} = resource, user) do
    resource
    |> Repo.preload(:users)
    |> Ecto.Changeset.change()
    |> Ecto.Changeset.put_assoc(:users, [user])
    |> Repo.update!
  end

This gives me a user_resources record in the database, and with the User in an Account Context, I have this function which gives me back a list of the users associated with the given resource:

  def list_resource_users(resource) do
    Repo.all(assoc(resource, :users))
  end

So far, so good.

Now I want to remove the association, so I’m following the advice of this post: Many-to-many associations in phoenix and ecto - #20 by idi527

That part of my resource controller looks like this:

  def remove_user(conn, %{"resource_id" => resource_id, "user_id" => user_id}) do
    Domain.remove_user(resource_id, user_id)

    conn
    |> put_flash(:info, "User removed from resource successfully.")
    |> redirect(to: resource_path(conn, :show, resource_id))
  end

And the function defined in the Domain Context looks like this:

  def remove_user(resource_id, user_id) do
    "user_resources"
    |> where(resource_id: ^resource_id)
    |> where(user_id: ^user_id)
    |> Repo.delete()
  end

However, when I initiate that code, I get this error:
function Ecto.Query.__changeset__/0 is undefined or private

I have tried many different things, and gotten a few small improvements, but I think there must be something very simple I’m missing that might stand out to someone more experienced?

I appreciate any help I can get, and I’ll try to provide more info as I work on things.