opened
Gazler
username_0
Instead of having actors displayed in the format:

 * user:1
 * user:2
 * user:404
 * country:uk

Aliases allow a function to be called with the flag, which could fetch
the users names from the database and transform them into:

 * User Name 1
 * User Name 2
 * user:404
 * United Kingdom

This is achieved with the following (optional) config:

    config :fun_with_flags_ui, :flag_page,
      alias_fn: &MyApp.Feature.flag_alias/1

The function expects a `%FunWithFlags.Flag{}` struct, and returns a
`%FunWithFlags.Flag{}` struct.

An example (inefficient) implementation of the
`MyApp.Feature.flag_alias/1` function could be:

    def flag_alias(flag) do
      gates = Enum.map(flag.gates, &get_gate_aliases/1)
      %{flag | gates: gates}
    end

    defp get_gate_aliases(%{for: "user:" <> id} = gate) do
      case MyApp.Repo.get(MyApp.User, id) do
        nil -> gate
        user -> %{gate | for: {"account:" <> id, user.name}}
      end
    end
    defp get_gate_aliases(%{for: "country:uk"} = gate) do
      %{gate | for: {"country:uk", "United Kingdom"}}
    end
    defp get_gate_aliases(gate), do: gate

If the `for` is a 2-tuple, in the format `{:id, :display_name}` then the
`:id` will be used for all form actions (such as enable/disable) and the
`:display_name` field will be used when actually displaying the actor
row.

I chose to use a 2-tuple as it doesn't require any modification of the existing structs. One downside is that it does violate the typespec at https://github.com/username_1/fun_with_flags/blob/master/lib/fun_with_flags/gate.ex#L6
Allow aliases for actors on the flag page
issue
created
tompave
username_1
Hello, and thank you for the PR!

I understand the feature, but I'm not too sure about including it into the library.

Feature toggles are mainly a tool for developers, and creating flags and gates – programmatically or through the web GUI – requires to know about the expected structure of actor IDs and which flag names will be referenced in code. Since users of the dashboard need to _think_ about the actual underlying IDs, I fear that displaying actors with prettified labels instead of the actual values would create confusion.

This is especially important because creating new actors will still require to enter the _actual ID values_ in the form input. Requiring to input values with a certain format and then displaying the same saved values with a different format would makes the UI harder to understand. Displaying the actual IDs serves also the purpose of providing examples of which kind of values are valid and already in use, which would be lost with this change.

Also, the actor ID formats are really up to the applications, so I'm not even sure about the default implementation for `alias_fn`. I used a colon in the examples because it's a common separator, but `user(52)`, `user-42` or even `userI_AM_BATMAN42` are all as valid formats as `user:42`.

In light of the above, I would discourage the introduction of this change.
----

If you want to keep pursuing this functionality in you fork, however, I have a few recommendations:

1. maybe display the prettified alias, but do so in a new column and keep the raw values in the screen.
2. at the moment this PR is changing the internal shape of `%Flag{}` and `%Gate{}` structs when they're loaded, with the consequence that the rest of the library needs to be aware that they could be either vanilla structs or transformed structs. This is less than ideal because those structs are private (nothing outside `FunWithFlags` should modify them), and the rest of the library should safely rely on them having a certain structure. The proof that is makes things more complicated is that you had to sprinkle extra functions here and there to handle the potentially different structs. What if instead you leave everything as it is, and just add a `generate_label(gate)` function to be invoked only when you need to display the alias?
3. doing what I suggested in the previous point also protect you from further changes in this library, to some extent. Try to keep the coupling to the internal details to a minimum.
4. It might be easier to just use a `fn` instead of a `{Module, :function}` tuple. As long as the arity it fixed, it's more portable.

I hope it makes sense!
comment
created
Gazler
username_0
This works fine when using Mix, but doesn't work with a release, the reference to the function will cause a syntax error in sys.config.
comment
created
tompave
username_1
I understand, but that then requires the developer to write a good aggregate query instead of an inefficient one.
comment