Crowdhailer

Crowdhailer

Creator of Raxx

Implementing middleware using `defoverridable` and `super`

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

Most Liked

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

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:

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:

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’). ^.^

Where Next?

Popular in Questions Top

Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
JulienCorb
I am trying to implement my new.html.eex file to create new posts on my website. new.html.eex: <h1>Create Post</h1> <...
New
jaysoifer
Is there a way to rollback a specific migration and only that one ("skipping" all the other ones)? Would mix ecto.rollback -v 2008090...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I fore...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35953 110
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31107 143
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 47849 226
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

We're in Beta

About us Mission Statement