开发者

Is that possible to call method that uses "content_tag" from controller in Rails 3?

In my Rails 3 application I use Ajax to get a formatted HTML:

$.get("/my/load_page?page=5", function(data) {
  alert(data);
});

class MyController < ApplicationController
  def load_page
    render :js => get_page(params[:page].to_i)
  end
end

get_page uses the content_tag method and should be available also in app/views/my/index.html.erb.

Since get_page u开发者_C百科ses many other methods, I encapsulated all the functionality in:

# lib/page_renderer.rb
module PageRenderer
  ...
  def get_page
    ...
  end
  ...
end

and included it like that:

# config/environment.rb
require 'page_renderer'

# app/controllers/my_controller.rb
class MyController < ApplicationController
  include PageRenderer
  helper_method :get_page
end

But, since the content_tag method isn't available in app/controllers/my_controller.rb, I got the following error:

undefined method `content_tag' for #<LoungeController:0x21486f0>

So, I tried to add:

module PageRenderer
  include ActionView::Helpers::TagHelper    
  ...
end

but then I got:

undefined method `output_buffer=' for #<LoungeController:0x21bded0>

What am I doing wrong ?

How would you solve this ?


To answer the proposed question, ActionView::Context defines the output_buffer method, to resolve the error simply include the relevant module:

module PageRenderer
 include ActionView::Helpers::TagHelper
 include ActionView::Context    
 ...
end


Helpers are really view code and aren't supposed to be used in controllers, which explains why it's so hard to make it happen.

Another (IMHO, better) way to do this would be to build a view or partial with the HTML that you want wrapped around the params[:page].to_i. Then, in your controller, you can use render_to_string to populate :js in the main render at the end of the load_page method. Then you can get rid of all that other stuff and it'll be quite a bit cleaner.

Incidentally, helper_method does the opposite of what you're trying to do - it makes a controller method available in the views.


If you don't want to include all of the cruft from those two included modules, another option is to call content_tag via ActionController::Base.helpers. Here's some code I recently used to achieve this, also utilizing safe_join:

helpers = ActionController::Base.helpers
code_reactions = user_code_reactions.group_by(&:code_reaction).inject([]) do |arr, (code_reaction, code_reactions_array)|
  arr << helpers.content_tag(:div, nil, class: "code_reaction_container") do
    helpers.safe_join([
      helpers.content_tag(:i, nil, class: "#{ code_reaction.fa_style } fa-#{ code_reaction.fa_icon }"),
      helpers.content_tag(:div, "Hello", class: "default_reaction_description"),
    ])
  end
end
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜