How to handle "not found" with Beacon.DataSource.Behaviour?
kwando opened this issue · 5 comments
How do we handle when data is not found in my BeaconDataSource? For instance in the demo app, what if I navigate to a blog post that does not exist?
Is there someway of signal back to beacon?
Maybe some async features here as well if the data is slow to get?
what if I navigate to a blog post that does not exist?
It depends how you structure your site and pages, for eg on dockyard.com each blog post is a page so visiting a broken url will render a 404 page, eg: https://dockyard.com/blog/2023/11/01/nothing-here
Such pages can be created and styled in the Admin interface since we merged support for error pages. It provides a default implementation too.
How do we handle when data is not found in my BeaconDataSource?
At this moment it's up to you to make sure the data source is correct and you're calling an existing key. This process will be easier after we get to merge BeaconCMS/beacon_live_admin#84 which will let you manage the data source in the admin interface at runtime. Besides that, I've been discussing this problem with @APB9785 and exploring ways to warn users about incorrect data source, the issue to track is #369
async features here as well if the data is slow to get?
Async and caching is not yet planned but I can see it'll be necessary eventually. It's too early to define the architecture for both but they would probably be implemented after LV async and Nextjs Data Caching, respectively. Just created two issues to keep track of it: #371 and #370
I hope that answer your questions so I'm closing the issue, but feel free to post more comments. Thanks!
Maybe I'm just confused with how the Datasource-thingy should work..
def live_data(:blog, ["posts", post_slug], _params) do
case BlogPosts.fetch_blog_post_by_slug(post_slug) do
{:ok, post} -> post
:error ->
nil # <==== what to return here to render a 404? nil? raise error?
end
end
For this situation, you can define your own custom exception which is treated as 404 by Phoenix:
defmodule YourApp.PageNotFoundError do
defexception plug_status: 404, message: nil, path: nil
def exception(opts) do
path = Keyword.fetch!(opts, :path)
%__MODULE__{message: "Page not found for path: #{Enum.join(path, "/")}", path: path}
end
end
and then in your live_data handler:
def live_data(:blog, ["posts", post_slug] = path, _params) do
case BlogPosts.fetch_blog_post_by_slug(post_slug) do
{:ok, post} -> %{post: post}
:error -> raise YourApp.PageNotFoundError, path: path
end
end
Note the successful case creates a map of live_data assigns, which will be used in your template.
Oh, didn't consider that option 😅
Not a fan of raising exceptions for non exceptional cases, but at least there is something.
@kwando that's how Phoenix knows what to do :)
https://hexdocs.pm/phoenix/1.7.10/custom_error_pages.html#custom-exceptions