Created
July 22, 2011 01:12
-
-
Save joseph/1098634 to your computer and use it in GitHub Desktop.
blocks_for helper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Iterates over an array and creates a bunch of "blocks" containing the | |
# yielded content. Example: | |
# | |
# <% urls = [ | |
# "http://inventivelabs.com.au", | |
# "http://booki.sh", | |
# "http://nomify.com", | |
# "http://rungs.com.au", | |
# "http://getslipcase.com" | |
# ] %> | |
# <% blocks_for(urls, 2) do |url, pos| %> | |
# <%= link_to(url, url) %> | |
# <% end %> | |
# | |
# ... produces ... | |
# | |
# <div class="block_first"> | |
# <a href="http://inventivelabs.com.au">http://inventivelabs.com.au</a> | |
# <a href="http://booki.sh">http://booki.sh</a> | |
# </div> | |
# <div> | |
# <a href="http://nomify.com">http://nomify.com</a> | |
# <a href="http://rungs.com.au">http://rungs.com.au</a> | |
# </div> | |
# <div class="block_last"> | |
# <a href="http://getslipcase.com">http://getslipcase.com</a> | |
# </div> | |
# | |
# | |
# Options: | |
# | |
# - :block_tag (defaults to "div") | |
# - :first_block_class (defaults to "block_first") | |
# - :last_block_class (defaults to "block_last") | |
# | |
# All other options are passed directly to block tag. | |
# | |
# Yielded to block: | |
# | |
# |obj, pos, index| | |
# | |
# ... where 'pos' is an object you can interrogate like this: | |
# | |
# pos.first? -> true if first object in the block | |
# pos.last? -> true if the per-block-th object in the block | |
# pos.middle? -> true if not first or last object in the block | |
# | |
# Not that if per-block is say, 6, and the array is 20 items long, the | |
# last block will contain 2 objects -- no object will have pos.last? in | |
# this block. | |
# | |
def blocks_for(array, per_block, options = {}, &blk) | |
options = options.with_indifferent_access | |
block_tag = options.delete(:block_tag) || "div" | |
first_class = options.delete(:first_block_class) || "block_first" | |
first_class += " #{options[:class]}" | |
last_class = options.delete(:last_block_class) || "block_last" | |
last_class += " #{options[:class]}" | |
blocks = [] | |
bits = [] | |
new_block = lambda { |cursor| | |
opts = options | |
if cursor < per_block | |
opts = opts.merge(:class => first_class.strip) | |
elsif cursor > (array.size - per_block) | |
opts = opts.merge(:class => last_class.strip) | |
end | |
blocks << content_tag(block_tag, bits.join("\n"), opts) | |
bits = [] | |
} | |
array.each_with_index { |obj, i| | |
mod_i = i % per_block | |
pos = ActiveSupport::StringInquirer.new( | |
mod_i == 0 ? "first" : mod_i == per_block - 1 ? "last" : "middle" | |
) | |
bits << capture(obj, pos, mod_i, &blk) | |
new_block.call(i) if pos.last? | |
} | |
new_block.call(array.size - 1) if bits.any? | |
concat(blocks.join("\n")) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment