Adding title slug to url

I’m trying to transfer a c# site to elixir/phoenix…

url is id/title.slug. Very easy to add to the router in c#.

But I can’t figure out how to do it in phoenix router. Title.slug is cosmetic, actual route is the page with id only.

Is there a “phoenix way” to add title to the url?

You can use a glob path like this:

get "/:id/*title", ...
1 Like

There are some packages on hex to do so, slugify, slugger…

Once You have a slug field, You can use it instead of id. It needs some work to be done, but is totally doable.

Here is a nice short video on how to do it

1 Like

Thank you, but these are only good for simple routing requirements… At one point, you have to use the slug as your primary id. I don’t want to use the slug as my primary id because you can never update the title.

Thank you. It looks like this is a good way to go. I played a little, but couldn’t do it… I think I have to try more…

In what sense did it not work? Any errors?

In the documentation, it says that it takes *slug as a param, but the router doesn’t take it as a param… (I inject it from index.html as a link to show.html)

Called with 2 arguments

  1. {:params, “slug”}
  2. &URI.char_unreserved?/1

Can you please share your code and your error?

1 Like

You can create slug when blank, and not on update…

1 Like

There is not much code related to this aspect…
There is classic get "/:id/*slug“, PostController, :show with *slug added.
I was looking if I could inject the post.slug field from the index like post_path(@conn, :show, post, slug: post.slug

Error is:
no function clause matching in URI.encode/2

Attempted function clauses (showing 1 out of 1) def encode(string, predicate) when is_binary(string) and is_function(predicate, 1)

Good idea… But, there are assoc data, and whatever you use as id, you have to use it everywhere.

No, internally it uses id, but slug to display :slight_smile:

I tried that, didn’t work for me… There are attached posts to main post. They need to get and write add_id, etc… It was getting to a point I didn’t like.

It should be post_path(@conn, :show, post, [post.slug])

3 Likes

Thanks, it worked.

There is something wrong with (*) glob path… I don’t know how, but it dominates the session and you have to move every line in the router above this glob path line… It’s not usable at this state.

Then you can change to using /:id/:title and post_path(@conn, :show, post, post.slug).

But if there is a chance that the :id can be sent without the :title you’ll need both routes:

get "/:id", PostController, :show
get "/:id/:title", PostController, :show

And in the controller you may want to create two function heads and pattern match:

def show(conn, %{"id" => id}) do
  # do something
end

def show(conn, %{"id" => id, "title" => title}) do
  # do something
end

But it really depends on if you need the value of :title or not and what you’re doing inside show/2. You may want to just do show(conn, params) and get the values via params["id"] or params["title"] etc.

7 posts were split to a new topic: API url security