Crowdhailer

Crowdhailer

Creator of Raxx

EDIT: I have written a blog post on this topic

I have been implementing middleware using the defoverridable and super. For example

# myapp.ex

defmodule MyApp do
  use Tokumei.Routing
  use Tokumei.Exceptions
  use Tokumei.ContentLength
  use Tokumei.CommonLogger
  use Tokumei.MethodOverride

  # define routes
end

The Routing module creates a function handle_request/2 and in each middle ware this function is defined as overridable and a new definition created that calls into super as needed. For example the implementation of Tokumei.MethodOverride is as follows, link to code on gihtub.

defmodule Tokumei.MethodOverride do
  def override_method(request = %{method: :POST, query: query}) do
    {method, query} = Map.pop(query, "_method")
    case method && String.upcase(method) do
      nil ->
        request
      method when method in ["PUT", "PATCH", "DELETE"] ->
        method = String.to_existing_atom(method)
        %{request | method: method, query: query}
    end
  end
  def override_method(request) do
    request
  end

  defmacro __using__(_opts) do
    quote do
      defoverridable [handle_request: 2]

      def handle_request(request, config) do
        request = unquote(__MODULE__).override_method(request)
        super(request, config)
      end
    end
  end
end

My questions are:

  • Is there any cost to repeatedly overriding a function?
  • Are there any other libraries doing similar?
  • General comments about the approach

Showing Posts 1 to 9

OvermindDL1

OvermindDL1

I hope there is not much cost! I’ve been using a lot of super to override action/2 in controllers to handle exceptions such as redirect’s when a permission exception is thrown. ^.^

But yeah, I’ve not looked at how super is implemented, hmm…

So it seems to be implemented at:
https://github.com/elixir-lang/elixir/blob/ff8dd1af7f6b53e482cd8be304093fabd36bc6dc/lib/elixir/src/elixir_overridable.erl#L16-L22

So it looks up the previous function definition and seems to call it, and just above that is where you see it defines in ets the information of what is overridable, with the store function being at the bottom.

So, it looks like the old/parent definitions are defined with a combination of the name and a counter, so always unique, and defp’d, so calls to them are always ‘local’ calls (in erlang parlance), which is fast.

So no issue, it looks like super is fast, I’d not worry about lots of them at all. :slight_smile:

Crowdhailer

Crowdhailer OP

Creator of Raxx

Well that is great news. I like the way we can have an essentially native middleware solution. :slight_smile:

OvermindDL1

OvermindDL1

Also entirely an implementation detail and you should not do this, but you could ‘directly’ call an older version of a function by using its hidden/internal name (for a ‘blah’ function it would be the function name of :"blah (overridable #{count})" for whatever count you want to go ‘up in the stack’). ^.^

Crowdhailer

Crowdhailer OP

Creator of Raxx

:slight_smile: yeah I will not be doing that, don’t worry

josevalim

josevalim

Creator of Elixir

I will change the private name of the autogenerated function to include a random component just so people don’t do that.

OvermindDL1

OvermindDL1

Woot! As it should be, as it is it is definitely not safe. ^.^

michalmuskala

michalmuskala

It needs to be deterministic, though. You don’t want to generate different .beam files each time the file is compiled, because functions with override get a different random component. The same source should always give the same .beam.

OvermindDL1

OvermindDL1

Can just add the hash of the existing name to the name, that way it still has the counter as well as it has some ‘more’. Though anything non-random (like hash’s) can still be generated other ways, so it is accessible regardless with enough work, but yeah random would be bad for generated files…

Crowdhailer

Crowdhailer OP

Creator of Raxx

I have publish the following blog post. Describing how to implement middleware with macros. I have been using this method for a while and it has been useful

— All posts loaded —

Where Next? Top

Trending in Questions Top

itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
yarrichar
I’m very new to Elixir, so sorry if this is a silly question: I am wondering what happens to the mailbox of a process when the machine i...
New
pragdave
How do I tell Hologram not to escape HTML when substituting into templates? {Textile.render(@product.long_description)} escapes the HTM...
New
Fl4m3Ph03n1x
Background When trying to execute mix release on a Windows 11 machine for a Phoenix project I get the following error: * assembling mark...
New
rlipscombe
I’d like to create a file with 600 permissions (rw-------), but there’s a race condition if I create it and then change the permissions. ...
New
saleyn
Is there a way to import record definitions in the iex shell for pretty printing (similar to the rr command in the erl shell)? This woul...
New
rlipscombe
When I use Mix.install with a git dependency, using git@github.com:... how do I change the SSH identity used? I’ve got two Github accoun...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
raa-ziq
Hi everyone :waving_hand: I wanted to share something I’ve been building — NowBlind, a random chat app designed to help people discover ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New
kip
Localize is the next generation localisation library for Elixir. Think of it as ex_cldr version 3.0. The first version will be released ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews