Kuqa
Kuqa

Reputation: 461

Creating almost the exact same 2 plugs, but slightly different

I have my own plug module:

defmodule Module1 do

  def init(opts) do
    opts
  end

  def call(conn, _opts) do
    # if some_condition1
    # something
  end

  # other stuff
end

And in router.ex

  pipeline :pipeline1 do
    plug(Module1)
  end

  scope "/scope", MyApp, as: :scope1 do
    pipe_through([:browser, :pipeline1])
    # .......

Now I want to create a second pipeline and scope using the same module Module1:

  pipeline :pipeline2 do
    plug(Module1)
  end

  scope "/scope2", MyApp, as: :scope2 do
    pipe_through([:browser, :pipeline2])
    # .......

However, if I were to create a second module, the difference would only be in this:

 def call(conn, _opts) do
    # if some_condition1 and some_condition2
    # something
  end

That is, I've only added "some_condition2", and everything else remains the same.

Now, how can I do that? Do I have to create the exact same module Module2 as Module1 and just sligtly change "call"? It'll result in code duplication.

Upvotes: 0

Views: 44

Answers (1)

Dogbert
Dogbert

Reputation: 222158

This is what the opts in Plug is meant for. You can pass it from your plug call and then use it inside call:

pipeline :pipeline1 do
  plug Module1, check_both: false
end

pipeline :pipeline2 do
  plug Module1, check_both: true
end
defmodule Module1 do
  def init(opts), do: opts

  def call(conn, opts) do
    if opts[:check_both] do
      # if some_condition1 and some_condition2 do something...
    else
      # if some_condition1 do something...
    end
  end
end

Now in pipeline1, opts[:check_both] will be false, and in pipeline2, it'll be true.


I'm passing a Keyword List here, but you can pass anything, even just a single true or false if that's enough (that should be a little bit faster than Keyword Lists as well).

You can also do some preprocessing with opts in init/1. Right now it just returns the initial value.

Upvotes: 7

Related Questions