Param protocol not being implemented, possibly due to protocols being consolidated

Hi folks!

I have a routing question. I have a model that has two field, one UUID field as a primary field and a title. I have those two working fine.

I’ve been trying to implement a custom to_param method for my model that has a UUID ID field. Basically, I’ll be generating “slugified” slugs from the title, and then base-62 encode the UUID as well, to get something like

/models/:slug_:id

However, no matter what I do, I can’t seem to get the to_param method be called, so the path_helpers are constantly returning the ID field.

So, here’s the model I have:

  @primary_key {:id, :binary_id, autogenerate: true}
  schema "posts" do
    field :title, :string

And this is the to_param I’ve been trying to wrangle:

defimpl Phoenix.Param, for: CMS.Post do
  def to_param(%{id: id, title: _title}) do
    "my_#{id}"
  end
end

For just testing, I want to see the to_param to be called so I can generate URLs in the Helpers. However, to no avail:


%App.CMS.Post{
  __meta__: #Ecto.Schema.Metadata<:built, "posts">,
  id: "foobar",
}

PheltWeb.Router.Helpers.posts_path(%URI{}, :show, slate)
"/posts/foobar"

You’ll see, while I expect a /posts/my_foobar, I keep seeing /posts/foobar

I do keep seeing this error in VSCode:

the Phoenix.Param protocol has already been consolidated, an implementation for CMS.Post has no effect. If you want to implement protocols after compilation or during tests, check the "Consolidation" section in the Protocol module documentation

I’m not sure if that’s related, but maybe? I was able to find this forum issue.

I tried the steps to “stop” consolidation on one of the answers, but didn’t seem to help. I saw this is fixed on master but what I little I was able to try, it still seemed broken with the same error message — or I was doing something very wrong.

I’m on Phoenix 1.5.7 and Ecto 3.5.6 if that helps.

I’m hoping I’m doing something utterly crazy dumb at this point…

Why is the protocol for ˋCarto.Slateˋ and not ˋApp.CMS.Postˋ?

This one you shouldn‘t need to care for. Protocol consolidation happens per beam instance, so it only affects the elixir-ls node. If you don‘t see the same warning elsewhere there should be nothing to worry about.

1 Like

I was removing some work-related naming :slight_smile: but missed a few, seems like it. I am sure the naming et al are all correct, though.

Well, seems like you got me. Nothing like a good-old asking someone the question to solve it myself.

I was implementing the protocol for Context.Model, not App.Context.Model. I changed it and voila!

Thanks a lot for the kind answer.