Rails view_context

Rails view_context

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

中获取参考

我不明白的是如何访问传递到数据表 class 的 view_context 的内容。

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

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

  def initialize(view)
    @view = view
  end

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

  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

理解视图上下文的关键实际上是查看像 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 的界面,这样它就不需要戳入另一个对象的内部。

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