【问题标题】:Rails view_contextRails view_context
【发布时间】:2022-01-20 02:25:23
【问题描述】:

我无法理解 view_context。我目前正在我的应用程序中实现数据表,参考来自this video

我不明白的是如何访问 view_context 的内容,即传递给数据表类。

  def index
    respond_to do |format|
      format.html
      format.json { render json: UsersDatatable.new(view_context) }
    end
  end

然后我在我的数据表类中访问它

  def initialize(view)
    @view = view
  end

我正在使用一个名为 subscribem 的 gem。我声明了一个 Subscribem::Account 并将变量 current_account 传递给每个视图。在数据表类中我可以像这样访问它

  def initialize(view)
    @view = view
    @current_account = @view.current_account
  end

但问题是在控制器中,我添加了一些变量,例如

  def index
    @date = DateTime.now #or date=DateTime.now
    respond_to do |format|
      format.html
      format.json { render json: UsersDatatable.new(view_context) }
    end
  end

我无法获取过去的日期或@date。

  def initialize(view)
    @view = view
    @current_account = @view.current_account
    @date = @view.date
  end

提前谢谢好兄弟/姐妹

【问题讨论】:

    标签: ruby-on-rails ruby model-view-controller datatables


    【解决方案1】:

    理解视图上下文的关键是真正了解像 ERB 这样的模板引擎是如何工作的(它们在高层次上的工作方式几乎相同)。

    您获取一个字符串(或缓冲区)和一个上下文,该上下文是您要插入到视图中的数据以及您可能想要使用的所有方法。

    举个简单的例子:

    require 'erb'
    
    class Person
      def initialize(first_name, last_name)
         @first_name = first_name
         @last_name  = last_name
      end
    
      def get_binding
        binding
      end
    end
    
    template = "Hello my name is <%= @first_name %> <%= @last_name %>"
    person = Person.new('John', 'Doe')
    erb = ERB.new(template)
    puts ERB.new(template).run(person.get_binding) # Hello my name is John Doe
    

    由于我们使用Person 实例内部的绑定运行模板引擎,我们可以访问它的实例变量。它本质上与视图上下文的工作方式相同。这种“魔法”就是控制器的实例变量如何在视图和帮助程序中可用,以及为什么初学者最终会将它们与全局变量混淆。

    但是在其他情况下,例如装饰器或序列化器封装仍然适用。 @date = DateTime.now 仍然是控制器的实例变量,如果你想访问它,你需要使用 instance_variable_get 来违反封装:

    def initialize(view)
      @view = view
      @current_account = @view.current_account
      @date = @view.instance_variable_get(:'@date')
    end
    

    声明一个访问器:

    class UsersController
      attr_reader :date
    
      def index
        @date = DateTime.now #or date=DateTime.now
        respond_to do |format|
          format.html
          format.json { render json: UsersDatatable.new(view_context) }
        end
      end
    end
    
    class UsersDatatable
      def initialize(view)
        @view = view
        @current_account = @view.current_account
        @date = @view.date
      end
    end
    

    或者改变你的类的接口,这样它就不需要插入另一个对象。

    class UsersDatatable
      def initialize(view, date: nil)
        @view = view
        @current_account = @view.current_account
        @date = date
      end
    end
    

    【讨论】:

    • 非常感谢。我理解数据如何从控制器传递到模板引擎/视图的概念。为什么根据我的代码无法获得数据是由于封装的原因?我还没有尝试过声明访问器的方式,但是我使用会话参数来存储数据,并且可以在数据表类中访问它。这是个好方法吗?
    • 并非如此。会话主要用于跨请求存储数据。由于它存储在 cookie 中,因此您还必须非常小心以避免溢出,因为它的大小非常有限。在其他方面,它非常类似于使用全局变量。我会向初始化程序添加参数并显式传递数据。
    猜你喜欢
    • 2019-08-04
    • 1970-01-01
    • 2013-02-10
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    • 2018-09-29
    • 1970-01-01
    相关资源
    最近更新 更多