Phoenix中的before_filter等效于Rails中的什么?

17

我刚开始开发我的第一个Phoenix应用程序,遇到的问题是,每个控制器中的每个操作都有一些共同的代码行,我希望将它们分离出来。它们从多个Ecto Models中获取数据并将其保存到变量中供使用。

在Rails中,我可以简单地定义一个方法,并在控制器中使用before_filter调用它。我可以从@variable中访问结果。我知道使用Plugs 是关键,但我不清楚如何实现这一点,更具体地说:

  • Plug 中访问请求params
  • 使变量在操作中可访问

作为参考,这是我正在尝试完成的Rails版本:

class ClassController < ApplicationController
    before_filter :load_my_models

    def action_one
        # Do something with @class, @students, @subject and @topics
    end

    def action_two
        # Do something with @class, @students, @subject and @topics
    end

    def action_three
        # Do something with @class, @students, @subject and @topics
    end

    def load_my_models
        @class    = Class.find    params[:class_id]
        @subject  = Subject.find  params[:subject_id]

        @students = @class.students
        @topics   = @subject.topics
    end
end

谢谢!

2个回答

25

您可以通过PlugPlug.Conn.assign实现此目的。

defmodule TestApp.PageController do
  use TestApp.Web, :controller

  plug :store_something
  # This line is only needed in old phoenix, if your controller doesn't
  # have it already, don't add it.
  plug :action

  def index(conn, _params) do
    IO.inspect(conn.assigns[:something]) # => :some_data
    render conn, "index.html"
  end

  defp store_something(conn, _params) do
    assign(conn, :something, :some_data)
  end
end

记得在你的操作插件之前添加插件声明,因为它们是按顺序执行的。


3
整个 Plug.Conn API 已经被导入,因此你可以执行 assign(conn, :something, :some_data) - Chris McCord

3
这段内容最好作为评论,但我缺少声望。使用当前版本的Phoenix(2018年8月的1.3.4版),如果您使用顶部答案中的代码,则只需执行plug :store_something:不要使用plug :action,因为这是多余的。操作将在你列出的插件之后运行。
如果包括plug :action,则会收到(Plug.Conn.AlreadySentError) the response was already sent,因为操作将运行两次,而Phoenix会生气。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接