simple-navigation 2.7.3 → 3.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/CHANGELOG +14 -4
  2. data/README +1 -2
  3. data/Rakefile +1 -0
  4. data/VERSION.yml +4 -4
  5. data/generators/navigation_config/templates/config/navigation.rb +14 -14
  6. data/lib/simple_navigation.rb +69 -151
  7. data/lib/simple_navigation/adapters.rb +9 -0
  8. data/lib/simple_navigation/adapters/base.rb +37 -0
  9. data/lib/simple_navigation/adapters/padrino.rb +20 -0
  10. data/lib/simple_navigation/adapters/rails.rb +93 -0
  11. data/lib/simple_navigation/adapters/sinatra.rb +76 -0
  12. data/lib/simple_navigation/core.rb +5 -0
  13. data/lib/simple_navigation/{configuration.rb → core/configuration.rb} +14 -19
  14. data/lib/simple_navigation/{item.rb → core/item.rb} +10 -11
  15. data/lib/simple_navigation/{item_adapter.rb → core/item_adapter.rb} +11 -7
  16. data/lib/simple_navigation/{item_container.rb → core/item_container.rb} +14 -21
  17. data/lib/simple_navigation/{items_provider.rb → core/items_provider.rb} +7 -7
  18. data/lib/simple_navigation/{controller_methods.rb → rails_controller_methods.rb} +67 -5
  19. data/lib/simple_navigation/rendering.rb +10 -0
  20. data/lib/simple_navigation/{helpers.rb → rendering/helpers.rb} +16 -18
  21. data/lib/simple_navigation/{renderer → rendering/renderer}/base.rb +20 -37
  22. data/lib/simple_navigation/{renderer → rendering/renderer}/breadcrumbs.rb +7 -7
  23. data/lib/simple_navigation/{renderer → rendering/renderer}/links.rb +7 -7
  24. data/lib/simple_navigation/{renderer → rendering/renderer}/list.rb +6 -6
  25. data/rails/init.rb +1 -5
  26. data/spec/lib/simple_navigation/adapters/padrino_spec.rb +29 -0
  27. data/spec/lib/simple_navigation/adapters/rails_spec.rb +269 -0
  28. data/spec/lib/simple_navigation/adapters/sinatra_spec.rb +60 -0
  29. data/spec/lib/simple_navigation/{configuration_spec.rb → core/configuration_spec.rb} +7 -18
  30. data/spec/lib/simple_navigation/{item_adapter_spec.rb → core/item_adapter_spec.rb} +11 -11
  31. data/spec/lib/simple_navigation/{item_container_spec.rb → core/item_container_spec.rb} +29 -46
  32. data/spec/lib/simple_navigation/{item_spec.rb → core/item_spec.rb} +30 -64
  33. data/spec/lib/simple_navigation/{items_provider_spec.rb → core/items_provider_spec.rb} +7 -7
  34. data/spec/lib/simple_navigation/rails_controller_methods_spec.rb +251 -0
  35. data/spec/lib/simple_navigation/{helpers_spec.rb → rendering/helpers_spec.rb} +34 -53
  36. data/spec/lib/simple_navigation/{renderer → rendering/renderer}/base_spec.rb +11 -62
  37. data/spec/lib/simple_navigation/{renderer → rendering/renderer}/breadcrumbs_spec.rb +9 -51
  38. data/spec/lib/simple_navigation/rendering/renderer/links_spec.rb +59 -0
  39. data/spec/lib/simple_navigation/{renderer → rendering/renderer}/list_spec.rb +17 -58
  40. data/spec/lib/simple_navigation_spec.rb +51 -298
  41. data/spec/spec_helper.rb +16 -5
  42. metadata +67 -48
  43. data/lib/simple_navigation/initializer.rb +0 -21
  44. data/lib/simple_navigation/railtie.rb +0 -7
  45. data/spec/lib/simple_navigation/controller_methods_spec.rb +0 -90
  46. data/spec/lib/simple_navigation/renderer/links_spec.rb +0 -121
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ *3.0.0.beta1
2
+
3
+ * moving deprecated rails controller methods (navigation, current_navigation) to separate file 'rails_controller_methods'. Deprecations removed. File can be required explicitly if controller methods should be still available.
4
+ * decoupling from Rails. Introducing the concept of adapters to work with several frameworks.
5
+ * tested with Rails 3.0.0
6
+ * adding support for Sinatra and Padrino frameworks.
7
+ * cherry picking active_support stuff instead of requiring the whole bunch (tested with active_support >= 2.3.2 and 3.0.0)
8
+ * created public sample project which includes demo for Rails2, Rails3, Sinatra and Padrino (will be available on github soon)
9
+ * better src file organization (adapters/core/rendering folders)
10
+
1
11
  *2.7.3
2
12
 
3
13
  * initializing SimpleNavigation.config_file_path with empty array (was nil before). Allows for adding paths before gem has been initialized.
@@ -62,7 +72,7 @@
62
72
 
63
73
  *2.2.3
64
74
 
65
- * changed error handling in config-file. Do not ignore errors in config-file anymore.
75
+ * changed error handling in config-file. Do not ignore errors in config-file anymore.
66
76
  * only load config-file if it is present. Needed when directly providing items in render_navigation.
67
77
 
68
78
  *2.2.2
@@ -92,16 +102,16 @@
92
102
  *2.0.0
93
103
 
94
104
  * added auto_highlight feature. Active navigation is determined by comparing urls, no need to explicitly set it in the controllers anymore. Thanks to Jack Dempsey and Florian Hanke for the support on this.
95
- * added ability to create multi-level navigations (not just limited to primary and secondary navigation). Thanks again to Jack Dempsey for the motivation ;-)
105
+ * added ability to create multi-level navigations (not just limited to primary and secondary navigation). Thanks again to Jack Dempsey for the motivation ;-)
96
106
  * simplified the process to explicitly set the navigation in the controller (where needed) - only deepest level has to be specified
97
- * made auto_highlight feature configurable both on global and item_container's level
107
+ * made auto_highlight feature configurable both on global and item_container's level
98
108
  * config file is now evaluated in template if ever possible (not in controller anymore)
99
109
 
100
110
  *1.4.2
101
111
 
102
112
  * explicitly loading all source files when requiring 'simple_navigation'.
103
113
 
104
- *1.4.0
114
+ *1.4.0
105
115
 
106
116
  * added the capability to have several navigation-contexts
107
117
  * doc-fix
data/README CHANGED
@@ -1,8 +1,7 @@
1
1
 
2
2
  == Simple Navigation
3
3
 
4
- Simple Navigation is a ruby library for creating navigations (with multiple levels) for your Ruby on Rails application.
5
- If you upgrade to version 2.x.x please recheck the updated documentation on http://wiki.github.com/andi/simple-navigation.
4
+ Simple Navigation is a ruby library for creating navigations (with multiple levels) for your Rails 2, Rails 3, Sinatra or Padrino applications.
6
5
 
7
6
  Source code:
8
7
  git://github.com/andi/simple-navigation.git
data/Rakefile CHANGED
@@ -39,6 +39,7 @@ begin
39
39
  gemspec.homepage = "http://github.com/andi/simple-navigation"
40
40
  gemspec.description = "With the simple-navigation gem installed you can easily create multilevel navigations for your Ruby on Rails applications. The navigation is defined in a single configuration file. It supports automatic as well as explicit highlighting of the currently active navigation."
41
41
  gemspec.add_development_dependency('rspec', '>= 1.2.8')
42
+ gemspec.add_dependency('activesupport', '>= 2.3.2')
42
43
  gemspec.authors = ["Andi Schacke"]
43
44
  gemspec.rdoc_options = ["--inline-source", "--charset=UTF-8"]
44
45
  gemspec.files = FileList["[A-Z]*", "{lib,spec,rails,generators}/**/*"] - FileList["**/*.log"]
@@ -1,4 +1,4 @@
1
- ---
2
- :patch: 3
3
- :major: 2
4
- :minor: 7
1
+ ---
2
+ :major: 3
3
+ :minor: 0
4
+ :patch: 0
@@ -1,17 +1,17 @@
1
1
  # Configures your navigation
2
- SimpleNavigation::Configuration.run do |navigation|
3
- # Specify a custom renderer if needed.
2
+ SimpleNavigation::Configuration.run do |navigation|
3
+ # Specify a custom renderer if needed.
4
4
  # The default renderer is SimpleNavigation::Renderer::List which renders HTML lists.
5
- # The renderer can also be specified as option in the render_navigation call.
5
+ # The renderer can also be specified as option in the render_navigation call.
6
6
  # navigation.renderer = Your::Custom::Renderer
7
-
7
+
8
8
  # Specify the class that will be applied to active navigation items. Defaults to 'selected'
9
9
  # navigation.selected_class = 'your_selected_class'
10
-
10
+
11
11
  # Item keys are normally added to list items as id.
12
12
  # This setting turns that off
13
13
  # navigation.autogenerate_item_ids = false
14
-
14
+
15
15
  # You can override the default logic that is used to autogenerate the item ids.
16
16
  # To do this, define a Proc which takes the key of the current item as argument.
17
17
  # The example below would add a prefix to each key.
@@ -36,18 +36,18 @@ SimpleNavigation::Configuration.run do |navigation|
36
36
  # be rendered (e.g. <tt>:unless => Proc.new { current_user.admin? }</tt>). The
37
37
  # proc should evaluate to a true or false value and is evaluated in the context of the view.
38
38
  # :method - Specifies the http-method for the generated link - default is :get.
39
- # :highlights_on - if autohighlighting is turned off and/or you want to explicitly specify
40
- # when the item should be highlighted, you can set a regexp which is matched
39
+ # :highlights_on - if autohighlighting is turned off and/or you want to explicitly specify
40
+ # when the item should be highlighted, you can set a regexp which is matched
41
41
  # against the current URI.
42
42
  #
43
43
  primary.item :key_1, 'name', url, options
44
-
44
+
45
45
  # Add an item which has a sub navigation (same params, but with block)
46
46
  primary.item :key_2, 'name', url, options do |sub_nav|
47
47
  # Add an item to the sub navigation (same params again)
48
48
  sub_nav.item :key_2_1, 'name', url, options
49
- end
50
-
49
+ end
50
+
51
51
  # You can also specify a condition-proc that needs to be fullfilled to display an item.
52
52
  # Conditions are part of the options. They are evaluated in the context of the views,
53
53
  # thus you can use all the methods and vars you have available in the views.
@@ -58,10 +58,10 @@ SimpleNavigation::Configuration.run do |navigation|
58
58
  # works for all levels of the menu
59
59
  # primary.dom_id = 'menu-id'
60
60
  # primary.dom_class = 'menu-class'
61
-
61
+
62
62
  # You can turn off auto highlighting for a specific level
63
63
  # primary.auto_highlight = false
64
-
64
+
65
65
  end
66
-
66
+
67
67
  end
@@ -1,122 +1,121 @@
1
- # Load all source files (if this is not done explicitly some naming conflicts may occur if rails app has classes with the same name)
2
- require 'simple_navigation/configuration'
3
- require 'simple_navigation/helpers'
4
- require 'simple_navigation/controller_methods'
5
- require 'simple_navigation/item_adapter'
6
- require 'simple_navigation/item'
7
- require 'simple_navigation/item_container'
8
- require 'simple_navigation/items_provider'
9
- require 'simple_navigation/renderer/base'
10
- require 'simple_navigation/renderer/list'
11
- require 'simple_navigation/renderer/links'
12
- require 'simple_navigation/renderer/breadcrumbs'
13
- require 'simple_navigation/initializer'
14
- require 'simple_navigation/railtie' if Rails::VERSION::MAJOR == 3
1
+ # cherry picking active_support stuff
2
+ require 'active_support/core_ext/array'
3
+ require 'active_support/core_ext/hash'
4
+ require 'active_support/core_ext/module/attribute_accessors'
5
+
6
+ require 'simple_navigation/core'
7
+ require 'simple_navigation/rendering'
8
+ require 'simple_navigation/adapters'
9
+
10
+ require 'forwardable'
15
11
 
16
12
  # A plugin for generating a simple navigation. See README for resources on usage instructions.
17
13
  module SimpleNavigation
14
+
15
+ mattr_accessor :adapter_class, :adapter, :config_files, :config_file_paths, :default_renderer, :registered_renderers, :root, :environment
18
16
 
19
- mattr_accessor :config_files, :config_file_paths, :default_renderer, :controller, :template, :explicit_current_navigation, :rails_env, :rails_root, :registered_renderers
20
-
17
+ # Cache for loaded config files
21
18
  self.config_files = {}
19
+
20
+ # Allows for multiple config_file_paths. Needed if a plugin itself uses simple-navigation and therefore has its own config file
22
21
  self.config_file_paths = []
22
+
23
+ # Maps renderer keys to classes. The keys serve as shortcut in the render_navigation calls (:renderer => :list)
23
24
  self.registered_renderers = {
24
25
  :list => SimpleNavigation::Renderer::List,
25
26
  :links => SimpleNavigation::Renderer::Links,
26
27
  :breadcrumbs => SimpleNavigation::Renderer::Breadcrumbs
27
28
  }
28
29
 
29
-
30
30
  class << self
31
+ extend Forwardable
32
+
33
+ def_delegators :adapter, :request, :request_uri, :request_path, :context_for_eval, :current_page?
34
+ def_delegators :adapter_class, :register
35
+
36
+ # Sets the root path and current environment as specified. Also sets the default config_file_path.
37
+ def set_env(root, environment)
38
+ self.root = root
39
+ self.environment = environment
40
+ self.config_file_paths << SimpleNavigation.default_config_file_path
41
+ end
42
+
43
+ # Returns the current framework in which the plugin is running.
44
+ def framework
45
+ return :rails if defined?(Rails)
46
+ return :padrino if defined?(Padrino)
47
+ return :sinatra if defined?(Sinatra)
48
+ raise 'simple_navigation currently only works for Rails, Sinatra and Padrino apps'
49
+ end
50
+
51
+ # Loads the adapter for the current framework
52
+ def load_adapter
53
+ self.adapter_class = case framework
54
+ when :rails
55
+ SimpleNavigation::Adapters::Rails
56
+ when :sinatra
57
+ SimpleNavigation::Adapters::Sinatra
58
+ when :padrino
59
+ SimpleNavigation::Adapters::Padrino
60
+ end
61
+ end
31
62
 
32
- # Sets the config file path and installs the ControllerMethods in ActionController::Base.
33
- def init_rails
34
- SimpleNavigation.config_file_paths << SimpleNavigation.default_config_file_path
35
- ActionController::Base.send(:include, SimpleNavigation::ControllerMethods)
63
+ # Creates a new adapter instance based on the context in which render_navigation has been called.
64
+ def init_adapter_from(context)
65
+ self.adapter = self.adapter_class.new(context)
36
66
  end
37
67
 
38
68
  def default_config_file_path
39
- File.join(SimpleNavigation.rails_root, 'config')
69
+ File.join(SimpleNavigation.root, 'config')
40
70
  end
41
-
71
+
42
72
  # Returns true if the config_file for specified context does exist.
43
73
  def config_file?(navigation_context = :default)
44
74
  !!config_file(navigation_context)
45
75
  end
46
-
47
- # Returns the config file for the given navigation context or nil if no matching config file can be found.
48
- # If multiple config_paths are set, it returns the first matching file.
49
- #
76
+
77
+ # Returns the path to the config file for the given navigation context or nil if no matching config file can be found.
78
+ # If multiple config_paths are set, it returns the first matching path.
50
79
  def config_file(navigation_context = :default)
51
80
  config_file_paths.collect { |path| File.join(path, config_file_name(navigation_context)) }.detect {|full_path| File.exists?(full_path)}
52
81
  end
53
-
82
+
54
83
  # Returns the name of the config file for the given navigation_context
55
84
  def config_file_name(navigation_context = :default)
56
85
  prefix = navigation_context == :default ? '' : "#{navigation_context.to_s.underscore}_"
57
86
  "#{prefix}navigation.rb"
58
87
  end
59
-
60
- # Returns a nice sentence including all config_paths
61
- def config_file_paths_sentence
62
- self.config_file_paths.to_sentence(
63
- :last_word_connector => ', or ',
64
- :two_words_connector => ' or '
65
- )
66
- end
67
88
 
68
- # Sets the config_file_path
89
+ # Resets the list of config_file_paths to the specified path
69
90
  def config_file_path=(path)
70
91
  self.config_file_paths = [path]
71
92
  end
72
-
93
+
73
94
  # Reads the config_file for the specified navigation_context and stores it for later evaluation.
74
95
  def load_config(navigation_context = :default)
75
- raise "Config file for #{navigation_context} context not found in #{config_file_paths_sentence}!" unless config_file?(navigation_context)
76
- if SimpleNavigation.rails_env == 'production'
96
+ raise "Config file '#{config_file_name(navigation_context)}' not found in path(s) #{config_file_paths.join(', ')}!" unless config_file?(navigation_context)
97
+ if self.environment == 'production'
77
98
  self.config_files[navigation_context] ||= IO.read(config_file(navigation_context))
78
99
  else
79
100
  self.config_files[navigation_context] = IO.read(config_file(navigation_context))
80
101
  end
81
102
  end
82
103
 
83
- def set_template_from(context)
84
- SimpleNavigation.controller = extract_controller_from context
85
- SimpleNavigation.template = SimpleNavigation.controller.instance_variable_get(:@template) || (SimpleNavigation.controller.respond_to?(:view_context) ? SimpleNavigation.controller.view_context : nil)
86
- end
87
-
88
- # Returns the context in which the config file should be evaluated.
89
- # This is preferably the template, otherwise te controller
90
- def context_for_eval
91
- raise 'no context set for evaluation the config file' unless SimpleNavigation.template || SimpleNavigation.controller
92
- SimpleNavigation.template || SimpleNavigation.controller
93
- end
94
-
95
104
  # Returns the singleton instance of the SimpleNavigation::Configuration
96
- def config
105
+ def config
97
106
  SimpleNavigation::Configuration.instance
98
107
  end
99
-
108
+
100
109
  # Returns the ItemContainer that contains the items for the primary navigation
101
110
  def primary_navigation
102
111
  config.primary_navigation
103
112
  end
104
113
 
105
- def explicit_navigation_args
106
- self.controller.instance_variable_get(:"@sn_current_navigation_args")
107
- end
108
-
109
- # Reads the current navigation for the specified level from the controller.
110
- # Returns nil if there is no current navigation set for level.
111
- def current_navigation_for(level)
112
- self.controller.instance_variable_get(:"@sn_current_navigation_#{level}")
113
- end
114
-
115
114
  # Returns the active item container for the specified level. Valid levels are
116
115
  # * :all - in this case the primary_navigation is returned.
117
116
  # * a specific level - the active item_container for the specified level will be returned
118
117
  # * a range of levels - the active item_container for the range's minimum will be returned
119
- #
118
+ #
120
119
  # Returns nil if there is no active item_container for the specified level.
121
120
  def active_item_container_for(level)
122
121
  case level
@@ -130,104 +129,23 @@ module SimpleNavigation
130
129
  raise ArgumentError, "Invalid navigation level: #{level}"
131
130
  end
132
131
  end
133
-
134
- # If any navigation has been explicitely set in the controller this method evaluates the specified args set in the controller and sets
135
- # the correct instance variable in the controller.
136
- def handle_explicit_navigation
137
- if SimpleNavigation.explicit_navigation_args
138
- begin
139
- level, navigation = parse_explicit_navigation_args
140
- self.controller.instance_variable_set(:"@sn_current_navigation_#{level}", navigation)
141
- rescue
142
- #we do nothing here
143
- #TODO: check if this is the right way to handle wrong explicit navigation
144
- end
145
- end
146
- end
147
-
148
- # Extracts a controller from the context.
149
- def extract_controller_from(context)
150
- if context.respond_to? :controller
151
- context.controller
152
- else
153
- context
154
- end
155
- end
156
-
132
+
157
133
  # Registers a renderer.
158
134
  #
159
135
  # === Example
160
- # To register your own renderer:
136
+ # To register your own renderer:
161
137
  #
162
138
  # SimpleNavigation.register_renderer :my_renderer => My::RendererClass
163
- #
139
+ #
164
140
  # Then in the view you can call:
165
141
  #
166
142
  # render_navigation(:renderer => :my_renderer)
167
- #
168
143
  def register_renderer(renderer_hash)
169
144
  self.registered_renderers.merge!(renderer_hash)
170
- end
171
-
172
- # Returns the current request.
173
- #
174
- def request
175
- SimpleNavigation.template.request if SimpleNavigation.template
176
- end
177
-
178
- # Returns the current request's URI.
179
- #
180
- def request_uri
181
- return '' unless SimpleNavigation.request
182
- return SimpleNavigation.request.fullpath if SimpleNavigation.request.respond_to?(:fullpath)
183
- SimpleNavigation.request.request_uri
184
- end
185
-
186
- private
187
-
188
-
189
- # TODO: refactor this ugly thing to make it nice and short
190
- def parse_explicit_navigation_args
191
- args = SimpleNavigation.explicit_navigation_args
192
- args = [Hash.new] if args.empty?
193
- if args.first.kind_of? Hash
194
- options = args.first
195
- else # args is a list of current navigation for several levels
196
- options = {}
197
- if args.size == 1 #only an navi-key has been specified, try to find out level
198
- level = SimpleNavigation.primary_navigation.level_for_item(args.first)
199
- options[:"level_#{level}"] = args.first if level
200
- else
201
- args.each_with_index {|arg, i| options[:"level_#{i + 1}"] = arg}
202
- end
203
- end
204
- #only the deepest level is relevant
205
- level = options.inject(0) do |max, kv|
206
- kv.first.to_s =~ /level_(\d)/
207
- max = $1.to_i if $1.to_i > max
208
- max
209
- end
210
- raise ArgumentError, "Invalid level specified or item key not found" if level == 0
211
- [level, options[:"level_#{level}"]]
212
- end
145
+ end
213
146
 
214
147
  end
215
148
 
216
149
  end
217
150
 
218
- # TODOs for the next releases:
219
- # 1) add ability to specify explicit highlighting in the config-file itself (directly with the item)
220
- # - item.highlight_on :controller => 'users', :action => 'show' ...^
221
- # --> with that we can get rid of the controller_methods...
222
- #
223
- # 2) ability to turn off autohighlighting for a single item...
224
- #
225
- # 3) add JoinRenderer (HorizontalRenderer?) (wich does not render a list, but just the items joined with a specified char (e.g. | ))
226
- #
227
- # 4) Enhance SampleProject (more examples)
228
- #
229
- # 5) Make SampleProject public
230
- #
231
- # - allow :function navigation item to specify function
232
- # - allow specification of link-options in item (currently options are passed to li-element)
233
- # - render_navigation: do not rescue from config-file not found error if no items are passed in directly
151
+ SimpleNavigation.load_adapter
@@ -0,0 +1,9 @@
1
+ require 'simple_navigation/adapters/base'
2
+
3
+ module SimpleNavigation
4
+ module Adapters
5
+ autoload :Rails, 'simple_navigation/adapters/rails'
6
+ autoload :Padrino, 'simple_navigation/adapters/padrino'
7
+ autoload :Sinatra, 'simple_navigation/adapters/sinatra'
8
+ end
9
+ end
@@ -0,0 +1,37 @@
1
+ module SimpleNavigation
2
+ module Adapters
3
+
4
+ # This is the base class for all adapters. This class mainly exists for documenting reasons.
5
+ # It lists all the methods that an adapter should implement.
6
+ #
7
+ class Base
8
+ attr_reader :context, :request
9
+
10
+ # This method is usually called when the framework is initialized.
11
+ # It should call SimpleNavigation.set_env and install SimpleNavigation::Helpers where appropriate.
12
+ def self.register; end
13
+
14
+ # Returns the full path incl. query params
15
+ def request_uri; end
16
+
17
+ # Returns the path without query params
18
+ def request_path; end
19
+
20
+ # Returns the context in which the config files will be evaluated
21
+ def context_for_eval; end
22
+
23
+ # Returns true if the current request's url matches the specified url.
24
+ # Used to determine if an item should be autohighlighted.
25
+ def current_page?(url); end
26
+
27
+ # Returns a link with the specified name, url and options.
28
+ # Used for rendering.
29
+ def link_to(name, url, options={}); end
30
+
31
+ # Returns a tag of the specified type, content and options.
32
+ # Used for rendering.
33
+ def content_tag(type, content, options={}); end
34
+
35
+ end
36
+ end
37
+ end