Reputation: 5382
Using RoR, I would like a helper to write a table of contents menu where root sections are dropdown menus for their subsections. In an each/do loop I would need to check if a section has subsections before outputting class="dropdown"
on li and class="dropdown-toggle" data-toggle="dropdown"
on the link.
Is there a way to check the properties of the next item (if any) in an each/do loop? Or do I need to switch to a loop with an index?
Here's my table of contents helper as is.
def showToc(standard)
html = ''
fetch_all_sections(standard).each do |section|
html << "<li>" << link_to("<i class=\"icon-chevron-right\"></i>".html_safe + raw(section[:sortlabel]) + " " + raw(section[:title]), '#s' + section[:id].to_s) << "</li>"
end
end
return html.html_safe
end
Upvotes: 0
Views: 149
Reputation: 67900
You can use the abstraction Enumerable#each_cons. An example:
>> xs = [:a, :b, :c]
>> (xs + [nil]).each_cons(2) { |x, xnext| p [x, xnext] }
[:a, :b]
[:b, :c]
[:c, nil]
That said, note your code is full of unidiomatic Ruby, you should probably post it to https://codereview.stackexchange.com/ for review.
Upvotes: 2
Reputation: 5382
I found a way to have class="dropdown"
on the <li>
and class="dropdown-toggle" data-toggle="dropdown"
on the link not affect the anchor tag. Therefore, in this case, I can just check if section depth is 0 and act accordingly. The other answers are probably more relevant to most people but here's what worked for me.
def showToc(standard, page_type, section = nil, nav2section = false, title = nil, wtf=nil)
html = ''
new_root = true
fetch_all_sections(standard).each do |section|
if section[:depth] == 0
if !new_root
# end subsection ul and root section li
html << "</li>\n</ul>"
new_root = true
end
html << "<li class=\"dropdown\">" << link_to("<i class=\"icon-chevron-right\"></i>".html_safe + raw(section[:sortlabel]) + " " + raw(section[:title]), '#s' + section[:id].to_s, :class => "dropdown-toggle", :data => {:toggle=>"dropdown"})
else
# write ul if new root
if new_root
new_root = false
html << "<ul class=\"dropdown-menu\">\n" << "<li>" << link_to(raw(section[:sortlabel]) + " " + raw(section[:title]), '#s' + section[:id].to_s) << "</li>"
else
html << "<li>" << link_to(raw(section[:sortlabel]) + " " + raw(section[:title]), '#s' + section[:id].to_s) << "</li>"
end
end
end
return html.html_safe
end
Upvotes: 0
Reputation: 731
If i'm reading your question correctly -- lets say fetch_all_sections(standard) returns an enumerable, such as Array, you could add a custom iterator to get what you want:
class Array
#yields |current, next|
def each_and_next
@index ||= 0
yield [self[@index], self[@index +=1]] until (@index == self.size)
@index = 0
end
end
p.s. I like @tokland's inline answer
a = [1,2,3,4]
a.each_and_next { |x,y| puts "#{x},#{y}" }
produces:
1,2
2,3
3,4
4,
Upvotes: 0