渲染前调用函数

时间:2011-08-10 17:01:26

标签: ruby-on-rails

我想在每次收到ajax请求时替换一组div(我正在处理的网站是完整的ajax ......)。例如,它可能是检查收件箱中的邮件数量,或显示用户统计信息......

问题是我不想在我的代码中多次重复这个对渲染函数的调用。

我试图在before_filter中调用我的函数,但是因为我调用了render:update,所以它第二次不起作用。

我尝试在application_controller中创建自己的函数render_page:

def render_page
  render :update do |page|
    yield(page)
    # page.replace_html :div, ...
  end
end

但不知怎的,上下文似乎丢失了:当我在控制器的函数上调用render_page时,我无法访问辅助函数......

谢谢!

1 个答案:

答案 0 :(得分:2)

发现它!

我在rails文档中挖掘了一些ruby,以了解render:update函数的工作原理。

首先,我看到了渲染:更新只是通过发送代码块来调用update_page ...

http://api.rubyonrails.org/classes/ActionView/Helpers/PrototypeHelper.html#method-i-update_page

此函数通过发送view_context(它只是ActionView :: Base的实例)来调用JavaScriptGenerator的构造函数。

JavaScriptGenerator.new(view_context, &block).to_s.html_safe

http://apidock.com/rails/ActionView/Helpers/PrototypeHelper/JavaScriptGenerator/new/class

在JavaScriptGenerator的构造函数中,我们可以观察

def initialize(context, &block) #:nodoc:
  @context, @lines = context, []
  include_helpers_from_context
  @context.with_output_buffer(@lines) do
    @context.instance_exec(self, &block)
  end
end

instance_exec是一个ruby函数,允许在上下文中调用一个块......这正是我所需要的。

所以,解决方案(或至少一个工作解决方案......)是在application_controller中定义render_page:

def render_page(&block)
  render :update do |page|
    page << 'console.log("before_code");'
    self.instance_exec(page, &block)
    page << 'console.log("after_code");'
  end
end

这样,而不是在我的控制器中调用

render :update do |page|
  page.replace_html ...
  helper_functions...
end

我打电话

render_page do |page|
  page.replace_html ...
  helper_functions...
end

我仍然可以调用我的辅助函数(因为已经传递了上下文)...