Parameterized path call

I need to find the right redirect path based on the name of the entity.
So my idea was to simply construct the path call myself and then to execute it.
Unfortunately, I haven’t figured out yet how I can get it working.

Code.eval_string("#{downcased_entity_name}_path(conn, :show, event.#{downcased_entity_name}_id)"))

I always get undefined function user_path/3. The path string is the following: "user_path(conn, :show, event.user_id)". So the path is constructed in the right way but somehow the execution does not seem to work.

Hi,

If you are using Phoenix 1.4 you need to use the alias Routes:

Routes.user_path(...)

Andrew

Code.eval_* runs your code in a pristine environment, you need to import whatever module defines the path helpers, or pass context_modules: [whatever_defines_the_helper] or simply pass __ENV__ to inherit the surrounding context.

But remember that eval_string will return a tuple, of which you are only interested in the first element.

Nevertheless, I’d strictly advice against the usage of Code.eval_* here and in production in general.

I tend to do it like this:

if downcased_entity_name in @whitelist_of_entity_names do
  key = String.to_existing_atom("#{downcased_entity_name}_id")
  %{^key => id} = event
  apply(AppWeb.Routes.Helpers, String.to_existing_atom("#{downcased_entity_name}_path"), [conn, :show, id)])
else
  # fail with a big red error message
end

This code is untested though, and you should probably provide an extra function to extract the id from the event.

Your Code.eval_string solution without checking a whitelist makes your code vulnerable for some attacks that target spamming your atom table with random values and therefore might finally OOM your application.

4 Likes

Awesome. I did some research and I only found the Code.* stuff. I also prefer your solution.

1 Like