Unable to cast_assoc with User and Credential with Schema prefix

Hi Elixir Aficionados,

I am trying to set up a multi tenancy application and I am unable to figure out how to cast_assoc with tenant prefix.

Context looks like this:

  def create_user(attrs \\ %{}, tenant) do

    credential_changeset = %Credential{}
    |> Credential.changeset(Map.get(attrs, "credential"))

    %User{}
    |> Ecto.put_meta(prefix: Triplex.to_prefix(tenant))
    |> User.changeset(attrs)
    |> Ecto.Changeset.prepare_changes(fn changeset ->
      Ecto.Changeset.cast_assoc(changeset, :credential, with: &Credential.changeset/2)
      
    end)
    |> Repo.insert(prefix: Triplex.to_prefix(tenant))

  end

I get error:

[error] #PID<0.573.0> running MyAppWeb.Endpoint (connection #PID<0.535.0>, stream id 11) terminated
Server: space-rocket.brand-place.local:4000 (http)
Request: POST /my-app-admin/users
** (exit) an exception was raised:
    ** (Ecto.ConstraintError) constraint error when attempting to insert struct:

    * users_org_id_fkey (foreign_key_constraint)

If you would like to stop this constraint violation from raising an
exception and instead add it as an error to your changeset, please
call `foreign_key_constraint/3` on your changeset with the constraint
`:name` as an option.

The changeset defined the following constraints:

    * users_username_index (unique_constraint)

        (ecto 3.4.3) lib/ecto/repo/schema.ex:700: anonymous fn/4 in Ecto.Repo.Schema.constraints_to_errors/3
        (elixir 1.10.2) lib/enum.ex:1396: Enum."-map/2-lists^map/1-0-"/2
        (ecto 3.4.3) lib/ecto/repo/schema.ex:685: Ecto.Repo.Schema.constraints_to_errors/3
        (ecto 3.4.3) lib/ecto/repo/schema.ex:666: Ecto.Repo.Schema.apply/4
        (ecto 3.4.3) lib/ecto/repo/schema.ex:263: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4
        (ecto 3.4.3) lib/ecto/repo/schema.ex:925: anonymous fn/3 in Ecto.Repo.Schema.wrap_in_transaction/6
        (ecto_sql 3.4.3) lib/ecto/adapters/sql.ex:875: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4
        (db_connection 2.2.2) lib/db_connection.ex:1427: DBConnection.run_transaction/4
        (my_app 0.1.0) lib/my_app_web/controllers/subdomain/user_controller.ex:29: MyAppWeb.Subdomain.UserController.create/2
        (my_app 0.1.0) lib/my_app_web/controllers/subdomain/user_controller.ex:1: MyAppWeb.Subdomain.UserController.action/2
        (my_app 0.1.0) lib/my_app_web/controllers/subdomain/user_controller.ex:1: MyAppWeb.Subdomain.UserController.phoenix_controller_pipeline/2
        (phoenix 1.5.1) lib/phoenix/router.ex:352: Phoenix.Router.__call__/2
        (my_app 0.1.0) lib/my_app/plugs/subdomain.ex:22: MyApp.Plug.Subdomain.call/2
        (my_app 0.1.0) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.plug_builder_call/2
        (my_app 0.1.0) lib/plug/debugger.ex:132: MyAppWeb.Endpoint."call (overridable 3)"/2
        (my_app 0.1.0) lib/my_app_web/endpoint.ex:1: MyAppWeb.Endpoint.call/2
        (phoenix 1.5.1) lib/phoenix/endpoint/cowboy2_handler.ex:64: Phoenix.Endpoint.Cowboy2Handler.init/4
        (cowboy 2.7.0) /Users/bigbassroller2017/Sites/my-app/my_app/deps/cowboy/src/cowboy_handler.erl:41: :cowboy_handler.execute/2
        (cowboy 2.7.0) /Users/bigbassroller2017/Sites/my-app/my_app/deps/cowboy/src/cowboy_stream_h.erl:320: :cowboy_stream_h.execute/3
        (cowboy 2.7.0) /Users/bigbassroller2017/Sites/my-app/my_app/deps/cowboy/src/cowboy_stream_h.erl:302: :cowboy_stream_h.request_process/3

Is it possible to cast_assoc with schema prefix? Or will I have to go at it a different way, ala this Github discussion: Joins in queries are not respecting a schema’s prefix, fix listed. But the prepare_changes gives me hope after seeing this SO: Preload Ecto Association on Insert

Any help or tips would be greatly appreciated!

I made an example repo to help debug and turns out that the schema prefixes are working on cast_assoc. So the problem I was having must have been from my user changesets getting mixed in with registration changesets.

I went ahead and published the repo for posterity:

2 Likes