codeplant / simple-navigation

A ruby gem for creating navigations (with multiple levels) for your Rails, Sinatra or Padrino applications. Render your navigation as html list, link list or breadcrumbs.
http://simple-navigation-demo.codeplant.ch/
MIT License
885 stars 136 forks source link

Feature suggestion: menu modification #138

Closed wvengen closed 5 years ago

wvengen commented 10 years ago

When putting some functionality of an app in engines, it can be useful to add something to the menu, or modify it. This is possible currently, but not documented and as such unclear if the method will keep working on updates.

Suggestion: add menu modification to the wishlist.

Perhaps it would be to (allow to) load menus from <plugin>/config/navigation.rb, but the order of loading would require some thought.

I'm currently using this method based on this gist.

ianneub commented 10 years ago

I'm also following the Engines pattern and this little trick was awesome. Thanks!

:+1: For a more "official" solution.

simonc commented 10 years ago

I don't really know what to think about this. @andi do you have any thoughts on that subject?

mjtko commented 10 years ago

Wow, I wrote that gist an awful long time ago. :grinning:

I'm not sure how we can support this without cluttering the configuration code with Rails specifics. I think this is two things:

  1. A request for supporting the enhancement of navigation from engines
  2. A request to define a cleaner API for modifying existing navigation programatically

(Warning, thinking aloud follows!)

Perhaps, for (1) we could introduce a SimpleNavigation::Provider mixin that, when included into an Engine (or any other class) registers its interest in enhancing the navigation when it's configured. At configuration time, SImpleNavigation would configure the navigation and then hand it off to each provider for further enhancement.

For (2), we could add to the API to replace the invocation of: primary[:existing_sub_menu].sub_navigation.items with modify(:existing_sub_menu) { |nav| ... } or somesuch.

andi commented 10 years ago

I think I would prefer 2)… But in general I’m not sure if this is an edge case. What are real world examples of changing the menu in an engine?

On Tue, Jul 29, 2014 at 3:04 PM, Mark J. Titorenko <notifications@github.com

wrote:

Wow, I wrote that gist an awful long time ago. [image: :grinning:]

I'm not sure how we can support this without cluttering the configuration code with Rails specifics. I think this is two things:

  1. A request for supporting the enhancement of navigation from engines
  2. A request to define a cleaner API for modifying existing navigation programatically

(Warning, thinking aloud follows!)

Perhaps, for (1) we could introduce a SimpleNavigation::Provider mixin that, when included into an Engine (or any other class) registers its interest in enhancing the navigation when it's configured. At configuration time, SImpleNavigation would configure the navigation and then hand it off the each provider for further enhancement.

For (2), we could add to the API to replace the invocation of: primary[:existing_sub_menu].sub_navigation.items with modify(:existing_sub_menu) { |nav| ... } or somesuch.

— Reply to this email directly or view it on GitHub https://github.com/codeplant/simple-navigation/issues/138#issuecomment-50472994 .

simonc commented 10 years ago

I suppose a blog engine could want to add the "Blog" entry to the menu or something like that. If you adopt the completely decoupled approach to Rails with engines composition, it could probably make sense.

ianneub commented 10 years ago

Here is a use case from my application:

I have a Rails app that is split up into many Rails engines. I have one Rails app that acts as the "top level" that includes all the other apps and sets up the layout. In that application I use Simple Navigation, and each engine needs to be able to plug into that interface to be able to display its navigation items.

The way I "fixed" it was the following:

In one of the engines (the ui engine) I have this:

SimpleNavigation::Configuration.run do |navigation|
  engines = Rails::Engine.subclasses.map(&:instance).select do |e|
    e.respond_to?(:navigation)
  end

  navigation.items do |primary|
    engines.sort{|a,b| a.class.to_s <=> b.class.to_s }.each do |e|
      e.navigation(primary, self)
    end
  end
end

In each of the other included engines I have something like this (from the pages engine):

def navigation(primary, context)
  primary.item :pages, {text: "Pages", icon: 'fa fa-cube'}, context.pages.root_path, if: proc{ context.can?(:read, Page) }, highlights_on: proc{ context.controller.class.name.split("::").first == "Pages" }
end

This effectively lets each engine add its own navigation items to the menu.