Resources vs get/put in router. Different behaviour?

If I have this in my router:

  scope "/", MyApp do
    pipe_through :browser

    # resources "/reset_password", ResetPasswordController, only: [:edit, :update]
    get "/reset_password", ResetPasswordController, :edit
    put "/reset_password", ResetPasswordController, :update
  end

  scope "/api", MyApp do
    pipe_through :api

    scope "/v1" do
      resources "/reset_password", ResetPasswordController, only: [:create]
    end
  end

This code works in my controller test:

conn = post(conn, reset_password_path(conn, :create), reset_password: %{email: "anna@example.com"})

However, if I change the get and put to also use resources, like this:

  scope "/", MyApp do
    pipe_through :browser

    resources "/reset_password", ResetPasswordController, only: [:edit, :update]
  end

  scope "/api", MyApp do
    pipe_through :api

    scope "/v1" do
      resources "/reset_password", ResetPasswordController, only: [:create]
    end
  end

This code throws an error:

conn = post(conn, reset_password_path(conn, :create), reset_password: %{email: "anna@example.com"})
** (Protocol.UndefinedError) protocol Phoenix.Param not implemented for [reset_password_token: "Kz5RHRYMSedylzSJOz8oItFl255GsR-crTCa8Q1DJDTlQYv5OMFknS5OPj-HRcjQ"]

Why would one work but not the other? :slight_smile: Also, why would changing the get/put routes break the post?

Is it because I use resources twice, and in different scopes?

Huh, I’m not actually sure, but you could always try putting an as: :api on your api scope, would have to use api_blah_path for the api paths then, which I like better as it is more explicit and what I do.

Can we see those controllers and your test cases?

No, sorry. I will create a minimal test case in a new app though and push to github!

The resources routes expect an :id as argument. When you change from get/put to resources, now your routes are expecting a parameter for the :id but instead you are passing the parameters suck as [reset_password_token: ...].

The place where this is happening should be in the stacktrace, try giving it a look. When reporting errors, always try to include information such as stacktrace and versions. The stacktrace in particular is very important and should not be skipped.

2 Likes

Ah, of course…! I knew there was something silly in there. :rolling_eyes:

Thank you @josevalim :heart: