wonder_navigation 0.1.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.
- 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
|
+
[](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:
|