antpaw antpaw - 1 month ago 16
Ruby Question

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}

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

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

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


I've tried the to do it this way: File.dirname(FILE)+"/../table/#{column.macro}/_#{column.display_type}.haml"))
.‌​render({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.‌​ 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

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
. But it already feels like the part where you grab the template and the render part is well separated.

Answer Source

Here is an example from one of my previous answers. It's extracted from PartialRenderer sources.

- local_names = [:i]
- partials = {}
- 1000.times do |i|
  - name = 'name_%s' % (i % 10)
  - partials[name] ||= lookup_context.find_template(name, lookup_context.prefixes, true, local_names)
  = partials[name].render(self, i: i)

I'd recommend you to wrap it with a helper method. Keep in mind that locals' names appear here twice: first in local_names as an array and second in hash's keys passed as the second argument of #render method.