menu_helper 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README +108 -0
- data/Rakefile +79 -0
- data/init.rb +1 -0
- data/lib/menu_helper/html_element.rb +48 -0
- data/lib/menu_helper/menu.rb +101 -0
- data/lib/menu_helper/menu_bar.rb +142 -0
- data/lib/menu_helper.rb +78 -0
- data/test/app_root/app/controllers/about_us_controller.rb +2 -0
- data/test/app_root/app/controllers/contact_controller.rb +2 -0
- data/test/app_root/app/controllers/home_controller.rb +2 -0
- data/test/app_root/config/routes.rb +15 -0
- data/test/test_helper.rb +18 -0
- data/test/unit/html_element_test.rb +50 -0
- data/test/unit/menu_bar_test.rb +60 -0
- data/test/unit/menu_helper_test.rb +30 -0
- data/test/unit/menu_test.rb +172 -0
- metadata +71 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2006-2007 Aaron Pfeifer & Neil Abraham
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
= menu_helper
|
2
|
+
|
3
|
+
menu_helper adds a helper method for generating a menubar.
|
4
|
+
|
5
|
+
== Resources
|
6
|
+
|
7
|
+
API
|
8
|
+
|
9
|
+
* http://api.pluginaweek.org/menu_helper
|
10
|
+
|
11
|
+
Wiki
|
12
|
+
|
13
|
+
* http://wiki.pluginaweek.org/Menu_helper
|
14
|
+
|
15
|
+
Announcement
|
16
|
+
|
17
|
+
* http://www.pluginaweek.org/
|
18
|
+
|
19
|
+
Source
|
20
|
+
|
21
|
+
* http://svn.pluginaweek.org/trunk/plugins/action_pack/menu_helper
|
22
|
+
|
23
|
+
Development
|
24
|
+
|
25
|
+
* http://dev.pluginaweek.org/browser/trunk/plugins/action_pack/menu_helper
|
26
|
+
|
27
|
+
== Description
|
28
|
+
|
29
|
+
The generation of a menubar's structure can often be a repetitive and unDRY
|
30
|
+
process. A standard using unordered lists is generally followed when creating
|
31
|
+
a menubar. menu_helper attempts to following this standard in addition to
|
32
|
+
automatically adding ids, classes for selected menus, and default urls each
|
33
|
+
menu is linked to (base on various information, such as the name of the menu).
|
34
|
+
|
35
|
+
== Example
|
36
|
+
|
37
|
+
routes.rb:
|
38
|
+
ActionController::Routing::Routes.draw do |map|
|
39
|
+
map.with_options(:controller => 'site') do |site|
|
40
|
+
site.home '', :action => 'index'
|
41
|
+
end
|
42
|
+
|
43
|
+
map.with_options(:controller => 'about_us') do |about_us|
|
44
|
+
about_us.about_us 'about_us', :action => 'index'
|
45
|
+
about_us.contact 'about_us/contact', :action => 'contact'
|
46
|
+
about_us.who_we_are 'about_us/who_we_are', :action => 'who_we_are'
|
47
|
+
end
|
48
|
+
|
49
|
+
map.with_options(:controller => 'products') do |products|
|
50
|
+
products.products 'products', :action => 'index'
|
51
|
+
end
|
52
|
+
|
53
|
+
map.with_options(:controller => 'services') do |services|
|
54
|
+
services.services 'services', :action => 'index'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
_menubar.rhtml:
|
59
|
+
<%=
|
60
|
+
menu_bar do |main|
|
61
|
+
main.menu :home
|
62
|
+
main.menu :products
|
63
|
+
main.menu :services
|
64
|
+
main.menu :about_us do |about_us|
|
65
|
+
about_us.menu :overview, 'Overview', about_us_url
|
66
|
+
about_us.menu :who_we_are
|
67
|
+
about_us.menu :contact, 'Contact Us'
|
68
|
+
end
|
69
|
+
main.menu :search, 'Search!', 'http://www.google.com', :class => 'ir'
|
70
|
+
end
|
71
|
+
%>
|
72
|
+
|
73
|
+
Output (formatted for sanity):
|
74
|
+
<ul id="menubar">
|
75
|
+
<li id="home"><a href="http://example.com/">Home</a></li>
|
76
|
+
<li id="products"><a href="http://example.com/products">Products</a></li>
|
77
|
+
<li id="services"><a href="http://example.com/services">Services</a></li>
|
78
|
+
<li class="selected" id="about_us"><a href="http://example.com/about_us">About Us</a>
|
79
|
+
<ul id="about_us_menubar">
|
80
|
+
<li id="overview"><a href="http://example.com/about_us">Overview</a></li>
|
81
|
+
<li class="selected" id="who_we_are"><a href="http://example.com/about_us/who_we_are">Who We Are</a></li>
|
82
|
+
<li class="last" id="contact"><a href="http://example.com/about_us/contact">Contact Us</a></li>
|
83
|
+
</ul>
|
84
|
+
<li class="search ir" id="search"><a href="http://www.google.com">Search!</a></li>
|
85
|
+
</ul>
|
86
|
+
|
87
|
+
== Using this plugin
|
88
|
+
|
89
|
+
Remember one of the basic principles of programming: KISS. There's no need to
|
90
|
+
use this plugin if you're writing a very, very simple menubar. The advantages
|
91
|
+
of this helper are consistency, DRYness, and decreased complexity if you have
|
92
|
+
lots of submenus.
|
93
|
+
|
94
|
+
I wrote this plugin half as an experiment and half to actually use in a
|
95
|
+
production application. I recommend trying it out and seeing if it actually
|
96
|
+
fits the needs of your application before committing to using it.
|
97
|
+
|
98
|
+
== Testing
|
99
|
+
|
100
|
+
This plugin requires that the plugin_test_helper gem be installed in order to
|
101
|
+
run the unit tests. To install this gem:
|
102
|
+
|
103
|
+
gem install plugin_test_helper
|
104
|
+
|
105
|
+
== Dependencies
|
106
|
+
|
107
|
+
This plugin depends on the presence of the following plugins:
|
108
|
+
# set_or_append - http://wiki.pluginaweek.org/Set_or_append
|
data/Rakefile
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'rake/contrib/sshpublisher'
|
5
|
+
|
6
|
+
PKG_NAME = 'menu_helper'
|
7
|
+
PKG_VERSION = '0.0.1'
|
8
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
9
|
+
RUBY_FORGE_PROJECT = 'pluginaweek'
|
10
|
+
|
11
|
+
desc 'Default: run unit tests.'
|
12
|
+
task :default => :test
|
13
|
+
|
14
|
+
desc 'Test the menu_helper plugin.'
|
15
|
+
Rake::TestTask.new(:test) do |t|
|
16
|
+
t.libs << 'lib'
|
17
|
+
t.pattern = 'test/**/*_test.rb'
|
18
|
+
t.verbose = true
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Generate documentation for the menu_helper plugin.'
|
22
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
23
|
+
rdoc.rdoc_dir = 'rdoc'
|
24
|
+
rdoc.title = 'MenuHelper'
|
25
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
26
|
+
rdoc.rdoc_files.include('README')
|
27
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
28
|
+
end
|
29
|
+
|
30
|
+
spec = Gem::Specification.new do |s|
|
31
|
+
s.name = PKG_NAME
|
32
|
+
s.version = PKG_VERSION
|
33
|
+
s.platform = Gem::Platform::RUBY
|
34
|
+
s.summary = 'Adds a helper method for generating a menubar'
|
35
|
+
|
36
|
+
s.files = FileList['{lib,tasks,test}/**/*'].to_a + %w(init.rb MIT-LICENSE Rakefile README)
|
37
|
+
s.require_path = 'lib'
|
38
|
+
s.autorequire = 'menu_helper'
|
39
|
+
s.has_rdoc = true
|
40
|
+
s.test_files = Dir['test/**/*_test.rb']
|
41
|
+
|
42
|
+
s.author = 'Aaron Pfeifer, Neil Abraham'
|
43
|
+
s.email = 'info@pluginaweek.org'
|
44
|
+
s.homepage = 'http://www.pluginaweek.org'
|
45
|
+
end
|
46
|
+
|
47
|
+
Rake::GemPackageTask.new(spec) do |p|
|
48
|
+
p.gem_spec = spec
|
49
|
+
p.need_tar = true
|
50
|
+
p.need_zip = true
|
51
|
+
end
|
52
|
+
|
53
|
+
desc 'Publish the beta gem'
|
54
|
+
task :pgem => [:package] do
|
55
|
+
Rake::SshFilePublisher.new('pluginaweek@pluginaweek.org', '/home/pluginaweek/gems.pluginaweek.org/gems', 'pkg', "#{PKG_FILE_NAME}.gem").upload
|
56
|
+
end
|
57
|
+
|
58
|
+
desc 'Publish the API documentation'
|
59
|
+
task :pdoc => [:rdoc] do
|
60
|
+
Rake::SshDirPublisher.new('pluginaweek@pluginaweek.org', "/home/pluginaweek/api.pluginaweek.org/#{PKG_NAME}", 'rdoc').upload
|
61
|
+
end
|
62
|
+
|
63
|
+
desc 'Publish the API docs and gem'
|
64
|
+
task :publish => [:pdoc, :release]
|
65
|
+
|
66
|
+
desc 'Publish the release files to RubyForge.'
|
67
|
+
task :release => [:gem, :package] do
|
68
|
+
require 'rubyforge'
|
69
|
+
|
70
|
+
ruby_forge = RubyForge.new
|
71
|
+
ruby_forge.login
|
72
|
+
|
73
|
+
%w( gem tgz zip ).each do |ext|
|
74
|
+
file = "pkg/#{PKG_FILE_NAME}.#{ext}"
|
75
|
+
puts "Releasing #{File.basename(file)}..."
|
76
|
+
|
77
|
+
ruby_forge.add_release(RUBY_FORGE_PROJECT, PKG_NAME, PKG_VERSION, file)
|
78
|
+
end
|
79
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'menu_helper'
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module PluginAWeek #:nodoc:
|
2
|
+
module Helpers #:nodoc:
|
3
|
+
module MenuHelper #:nodoc:
|
4
|
+
# Represents an HTML element
|
5
|
+
#
|
6
|
+
# == Modifying HTML options
|
7
|
+
#
|
8
|
+
# HTML options can normally be specified when creating the element.
|
9
|
+
# However, if they need to be modified after the element has been created,
|
10
|
+
# you can access the properties like so:
|
11
|
+
#
|
12
|
+
# m = Menu.new
|
13
|
+
# m[:style] = 'display: none;'
|
14
|
+
#
|
15
|
+
# or for a menu bar:
|
16
|
+
#
|
17
|
+
# b = MenuBar.new
|
18
|
+
# b[:style] = 'display: none;'
|
19
|
+
class HtmlElement
|
20
|
+
include ActionView::Helpers::TagHelper
|
21
|
+
|
22
|
+
delegate :[],
|
23
|
+
:[]=,
|
24
|
+
:to => '@html_options'
|
25
|
+
|
26
|
+
def initialize(html_options = {}) #:nodoc:
|
27
|
+
@html_options = html_options.symbolize_keys
|
28
|
+
end
|
29
|
+
|
30
|
+
# Generates the html representing this element
|
31
|
+
def html
|
32
|
+
content_tag(tag_name, content, @html_options)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
# The name of the element tag to use (e.g. td, th, tr, etc.)
|
37
|
+
def tag_name
|
38
|
+
''
|
39
|
+
end
|
40
|
+
|
41
|
+
# The content that will be displayed inside of the tag
|
42
|
+
def content
|
43
|
+
''
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'set_or_append'
|
2
|
+
|
3
|
+
module PluginAWeek #:nodoc:
|
4
|
+
module Helpers #:nodoc:
|
5
|
+
module MenuHelper #:nodoc:
|
6
|
+
# Represents a single menu within a menu bar
|
7
|
+
class Menu < HtmlElement
|
8
|
+
include ActionView::Helpers::UrlHelper
|
9
|
+
|
10
|
+
# The url where this menu is linked to
|
11
|
+
attr_reader :url_options
|
12
|
+
|
13
|
+
# If there are submenus under this menu, they are stored in here
|
14
|
+
attr_reader :menu_bar
|
15
|
+
|
16
|
+
# Allow submenus to be created
|
17
|
+
delegate :menu,
|
18
|
+
:to => :menu_bar
|
19
|
+
|
20
|
+
def initialize(id, request_controller, parent = nil, *args) #:nodoc
|
21
|
+
id = id.to_s
|
22
|
+
@controller = @request_controller = request_controller
|
23
|
+
@parent = parent
|
24
|
+
@content = args.first.is_a?(String) ? args.shift : id.underscore.titleize
|
25
|
+
@url_options = args.shift || {}
|
26
|
+
super(args.shift || {})
|
27
|
+
|
28
|
+
# Set the default html options
|
29
|
+
@html_options[:id] ||= id
|
30
|
+
|
31
|
+
@menu_bar = MenuBar.new(@request_controller, {}, {:id => "#{self[:id]}_menubar"}, self)
|
32
|
+
|
33
|
+
# Build the url for the menu
|
34
|
+
url, @url_options = build_url(@url_options)
|
35
|
+
@content = link_to(@content, url) if auto_link?
|
36
|
+
|
37
|
+
yield self if block_given?
|
38
|
+
end
|
39
|
+
|
40
|
+
# Should we try to automatically generate the link?
|
41
|
+
def auto_link?
|
42
|
+
!@url_options.is_a?(Hash) || !@url_options.include?(:auto_link)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Is this menu selected? A menu is considered selected if it or any of
|
46
|
+
# its submenus are selected
|
47
|
+
def selected?
|
48
|
+
current_page?(@url_options) || @menu_bar.menus.any? {|menu| menu.selected?}
|
49
|
+
end
|
50
|
+
|
51
|
+
# Builds the actual html of the menu
|
52
|
+
def build(last = false)
|
53
|
+
html = @content + @menu_bar.build
|
54
|
+
html_options = @html_options.dup
|
55
|
+
html_options.set_or_prepend(:class, 'selected') if selected?
|
56
|
+
html_options.set_or_prepend(:class, 'last') if last
|
57
|
+
|
58
|
+
content_tag('li', html, html_options)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
# Builds the url based on the options provided in the construction of
|
63
|
+
# the menu
|
64
|
+
def build_url(options = {})
|
65
|
+
# Check if the name given for the menu is a named route
|
66
|
+
if options.blank? && route_options = (named_route(self[:id], @parent) || named_route(self[:id]))
|
67
|
+
options = route_options
|
68
|
+
elsif options.is_a?(Hash)
|
69
|
+
options[:controller] ||= find_controller(options)
|
70
|
+
options[:action] ||= self[:id] unless options[:controller] == self[:id]
|
71
|
+
options[:only_path] ||= false
|
72
|
+
end
|
73
|
+
|
74
|
+
url = options.is_a?(Hash) ? url_for(options) : options
|
75
|
+
return url, options
|
76
|
+
end
|
77
|
+
|
78
|
+
# Finds the most likely controller that this menu should link to, in
|
79
|
+
# order of:
|
80
|
+
# 1. The specified controller in the menu link options
|
81
|
+
# 2. The name of the menu (e.g. products = ProductsController)
|
82
|
+
# 3. The parent's controller
|
83
|
+
# 4. The request controller
|
84
|
+
def find_controller(options)
|
85
|
+
options[:controller] ||
|
86
|
+
(begin; "#{self[:id].camelize}Controller".constantize.controller_path; rescue; nil; end) ||
|
87
|
+
@parent && @parent.url_options[:controller] ||
|
88
|
+
@request_controller.params[:controller]
|
89
|
+
end
|
90
|
+
|
91
|
+
# Finds the named route that is being linked to (if that route exists)
|
92
|
+
def named_route(name, parent = nil)
|
93
|
+
name = "#{parent[:id]}_#{name}" if parent
|
94
|
+
method_name = "hash_for_#{name}_url"
|
95
|
+
|
96
|
+
@request_controller.send(method_name) if @request_controller.respond_to?(method_name)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module PluginAWeek #:nodoc:
|
2
|
+
module Helpers #:nodoc:
|
3
|
+
module MenuHelper #:nodoc:
|
4
|
+
# Represents a group of menus. A menu bar can either be the main menu
|
5
|
+
# bar or a menu bar nested within a menu.
|
6
|
+
class MenuBar < HtmlElement
|
7
|
+
# The menus within this menu bar
|
8
|
+
attr_reader :menus
|
9
|
+
|
10
|
+
def initialize(request_controller, options = {}, html_options = {}, parent_menu = nil) #:nodoc:
|
11
|
+
super(html_options)
|
12
|
+
|
13
|
+
options.assert_valid_keys(:auto_set_ids)
|
14
|
+
options.reverse_merge!(:auto_set_ids => true)
|
15
|
+
@options = options
|
16
|
+
@request_controller = request_controller
|
17
|
+
@parent_menu = parent_menu
|
18
|
+
|
19
|
+
@menus = []
|
20
|
+
|
21
|
+
if @parent_menu
|
22
|
+
self[:id] ||= "#{@parent_menu[:id]}_menubar"
|
23
|
+
else
|
24
|
+
self[:id] ||= 'menubar'
|
25
|
+
end
|
26
|
+
|
27
|
+
yield self if block_given?
|
28
|
+
end
|
29
|
+
|
30
|
+
# Creates a new menu in this bar with the given id. The content
|
31
|
+
# within the menu is, by default, set to a humanized version of the id.
|
32
|
+
#
|
33
|
+
# == URLs with routes
|
34
|
+
#
|
35
|
+
# If you have named routes setup in the application, the menu attempts
|
36
|
+
# to automatically figure out what URL you're trying to link to. It
|
37
|
+
# does this by looking at the id of the menu and the id of its parent.
|
38
|
+
#
|
39
|
+
# For example, a menu_bar with the id 'home' and a menu with the id
|
40
|
+
# 'contact_us' will attempt to look for the following named routes as
|
41
|
+
# the URL to link to (in order of priority):
|
42
|
+
# 1. contact_us_url
|
43
|
+
# 2. home_contact_us_url
|
44
|
+
#
|
45
|
+
# Example routes.rb:
|
46
|
+
# ActionController::Routing::Routes.draw do |map|
|
47
|
+
# map.with_options(:controller => 'home') do |home|
|
48
|
+
# home.home '', :action => 'index'
|
49
|
+
# home.home_search 'search', :action => 'search'
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# map.with_options(:controller => 'about_us') do |about_us|
|
53
|
+
# about_us.about_us 'about_us', :action => 'index'
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# Example menubar:
|
58
|
+
# menu :home do |home|
|
59
|
+
# menu :about_us
|
60
|
+
# #=> Links to about_us_url
|
61
|
+
# menu :search
|
62
|
+
# #=> Links to home_search_url
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# == URLs with url_for
|
66
|
+
#
|
67
|
+
# If neither of these named routes are being used, the url will be based
|
68
|
+
# on the options passed into the menu. The url_options takes the same
|
69
|
+
# values as +url_for+. By default, the name of the controller will be
|
70
|
+
# guessed in the following order:
|
71
|
+
# 1. The id of the menu ('contact_us' => ContactUsController)
|
72
|
+
# 2. The controller of the parent menu/menu bar
|
73
|
+
# 3. The request controller
|
74
|
+
#
|
75
|
+
# To override the default controller being linked to, you can explicitly
|
76
|
+
# define it like so:
|
77
|
+
# menu :contact, 'Contact Us', {}, :controller => 'about_us'
|
78
|
+
#
|
79
|
+
# Examples:
|
80
|
+
# menu :home do |home|
|
81
|
+
# menu :about, 'About Us', :action => 'about_us'
|
82
|
+
# #=> Links to {:controller => 'home', :action => 'about_us'}
|
83
|
+
# menu :who_we_are
|
84
|
+
# #=> Links to {:controller => 'home', :action => 'who_we_are'}
|
85
|
+
# menu :contact_us, 'Contact Us', :controller => 'contact', :action => 'index'
|
86
|
+
# #=> Links to {:controller => 'contact', :action => 'index'}
|
87
|
+
# menu :search
|
88
|
+
# #=> Links to {:controller => 'search'}
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# You can also link to an explicit URL like so:
|
92
|
+
# menu :search, 'http://www.google.com'
|
93
|
+
#
|
94
|
+
# == Turning off links
|
95
|
+
#
|
96
|
+
# If you don't want a menu to link to a URL, you can turn off linking like so:
|
97
|
+
# menu :contact_us, 'Contact Us', {}, :auto_link => false
|
98
|
+
#
|
99
|
+
# == Defining content and html attributes
|
100
|
+
#
|
101
|
+
# By default, the content within a menu will be set as a humanized
|
102
|
+
# version of the menu's id. Examples of menus which customize the
|
103
|
+
# content and/or html attributes are below:
|
104
|
+
#
|
105
|
+
# menu :contact
|
106
|
+
# #=> <li id="contact"><a href="/contact">Contact</a></li>
|
107
|
+
# menu :contact, 'Contact Us'
|
108
|
+
# #=> <li id="contact"><a href="/contact">Contact Us</a></li>
|
109
|
+
# menu :contact, :class => 'pretty'
|
110
|
+
# #=> <li id="contact" class="pretty"><a href="/contact">Contact</a></li>
|
111
|
+
# menu :contact, 'Contact Us', :class => 'pretty'
|
112
|
+
# #=> <li id="contact" class="pretty"><a href="/contact">Contact Us</a></li>
|
113
|
+
#
|
114
|
+
# == Submenus
|
115
|
+
#
|
116
|
+
# Menus can also have their own submenus by passing in a block. You can
|
117
|
+
# create submenus in the same manner that the main menus are created.
|
118
|
+
# For example,
|
119
|
+
#
|
120
|
+
# menu :about do |about|
|
121
|
+
# about.menu :who_we_are
|
122
|
+
# about.menu :contact_us
|
123
|
+
# end
|
124
|
+
def menu(id, *args, &block)
|
125
|
+
menu = Menu.new(id, @request_controller, @parent_menu, *args, &block)
|
126
|
+
@menus << menu
|
127
|
+
|
128
|
+
menu
|
129
|
+
end
|
130
|
+
|
131
|
+
# Builds the actual html for the menu bar
|
132
|
+
def build
|
133
|
+
html = @menus.inject('') do |html, menu|
|
134
|
+
html << menu.build(@menus.last == menu)
|
135
|
+
end
|
136
|
+
|
137
|
+
html.blank? ? html : content_tag('ul', html, @html_options)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
data/lib/menu_helper.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'menu_helper/html_element'
|
2
|
+
require 'menu_helper/menu_bar'
|
3
|
+
require 'menu_helper/menu'
|
4
|
+
|
5
|
+
module PluginAWeek #:nodoc:
|
6
|
+
module Helpers #:nodoc:
|
7
|
+
# Provides a builder for generating html menubars. The structure of the
|
8
|
+
# menubars/menus is based on lists and should be styled using css.
|
9
|
+
module MenuHelper
|
10
|
+
# Creates a new 1st-level menu bar. The first parameter is the menubar's
|
11
|
+
# configuration options. The second parameter is the menubar's html
|
12
|
+
# options. Both of these parameters are optional.
|
13
|
+
#
|
14
|
+
# Configuration options:
|
15
|
+
# * <tt>auto_set_id</tt> - Whether or not to automatically add ids to each menu.
|
16
|
+
#
|
17
|
+
# Examples:
|
18
|
+
# menu_bar {}, :id => 'menus', :class => 'pretty' do |main|
|
19
|
+
# main.menu :home
|
20
|
+
# main.menu :about_us do |about_us|
|
21
|
+
# about_us.who_we_are
|
22
|
+
# about_us.what_we_do
|
23
|
+
# about_us.where_we_are
|
24
|
+
# about_us.contact, 'Contact', 'mailto:contact@us.com'
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# #=>
|
28
|
+
# <ul id="menus" class="pretty">
|
29
|
+
# <li id="about_us">About Us
|
30
|
+
# <ul id="about_us_menubar">
|
31
|
+
# <li id="who_we_are"><a href="/about_us/who_we_are">Who We Are</a></li>
|
32
|
+
# <li id="what_we_do"><a href="/about_us/what_we_do">What We Do</a></li>
|
33
|
+
# <li id="contact"><a href="mailto:contact@us.com">Contact</a></li>
|
34
|
+
# </ul>
|
35
|
+
# </li>
|
36
|
+
# </ul>
|
37
|
+
#
|
38
|
+
# == Menu Selection
|
39
|
+
#
|
40
|
+
# The currently selected menu is based on the current page that the user
|
41
|
+
# is currently on. If the url that the menu links to is the same as the
|
42
|
+
# current page, then that menu will be selected. This menu uses
|
43
|
+
# ActionView::Helpers::UrlHelper#current_page? to determine whether or not
|
44
|
+
# it is the currently selected menu.
|
45
|
+
#
|
46
|
+
# If the menu that is selected is nested within another menu, then those
|
47
|
+
# menus will be selected as well.
|
48
|
+
#
|
49
|
+
# A "selected" menu is indicated by an additional class html attribute
|
50
|
+
# that is added to the list item.
|
51
|
+
#
|
52
|
+
# For example, if a submenu is selected, the html generated from the
|
53
|
+
# above full example would look like so:
|
54
|
+
#
|
55
|
+
# <ul id="menus" class="pretty">
|
56
|
+
# <li id="about_us" class="selected">About Us
|
57
|
+
# <ul id="about_us_menubar">
|
58
|
+
# <li id="who_we_are" class="selected"><a href="/about_us/who_we_are">Who We Are</a></li>
|
59
|
+
# <li id="what_we_do"><a href="/about_us/what_we_do">What We Do</a></li>
|
60
|
+
# <li id="contact"><a href="mailto:contact@us.com">Contact</a></li>
|
61
|
+
# </ul>
|
62
|
+
# </li>
|
63
|
+
# </ul>
|
64
|
+
#
|
65
|
+
# == Menu Creation
|
66
|
+
#
|
67
|
+
# For more information about how menus are created, see the documentation
|
68
|
+
# for MenuBar#menu.
|
69
|
+
def menu_bar(*args, &block)
|
70
|
+
MenuBar.new(@controller, *args, &block).build
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
ActionController::Base.class_eval do
|
77
|
+
helper PluginAWeek::Helpers::MenuHelper
|
78
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
ActionController::Routing::Routes.draw do |map|
|
2
|
+
# Home
|
3
|
+
map.with_options(:controller => 'home') do |home|
|
4
|
+
home.home '', :action => 'index'
|
5
|
+
home.home_search 'search_stuff', :action => 'search'
|
6
|
+
end
|
7
|
+
|
8
|
+
# Contact
|
9
|
+
map.with_options(:controller => 'contact') do |contact|
|
10
|
+
contact.contact 'contact', :action => 'index'
|
11
|
+
end
|
12
|
+
|
13
|
+
map.connect ':controller/:action/:id.:format'
|
14
|
+
map.connect ':controller/:action/:id'
|
15
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
$:.unshift("#{File.dirname(__FILE__)}/../../../ruby/hash/set_or_append/lib")
|
2
|
+
|
3
|
+
# Load the plugin testing framework
|
4
|
+
$:.unshift("#{File.dirname(__FILE__)}/../../../test/plugin_test_helper/lib")
|
5
|
+
require 'rubygems'
|
6
|
+
require 'plugin_test_helper'
|
7
|
+
|
8
|
+
class Test::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
request = ActionController::TestRequest.new
|
11
|
+
request.request_uri = '/contact'
|
12
|
+
request.path_parameters = {:action => 'index', :controller => 'contact'}
|
13
|
+
@controller = HomeController.new
|
14
|
+
@controller.request = request
|
15
|
+
@controller.instance_eval {@_params = request.path_parameters}
|
16
|
+
@controller.send(:initialize_current_url)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class HtmlElementTest < Test::Unit::TestCase
|
4
|
+
class DivElement < PluginAWeek::Helpers::MenuHelper::HtmlElement
|
5
|
+
def tag_name
|
6
|
+
'div'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_html_options_on_initialization
|
11
|
+
e = PluginAWeek::Helpers::MenuHelper::HtmlElement.new('class' => 'fancy')
|
12
|
+
assert_equal 'fancy', e[:class]
|
13
|
+
|
14
|
+
e = PluginAWeek::Helpers::MenuHelper::HtmlElement.new(:class => 'fancy')
|
15
|
+
assert_equal 'fancy', e[:class]
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_html_no_content
|
19
|
+
assert_equal '<></>', PluginAWeek::Helpers::MenuHelper::HtmlElement.new.html
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_html_with_content
|
23
|
+
e = DivElement.new
|
24
|
+
e.instance_eval do
|
25
|
+
def content
|
26
|
+
'hello world'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
assert_equal '<div>hello world</div>', e.html
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_html_with_html_options
|
34
|
+
e = DivElement.new
|
35
|
+
e[:class] = 'fancy'
|
36
|
+
|
37
|
+
assert_equal '<div class="fancy"></div>', e.html
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_get_html_option
|
41
|
+
e = PluginAWeek::Helpers::MenuHelper::HtmlElement.new
|
42
|
+
assert_nil e[:class]
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_set_html_option
|
46
|
+
e = PluginAWeek::Helpers::MenuHelper::HtmlElement.new
|
47
|
+
e[:float] = 'left'
|
48
|
+
assert_equal 'left', e[:float]
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class MenuBarTest < Test::Unit::TestCase
|
4
|
+
def test_should_raise_exception_if_invalid_option_specified
|
5
|
+
assert_raise(ArgumentError) {create_menu_bar(:invalid => true)}
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_should_have_no_menus_by_default
|
9
|
+
menu_bar = create_menu_bar
|
10
|
+
assert_equal [], menu_bar.menus
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_set_default_id_if_no_parent_specified
|
14
|
+
menu_bar = create_menu_bar
|
15
|
+
assert_equal 'menubar', menu_bar[:id]
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_should_set_default_id_based_on_parent_if_parent_specified
|
19
|
+
menu_bar = create_menu_bar({}, {}, PluginAWeek::Helpers::MenuHelper::Menu.new(:home, @controller))
|
20
|
+
assert_equal 'home_menubar', menu_bar[:id]
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_accept_block
|
24
|
+
in_block = false
|
25
|
+
menu_bar = create_menu_bar do |main_menu|
|
26
|
+
in_block = true
|
27
|
+
end
|
28
|
+
|
29
|
+
assert in_block
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_should_create_menus
|
33
|
+
menu_bar = create_menu_bar do |main|
|
34
|
+
main.menu :home
|
35
|
+
main.menu :contact
|
36
|
+
end
|
37
|
+
|
38
|
+
assert_equal 2, menu_bar.menus.size
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_should_build_menu_bar_and_menus
|
42
|
+
menu_bar = create_menu_bar do |main|
|
43
|
+
main.menu :home
|
44
|
+
main.menu :contact, 'Contact Us'
|
45
|
+
end
|
46
|
+
|
47
|
+
expected = <<-eos
|
48
|
+
<ul id="menubar">
|
49
|
+
<li id="home"><a href="http://test.host/">Home</a></li>
|
50
|
+
<li class="last selected" id="contact"><a href="http://test.host/contact">Contact Us</a></li>
|
51
|
+
</ul>
|
52
|
+
eos
|
53
|
+
assert_equal expected.gsub(/\n\s*/, ''), menu_bar.build
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def create_menu_bar(*args, &block)
|
58
|
+
PluginAWeek::Helpers::MenuHelper::MenuBar.new(@controller, *args, &block)
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class MenuHelperTest < Test::Unit::TestCase
|
4
|
+
include PluginAWeek::Helpers::MenuHelper
|
5
|
+
|
6
|
+
def test_should_build_menu_bar
|
7
|
+
menu_bar_html = menu_bar({}, :class => 'pretty') do |main|
|
8
|
+
main.menu :home do |home|
|
9
|
+
home.menu :browse
|
10
|
+
home.menu :search
|
11
|
+
end
|
12
|
+
main.menu :contact, 'Contact Us'
|
13
|
+
main.menu :about_us
|
14
|
+
end
|
15
|
+
|
16
|
+
expected = <<-eos
|
17
|
+
<ul class="pretty" id="menubar">
|
18
|
+
<li id="home"><a href="http://test.host/">Home</a>
|
19
|
+
<ul id="home_menubar">
|
20
|
+
<li id="browse"><a href="http://test.host/home/browse">Browse</a></li>
|
21
|
+
<li class="last" id="search"><a href="http://test.host/search_stuff">Search</a></li>
|
22
|
+
</ul>
|
23
|
+
</li>
|
24
|
+
<li class="selected" id="contact"><a href="http://test.host/contact">Contact Us</a></li>
|
25
|
+
<li class="last" id="about_us"><a href="http://test.host/about_us">About Us</a></li>
|
26
|
+
</ul>
|
27
|
+
eos
|
28
|
+
assert_equal expected.gsub(/\n\s*/, ''), menu_bar_html
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class MenuTest < Test::Unit::TestCase
|
4
|
+
def test_default_content_should_be_humanized_id
|
5
|
+
menu = create_menu(:home)
|
6
|
+
assert_equal '<li id="home"><a href="http://test.host/">Home</a></li>', menu.build
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_default_html_id_should_be_id
|
10
|
+
menu = create_menu(:home)
|
11
|
+
assert_equal 'home', menu[:id]
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_not_linkify_if_not_auto_linking
|
15
|
+
menu = create_menu(:home, nil, :auto_link => false)
|
16
|
+
assert_equal '<li id="home">Home</li>', menu.build
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_default_menubar_id_should_use_menu_id
|
20
|
+
menu = create_menu(:home, nil)
|
21
|
+
assert_equal 'home_menubar', menu.menu_bar[:id]
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_not_auto_link_if_auto_link_is_false
|
25
|
+
menu = create_menu(:home, nil, :auto_link => false)
|
26
|
+
assert !menu.auto_link?
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_should_auto_link_if_url_options_is_string
|
30
|
+
menu = create_menu(:home, nil, 'http://www.google.com')
|
31
|
+
assert menu.auto_link?
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_should_auto_link_if_url_options_is_hash_without_auto_link
|
35
|
+
menu = create_menu(:home, nil, {})
|
36
|
+
assert menu.auto_link?
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_be_selected_if_url_is_current_page
|
40
|
+
menu = create_menu(:contact)
|
41
|
+
assert menu.selected?
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_should_be_selected_if_submenu_is_selected
|
45
|
+
menu = create_menu(:home) do |home|
|
46
|
+
home.menu :contact
|
47
|
+
end
|
48
|
+
assert menu.selected?
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_should_be_selected_if_submenu_of_submenu_is_selected
|
52
|
+
menu = create_menu(:home) do |home|
|
53
|
+
home.menu :about_us do |about_us|
|
54
|
+
about_us.menu :contact
|
55
|
+
end
|
56
|
+
end
|
57
|
+
assert menu.selected?
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_should_not_be_selected_if_url_is_not_current_page
|
61
|
+
menu = create_menu(:home)
|
62
|
+
assert !menu.selected?
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_should_build_url_from_named_route_if_id_named_route_exists
|
66
|
+
menu = create_menu(:home)
|
67
|
+
expected = {:controller => 'home', :action => 'index', :only_path => false, :use_route => :home}
|
68
|
+
assert_equal expected, menu.url_options
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_should_build_url_from_named_route_if_id_and_parent_named_route_exists
|
72
|
+
parent = create_menu(:home)
|
73
|
+
menu = create_menu(:search, parent)
|
74
|
+
expected = {:controller => 'home', :action => 'search', :only_path => false, :use_route => :home_search}
|
75
|
+
assert_equal expected, menu.url_options
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_should_use_id_as_default_controller_if_controller_exists
|
79
|
+
menu = create_menu(:about_us)
|
80
|
+
expected = {:controller => 'about_us', :only_path => false}
|
81
|
+
assert_equal expected, menu.url_options
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_should_use_parent_controller_as_default_controller_if_id_controller_does_not_exist
|
85
|
+
create_menu(:home) do |home|
|
86
|
+
menu = home.menu :privacy_policy
|
87
|
+
expected = {:controller => 'home', :action => 'privacy_policy', :only_path => false}
|
88
|
+
assert_equal expected, menu.url_options
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_should_use_request_controller_as_default_controller_if_parent_and_id_controller_does_not_exist
|
93
|
+
menu = create_menu(:investors)
|
94
|
+
expected = {:controller => 'contact', :action => 'investors', :only_path => false}
|
95
|
+
assert_equal expected, menu.url_options
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_should_use_custom_value_if_controller_is_specified
|
99
|
+
menu = create_menu(:privacy_policy, nil, :controller => 'home')
|
100
|
+
expected = {:controller => 'home', :action => 'privacy_policy', :only_path => false}
|
101
|
+
assert_equal expected, menu.url_options
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_should_not_use_id_as_default_action_if_same_as_controller
|
105
|
+
menu = create_menu(:about_us, nil, :controller => 'about_us')
|
106
|
+
expected = {:controller => 'about_us', :only_path => false}
|
107
|
+
assert_equal expected, menu.url_options
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_should_use_custom_value_if_action_is_specified
|
111
|
+
menu = create_menu(:privacy_policy, nil, :controller => 'home', :action => 'privacy')
|
112
|
+
expected = {:controller => 'home', :action => 'privacy', :only_path => false}
|
113
|
+
assert_equal expected, menu.url_options
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_should_allow_string_urls
|
117
|
+
menu = create_menu(:search, nil, 'Search', 'http://www.google.com')
|
118
|
+
assert_equal 'http://www.google.com', menu.url_options
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_should_include_selected_class_in_html_if_selected
|
122
|
+
menu = create_menu(:contact)
|
123
|
+
assert_equal '<li class="selected" id="contact"><a href="http://test.host/contact">Contact</a></li>', menu.build
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_should_prepend_selected_class_if_class_attribute_already_exists
|
127
|
+
menu = create_menu(:contact, nil, {}, :class => 'pretty')
|
128
|
+
assert_equal '<li class="selected pretty" id="contact"><a href="http://test.host/contact">Contact</a></li>', menu.build
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_should_include_last_class_in_html_if_last_menu
|
132
|
+
menu = create_menu(:home)
|
133
|
+
assert_equal '<li class="last" id="home"><a href="http://test.host/">Home</a></li>', menu.build(true)
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_should_prepend_last_class_if_class_attribute_already_exists
|
137
|
+
menu = create_menu(:home, nil, {}, :class => 'pretty')
|
138
|
+
assert_equal '<li class="last pretty" id="home"><a href="http://test.host/">Home</a></li>', menu.build(true)
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_should_not_modify_html_options_after_building_menu
|
142
|
+
menu = create_menu(:home)
|
143
|
+
menu.build
|
144
|
+
assert_nil menu[:class]
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_should_include_submenus_if_submenus_exist
|
148
|
+
menu = create_menu(:home) do |home|
|
149
|
+
home.menu :about_us do |about_us|
|
150
|
+
about_us.menu :contact
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
expected = <<-eos
|
155
|
+
<li class="selected" id="home"><a href="http://test.host/">Home</a>
|
156
|
+
<ul id="home_menubar">
|
157
|
+
<li class="last selected" id="about_us"><a href="http://test.host/about_us">About Us</a>
|
158
|
+
<ul id="about_us_menubar">
|
159
|
+
<li class="last selected" id="contact"><a href="http://test.host/contact">Contact</a></li>
|
160
|
+
</ul>
|
161
|
+
</li>
|
162
|
+
</ul>
|
163
|
+
</li>
|
164
|
+
eos
|
165
|
+
assert_equal expected.gsub(/\n\s*/, ''), menu.build
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
def create_menu(id, parent = nil, *args, &block)
|
170
|
+
PluginAWeek::Helpers::MenuHelper::Menu.new(id, @controller, parent, *args, &block)
|
171
|
+
end
|
172
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: menu_helper
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2007-08-16 00:00:00 -04:00
|
8
|
+
summary: Adds a helper method for generating a menubar
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: info@pluginaweek.org
|
12
|
+
homepage: http://www.pluginaweek.org
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: menu_helper
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Aaron Pfeifer, Neil Abraham
|
31
|
+
files:
|
32
|
+
- lib/menu_helper.rb
|
33
|
+
- lib/menu_helper
|
34
|
+
- lib/menu_helper/html_element.rb
|
35
|
+
- lib/menu_helper/menu_bar.rb
|
36
|
+
- lib/menu_helper/menu.rb
|
37
|
+
- test/test_helper.rb
|
38
|
+
- test/app_root
|
39
|
+
- test/unit
|
40
|
+
- test/app_root/config
|
41
|
+
- test/app_root/app
|
42
|
+
- test/app_root/config/routes.rb
|
43
|
+
- test/app_root/app/controllers
|
44
|
+
- test/app_root/app/controllers/contact_controller.rb
|
45
|
+
- test/app_root/app/controllers/about_us_controller.rb
|
46
|
+
- test/app_root/app/controllers/home_controller.rb
|
47
|
+
- test/unit/html_element_test.rb
|
48
|
+
- test/unit/menu_test.rb
|
49
|
+
- test/unit/menu_helper_test.rb
|
50
|
+
- test/unit/menu_bar_test.rb
|
51
|
+
- init.rb
|
52
|
+
- MIT-LICENSE
|
53
|
+
- Rakefile
|
54
|
+
- README
|
55
|
+
test_files:
|
56
|
+
- test/unit/html_element_test.rb
|
57
|
+
- test/unit/menu_test.rb
|
58
|
+
- test/unit/menu_helper_test.rb
|
59
|
+
- test/unit/menu_bar_test.rb
|
60
|
+
rdoc_options: []
|
61
|
+
|
62
|
+
extra_rdoc_files: []
|
63
|
+
|
64
|
+
executables: []
|
65
|
+
|
66
|
+
extensions: []
|
67
|
+
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
dependencies: []
|
71
|
+
|