Just saw this blog post by @leejarvis: Phoenix: Using Plugs to improve scoped resources - Lee Jarvis
The post explains how to resolve nested resources in a central place.
post_comment_path GET /projects/:project_id/posts/:post_id/comments AppWeb.CommentController :index
post_comment_path GET /projects/:project_id/posts/:post_id/comments/:id/edit AppWeb.CommentController :edit
post_comment_path GET /projects/:project_id/posts/:post_id/comments/new AppWeb.CommentController :new
[…] every one of our controller actions are going to need to handle this
project_id
parameter.I come from a Rails background, and the canonical way to solve this in Rails is to add a
before_action
:
class CommentController
before_action :set_project
# actions
def set_project
@project = Project.find(params[:project_id])
end
end
The author then uses a custom Plug to add the project
to conn.assigns
:
defmodule AppWeb.CommentController do
use AppWeb, :controller
plug :put_project
def show(conn, %{"post_id" => post_id, "id" => comment_id}) do
%{current_project: project} = conn.assigns
render(conn, "show.html", comment: get_comment!(project, post_id, comment_id))
end
defp put_project(conn, _opts) do
current_project = fetch_current_project(conn.params["project_id"])
assign(conn, :current_project, current_project)
end
end
I am curious about your opinions. How do you handle this in your projects?