Skip to content
Browse files

tweaks to support :if conditions via proc objects - conditions can no…

…w apply to an entire menu or just a single item
  • Loading branch information...
1 parent 26bafea commit 98baef3a21caa51468f7ce87ab87b2adbdf61af3 Ryan Heath committed Oct 15, 2009
Showing with 35 additions and 9 deletions.
  1. +3 −1 lib/navigation.rb
  2. +4 −2 lib/navigation/builder.rb
  3. +3 −2 lib/navigation/menu.rb
  4. +25 −4 lib/navigation/navigator.rb
View
4 lib/navigation.rb
@@ -16,7 +16,9 @@ module Helpers
def navigation(key, options = {})
options.merge!(:view => self)
navigator = Navigator.new(key, options)
- content_tag(:ul, navigator.links, options.merge!(:class => navigator.css_class))
+ if navigator.allowed?
+ content_tag(:ul, navigator.links, options.merge!(:class => navigator.css_class))
+ end
end
end
end
View
6 lib/navigation/builder.rb
@@ -17,9 +17,11 @@ def self.config
# accepts a name/key, and yields
# a Menu instance to the block
- def define(name, action_level = false)
+ def define(*args)
+ name, options = args.first, args.extract_options!
+
raise InvalidMenuDefinition, InvalidMenuDefinition.message if name.blank?
- yield Menu.new(normalize(name), action_level)
+ yield Menu.new(normalize(name), options)
end
end
end
View
5 lib/navigation/menu.rb
@@ -3,9 +3,10 @@ module Navigation
# handles adding items
# to a specific menu
class Menu < Base
- def initialize(name, action_level)
+ def initialize(name, options = {})
@name = name
- (MENUS[@name] = ActiveSupport::OrderedHash.new).merge!(:action_level => action_level)
+ (MENUS[@name] = ActiveSupport::OrderedHash.new).merge!(
+ :action_menu => options[:action_menu], :if => options[:if])
end
def item(key, options = {}, &block)
View
29 lib/navigation/navigator.rb
@@ -20,7 +20,15 @@ def initialize(name, options)
# support building separate menus for actions,
# without forcing it to be nested
- @action_level = MENUS[@name].delete(:action_level)
+ @action_menu = MENUS[@name][:action_menu]
+
+ # menus can be shown/hidden based on
+ # conditions by passing a Proc object
+ # Ex:
+ # navigation.define :primary, :if => Proc.new { |c| c.logged_in? } do |menu|
+ # ...
+ # end
+ @proc = MENUS[@name][:if]
end
# the css class of the
@@ -34,11 +42,22 @@ def css_class
def links
construct_html(self.items)
end
+
+ def allowed?
+ execute_proc @proc
+ end
protected
+ # calls a proc and hands it
+ # the controller isntance
+ def execute_proc(proc)
+ return true unless proc.is_a?(Proc)
+ proc.call(self.view.controller)
+ end
+
# convenience method
def items
- MENUS[@name]
+ MENUS[@name].except(:action_menu, :if)
end
# checks to make sure the menu
@@ -53,6 +72,8 @@ def construct_html(menu, nested = false)
return if menu.blank?
links = menu.inject([]) do |items, (item, opts)|
+ next(items) unless execute_proc(opts[:if])
+
text, path, attrs = self.disect(item, opts)
subnav = construct_html(menu[item][SUBMENU], true).to_s
attrs.merge!(:class => [attrs[:class], self.current_css(item, nested)].compact.join(' '))
@@ -65,7 +86,7 @@ def construct_html(menu, nested = false)
# determines if the menu item matches the current section
# (considers both levels: controller and action)
def current_css(item, nested = false)
- name = nested || @action_level ? self.view.action_name : self.view.controller_name
+ name = nested || @action_menu ? self.view.action_name : self.view.controller_name
'current' if normalize(name) == normalize(item)
end
@@ -76,7 +97,7 @@ def disect(item, opts)
path = self.view.send(opts.delete(:path) || "#{item.to_s.underscore}_path" || :root_path)
text = opts.delete(:text) || item.to_s.titleize
- attrs = opts.except(SUBMENU)
+ attrs = opts.except(SUBMENU, :if)
[text, path, attrs]
end

0 comments on commit 98baef3

Please sign in to comment.
Something went wrong with that request. Please try again.