Skip to content

Instantly share code, notes, and snippets.

@pigoz
Created August 6, 2012 17:24
Show Gist options
  • Save pigoz/3276913 to your computer and use it in GitHub Desktop.
Save pigoz/3276913 to your computer and use it in GitHub Desktop.
composite-pattern-navigation menu
module ApplicationHelper
## ..snip
def build_taxon_subtree(root)
tree = Navigation::Tree("#{root.permalink}", root.name)
Spree::Taxon.where(:parent_id => root.id).all.each do |taxon|
count = Spree::Taxon.where(:parent_id => taxon.id).count
if count > 0
tree.add(build_taxon_subtree(taxon))
else
tree.add_leaf(taxon.name, seo_url(taxon))
end
end
tree
end
def navigation_tree
root_catalogue, root_categories = \
[Config::TAXONS[:catalogue], Config::TAXONS[:categories]].map do |ident|
Spree::Taxon.find_by_permalink!(ident)
end
Navigation::Root("main-menu").tap {|t|
t.add_leaf t('navbar.home'), root_path
Spree::Taxon.where(:parent_id => root_categories.id).all.each do |taxon|
t.add_leaf taxon.name, seo_url(taxon)
end
t.add build_taxon_subtree(root_catalogue)
t.add_leaf t('navbar.digital_store'), '/cms/digital_store'
t.add_leaf t('navbar.bookshop'), "/cms/bookshop"
t.add_leaf t('navbar.club'), "/cms/club"
t.add_leaf t('navbar.exibitions'), "/cms/exibitions", "separated"
t.add_leaf t('navbar.partners'), "/cms/partners", "separated"
t.add_leaf t('navbar.contact_us'), "/cms/contact_us", "separated"
}
end
end
module Navigation
class << self
def Root(id)
Tree.new(id)
end
def Tree(id, label)
SubTree.new(id, label)
end
end
module ComponentsFactoryMethods
def add(tree)
self << tree
self
end
def add_leaf(*args)
self << Leaf.new(*args)
self
end
end
class Component < DelegateClass(Array)
def initialize
super([])
end
def render
raise NotImplementedError.new("subclass me!")
end
end
class Composite < Component
def render_children(context)
self.inject("") {|memo, n| memo << n.render(context)}
end
end
class Leaf < Component
attr_reader :title, :url, :type
def initialize(title, url, type='normal')
super()
@title, @url, @type = title, url, type
end
def render(context)
context.render(:partial => "shared/nav_leaf", :locals => { leaf: self })
end
end
class Tree < Composite
include ComponentsFactoryMethods
attr_accessor :id
def initialize(id=nil)
super()
@id = id
end
def render(context)
context.render(:partial => partial, :locals => { :tree => self })
end
def partial
"shared/nav_tree"
end
end
class SubTree < Tree
include ComponentsFactoryMethods
attr_reader :title
def initialize(id, title)
super(id)
@title = title
end
def partial
"shared/nav_sub_tree"
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment