Skip to content

Instantly share code, notes, and snippets.

@geekq
Created December 22, 2009 17:07
Show Gist options
  • Save geekq/261862 to your computer and use it in GitHub Desktop.
Save geekq/261862 to your computer and use it in GitHub Desktop.
# Check the impact of Nokogiri builder / HAML engine caching
require 'benchmark'
require 'sinatra-nokogiri-menu.rb'
require 'haml'
def render_with_haml(current = nil)
@engine ||= Haml::Engine.new <<here
%ul
- MENU_ITEMS.each do |item|
- opts = {}
- item, check_proc = *item if item.is_a?(Array)
- if check_proc.nil? or check_proc.call
- if current.to_s == item.to_s
%li{:class => 'current_item'}
= item.to_s
- else
%li= item.to_s
%li world
here
@engine.render(Object.new, :current => current)
end
# doc.li item.to_s, opts
puts render_with_haml(:contact)
puts
puts "Compare different approaches running 1000 times:\n"
Benchmark.bm(30) do |b|
b.report('Nokogiri, singleton builder') do
1000.times{ main_menu(:contact) }
end
b.report('Nokogiri, recreate builder') do
1000.times{ main_menu(:contact); @main_menu_builder = nil }
end
b.report('HAML, singleton engine') do
1000.times{ render_with_haml(:contact) }
end
b.report('HAML, recreate engine') do
1000.times{ render_with_haml(:contact); @engine = nil }
end
end
# Generates a menu for your web site.
# Features:
# * current menu item highlighting
# * dynamic list of menu items, based on your application logic,
# controlled by user provided procs
require 'rubygems'
require 'nokogiri'
# current_user is mocked here, use you real implementation instead
current_user = Object.new
def current_user.has_role?(role); false; end
def current_user.is_admin?; true; end
MENU_ITEMS = [
:orders,
[:customers, Proc.new {current_user.has_role?(:supervisor)}],
[:admin, Proc.new {current_user.is_admin?}],
:contact
]
def main_menu(current=nil)
@main_menu_builder ||= Nokogiri::HTML::Builder.new do |doc|
doc.ul {
MENU_ITEMS.each do |item|
opts = {}
item, check_proc = *item if item.is_a?(Array)
opts[:class] = 'current_item' if current.to_s == item.to_s
doc.li item.to_s, opts if check_proc.nil? or check_proc.call
end
}
end
@main_menu_builder.doc.inner_html
end
puts main_menu(:contact)
# generates:
# <ul>
# <li>orders</li>
# <li>admin</li>
# <li class="current_item">contact</li>
# </ul>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment