Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested phoenix resources #245

Open
char0n opened this issue Jan 15, 2020 · 1 comment
Open

Nested phoenix resources #245

char0n opened this issue Jan 15, 2020 · 1 comment

Comments

@char0n
Copy link

char0n commented Jan 15, 2020

Hi,

I've intercepted a problem that I couldn't find solution to. It concerns nested phoenix resources and documenting them with swagger macros.

It is possible to define nested resources in your router.

# router.ex
resources "/video-channels", VideoChannelController, only: [:show] do
  resources "/videos", VideoController, only: [:index]
end

resources "/videos", VideoController, only: [:index]

By route definition like this I end up with having two index functions inside VideoController that are pattern matching different params.

# VideoController.ex

def VideoController do
  use HelloWeb, :controller
  use PhoenixSwagger 

  swagger_path :index do
    get("/api/v1/video-channels/{video_channel_id}/videos")
    description("Returns videos filtered by video channel.")
  end

  def index(conn, %{"video_channel_id" => video_channel_id} = params}) do
    ..list of videos filtered by video channel ID..
  end

  swagger_path :index do
    get("/api/v1/videos")
    description("Returns videos filtered by video channel.")
  end

  def index(conn, params) do
    ..list of videos... 
 end
end

Then during the compilation I get:

 $ mix phx.swagger.generate
Compiling 2 files (.ex)
warning: this clause cannot match because a previous clause at line 20 always matches
  */video_controller.ex:87

The problem is that both swagger_paths are using the same action :index, although they handle completely different urls. Is this scenario supported? If it's not supported, is there some recommended workaround for nested resources then ?

Thank you

@char0n
Copy link
Author

char0n commented Jan 15, 2020

The only workaround so far I could come up with is not using nested resources, but rather define urls in router statically and use defdelegate to keep backward compatibility with nested resources if utilized again in the future:

# router.ex
resources "/video-channels", VideoChannelController, only: [:show] 
get "/video-channels/:video_channel_id/videos", VideoController, :index_by_video_channel
resources "/videos", VideoController, only: [:index]
# VideoController.ex

def VideoController do
  use HelloWeb, :controller
  use PhoenixSwagger 

  defdelegate index_by_video_channel(conn, params), 
    to: VideoController, 
    as: :index

  swagger_path :index_by_video_channel do
    get("/api/v1/video-channels/{video_channel_id}/videos")
    description("Returns videos filtered by video channel.")
  end

  def index(conn, %{"video_channel_id" => video_channel_id} = params}) do
    ..list of videos filtered by video channel ID..
  end

  swagger_path :index do
    get("/api/v1/videos")
    description("Returns videos filtered by video channel.")
  end

  def index(conn, params) do
    ..list of videos... 
 end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant