开发者

Call function before render

开发者 https://www.devze.com 2023-03-27 17:55 出处:网络
I would like to replace a set of div each time I receive an ajax request (the website I am working on is full ajax...). For example, it could be checking the number of messages in an inbox, or display

I would like to replace a set of div each time I receive an ajax request (the website I am working on is full ajax...). For example, it could be checking the number of messages in an inbox, or displaying user statistics...

The thing is I don't wan't to repeat this call to my rendering function many times in my code.

I tried to call my function in before_filter, but since I call render :update, it doesn't work the second time.

I tried to create my own function render_page in application_controller :

def render_page
  render :update do |page|
    yield(page)
  开发者_运维问答  # page.replace_html :div, ...
  end
end

But somehow the context seem to be lost : when i call render_page on a controller's function, I can't access helper functions...

Thanks !


Found it !

I dug a little into the ruby on rails documentation to find out how the render :update function works.

First, I saw that render :update was simply calling update_page by sending the code block...

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

And this function is calling the constructor of JavaScriptGenerator by sending view_context (which is simply the instance of ActionView::Base).

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

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

And in the constructor of JavaScriptGenerator, we can observe

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 is a ruby function that allows to call a block within a context... That was exactly what I needed.

So, the solution (or at least one working solution...) is to define render_page in application_controller :

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

This way, instead of calling in my controllers

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

I call

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

And I am still allowed to call my helper functions (since the context has been passed)...

0

精彩评论

暂无评论...
验证码 换一张
取 消