chrisdel101

chrisdel101

TL;DR I added a /foo/:name so I can access by name but param is catching actual routes, and vice versa.

But when I do /foo/new this is treated like the /foo/:name param and goes to :show (which is normally /foo/:id) rather than the proper /foo/new, and causes an error.

[info] GET /foo/new
[debug] Processing with MyApp.FooController.show/2
  Parameters: %{"name" => "new"}
  Pipelines: [:browser]

It’s getting caught by "/foo/:name", FooController, :show , which is above the default resources "/foo", FooController in file. Reordering doesn’t solve this since then /foo/:name gets caught by /foo/:id inside resources.

How can I make this work? I want to exclude the word new from being a param. Is there some kind of next() function so I could pass on the request when it’s rejected?

I don’t want to change id to name for all /foo routes, which is the only option I can find.

This solves it temporarily, but then I cannot access by id:
resources "/organizations", OrganizationController, except: [:show]

Showing Posts 1 to 4

LostKobrakai

LostKobrakai

There’s not. Routes are matched with pattern matching, which matches the first item. You’d need to decompose resources into its individual routes and solve things by reordering after that.

chrisdel101

chrisdel101 OP

Ahh okay, so then maybe I cannot use resources here. I’ll try breaking it up.

awerment

awerment

You must consider that /foos/:name and /foos/:id is essentially the same route - just that the name of the bound parameter is different regardless of if it’s an ID or a name. If you want to be able to fetch Foo resources by name or ID, you will have to do that inside the controller - treat the incoming parameter as id_or_name and write your lookup logic accordingly.

There’s nothing wrong per se with using resources here, just that the generated route clause for show will have the path parameter named "id" by default. You could leave that as it is, and just treat it as id_or_name in the controller: def show(conn, %{"id" => id_or_name}) do ....

Update: maybe to expand a bit on the parameter names in the route definitions, in case that’s the source of the confusion: the router does not “know” about the fields of your resources, the fact that Foo has a :name field does not matter. You could define a route with get "/foos/:whatever", FooController, :show - this will only affect the name of the parameter passed to the controller: def show(conn, %{"whatever" => value}) do ....

chrisdel101

chrisdel101 OP

These helped me solve the problem. I thought I’d need a middleware-type thing, like next() but I didn’t. I was over-complicating it. Once I got the routing right, it works. Here’s a psuedo-codey version of what I did.

Controller

 def show(conn, %{"param" => param}) do
    # if param is ID
    if is_digit(param) do
       # query ecto by ID with Repo.get! inside
       looked_up_obj =  MyObj.get_obj!(param)
       #redirect to show route so rest param uses name  slug in URL, not ID
       redirect(conn, to: "/foo/#{looked_up_obj.slug}")
    else # is slugged slug name as param
       #query ecto by name using Repo.get_by! inside
       looked_up_obj =  MyObj.get_obj_by_name!(param)
      render(conn, "show.html", organization: organization)
    end
  end

Router.ex

scope "/", MyAppWeb do
    pipe_through :browser
   
   resources "/foo", FooController, except: [:show]
   get "/foo/:param", FooController, :show
end

Thanks alot for the help!

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews