tags:

views:

63

answers:

2
def partial(template, *args)
  options = args.extract_options!
  options.merge!(:layout => false)
  if collection = options.delete(:collection) then
    collection.inject([]) do |buffer, member|
      buffer << erb(template, options.merge(:layout =>
      false, :locals => {template.to_sym => member}))
    end.join("\n")
  else
    erb(template, options)
  end
end

This method has no docs. It seems to be some way of letting you add additional features to partial rendering in an erb template.

How does this Ruby code work?

I don't care as much about the role this plays in a web framework. I just would like to understand what's going on in terms of Ruby syntax.

+2  A: 

It works much like doing render :partial in Rails — it takes a partial and a list of options (e.g. a collection of objects to render using the partial) and renders the partial with those options. Except this method appears to have ERb hardcoded in. If this is from Rails, I think this must be a very old method that isn't meant for use but hasn't yet been removed (maybe for compatibility with something or another).

The options.merge!(:layout => false) is effectively like doing options[:layout] = false.

options.delete(:collection) deletes the entry for ":collection" from the options hash and returns it if it exists. If there wasn't a collection entry, it returns nil, so the associated if-block won't run. If there is a collection, it renders the partial for each element of the collection and returns the accumulated result of rendering all of them. If there is not a collection, it just renders the partial with the options specified.

Chuck
Wow. What a great explanation. Thank you. Actually it's not for Rails. Someone wrote this as an extension for Sinatra because Sinatra has minimal features for partials. I just couldn't figure out what it was adding. But your explanation makes sense. I think the main feature is to be able to render multiple times for a collection - like maybe a collection of comments or orders. Just one question. You said "options.merge!(:layout => false) is effectively like doing options[:layout] = false." Does that mean it's always setting :layout to 'false'? Kind of like setting a default value to be re-set?
i_like_monkeys
Yes, it always sets options[:layout] to false, because you don't want a partial wrapped with a layout.
Chuck
Got it. Thanks again.
i_like_monkeys
A: 

To understand this, you need to understand the docs on these methods:

  • extract_options!
  • Enumerable/Array: merge, merge!, inject, join, delete

Once you understand those, there's nothing tricky about the syntax here. You should be able to read it straight through.

Something in particular?

ndp