ramenu 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +12 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile +3 -0
- data/LICENSE +23 -0
- data/README.md +372 -0
- data/Rakefile +13 -0
- data/init.rb +1 -0
- data/lib/ramenu.rb +13 -0
- data/lib/ramenu/action_controller.rb +223 -0
- data/lib/ramenu/config.rb +44 -0
- data/lib/ramenu/menus.rb +167 -0
- data/lib/ramenu/railtie.rb +12 -0
- data/lib/ramenu/ramenu_definer.rb +23 -0
- data/lib/ramenu/ramenu_methods.rb +39 -0
- data/lib/ramenu/version.rb +14 -0
- data/ramenu.gemspec +28 -0
- data/test/dummy.rb +34 -0
- data/test/minitest_helper.rb +19 -0
- data/test/test_helper.rb +22 -0
- data/test/unit/action_controller_test.rb +109 -0
- data/test/unit/builder_test.rb +117 -0
- data/test/unit/element_test.rb +52 -0
- data/test/unit/simple_builder_test.rb +68 -0
- metadata +183 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
|
4
|
+
## master
|
5
|
+
|
6
|
+
|
7
|
+
## Release 3.0.0
|
8
|
+
|
9
|
+
* Initial version, forked from breadcrumbs_on_rails gem, and adding :
|
10
|
+
- multi-level menus (to add alternate menus)
|
11
|
+
- multiple menus, to have different menus displayed at one time
|
12
|
+
- static menus to create static menus to be defined at one place
|
13
|
+
- flags to interact with menus and activate or toggle highlights for example
|
14
|
+
- definer method, to define the whole menu in one block
|
15
|
+
- documentation in readme file to create new builders and to use all the features
|
16
|
+
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2013 La Fourmi Immo
|
2
|
+
Including code Copyright (c) 2009-2012 Simone Carletti
|
3
|
+
|
4
|
+
MIT License
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,372 @@
|
|
1
|
+
# Ramenu - Rails 'A la carte' menu
|
2
|
+
|
3
|
+
*Ramenu* is a simple Ruby on Rails plugin for creating and managing a menu navigation for a Rails project.
|
4
|
+
It provides helpers for creating navigation elements with a flexible interface.
|
5
|
+
|
6
|
+
|
7
|
+
## Requirements
|
8
|
+
|
9
|
+
* Rails 3
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
[RubyGems](http://rubygems.org) is the preferred way to install *Ramenu* and the best way if you want install a stable version.
|
14
|
+
|
15
|
+
$ gem install ramenu
|
16
|
+
|
17
|
+
Specify the Gem dependency in the [Bundler](http://gembundler.com) `Gemfile`.
|
18
|
+
|
19
|
+
gem "ramenu"
|
20
|
+
|
21
|
+
Use [Bundler](http://gembundler.com) and the [:git option](http://gembundler.com/v1.0/git.html) if you want to grab the latest version from the Git repository.
|
22
|
+
|
23
|
+
|
24
|
+
## Basic Usage
|
25
|
+
|
26
|
+
Creating a navigation menu in your Rails app using **Ramenu** is really straightforward.
|
27
|
+
There are two kinds of menus types, statics and volatiles. The first are kept whereas the second ones are only defined in controllers.
|
28
|
+
Aside to the menu, you may want to set flags to interact with you menu generator.
|
29
|
+
|
30
|
+
To define static menus, do it only once by creating an initializer, there will be availlable everywhere in your controllers.
|
31
|
+
|
32
|
+
# config/initializers/ramenu_config.rb
|
33
|
+
Ramenu.configure do |config|
|
34
|
+
# define a menu (by default, the :default menu is used)
|
35
|
+
config.add_menu :welcome, :root_path #, :menu => :default
|
36
|
+
|
37
|
+
# define a menu
|
38
|
+
config.add_menu :home, :root_path, :menu => :bottom_menu
|
39
|
+
|
40
|
+
# definer takes as argument the symbol name of the menus/flags to use
|
41
|
+
config.definer :main_menu do |d|
|
42
|
+
# add_menu method here takes the sames arguments as in a controller (see below)
|
43
|
+
d.add_menu :home, :root_path
|
44
|
+
d.add_menu :account, :root_path
|
45
|
+
d.add_menu :bien, :root_path
|
46
|
+
end
|
47
|
+
|
48
|
+
# definer have an optional argument to pass options.
|
49
|
+
# The main option is ':flag_for_menu'.
|
50
|
+
# Turn it to 'true' and your definer will associate a flag of the same name for each menu
|
51
|
+
# created. The flag is an option set in the menu element, and is later accessible in the
|
52
|
+
# builder, use it at your own convenience.
|
53
|
+
#
|
54
|
+
config.definer :main_menu, :flag_for_menu => true do |d|
|
55
|
+
# add_menu method here takes the sames arguments as in a controller (see below)
|
56
|
+
d.add_menu :home, :root_path
|
57
|
+
d.add_menu :account, :root_path
|
58
|
+
d.add_menu :bien, :root_path
|
59
|
+
|
60
|
+
# flags attributes can be set here
|
61
|
+
d.set_flag :home, true
|
62
|
+
d.set_flag :bien, false
|
63
|
+
|
64
|
+
# you can use as may flag as you need.
|
65
|
+
# theses options are accessible in your builders (see below)
|
66
|
+
d.add_menu :visits, :users_path, :right_icon => :visits_icon_flag
|
67
|
+
|
68
|
+
# and flag can be set with any value, boolean, or symbols for example
|
69
|
+
d.set_flag :visits_icon_flag, :waiting
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
In your controller, call `add_menu` to push a new element on the menu stack. `add_menu` requires two arguments: the name of the menu and the target path. See the section "Menus Element" for more details about name and target class types.
|
76
|
+
The third, optional argument is a Hash of options to customize the menu.
|
77
|
+
|
78
|
+
You can use the same definer as in the configuration, by calling `definer`, except that it will create a volatile block by default.
|
79
|
+
During the rendering, volatile menus/flags will merge with statics ones or override them if they have the same name.
|
80
|
+
Doing that, you can define default flags in the configuration, and change their values in the controllers.
|
81
|
+
|
82
|
+
class MyController
|
83
|
+
|
84
|
+
add_menu "home", :root_path
|
85
|
+
add_menu "my", :my_path
|
86
|
+
|
87
|
+
# you may specify the menus you want to use instead of the default one
|
88
|
+
add_menu "my", :my_path, :menu => :bottom_menu
|
89
|
+
|
90
|
+
# to add sub-menu (alternate menus for the same level)
|
91
|
+
add_menu :users, :users_path do |mm|
|
92
|
+
# add submenu using a symbol for translation (see translation below)
|
93
|
+
mm.add_menu :accounts, :accounts_path
|
94
|
+
# or a string
|
95
|
+
mm.add_menu "Profiles", :profiles_path
|
96
|
+
end
|
97
|
+
|
98
|
+
# to add a menu for current view
|
99
|
+
add_menu_for_current "My profile"
|
100
|
+
|
101
|
+
# definer takes as argument the symbol name of the menu/flags to use
|
102
|
+
definer :main_menu do |d|
|
103
|
+
d.add_menu :home, :root_path
|
104
|
+
d.add_menu :bien, :root_path
|
105
|
+
end
|
106
|
+
|
107
|
+
# definer in the controller takes the same optional argument as in the configuration, to pass options.
|
108
|
+
definer :main_menu, :flag_for_menu => true do |d|
|
109
|
+
d.add_menu :folder, :folders_path
|
110
|
+
|
111
|
+
# volatile flags override statics ones
|
112
|
+
d.set_flag :visits_icon_flag, :valid
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
def index
|
117
|
+
# ...
|
118
|
+
|
119
|
+
add_menu "index", index_path
|
120
|
+
end
|
121
|
+
|
122
|
+
def create
|
123
|
+
# definer in the controller takes the same optional argument as in the configuration, to pass options.
|
124
|
+
# By default, volatile blocks are defined in the controller. You may use the <tt>static</tt> option to create static block.
|
125
|
+
definer :main_menu, :flag_for_menu => true, :static => true do |d|
|
126
|
+
d.add_menu :account, :account_path
|
127
|
+
|
128
|
+
# flags attributes can be set here
|
129
|
+
d.set_flag :home, true
|
130
|
+
d.set_flag :bien, false
|
131
|
+
|
132
|
+
# you can use as may flag as you need.
|
133
|
+
# theses options are accessible in your builders (see below)
|
134
|
+
d.add_menu :cart, :cart_path, :right_icon => :cart_icon_flag
|
135
|
+
|
136
|
+
# and flag can be set with any value, boolean, or symbols for example
|
137
|
+
d.set_flag :cart_icon_flag, :waiting
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
In your view, you can render the menu menu with the `render_menus` helper.
|
144
|
+
|
145
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
146
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
147
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
148
|
+
<head>
|
149
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
150
|
+
<title>untitled</title>
|
151
|
+
</head>
|
152
|
+
|
153
|
+
<body>
|
154
|
+
<%= render_ramenu %>
|
155
|
+
</body>
|
156
|
+
</html>
|
157
|
+
|
158
|
+
`render_ramenu` understands a limited set of options. For example, you can pass change the default separator with the `:separator` option, or the default menu to use with the `:menu` option.
|
159
|
+
|
160
|
+
<body>
|
161
|
+
<%= render_ramenu :separator => ' / ', :menu => :side_menu_menu %>
|
162
|
+
</body>
|
163
|
+
|
164
|
+
More complex customizations require a custom Builder, see custom builder below.
|
165
|
+
|
166
|
+
### Menus Element
|
167
|
+
|
168
|
+
A menu is composed by a number of `Element` objects. Each object contains two attributes: the name of the menu and the target path.
|
169
|
+
|
170
|
+
When you call `add_menu`, the method automatically creates a new `Element` object for you and append it to the menus stack. `Element` name and path can be one of the following Ruby types:
|
171
|
+
|
172
|
+
* Symbol
|
173
|
+
* Proc
|
174
|
+
* String
|
175
|
+
|
176
|
+
#### Symbol
|
177
|
+
|
178
|
+
If the value is a Symbol, it can be used for two different things.
|
179
|
+
At first, the library try to call the corresponding method in the same context and sets the `Element` attribute to the returned value.
|
180
|
+
Then, if no method are found with that name, the library search for a key in the translation. (see below for translation keys examples)
|
181
|
+
|
182
|
+
class MyController
|
183
|
+
|
184
|
+
# The Name is set to the value returned by
|
185
|
+
# the :root_name method.
|
186
|
+
add_menu :function_name, "/"
|
187
|
+
add_menu :translate_me, "/"
|
188
|
+
|
189
|
+
protected
|
190
|
+
|
191
|
+
def function_name
|
192
|
+
"the name"
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
#### Proc
|
198
|
+
|
199
|
+
If the value is a Proc, the library calls the proc passing the current view context as argument and sets the `Element` attribute to the returned value. This is useful if you want to postpone the execution to get access to some special methods/variables created in your controller action.
|
200
|
+
|
201
|
+
class MyController
|
202
|
+
|
203
|
+
# The Name is set to the value returned by
|
204
|
+
# the :root_name method.
|
205
|
+
add_menu Proc.new { |c| c.my_helper_method },
|
206
|
+
"/"
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
#### String
|
211
|
+
|
212
|
+
If the value is a String, the library sets the `Element` attribute to the string value.
|
213
|
+
|
214
|
+
class MyController
|
215
|
+
|
216
|
+
# The Name is set to the value returned by
|
217
|
+
# the :root_name method.
|
218
|
+
add_menu "homepage", "/"
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
### Restricting menu scope
|
224
|
+
|
225
|
+
The `add_menu` method understands all options you are used to pass to a Rails controller filter.
|
226
|
+
In fact, behind the scenes this method uses a `before_filter` to store the tab in the `@ramenu_menus` variable.
|
227
|
+
|
228
|
+
Taking advantage of Rails filter options, you can restrict a tab to a selected group of actions in the same controller.
|
229
|
+
|
230
|
+
class PostsController < ApplicationController
|
231
|
+
add_menu "admin", :admin_path
|
232
|
+
add_menu "posts", :posts_path, :only => %w(index show)
|
233
|
+
end
|
234
|
+
|
235
|
+
class ApplicationController < ActionController::Base
|
236
|
+
add_menu "admin", :admin_path, :if => :admin_controller?
|
237
|
+
|
238
|
+
def admin_controller?
|
239
|
+
self.class.name =~ /^Admin(::|Controller)/
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
### Internationalization and Localization
|
244
|
+
|
245
|
+
Ramenu is compatible with the standard Rails internationalization framework.
|
246
|
+
|
247
|
+
For our previous example, if you want to localize your menu, define a new menus node in your .yml file with all the keys for your elements.
|
248
|
+
The convention is 'ramenu.menus' followed by your menus symbol (:default by default) then by the menu hierachy.
|
249
|
+
|
250
|
+
add_menu :users, :users_path do |mm|
|
251
|
+
# add submenu using a symbol for translation (see translation below)
|
252
|
+
mm.add_child :accounts, :accounts_path
|
253
|
+
end
|
254
|
+
|
255
|
+
The menu itself is translated here by 'ramenu.menus.default.users.root', and the sub-menu is 'ramenu.menus.default.users.accounts'.
|
256
|
+
|
257
|
+
# config/locales/en.yml
|
258
|
+
en:
|
259
|
+
ramenu:
|
260
|
+
menus:
|
261
|
+
default:
|
262
|
+
translate_me: "Translated"
|
263
|
+
users:
|
264
|
+
root: "Menu title"
|
265
|
+
accounts: "Accounts sub menu"
|
266
|
+
|
267
|
+
|
268
|
+
In your controller, you can also use the `I18n.t` method directly as it returns a string.
|
269
|
+
|
270
|
+
class PostsController < ApplicationController
|
271
|
+
add_menu I18n.t("events.new_year"), :events_path
|
272
|
+
add_menu I18n.t("events.holidays"), :events_path, :only => %w(holidays)
|
273
|
+
end
|
274
|
+
|
275
|
+
class ApplicationController < ActionController::Base
|
276
|
+
add_menu I18n.t("homepage"), :root_path
|
277
|
+
end
|
278
|
+
|
279
|
+
### Custom builder
|
280
|
+
|
281
|
+
If you need a specific menu, you'll need to define a custom builder.
|
282
|
+
To create such builder, add a file like the following.
|
283
|
+
In your builder, you can use `flag_for(element, [:name_of_the_flag])`, without its optional argument you'll get the flag named ':flag'
|
284
|
+
|
285
|
+
# /lib/ramenu/menus/html_builder.rb
|
286
|
+
module Ramenu
|
287
|
+
module Menus
|
288
|
+
# The HtmlBuilder is an html5 menu builder.
|
289
|
+
# It provides a simple way to render menu navigation as html5 tags.
|
290
|
+
# It may be used to display breadcrumbs-like menu or site menu, it is just a question of css.
|
291
|
+
#
|
292
|
+
# To use this custom Builder pass the option :builder => BuilderClass to the `render_ramenu` helper method.
|
293
|
+
#
|
294
|
+
class HtmlBuilder < Builder
|
295
|
+
|
296
|
+
def render
|
297
|
+
# creating nav id=breadcrumb
|
298
|
+
@context.content_tag(:nav, :id => @options[:id], :role => @options[:role]) do
|
299
|
+
render_elements(@elements)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def render_elements(elements)
|
304
|
+
content = nil
|
305
|
+
elements.each do |element|
|
306
|
+
if content.nil?
|
307
|
+
content = render_element(element)
|
308
|
+
else
|
309
|
+
content << render_element(element)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
@context.content_tag(:ul, content)
|
313
|
+
end
|
314
|
+
|
315
|
+
def render_element(element)
|
316
|
+
name = compute_name(element)
|
317
|
+
path = compute_path(element)
|
318
|
+
|
319
|
+
content = @context.link_to(path, :title => name) do
|
320
|
+
@context.content_tag(:span, "#{name}", :class => 'label')
|
321
|
+
end
|
322
|
+
|
323
|
+
# rendering sub-elements
|
324
|
+
if element.childs.length > 0
|
325
|
+
content = content + render_elements(element.childs)
|
326
|
+
end
|
327
|
+
|
328
|
+
class_arr = []
|
329
|
+
class_arr << 'activ' if flag_for(element) == true
|
330
|
+
class_arr << 'highlight' if element.childs.length > 0
|
331
|
+
@context.content_tag(:li, content, :class => class_arr.compact.join(' '))
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
|
338
|
+
And do not forget to add /lib to rails autoload_paths by adding the following line.
|
339
|
+
|
340
|
+
# config/application.rb
|
341
|
+
module MyNiceRailsApplication
|
342
|
+
class Application < Rails::Application
|
343
|
+
|
344
|
+
...
|
345
|
+
|
346
|
+
# Custom directories with classes and modules you want to be autoloadable.
|
347
|
+
# config.autoload_paths += %W(#{config.root}/extras)
|
348
|
+
config.autoload_paths += %W( #{config.root}/lib )
|
349
|
+
|
350
|
+
...
|
351
|
+
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
Use your new builder by adding the builder option to the renderer.
|
356
|
+
|
357
|
+
<%= render_ramenu(:builder => Ramenu::Menus::HtmlBuilder) %>
|
358
|
+
|
359
|
+
## Resources
|
360
|
+
|
361
|
+
* [Homepage](https://github.com/lafourmi/ramenu)
|
362
|
+
* [Documentation](https://github.com/lafourmi/ramenu)
|
363
|
+
* [API](http://rubydoc.info/gems/ramenu)
|
364
|
+
* [Repository](https://github.com/lafourmi/ramenu)
|
365
|
+
* [Issue Tracker](http://github.com/lafourmi/ramenu/issues)
|
366
|
+
|
367
|
+
|
368
|
+
## License
|
369
|
+
|
370
|
+
*Ramenu* is Copyright (c) 2013 La Fourmi Immo.
|
371
|
+
This is Free Software distributed under the MIT license and include code from Simone Carletti Copyright (c) 2009-2012.
|
372
|
+
Some ideas (I18n, Configuration) comes from [stijnster/alacarte](https://github.com/stijnster/alacarte).
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
require 'rake/testtask'
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.libs << 'lib/ramenu'
|
7
|
+
t.libs << 'test' # to find test_helper
|
8
|
+
#t.test_files = FileList['test/lib/calendrier/*_test.rb']
|
9
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
10
|
+
#t.verbose = !!ENV["VERBOSE"]
|
11
|
+
t.verbose = true
|
12
|
+
end
|
13
|
+
task :default => :test
|