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/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