Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a partial to method/block for speed

I have a loop that renders a partial

1000.times do |i|
  render partial: 'test', locals: {i: i}
end

this is really slow, up to 0.1 ms for foreach render call, even if the partial only prints out i

my_partial = render_to_method(partial: 'test')
1000.times do |i|
  my_partial(locals: {i: i})
end

Now this should be doing the same thing way faster right? But I don't know how to do this.

update:

I've tried the to do it this way:

Haml::Engine.new(File.read(File.expand_path File.dirname(FILE)+"/../table/#{column.macro}/_#{column.display_type}.haml"))
.‌​render(OpenStruct.new({column_value: column_value, object: object})) 

two major drawbacks:

  • The path to the views will not watch for fallbacks like it does when you do it with render (parital: 'partial' will look for the parital in the current view dir, in some gems and also in the view/application.
  • The Rails view helpers aren't available any more

update 2:

Many of the answers try to solve the problem by using other techniques. I my real application this techniques can't be applied. https://github.com/antpaw/bhf/blob/master/app/views/bhf/pages/_platform.haml#L54‌​ mainly because this line is a dynamic string that sometimes links to partials that don't even exsist in the gem and are defined in the main_app. I wonder why it's so hard to do something that is so basic: 1. grab the view. 2. render it. (3. render it again.)

update 3:

@Flash Gordon suggested this https://gist.github.com/antpaw/d6670c23d6f08e35812e#file-gistfile1-haml-L54

template = lookup_context.find_template "#{column.macro}/#{column.display_type}", ['bhf/table'], true
template.render(self, {column_value: column_value, object: object})

it almost works just having some troubles with locals. But it already feels like the part where you grab the template and the render part is well separated.

like image 206
antpaw Avatar asked Jun 16 '14 07:06

antpaw


Video Answer


1 Answers

I love this question, but it may be a "wrong tool for the job" thing

Basically:

  1. if the partial is simple - consider not using a partial at all, the overhead isn't worth it
  2. if the partial is complex - then rendering 1000s of things will take TIME out of which partial overhead is just a fraction of, you'll need a plan B

Plan Bs:

  1. render 25-50-100.... thingies at first and fetch additional records from the server as the user scrolls - http://railscasts.com/episodes/114-endless-page
  2. send a JSON array from the server and let client side JS iterate through the collection and render HTML - this way the partial template can still be rendered in rails and client side JS can do gsub
  3. cache everything you possibly can - this doesn't include forms unfortunately which are typically the slowest rendering components
  4. ...

PS have you tried out cells? https://github.com/apotonick/cells

like image 64
bbozo Avatar answered Sep 23 '22 23:09

bbozo