wonder_navigation 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/README.md +66 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/wonder_navigation/controller.rb +26 -0
- data/lib/wonder_navigation/crumb.rb +10 -0
- data/lib/wonder_navigation/deferrable_option.rb +43 -0
- data/lib/wonder_navigation/helper.rb +62 -0
- data/lib/wonder_navigation/menu.rb +70 -0
- data/lib/wonder_navigation/menu_entry.rb +38 -0
- data/lib/wonder_navigation/menu_item.rb +157 -0
- data/lib/wonder_navigation/menu_manager.rb +70 -0
- data/lib/wonder_navigation/version.rb +3 -0
- data/lib/wonder_navigation.rb +17 -0
- data/wonder_navigation.gemspec +36 -0
- metadata +150 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d76249b8eec88051a188e99388c1975634a29be2
|
4
|
+
data.tar.gz: 352d500b597833be7f75484bbb1f62c4e5372e49
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c1a0790d51e750d70556929d60f5c8ef7eda8bfc14799f32406984565c77deed0a7c847cc7f8bc7b7e6eabc488450c49200151838c07048a9a9efe273c23e3f2
|
7
|
+
data.tar.gz: 4fc8b58b919bf87c65d84d5536752f0c14bbc8286423cc2baf5a34656ad8f943bd68ded2b11a005280755e8c21ae85cb7d7ad6bbb6817ee1faa5cd229ea32d18
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Rails Wonderful Navigation
|
2
|
+
|
3
|
+
[![Code Climate](https://codeclimate.com/github/douglaslise/wonder_navigation/badges/gpa.svg)](https://codeclimate.com/github/douglaslise/wonder_navigation)
|
4
|
+
|
5
|
+
Describe your Rails' menus and breadcrumbs in a single place, with support for permissions, fixed and resource based labels.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'wonder_navigation'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install wonder_navigation
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
In Rails, create a folder `config/navigation/default` and a file called `config/navigation/default.yml`. Inside the yml file you put the list of files that contains menu definitions:
|
26
|
+
```yml
|
27
|
+
---
|
28
|
+
default:
|
29
|
+
- public
|
30
|
+
- admin
|
31
|
+
```
|
32
|
+
After, create the corresponding files (`config/navigation/default/public.rb`, `config/navigation/default/admin.rb`):
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
WonderNavigation::Menu.register(:default) do
|
36
|
+
label { "Begin" }
|
37
|
+
path { root_path }
|
38
|
+
menu :blog, "Blog" do #Non-linked menu level
|
39
|
+
resource :posts, label: "Posts", path: posts_path do |index, new, show|
|
40
|
+
show.label {|post| post.title.truncate(15) }
|
41
|
+
# Here you can overwrite new and index entries
|
42
|
+
|
43
|
+
menu :comments, "Comments", path: post_comments_path do
|
44
|
+
menu :comment_show do
|
45
|
+
label {|comment| "Comment from #{comment.author}" }
|
46
|
+
path {|comment| post_comment_path(comment) }
|
47
|
+
menu :comment_edit, "Editing" do
|
48
|
+
path {|comment| edit_post_comment_path(comment)}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
|
57
|
+
## Development
|
58
|
+
|
59
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
60
|
+
|
61
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
62
|
+
|
63
|
+
## Contributing
|
64
|
+
|
65
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/douglaslise/wonder_navigation.
|
66
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "wonder_navigation"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module WonderNavigation
|
2
|
+
module Controller
|
3
|
+
|
4
|
+
def self.included(controller)
|
5
|
+
controller.before_action :set_default_wonder_navigation_page
|
6
|
+
end
|
7
|
+
|
8
|
+
def set_default_wonder_navigation_page
|
9
|
+
page_action = case action_name.to_sym
|
10
|
+
when :create then :new
|
11
|
+
when :update then :edit
|
12
|
+
else action_name
|
13
|
+
end
|
14
|
+
set_navigation_page "#{controller_path.tr('/','_')}_#{page_action}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_wonder_navigation_object(navigation_object)
|
18
|
+
@navigation_object = navigation_object
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_navigation_page(navigation_page)
|
22
|
+
@navigation_page = navigation_page.to_sym
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module WonderNavigation
|
2
|
+
class DeferrableOption
|
3
|
+
attr_accessor :fixed_value, :block, :name, :fixed_value_assigned
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@fixed_value_assigned = options.has_key?(:fixed) && !options[:fixed].nil?
|
7
|
+
@fixed_value = options[:fixed]
|
8
|
+
@block = options[:block]
|
9
|
+
@name = options[:name]
|
10
|
+
end
|
11
|
+
|
12
|
+
def present?
|
13
|
+
fixed_value_assigned || !!block
|
14
|
+
end
|
15
|
+
|
16
|
+
def resolvable?(object)
|
17
|
+
fixed_value_assigned || !!block && (!!object || block.arity.zero?)
|
18
|
+
end
|
19
|
+
|
20
|
+
def try_resolve(object)
|
21
|
+
resolve(object) if resolvable?(object)
|
22
|
+
end
|
23
|
+
|
24
|
+
def resolve(object)
|
25
|
+
check_resolvable(object)
|
26
|
+
fixed_value_assigned ? fixed_value : block.call(object)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def check_resolvable(object)
|
32
|
+
unless resolvable?(object)
|
33
|
+
if present?
|
34
|
+
raise EObjectNotSupplied.new "A block was defined to require an object but none (or nil) was supplied on deferrable option #{name}"
|
35
|
+
else
|
36
|
+
raise EDeferrableOptionEmpty.new "Neither a fixed value or a block was passed to deferrable option #{name}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
class EObjectNotSupplied < StandardError; end
|
42
|
+
class EDeferrableOptionEmpty < StandardError; end
|
43
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module WonderNavigation
|
2
|
+
module Helper
|
3
|
+
|
4
|
+
def navigation_breadcrumb
|
5
|
+
crumbs = crumbs_for_current_page
|
6
|
+
crumbs.any? ? breadcrumb(crumbs) : "Breadcrumb undefined for '#{@navigation_page}'"
|
7
|
+
end
|
8
|
+
|
9
|
+
def navigation_title_breadcrumb(prefix)
|
10
|
+
crumbs = crumbs_for_current_page.collect(&:label)
|
11
|
+
crumbs[0] = prefix
|
12
|
+
crumbs.join(" - ")
|
13
|
+
end
|
14
|
+
|
15
|
+
def menu_tree(menu_id, current_user)
|
16
|
+
WonderNavigation::MenuManager.get(menu_id).menu_tree(current_page: @navigation_page, current_user: current_user)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def crumbs_for_current_page(menu_id = :default)
|
22
|
+
page = @navigation_page
|
23
|
+
|
24
|
+
object = @navigation_object
|
25
|
+
unless object
|
26
|
+
# If object was not given by set_wonder_navigation_object then try get an instance variable called with the same name that the controller in singular
|
27
|
+
mod, resource = controller_path.split("/")
|
28
|
+
mod, resource = nil, mod if resource.nil?
|
29
|
+
variable_name = [mod, resource.singularize].compact.join("_")
|
30
|
+
variable_name = "@#{variable_name}"
|
31
|
+
object = controller.instance_variable_get(variable_name.to_sym)
|
32
|
+
end
|
33
|
+
# object ||= @navigation_parent_object
|
34
|
+
crumbs_for(menu_id, page.to_sym, object)
|
35
|
+
end
|
36
|
+
|
37
|
+
def crumbs_for(menu_id, id, object)
|
38
|
+
menu = WonderNavigation::MenuManager.get(menu_id)
|
39
|
+
if menu.item_exists?(id)
|
40
|
+
menu.breadcrumb_for(id, object)
|
41
|
+
else
|
42
|
+
[]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def breadcrumb(crumbs)
|
47
|
+
content_tag(:ol, class: "breadcrumb") do
|
48
|
+
raw(crumbs.collect do |menu_item|
|
49
|
+
content_tag(:li) do
|
50
|
+
if menu_item.path
|
51
|
+
link_to menu_item.label, menu_item.path
|
52
|
+
else
|
53
|
+
menu_item.label
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end.join(" "))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module WonderNavigation
|
2
|
+
class ENotDefinedMenu < StandardError; end
|
3
|
+
class Menu
|
4
|
+
attr_reader :items
|
5
|
+
attr_accessor :permission_checker
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@items = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.register_permission_check(menu_id, menu_manager = MenuManager, &block)
|
12
|
+
get_instance(menu_id, menu_manager).tap do |instance|
|
13
|
+
instance.permission_checker = block
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.register(menu_id, menu_manager = MenuManager, &block)
|
18
|
+
get_instance(menu_id, menu_manager).tap do |instance|
|
19
|
+
instance.items[:root].instance_eval(&block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.get_instance(menu_id, menu_manager)
|
24
|
+
instance = menu_manager.fetch(menu_id)
|
25
|
+
unless instance
|
26
|
+
instance = Menu.new
|
27
|
+
instance.items[:root] = MenuItem.new(instance, 0, :root, validate: false)
|
28
|
+
menu_manager.set(menu_id, instance)
|
29
|
+
end
|
30
|
+
|
31
|
+
instance
|
32
|
+
end
|
33
|
+
|
34
|
+
def item_exists?(id)
|
35
|
+
items[id].present?
|
36
|
+
end
|
37
|
+
|
38
|
+
def breadcrumb_for(id, object = nil)
|
39
|
+
if items[id]
|
40
|
+
items[id].breadcrumbs(object)
|
41
|
+
else
|
42
|
+
raise ENotDefinedMenu.new "Menu '#{id}' not defined"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def menu_tree(options = {})
|
47
|
+
current_user = options[:current_user]
|
48
|
+
current_page = options[:current_page]
|
49
|
+
max_depth = options[:max_depth] || 10
|
50
|
+
items[:root].tree(current_page, max_depth, current_user)
|
51
|
+
end
|
52
|
+
|
53
|
+
def menu_tree_flat(options = {})
|
54
|
+
extract_children menu_tree(options)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def extract_children(menu_entry)
|
60
|
+
result = []
|
61
|
+
result << menu_entry
|
62
|
+
result << menu_entry.visible_children.collect do |child|
|
63
|
+
extract_children(child)
|
64
|
+
end
|
65
|
+
menu_entry.children = []
|
66
|
+
|
67
|
+
result.flatten
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module WonderNavigation
|
2
|
+
class MenuEntry
|
3
|
+
attr_accessor :id, :label, :path, :level, :active, :visible, :children
|
4
|
+
def initialize(id, level)
|
5
|
+
@id = id
|
6
|
+
@level = level
|
7
|
+
@children = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def active?
|
11
|
+
active || children.any?(&:active?)
|
12
|
+
end
|
13
|
+
|
14
|
+
def has_visible_children?
|
15
|
+
children.any?(&:visible)
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_active_children?
|
19
|
+
children.any?(&:active)
|
20
|
+
end
|
21
|
+
|
22
|
+
def promote_active_state
|
23
|
+
self.active ||= has_active_children?
|
24
|
+
end
|
25
|
+
|
26
|
+
def visible_children
|
27
|
+
children.select(&:visible)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.level_class(level)
|
31
|
+
classes = {
|
32
|
+
2 => "second",
|
33
|
+
3 => "third"
|
34
|
+
}
|
35
|
+
classes[level]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module WonderNavigation
|
2
|
+
class ELabelNotDefined < StandardError; end
|
3
|
+
class MenuItem
|
4
|
+
attr_accessor :menu_instance, :level, :id, :parent_item, :subitems, :deferrables, :permission
|
5
|
+
|
6
|
+
def initialize(menu_instance, level, id, options = {}, &block)
|
7
|
+
@level = level
|
8
|
+
@menu_instance = menu_instance
|
9
|
+
@id = id
|
10
|
+
@subitems = []
|
11
|
+
@permission = options[:permission]
|
12
|
+
@menu_instance.items[id] = self
|
13
|
+
initialize_deferrables(options)
|
14
|
+
|
15
|
+
self.instance_eval(&block) if block_given?
|
16
|
+
|
17
|
+
validate if options.fetch(:validate, true)
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate
|
21
|
+
unless label_deferrable.present?
|
22
|
+
raise ELabelNotDefined.new("MenuItem #{id} was called without define a label text or proc")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def menu(id, label = nil, options = {}, &block)
|
27
|
+
if label.is_a?(Hash)
|
28
|
+
options = label
|
29
|
+
else
|
30
|
+
options[:label] = label
|
31
|
+
end
|
32
|
+
sub_item = MenuItem.new(menu_instance, level + 1, id.to_sym, options, &block)
|
33
|
+
sub_item.parent_item = self
|
34
|
+
sub_item
|
35
|
+
end
|
36
|
+
|
37
|
+
def resource(id, options = {}, &block)
|
38
|
+
new = show = nil
|
39
|
+
index = menu "#{id}_index", options do
|
40
|
+
new = menu "#{id}_new", "Novo", visible: false
|
41
|
+
show = menu "#{id}_show" do
|
42
|
+
label {|obj| obj.to_s }
|
43
|
+
path {|obj| obj }
|
44
|
+
menu "#{id}_edit", "Edição"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
index.instance_exec(index, new, show, &block) if block_given?
|
48
|
+
end
|
49
|
+
|
50
|
+
def breadcrumbs(object = nil)
|
51
|
+
result = []
|
52
|
+
if parent_item
|
53
|
+
parent_object = object
|
54
|
+
if parent_deferrable.present?
|
55
|
+
parent_object = parent_deferrable.resolve(object)
|
56
|
+
end
|
57
|
+
result += parent_item.breadcrumbs(parent_object)
|
58
|
+
end
|
59
|
+
current = Crumb.new(id)
|
60
|
+
current.label = label_deferrable.resolve(object)
|
61
|
+
current.path = path_deferrable.resolve(object) if path_deferrable.resolvable?(object)
|
62
|
+
|
63
|
+
result << current
|
64
|
+
end
|
65
|
+
|
66
|
+
def entry_visible?(max_depth, current_user)
|
67
|
+
# require "byebug"; debugger
|
68
|
+
|
69
|
+
level < max_depth &&
|
70
|
+
visible_deferrable.resolve(current_user) &&
|
71
|
+
label_deferrable.resolvable?(nil) &&
|
72
|
+
has_permission?(current_user)
|
73
|
+
end
|
74
|
+
|
75
|
+
def tree(current_page, max_depth, current_user)
|
76
|
+
MenuEntry.new(id, level).tap do |entry|
|
77
|
+
entry.active = id == current_page
|
78
|
+
entry.visible = entry_visible?(max_depth, current_user)
|
79
|
+
if entry.visible
|
80
|
+
entry.label = label_deferrable.resolve(nil)
|
81
|
+
entry.path = path_deferrable.try_resolve(nil)
|
82
|
+
end
|
83
|
+
|
84
|
+
entry.children = subtree(current_page, max_depth, current_user)
|
85
|
+
entry.promote_active_state
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def has_permission?(current_user)
|
90
|
+
if !!permission && !!menu_instance.permission_checker
|
91
|
+
# debugger
|
92
|
+
instance_exec(permission, current_user, &menu_instance.permission_checker)
|
93
|
+
else
|
94
|
+
true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def parent_item=(parent_item)
|
99
|
+
if parent_item
|
100
|
+
@parent_item = parent_item
|
101
|
+
parent_item.subitems << self
|
102
|
+
elsif @parent_item
|
103
|
+
@parent_item.subitems.delete(self)
|
104
|
+
@parent_item = nil
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def label(&block)
|
109
|
+
deferrables[:label] = DeferrableOption.new(block: block, name: "Label for #{id}")
|
110
|
+
end
|
111
|
+
|
112
|
+
def path(&block)
|
113
|
+
deferrables[:path] = DeferrableOption.new(block: block, name: "Path for #{id}")
|
114
|
+
end
|
115
|
+
|
116
|
+
def visible(&block)
|
117
|
+
deferrables[:visible] = DeferrableOption.new(block: block, name: "Visible for #{id}")
|
118
|
+
end
|
119
|
+
|
120
|
+
def parent(&block)
|
121
|
+
deferrables[:parent] = DeferrableOption.new(block: block, name: "Parent for #{id}")
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def initialize_deferrables(options)
|
127
|
+
@deferrables = {}
|
128
|
+
visible = options.fetch(:visible, true)
|
129
|
+
deferrables[:visible] = DeferrableOption.new(fixed: visible, name: "Visible for #{id}")
|
130
|
+
deferrables[:label] = DeferrableOption.new(fixed: options[:label], name: "Label for #{id}")
|
131
|
+
deferrables[:path] = DeferrableOption.new(fixed: options[:path], name: "Path for #{id}")
|
132
|
+
deferrables[:parent] = DeferrableOption.new(name: "Parent for #{id}")
|
133
|
+
end
|
134
|
+
|
135
|
+
def label_deferrable
|
136
|
+
deferrables[:label]
|
137
|
+
end
|
138
|
+
|
139
|
+
def path_deferrable
|
140
|
+
deferrables[:path]
|
141
|
+
end
|
142
|
+
|
143
|
+
def visible_deferrable
|
144
|
+
deferrables[:visible]
|
145
|
+
end
|
146
|
+
|
147
|
+
def parent_deferrable
|
148
|
+
deferrables[:parent]
|
149
|
+
end
|
150
|
+
|
151
|
+
def subtree(current_page, max_depth, current_user)
|
152
|
+
subitems.collect do |sub_item|
|
153
|
+
sub_item.tree(current_page, max_depth, current_user)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module WonderNavigation
|
2
|
+
class MenuManager
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def fetch(menu_id)
|
6
|
+
menus[menu_id]
|
7
|
+
end
|
8
|
+
|
9
|
+
def get(menu_id)
|
10
|
+
load_menus
|
11
|
+
fetch(menu_id)
|
12
|
+
end
|
13
|
+
|
14
|
+
def set(menu_id, menu_instance)
|
15
|
+
menus[menu_id] = menu_instance
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def menus
|
21
|
+
@menus ||= Hash.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def reset
|
25
|
+
@menus = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_menus
|
29
|
+
if need_reload?
|
30
|
+
reset
|
31
|
+
load_register_files
|
32
|
+
@loaded_file_mtimes = get_file_mtimes
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_register_files
|
37
|
+
register_files.each do |file|
|
38
|
+
Rails.logger.info("Reloading menu on file #{file}")
|
39
|
+
instance_eval open(file).read, file
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def yml_files
|
44
|
+
Dir[Rails.root.join("config", "navigation", "*.yml")]
|
45
|
+
end
|
46
|
+
|
47
|
+
def register_files
|
48
|
+
yml_files.flat_map do |file|
|
49
|
+
YAML.load(File.new(file)).flat_map do |folder, files|
|
50
|
+
files.collect do |menu_file|
|
51
|
+
File.join(Rails.root.join("config", "navigation", folder, "#{menu_file}.rb"))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def need_reload?
|
58
|
+
!@loaded_file_mtimes || files_modified?
|
59
|
+
end
|
60
|
+
|
61
|
+
def files_modified?
|
62
|
+
Rails.env.development? && get_file_mtimes != @loaded_file_mtimes
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_file_mtimes
|
66
|
+
(yml_files + register_files).flatten.collect { |file| File.mtime(file) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
require "wonder_navigation/version"
|
3
|
+
require "wonder_navigation/menu"
|
4
|
+
require "wonder_navigation/menu_manager"
|
5
|
+
require "wonder_navigation/menu_item"
|
6
|
+
require "wonder_navigation/menu_entry"
|
7
|
+
require "wonder_navigation/deferrable_option"
|
8
|
+
require "wonder_navigation/crumb"
|
9
|
+
require "wonder_navigation/controller"
|
10
|
+
|
11
|
+
if defined?(ActionView)
|
12
|
+
require "wonder_navigation/helper"
|
13
|
+
ActionView::Base.send :include, WonderNavigation::Helper
|
14
|
+
end
|
15
|
+
|
16
|
+
module WonderNavigation
|
17
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'wonder_navigation/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "wonder_navigation"
|
8
|
+
spec.version = WonderNavigation::VERSION
|
9
|
+
spec.authors = ["Douglas Lise", "Rodrigo Rosa"]
|
10
|
+
spec.email = ["douglaslise@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "Rails Wonderful Navigation"
|
13
|
+
spec.description = "Describe your Rails' menus and breadcrumbs in a single place, with support for permissions, fixed and resource based labels."
|
14
|
+
spec.homepage = "http://github.com/douglaslise/wonder_navigation"
|
15
|
+
spec.licenses = ['MIT']
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
19
|
+
# if spec.respond_to?(:metadata)
|
20
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
+
# else
|
22
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
+
# end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "rails", "~> 4.2"
|
31
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
32
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
33
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
34
|
+
spec.add_development_dependency "simplecov", "~> 0.10"
|
35
|
+
spec.add_development_dependency "byebug", "~> 6.0"
|
36
|
+
end
|
metadata
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wonder_navigation
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Douglas Lise
|
8
|
+
- Rodrigo Rosa
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2016-03-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '4.2'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '4.2'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: bundler
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.11'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.11'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '10.0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '10.0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rspec
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '3.0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '3.0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: simplecov
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0.10'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0.10'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: byebug
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '6.0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '6.0'
|
98
|
+
description: Describe your Rails' menus and breadcrumbs in a single place, with support
|
99
|
+
for permissions, fixed and resource based labels.
|
100
|
+
email:
|
101
|
+
- douglaslise@gmail.com
|
102
|
+
executables: []
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- ".gitignore"
|
107
|
+
- ".rspec"
|
108
|
+
- ".travis.yml"
|
109
|
+
- Gemfile
|
110
|
+
- README.md
|
111
|
+
- Rakefile
|
112
|
+
- bin/console
|
113
|
+
- bin/setup
|
114
|
+
- lib/wonder_navigation.rb
|
115
|
+
- lib/wonder_navigation/controller.rb
|
116
|
+
- lib/wonder_navigation/crumb.rb
|
117
|
+
- lib/wonder_navigation/deferrable_option.rb
|
118
|
+
- lib/wonder_navigation/helper.rb
|
119
|
+
- lib/wonder_navigation/menu.rb
|
120
|
+
- lib/wonder_navigation/menu_entry.rb
|
121
|
+
- lib/wonder_navigation/menu_item.rb
|
122
|
+
- lib/wonder_navigation/menu_manager.rb
|
123
|
+
- lib/wonder_navigation/version.rb
|
124
|
+
- wonder_navigation.gemspec
|
125
|
+
homepage: http://github.com/douglaslise/wonder_navigation
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
metadata: {}
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubyforge_project:
|
145
|
+
rubygems_version: 2.4.8
|
146
|
+
signing_key:
|
147
|
+
specification_version: 4
|
148
|
+
summary: Rails Wonderful Navigation
|
149
|
+
test_files: []
|
150
|
+
has_rdoc:
|