ramenu 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'ramenu'
@@ -0,0 +1,13 @@
1
+ require 'ramenu/menus'
2
+ require 'ramenu/version'
3
+ require 'ramenu/action_controller'
4
+ require 'ramenu/railtie'
5
+ require 'ramenu/ramenu_methods'
6
+ require 'ramenu/ramenu_definer'
7
+ require 'ramenu/config'
8
+
9
+ module Ramenu
10
+
11
+ DEFAULT_GROUP = :default
12
+
13
+ end
@@ -0,0 +1,223 @@
1
+ module Ramenu
2
+ module ActionController
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ extend ClassMethods
7
+ helper HelperMethods
8
+ helper_method :add_menu, :menus, :flags
9
+ end
10
+
11
+
12
+ module Utils
13
+
14
+ def self.instance_proc(string)
15
+ if string.kind_of?(String)
16
+ proc { |controller| controller.instance_eval(string) }
17
+ else
18
+ string
19
+ end
20
+ end
21
+
22
+ # This is an horrible method with an horrible name.
23
+ #
24
+ # convert_to_set_of_strings(nil, [:foo, :bar])
25
+ # # => nil
26
+ # convert_to_set_of_strings(true, [:foo, :bar])
27
+ # # => ["foo", "bar"]
28
+ # convert_to_set_of_strings(:foo, [:foo, :bar])
29
+ # # => ["foo"]
30
+ # convert_to_set_of_strings([:foo, :bar, :baz], [:foo, :bar])
31
+ # # => ["foo", "bar", "baz"]
32
+ #
33
+ def self.convert_to_set_of_strings(value, keys)
34
+ if value == true
35
+ keys.map(&:to_s).to_set
36
+ elsif value
37
+ Array(value).map(&:to_s).to_set
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ module HelperMethods
44
+
45
+ def render_ramenu(options = {}, &block)
46
+ # passing all flags to Builder (static + volatile)
47
+ options[:flags] = flags(options[:menu])
48
+ builder = (options.delete(:builder) || Menus::SimpleBuilder).new(self, menus(options[:menu]), options)
49
+ content = builder.render.html_safe
50
+ if block_given?
51
+ capture(content, &block)
52
+ else
53
+ content
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+ module ClassMethods
60
+
61
+ #
62
+ # flags methods
63
+ #
64
+
65
+ # get flag value
66
+ def get_flag(name, filter_options = {})
67
+ before_filter(filter_options) do |controller|
68
+ controller.send(:get_flag, name, filter_options)
69
+ end
70
+ end
71
+
72
+ # set flag value
73
+ def set_flag(name, value, filter_options = {})
74
+ before_filter(filter_options) do |controller|
75
+ controller.send(:set_flag, name, value, filter_options)
76
+ end
77
+ end
78
+
79
+ # reset flag value
80
+ def reset_flag(name, filter_options = {})
81
+ before_filter(filter_options) do |controller|
82
+ controller.send(:reset_flag, name, filter_options)
83
+ end
84
+ end
85
+
86
+ #
87
+ # menus methods
88
+ #
89
+
90
+ # add a menu
91
+ def add_menu(name, path = nil, filter_options = {}, &block)
92
+ # This isn't really nice here
93
+ if eval = Utils.convert_to_set_of_strings(filter_options.delete(:eval), %w(name path))
94
+ name = Utils.instance_proc(name) if eval.include?("name")
95
+ unless path.nil?
96
+ path = Utils.instance_proc(path) if eval.include?("path")
97
+ end
98
+ end
99
+
100
+ before_filter(filter_options) do |controller|
101
+ # if path isn't defined, use current path
102
+ path = request.fullpath if path.nil?
103
+
104
+ controller.send(:add_menu, name, path, filter_options, &block)
105
+ end
106
+ end
107
+ alias :add_menu_for_current :add_menu
108
+
109
+ # define volatile menus/flags in a block
110
+ def definer(name = nil, filter_options = {}, &block)
111
+ before_filter(filter_options) do |controller|
112
+ controller.send(:definer, name, filter_options, &block)
113
+ end
114
+ end
115
+ end
116
+
117
+ protected
118
+
119
+ # common
120
+
121
+ def definer(name = nil, options = {}, &block)
122
+ static = options[:static] || false
123
+
124
+ menus = static ? static_menus(name) : volatile_menus(name)
125
+ flags = static ? static_flags(name) : volatile_flags(name)
126
+
127
+ # use a definer to allow block
128
+ rd = Ramenu::RamenuDefiner.new(menus, flags, options)
129
+ yield rd if block_given?
130
+ end
131
+
132
+ # flags
133
+
134
+ # get flag value
135
+ def get_flag(name, options = {})
136
+ # getting options
137
+ static = options[:static] || false
138
+ volatile = options[:volatile] || false
139
+
140
+ f = static_flags(options[:flagset]) if static
141
+ f = volatile_flags(options[:flagset]) if volatile
142
+ f = flags(options[:flagset]) unless static || volatile
143
+
144
+ f[name] if f.include?(name)
145
+ end
146
+
147
+ # reset flag value
148
+ def reset_flag(name, options = {})
149
+ set_flag(name, nil, options) unless name.nil?
150
+ end
151
+
152
+ # set flag value
153
+ def set_flag(name, value = nil, options = {})
154
+ # getting options
155
+ static = options[:static] || false
156
+
157
+ # setting flag
158
+ if static
159
+ set_static_flag(name, value, options)
160
+ else #if volatile
161
+ # default is volatile when nothing's set
162
+ set_volatile_flag(name, value, options)
163
+ end
164
+ end
165
+
166
+ # add a static flag, which will be kept for next instances
167
+ def set_static_flag(name, value, options = {})
168
+ flagset = options[:flagset]
169
+ Ramenu.set_flag_in(static_flags(flagset), name, value, options)
170
+ end
171
+
172
+ # add a volatile flag, only valid in the current instances
173
+ def set_volatile_flag(name, value, options = {})
174
+ flagset = options[:flagset]
175
+ Ramenu.set_flag_in(volatile_flags(flagset), name, value, options)
176
+ end
177
+
178
+ # return volatile flags defined in the current instance
179
+ def volatile_flags(flagset = nil)
180
+ flagset = :default if flagset.nil?
181
+ @flags ||= {}
182
+ @flags[flagset] ||= {}
183
+ @flags[flagset]
184
+ end
185
+ # return static flags defined in the configuration
186
+ def static_flags(flagset = nil)
187
+ Ramenu.static_flags(flagset)
188
+ end
189
+ # return all defined flags, static ones first then volatile ones
190
+ def flags(flagset = nil)
191
+ static_flags(flagset).merge(volatile_flags(flagset))
192
+ end
193
+
194
+ # add a static menu, which will be kept for next instances
195
+ def add_static_menu(name, path, options = {}, &block)
196
+ menu = options[:menu]
197
+ Ramenu.add_menu_to(static_menus(menu), name, path, options, &block)
198
+ end
199
+
200
+ # add a volatile menu, only valid in the current instances
201
+ def add_volatile_menu(name, path, options = {}, &block)
202
+ menu = options[:menu]
203
+ Ramenu.add_menu_to(volatile_menus(menu), name, path, options, &block)
204
+ end
205
+ alias :add_menu :add_volatile_menu
206
+
207
+ # return volatile menus defined in the current instance
208
+ def volatile_menus(menu = nil)
209
+ menu = :default if menu.nil?
210
+ @ramenu_menus ||= {}
211
+ @ramenu_menus[menu] ||= []
212
+ end
213
+ # return static menus defined in the configuration
214
+ def static_menus(menu = nil)
215
+ Ramenu.static_menus(menu)
216
+ end
217
+ # return all defined menus, static ones first then volatile ones
218
+ def menus(menu = nil)
219
+ static_menus(menu) + volatile_menus(menu)
220
+ end
221
+
222
+ end
223
+ end
@@ -0,0 +1,44 @@
1
+ require 'active_support/configurable'
2
+
3
+ module Ramenu
4
+ # Configures global settings for Ramenu
5
+ def self.configure(&block)
6
+ yield @config ||= Ramenu::Configuration.new
7
+ end
8
+
9
+ # Global settings for Ramenu
10
+ def self.config
11
+ @config
12
+ end
13
+
14
+ # need a Class for 3.0
15
+ class Configuration #:nodoc:
16
+ include ActiveSupport::Configurable
17
+ config_accessor :menus
18
+ config_accessor :flags
19
+
20
+ # common
21
+ def definer(name = nil, options = {}, &block)
22
+ # menus
23
+ menus = Ramenu.static_menus(name)
24
+ # flags
25
+ flags = Ramenu.static_flags(name)
26
+
27
+ # use a definer to allow block
28
+ rd = RamenuDefiner.new(menus, flags, options)
29
+ yield rd if block_given?
30
+ end
31
+
32
+ # create a new static flag in the configuration
33
+ def set_flag(name, value = nil, options = {})
34
+ flags = Ramenu.static_flags(options[:flagset])
35
+ Ramenu.set_flag_in(flags, name, value, options)
36
+ end
37
+
38
+ # create a new static menus in the configuration
39
+ def add_menu(name, path = nil, options = {}, &block)
40
+ menus = Ramenu.static_menus(options[:menu])
41
+ Ramenu.add_menu_to(menus, name, path, options, &block)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,167 @@
1
+ module Ramenu
2
+
3
+ module Menus
4
+
5
+ # The Builder class represents the abstract class for any custom Builder.
6
+ #
7
+ # To create a custom Builder, just extend this class
8
+ # and implement the following abstract methods:
9
+ #
10
+ # * <tt>#render</tt>: Renders and returns the collection of navigation elements
11
+ #
12
+ class Builder
13
+
14
+ # Initializes a new Builder with <tt>context</tt>,
15
+ # <tt>element</tt> and <tt>options</tt>.
16
+ #
17
+ # @param [ActionView::Base] context The view context.
18
+ # @param [Array<Element>] elements The collection of Elements.
19
+ # @param [Hash] options Hash of options to customize the rendering behavior.
20
+ #
21
+ def initialize(context, elements, options = {})
22
+ @context = context
23
+ @elements = elements
24
+ @options = options
25
+ end
26
+
27
+ # Renders Elements and returns the Breadcrumb navigation for the view.
28
+ #
29
+ # @return [String] The result of the menu rendering.
30
+ #
31
+ # @abstract You must implement this method in your custom Builder.
32
+ def render
33
+ raise NotImplementedError
34
+ end
35
+
36
+ # get flag associated to element
37
+ def flag_for(element, option = :flag)
38
+ flag = nil
39
+ flag_selector = element.options[option]
40
+ unless flag_selector.nil?
41
+ flag = @options[:flags][flag_selector] if @options[:flags].include?(flag_selector)
42
+ end
43
+ return flag
44
+ end
45
+
46
+ protected
47
+
48
+ def compute_name(element)
49
+ case name = element.name
50
+ when Symbol
51
+ begin
52
+ @context.send(name)
53
+ rescue NoMethodError
54
+ key = 'ramenu.menus.' + @options[:menu].to_s + element.translation_key
55
+ I18n.t(key)
56
+ end
57
+ when Proc
58
+ name.call(@context)
59
+ else
60
+ name.to_s
61
+ end
62
+ end
63
+
64
+ def compute_path(element)
65
+ case path = element.path
66
+ when Symbol
67
+ @context.send(path)
68
+ when Proc
69
+ path.call(@context)
70
+ when Hash
71
+ @context.url_for(path)
72
+ else
73
+ path.to_s
74
+ end
75
+ end
76
+
77
+ end
78
+
79
+ # The SimpleBuilder is the default menu builder.
80
+ # It provides basic functionalities to render a menu navigation.
81
+ #
82
+ # The SimpleBuilder accepts a limited set of options.
83
+ # If you need more flexibility, create a custom Builder and
84
+ # pass the option :builder => BuilderClass to the <tt>render_menus</tt> helper method.
85
+ #
86
+ class SimpleBuilder < Builder
87
+
88
+ def render
89
+ @elements.collect do |element|
90
+ render_element(element)
91
+ end.join(@options[:separator] || " &raquo; ")
92
+ end
93
+
94
+ def render_element(element)
95
+ content = @context.link_to_unless_current(compute_name(element), compute_path(element), element.options)
96
+
97
+ # rendering sub-elements
98
+ if (element.childs.length > 0)
99
+ content = content + " |"
100
+ element.childs.each do |child|
101
+ content = content + @context.link_to_unless_current(compute_name(child), compute_path(child)) + "|"
102
+ end
103
+ end
104
+
105
+ if @options[:tag]
106
+ @context.content_tag(@options[:tag], content)
107
+ else
108
+ content
109
+ end
110
+ end
111
+
112
+ end
113
+
114
+
115
+ # Represents a navigation element in the menu collection.
116
+ #
117
+ class Element
118
+
119
+ # @return [String] The element/link name.
120
+ attr_accessor :name
121
+ # @return [String] The element/link URL.
122
+ attr_accessor :path
123
+ # @return [Hash] The element/link childs
124
+ attr_accessor :childs
125
+ # @return [Element] The element/link parent
126
+ attr_accessor :parent
127
+ # @return [Hash] The element/link URL.
128
+ attr_accessor :options
129
+
130
+ # Initializes the Element with given parameters.
131
+ #
132
+ # @param [String] name The element/link name.
133
+ # @param [String] path The element/link URL.
134
+ # @param [Hash] options The element/link URL.
135
+ # @return [Element]
136
+ #
137
+ def initialize(name, path, options = {})
138
+ self.name = name
139
+ self.path = path
140
+ self.childs = []
141
+ #self.parent = @options[:parent]
142
+ self.parent = options.delete(:parent)
143
+ self.options = options
144
+ end
145
+
146
+ def translation_key
147
+ key = ''
148
+ elem = self
149
+ while !elem.nil? do
150
+ key = '.' + elem.name.to_s + key if elem.name.is_a?(Symbol)
151
+ key = '.' + elem.name.to_sym.to_s + key if elem.name.is_a?(String)
152
+ elem = elem.parent
153
+ end
154
+ key += '.root' if self.childs.count > 0
155
+ return key
156
+ end
157
+
158
+ def add_menu(name, path, options = {}, &block)
159
+ opts = options.merge({:parent => self})
160
+ self.childs << Ramenu.new_ramenu_element(name, path, opts, &block)
161
+ end
162
+ alias :add_child :add_menu
163
+ end
164
+
165
+ end
166
+
167
+ end