jonuts-merb-menus 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +8 -7
- data/lib/merb-menus/item.rb +32 -0
- data/lib/merb-menus/menu.rb +118 -0
- data/lib/merb-menus/merb_controller.rb +100 -0
- data/lib/merb-menus/merbtasks.rb +6 -0
- data/lib/merb-menus/rule.rb +39 -0
- data/lib/merb-menus/submenu.rb +45 -0
- data/lib/merb-menus/version.rb +10 -0
- data/lib/merb-menus.rb +51 -0
- metadata +12 -4
data/Rakefile
CHANGED
@@ -4,15 +4,16 @@ require 'rake/gempackagetask'
|
|
4
4
|
require 'merb-core'
|
5
5
|
require 'merb-core/tasks/merb'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
require File.dirname(__FILE__) + '/lib/merb-menus/version'
|
8
|
+
|
9
|
+
GEM_NAME = "merb-menus"
|
10
|
+
GEM_VERSION = Merb::Menus::VERSION
|
11
|
+
AUTHOR = "jonah honeyman"
|
12
|
+
EMAIL = "jonah@honeyman.org"
|
13
|
+
HOMEPAGE = "http://github.com/jonuts/merb-menus"
|
14
|
+
SUMMARY = "Merb plugin that provides dot dot dot uh menus"
|
13
15
|
|
14
16
|
spec = Gem::Specification.new do |s|
|
15
|
-
s.rubyforge_project = 'merb'
|
16
17
|
s.name = GEM_NAME
|
17
18
|
s.version = GEM_VERSION
|
18
19
|
s.platform = Gem::Platform::RUBY
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Merb::Menus
|
2
|
+
class Item
|
3
|
+
def initialize(opts)
|
4
|
+
@submenu = opts[:submenu]
|
5
|
+
@name = opts[:name]
|
6
|
+
@anchor = opts[:anchor] || build_anchor
|
7
|
+
@href = opts[:href] || build_url
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :name, :anchor, :href, :submenu
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
"<Merb::Menus::Item> - name~>#{name}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
anchor.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def build_url
|
23
|
+
submenu.url_generator.rule.call(@submenu.name,@name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_anchor
|
27
|
+
submenu.display_style.rule.call(@name)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Merb::Menus
|
2
|
+
|
3
|
+
# This is the top level menu
|
4
|
+
#
|
5
|
+
# ==== Usage
|
6
|
+
# Generate a menu in a controller:
|
7
|
+
#
|
8
|
+
# create_menu :main_menu do
|
9
|
+
# # add some display styles
|
10
|
+
# display_style(:splitncap) {|thing| thing.to_s.split("_").map{|e| e.capitalize}.join(" ")}
|
11
|
+
# display_style(:dollarify) {|thing| "$#{thing.to_s.gsub(/_/,',')}"}
|
12
|
+
# default_display_style :splitncap
|
13
|
+
#
|
14
|
+
# # define all of the submenus with their individual items
|
15
|
+
# submenu :videos do
|
16
|
+
# item :home, :url => '/videos'
|
17
|
+
#
|
18
|
+
# #this item will be generated with href '/videos/humor' and text 'Humor'
|
19
|
+
# item :humor
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# submenu :audio do
|
23
|
+
# display_style :dollarify
|
24
|
+
#
|
25
|
+
# item :home, :href => '/audio'
|
26
|
+
# item :humor, :anchor => "LOL!!!"
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
#
|
31
|
+
class Menu
|
32
|
+
extend Enumerable
|
33
|
+
|
34
|
+
class << self
|
35
|
+
attr_reader :collection
|
36
|
+
|
37
|
+
def each
|
38
|
+
@collection.each{|i| yield i}
|
39
|
+
end
|
40
|
+
|
41
|
+
def [](name)
|
42
|
+
find{|e| e.name == name}
|
43
|
+
end
|
44
|
+
|
45
|
+
def first
|
46
|
+
@collection.first
|
47
|
+
end
|
48
|
+
|
49
|
+
def reset
|
50
|
+
each{ |e| e.submenus.each{ |menu| menu.current_item = nil} ; e.current_submenu = nil}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
@collection ||= []
|
55
|
+
|
56
|
+
def initialize(name, is_default=false)
|
57
|
+
@name = name
|
58
|
+
@is_default = is_default
|
59
|
+
@submenus = []
|
60
|
+
create_default_rules
|
61
|
+
use_display_style :default
|
62
|
+
use_url_generator :default
|
63
|
+
add_self_to_collection
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_accessor :current_submenu, :default_display_style, :default_url_generator
|
67
|
+
attr_reader :name, :submenus
|
68
|
+
|
69
|
+
def submenu(name, opts={}, &blk)
|
70
|
+
submenu = Submenu.new(name, self, opts)
|
71
|
+
submenu.instance_eval(&blk)
|
72
|
+
@submenus << submenu
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
def display_style(key, &rule)
|
77
|
+
DisplayStyle.add_rule(key, self, &rule)
|
78
|
+
end
|
79
|
+
|
80
|
+
def url_generator(key, &rule)
|
81
|
+
UrlGenerator.add_rule(key, self, &rule)
|
82
|
+
end
|
83
|
+
|
84
|
+
def use_display_style(rule)
|
85
|
+
self.default_display_style = DisplayStyle[rule]
|
86
|
+
end
|
87
|
+
|
88
|
+
def use_url_generator(rule)
|
89
|
+
self.default_url_generator = UrlGenerator[rule]
|
90
|
+
end
|
91
|
+
|
92
|
+
def default?
|
93
|
+
@is_default
|
94
|
+
end
|
95
|
+
|
96
|
+
def inspect
|
97
|
+
"Merb::Menus::Menu - name~>#{self.name} - submenus~>[#{submenus.map{|e| e.name}.join(", ")}]"
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_s
|
101
|
+
name.to_s
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def add_self_to_collection
|
107
|
+
Menu.collection << self unless Menu[name]
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
def create_default_rules
|
112
|
+
display_style(:default){|thing| thing.to_s}
|
113
|
+
url_generator(:default){|menu, item| "/#{menu}/#{item}"}
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
class Merb::Controller
|
2
|
+
before do
|
3
|
+
Merb::Menus.reset
|
4
|
+
|
5
|
+
controller = params[:controller]
|
6
|
+
action = params[:action]
|
7
|
+
|
8
|
+
if top = Merb::Menus.current_menu = Merb::Menus.default
|
9
|
+
if menu = top.current_submenu = get_submenu(top,controller)
|
10
|
+
menu.current_item = get_item(menu,action)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
callback = self.class.instance_variable_get(:@callback)
|
15
|
+
callback.call if callback
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.create_menu(name, &blk)
|
19
|
+
Merb::Menus::Menu.new(name).instance_eval(&blk)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.set_current
|
23
|
+
end
|
24
|
+
|
25
|
+
# FIXME: if only one arg is given, we probably want to set submenu only? maybe? grr
|
26
|
+
def self.use_menu(*args)
|
27
|
+
@callback = lambda{
|
28
|
+
menu, submenu = *args
|
29
|
+
top = Merb::Menus[menu]
|
30
|
+
Merb::Menus.current_menu = top
|
31
|
+
raise Merb::Menus::NoMenuError.new("Menu '#{menu}' does not exist") unless top
|
32
|
+
|
33
|
+
if submenu
|
34
|
+
top.current_submenu = get_submenu(top, submenu)
|
35
|
+
raise Merb::Menus::NoMenuError.new("Menu '#{submenu}' does not exist") unless top.current_submenu
|
36
|
+
end
|
37
|
+
}
|
38
|
+
@callback.call
|
39
|
+
end
|
40
|
+
|
41
|
+
# ==== Parameters
|
42
|
+
# top<Merb::Menus::Menu>::
|
43
|
+
# sub<Symbol>:: name of desired submenu
|
44
|
+
def self.get_submenu(top, sub)
|
45
|
+
top.submenus.find {|m| m.name.to_s == sub.to_s}
|
46
|
+
end
|
47
|
+
|
48
|
+
# ==== Parameters
|
49
|
+
# menu<Merb::Menus::Submenu>::
|
50
|
+
# item<Symbol>:: name of desired item
|
51
|
+
def self.get_item(menu, item)
|
52
|
+
menu.items.find{|e| e.name.to_s == item.to_s}
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_submenu(top, sub)
|
56
|
+
self.class.get_submenu(top, sub)
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_item(menu, item)
|
60
|
+
self.class.get_item(menu, item)
|
61
|
+
end
|
62
|
+
|
63
|
+
def menu_item(*args)
|
64
|
+
case args.size
|
65
|
+
when 3
|
66
|
+
menu, submenu, item = *args
|
67
|
+
self.class.use_menu(menu, submenu)
|
68
|
+
top = Merb::Menus[menu]
|
69
|
+
menu = get_submenu(top,submenu)
|
70
|
+
menu.current_item = get_item(menu,item)
|
71
|
+
when 2
|
72
|
+
submenu, item = *args
|
73
|
+
top = Merb::Menus.default
|
74
|
+
self.class.use_menu(top.name,submenu)
|
75
|
+
menu = get_submenu(top,submenu)
|
76
|
+
menu.current_item = get_item(menu,item)
|
77
|
+
when 1
|
78
|
+
item = *args
|
79
|
+
top = Merb::Menus.default
|
80
|
+
menu = top.current_submenu
|
81
|
+
menu.current_item = get_item(menu,item)
|
82
|
+
else
|
83
|
+
raise ArgumentError.new("Wrong number of arguments given (#{args.size} for 1)")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def current_menu
|
88
|
+
Merb::Menus.current_menu
|
89
|
+
end
|
90
|
+
|
91
|
+
def current_submenu
|
92
|
+
Merb::Menus.current_submenu
|
93
|
+
end
|
94
|
+
|
95
|
+
def current_item
|
96
|
+
Merb::Menus.current_item
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Merb::Menus
|
2
|
+
class Rule
|
3
|
+
extend Enumerable
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_reader :collection
|
7
|
+
|
8
|
+
def add_rule(key, owner, &rule)
|
9
|
+
return nil unless block_given? and unique?(key, owner)
|
10
|
+
@collection << new(key, &rule)
|
11
|
+
end
|
12
|
+
|
13
|
+
def each
|
14
|
+
@collection.each{|i| yield i}
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](key)
|
18
|
+
find{|rule| rule.key == key}
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def unique?(key, owner)
|
24
|
+
!find{|rule| rule.key == key && rule.owner == owner}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(key, &rule)
|
29
|
+
@key = key
|
30
|
+
@rule = rule
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :key, :rule, :owner
|
34
|
+
end
|
35
|
+
|
36
|
+
class UrlGenerator < Rule; @collection ||= []; end
|
37
|
+
class DisplayStyle < Rule; @collection ||= []; end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Merb::Menus
|
2
|
+
class Submenu
|
3
|
+
def initialize(name, menu, opts={})
|
4
|
+
@name = name
|
5
|
+
@menu = menu
|
6
|
+
@display_style = @menu.default_display_style
|
7
|
+
@url_generator = @menu.default_url_generator
|
8
|
+
@details = Item.new(opts.merge({:name => name, :submenu => self}))
|
9
|
+
@items = []
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_accessor :current_item
|
13
|
+
attr_reader :name, :items, :menu, :display_style, :url_generator
|
14
|
+
|
15
|
+
def anchor
|
16
|
+
@details.anchor
|
17
|
+
end
|
18
|
+
|
19
|
+
def href
|
20
|
+
@details.href
|
21
|
+
end
|
22
|
+
|
23
|
+
def item(name, opts={})
|
24
|
+
@items << Item.new(opts.merge({:name => name, :submenu => self}))
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def use_display_style(name)
|
29
|
+
@display_style = DisplayStyle[name]
|
30
|
+
end
|
31
|
+
|
32
|
+
def use_url_generator(name)
|
33
|
+
@url_generator = UrlGenerator[name]
|
34
|
+
end
|
35
|
+
|
36
|
+
def inspect
|
37
|
+
"Merb::Menus::Submenu - name~>#{name} - items~>[#{items.map{|e| e.name}.join(", ")}]"
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
anchor
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
data/lib/merb-menus.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# make sure we're running inside Merb
|
2
|
+
if defined?(Merb::Plugins)
|
3
|
+
# Merb gives you a Merb::Plugins.config hash...feel free to put your stuff in your piece of it
|
4
|
+
Merb::Plugins.config[:merb_menus] = {
|
5
|
+
:chickens => false
|
6
|
+
}
|
7
|
+
|
8
|
+
Merb::BootLoader.before_app_loads do
|
9
|
+
$:.push File.dirname(__FILE__)
|
10
|
+
|
11
|
+
require 'merb-menus/merb_controller'
|
12
|
+
require 'merb-menus/rule'
|
13
|
+
require 'merb-menus/menu'
|
14
|
+
require 'merb-menus/submenu'
|
15
|
+
require 'merb-menus/item'
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
Merb::BootLoader.after_app_loads do
|
20
|
+
end
|
21
|
+
|
22
|
+
Merb::Plugins.add_rakefiles "merb-menus/merbtasks"
|
23
|
+
|
24
|
+
module Merb::Menus
|
25
|
+
class << self; attr_accessor :current_menu; end
|
26
|
+
|
27
|
+
class NoMenuError < StandardError;end
|
28
|
+
|
29
|
+
def self.[](menu)
|
30
|
+
Menu[menu]
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.default
|
34
|
+
Menu.find{|menu| menu.default?} || Menu.first
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.reset
|
38
|
+
Menu.reset
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.current_submenu
|
42
|
+
current_menu.current_submenu rescue nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.current_item
|
46
|
+
current_submenu.current_item rescue nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jonuts-merb-menus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jonah honeyman
|
@@ -9,11 +9,11 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-05-
|
12
|
+
date: 2009-05-06 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description: Merb plugin that provides dot dot dot
|
16
|
+
description: Merb plugin that provides dot dot dot uh menus!
|
17
17
|
email: jonah@honeyman.org
|
18
18
|
executables: []
|
19
19
|
|
@@ -22,6 +22,14 @@ extensions: []
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
+
- lib/merb-menus.rb
|
26
|
+
- lib/merb-menus/item.rb
|
27
|
+
- lib/merb-menus/menu.rb
|
28
|
+
- lib/merb-menus/merb_controller.rb
|
29
|
+
- lib/merb-menus/merbtasks.rb
|
30
|
+
- lib/merb-menus/rule.rb
|
31
|
+
- lib/merb-menus/submenu.rb
|
32
|
+
- lib/merb-menus/version.rb
|
25
33
|
- LICENSE
|
26
34
|
- README
|
27
35
|
- Rakefile
|
@@ -53,6 +61,6 @@ rubyforge_project:
|
|
53
61
|
rubygems_version: 1.2.0
|
54
62
|
signing_key:
|
55
63
|
specification_version: 2
|
56
|
-
summary: Merb plugin that provides dot dot dot
|
64
|
+
summary: Merb plugin that provides dot dot dot uh menus!
|
57
65
|
test_files: []
|
58
66
|
|