ramenu 3.0.0
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/.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
|