before_action:设置相当于在凤凰城

问题描述:

我想干涸此控制器:before_action:设置相当于在凤凰城

defmodule Xyz.ExampleController do 
    use Xyz, :controller 

    alias XyZ.Shops 

    def a(conn, %{"id" => id}) do 
    product = Shops.get_product!(id) 
    tax = product.price * 0.15 

    ... 

    render(conn, "a.html", foobar: foobar, product: product) 
    end 

    def b(conn, %{"id" => id}) do 
    product = Shops.get_product!(id) 
    tax = product.price * 0.15 

    ... 

    render(conn, "b.html", foobar: foobar, tax: tax) 
    end 

    def c(conn, %{"id" => id}) do 
    product = Shops.get_product!(id) 
    tax = product.price * 0.15 

    ... 

    render(conn, "c.html", foobar: foobar) 
    end 

end 

每个函数这个部分开始:

product = Shops.get_product!(id) 
    tax = product.price * 0.15 

在Ruby on Rails的世界,我想把它调用before_action :setup来调用控制器。

在凤凰城实现这一目标的最佳方法是什么?

+3

你可以使用一个插件 - > https://hexdocs.pm/phoenix/plug.html,我求求你,不要把商业逻辑放到框架模块中。 – JustMichael

+2

该逻辑不应位于控制器IMO中。如果是我,我会定义一个像这样工作的函数:'{product,tax} = Shops.get_product_and_tax!(id)'并且从每个动作调用它。 – Dogbert

+0

比我会那样做。我认为将它放在一个插头中会更清洁。但我很高兴在每个操作中保留一行代码。 – wintermeyer

您可以尝试使用action/2控制器方法。从controller docs

由于控制器是插头,它们同时实现初始化/ 1和呼叫/ 2, 还提供/ 2命名作用的功能,该功能负责 调度插头堆叠之后的适当的动作(也可以覆盖 )。

在书中Programming Phoenix克里斯·麦科德使用这个动作把一个通用参数所有控制器的功能是这样的:

def​ action(conn, _) ​do​ 
​ apply(__MODULE__, action_name(conn), [conn, conn.params, conn.assigns.current_user]) 
​end​ 

所以像index/2的每一个动作,现在是index/3并具有当前用户为第三参数。

也许这可以帮助你?

+1

我不认为使用这种方法比插头更好,它不够灵活,并且在这种情况下不会给插件带来任何优势。 – JustMichael