Url attribute error in json

Hello,
I am trying to implement autocomplete search. I need json url attribute. My search.json is in “/api” scope, my book_path is “/” in scope

I get that error

(UndefinedFunctionError) function nil.path/1 is undefined or private
nil.path(“/books/1”)

def render(“search.json”, %{books: books} ) do

%{data:

   for book <- books do
   %{
 	title: book.title,
 	url: book_path( @conn, :show, book) }
   end

}
end

scope “/api”, BookTimeWeb do
pipe_through :api
get “/search”, Api.V1.SearchController, :search
end

scope “/”, BookTimeWeb do
pipe_through :browser # Use the default browser stack
resources “/books”, BookController
end

@conn seems to be undefined inside render. You can compute url for each book (in Api.V1.SearchController?) before rendering it.

So that the render function would become

def render("search.json", %{books: books}) do
  %{data: Enum.map(books, fn %{title: title, url: url} -> %{title: title, url: url} end)}
end

thanks for reply. @conn defined inside render. I solved with string interpolation. But i didnt understand what cause that

Maybe change your router… I think paths should use lowercase

from

resources "/Books", BookController do
end

to

resources "/books", BookController

You can always display routes with

$ mix phx.routes

This will give a list of corresponding path_helper, method, path, controller, action

UPDATE: As You updated code in your post, mine is now irrelevant :slight_smile:

i realised that typo mistake after create topic. I fixed but i still get same error.

If You don’t have access to path helper, You can use a simple string interpolation

url: book_path( @conn, :show, book)

to

url: "/books/#{book.id}"

Instead of passing in @conn pass in YourAppName.Endpoint module instead. It’s better than string interpolation because the knowledge of building up the urls is still contained in one place in the router.

3 Likes

Thanks it works. So code is

book_path(MyApp.Endpoint, :show, book)