Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Completely refactored the menu system to work with i18n

Menu's are now generated on demand using the MenuBuilder instead of
being created as the resources are registered. MenuItem can now store
labels as procs, which allows us to properly i18n all the menu labels
at runtime.

ActiveAdmin::Resource's are now in charge of building their own MenuItem
objects.

The controller now stores the instance of the currently selected tab in
@current_tag instead of just a string label.
  • Loading branch information...
commit 7930e2fdff2ca4adc620103073108890bace1728 1 parent b7b7401
@gregbell gregbell authored
Showing with 385 additions and 320 deletions.
  1. +1 −0  Gemfile
  2. +16 −0 features/i18n.feature
  3. +1 −2  features/step_definitions/configuration_steps.rb
  4. +3 −0  features/step_definitions/i18n_steps.rb
  5. +0 −3  lib/active_admin/application.rb
  6. +3 −3 lib/active_admin/base_controller/menu.rb
  7. +42 −30 lib/active_admin/menu.rb
  8. +75 −0 lib/active_admin/menu_builder.rb
  9. +55 −14 lib/active_admin/menu_item.rb
  10. +12 −44 lib/active_admin/namespace.rb
  11. +4 −0 lib/active_admin/page.rb
  12. +19 −21 lib/active_admin/resource/menu.rb
  13. +3 −3 lib/active_admin/views/tabbed_navigation.rb
  14. +1 −1  spec/spec_helper.rb
  15. +3 −6 spec/unit/base_controller_shared_examples.rb
  16. +14 −29 spec/unit/config_shared_examples.rb
  17. +49 −53 spec/unit/menu_item_spec.rb
  18. +47 −32 spec/unit/menu_spec.rb
  19. +0 −6 spec/unit/namespace/register_page_spec.rb
  20. +0 −7 spec/unit/namespace/register_resource_spec.rb
  21. +2 −2 spec/unit/namespace_spec.rb
  22. +1 −1  spec/unit/page_spec.rb
  23. +0 −2  spec/unit/resource_registration_spec.rb
  24. +0 −42 spec/unit/resource_spec.rb
  25. +34 −19 spec/unit/views/tabbed_navigation_spec.rb
View
1  Gemfile
@@ -25,6 +25,7 @@ group :development, :test do
gem 'haml', '~> 3.1.1', :require => false
gem 'yard'
gem 'rdiscount' # For yard
+ gem 'rails-i18n' # Gives us default i18n for many languages
end
group :test do
View
16 features/i18n.feature
@@ -17,3 +17,19 @@ Feature: Internationalization
Then I should see "Edit Bookstore"
When I press "Update Bookstore"
Then I should see a flash with "Bookstore was successfully updated."
+
+ Scenario: Switching language at runtime
+ Given I am logged in
+ And a configuration of:
+ """
+ ActiveAdmin.register Store
+ """
+ When I set my locale to "fr"
+ And I go to the dashboard
+ Then I should see "Store"
+ And I should see "Tableau de Bord"
+
+ When I set my locale to "en"
+ And I go to the dashboard
+ Then I should see "Bookstore"
+ And I should see "Dashboard"
View
3  features/step_definitions/configuration_steps.rb
@@ -4,7 +4,7 @@ def load_active_admin_configuration(configuration_content)
eval(configuration_content)
ActiveAdmin::Event.dispatch ActiveAdmin::Application::LoadEvent, ActiveAdmin.application
Rails.application.reload_routes!
- ActiveAdmin.application.namespaces.values.each{|n| n.load_menu! }
+ ActiveAdmin.application.namespaces.values.each{|n| n.reset_menu! }
end
end
@@ -46,7 +46,6 @@ def self.rollback!
Given /^a configuration of:$/ do |configuration_content|
load_active_admin_configuration(configuration_content)
- ActiveAdmin.application.namespaces.values.each{|n| n.load_menu! }
end
Given /^an index configuration of:$/ do |configuration_content|
View
3  features/step_definitions/i18n_steps.rb
@@ -0,0 +1,3 @@
+When /^I set my locale to "([^"]*)"$/ do |lang|
+ I18n.locale = lang
+end
View
3  lib/active_admin/application.rb
@@ -163,9 +163,6 @@ def load!
# If no configurations, let's make sure you can still login
load_default_namespace if namespaces.values.empty?
- # Load Menus
- namespaces.values.each{|namespace| namespace.load_menu! }
-
# Dispatch an ActiveAdmin::Application::LoadEvent with the Application
ActiveAdmin::Event.dispatch LoadEvent, self
View
6 lib/active_admin/base_controller/menu.rb
@@ -18,11 +18,11 @@ def current_menu
# Get's called through a before filter
def set_current_tab
@current_tab = if active_admin_config.belongs_to? && parent?
- active_admin_config.belongs_to_config.target.menu_item_name
+ active_admin_config.belongs_to_config.target.menu_item
else
- [active_admin_config.parent_menu_item_name, active_admin_config.menu_item_name].compact.join("/")
+ active_admin_config.menu_item
end
- end
+ end
end
end
View
72 lib/active_admin/menu.rb
@@ -1,42 +1,54 @@
module ActiveAdmin
+
class Menu
-
+
+ attr_accessor :children
+
def initialize
- @items = []
+ @children = Menu::ItemCollection.new
+
yield(self) if block_given?
- end
-
- def add(*args, &block)
- @items << MenuItem.new(*args, &block)
end
-
- def [](name)
- items.find{ |i| i.name == name }
+
+ # Add a new MenuItem to the menu
+ #
+ # Example:
+ # menu = Menu.new
+ # dash = MenuItem.new :label => "Dashboard"
+ # menu.add dash
+ #
+ # Accepts as many menu items as you wish to add:
+ #
+ # menu = Menu.new
+ # dash = MenuItem.new :label => "Dashboard"
+ # admin = MenuItem.new :label => "Admin"
+ # menu.add dash, admin
+ #
+ # @param [MenuItem] menu_items Add as many menu items as you pass in
+ def add(*menu_items)
+ menu_items.each do |menu_item|
+ menu_item.parent = nil
+ @children << menu_item
+ end
end
-
- def items
- @items.sort
+
+ def [](id)
+ @children.find_by_id(id)
end
-
- def find_by_url(url)
- recursive_find_by_url(items, url)
+
+ def items
+ @children.sort
end
-
- private
-
- def recursive_find_by_url(collection, url)
- found = nil
- collection.each do |item|
- if item.url == url
- found = item
- break
- else
- found = recursive_find_by_url(item.children, url)
- break if found
- end
+
+ class ItemCollection < Array
+
+ def find_by_id(id)
+ id = MenuItem.generate_item_id(id)
+ find{ |i| i.id == id }
end
- found
+
end
-
+
end
+
end
View
75 lib/active_admin/menu_builder.rb
@@ -0,0 +1,75 @@
+module ActiveAdmin
+
+ class MenuBuilder
+
+ def self.build_for_namespace(namespace)
+ new(namespace).menu
+ end
+
+ attr_reader :menu
+
+ def initialize(namespace)
+ @namespace = namespace
+ end
+
+ def menu
+ @menu ||= build_menu
+ end
+
+ private
+
+ def namespace
+ @namespace
+ end
+
+ def build_menu
+ menu = Menu.new
+
+ add_dashboard_to_menu(menu)
+
+ namespace.resources.each do |resource|
+ register_with_menu(menu, resource) if resource.include_in_menu?
+ end
+
+ menu
+ end
+
+ def add_dashboard_to_menu(menu)
+ dashboard_path = namespace.root? ? :dashboard_path : "#{@namespace.name}_dashboard_path".to_sym
+
+ item = MenuItem.new :id => "dashboard",
+ :label => proc{ I18n.t("active_admin.dashboard") },
+ :url => dashboard_path,
+ :priority => 1
+ menu.add item
+ end
+
+ # Does all the work of registernig a config with the menu system
+ def register_with_menu(menu, resource)
+ # The menu we're going to add this resource to
+ add_to = menu
+
+ # Adding as a child
+ if resource.parent_menu_item_name
+ # Create the parent if it doesn't exist
+ unless menu[resource.parent_menu_item_name]
+ item = MenuItem.new(:label => resource.parent_menu_item_name, :url => "#", :id => resource.parent_menu_item_name)
+ add_to.add(item)
+ end
+
+ add_to = menu[resource.parent_menu_item_name]
+ end
+
+ if add_to[resource.menu_item.id]
+ existing = add_to[resource.menu_item.id]
+ add_to.children.delete(existing)
+ add_to.add(resource.menu_item)
+ resource.menu_item.add(*existing.children)
+ else
+ add_to.add resource.menu_item
+ end
+ end
+
+ end
+
+end
View
69 lib/active_admin/menu_item.rb
@@ -1,22 +1,63 @@
module ActiveAdmin
+
class MenuItem
- attr_accessor :name, :url, :priority, :parent, :display_if_block
+ attr_accessor :id, :label, :url, :priority, :parent, :display_if_block, :children
- def initialize(name, url, priority = 10, options = {})
- @name, @url, @priority = name, url, priority
- @children = []
- @cached_url = {} # Stores the cached url in a hash to allow us to change it and still cache it
+ # Build a new menu item
+ #
+ # @param [Hash] options The options for the menu
+ #
+ # @option options [String, Proc] :label
+ # The label to display for this menu item. It can either be a String or a
+ # Proc. If the option is Proc, it is called each time the label is requested.
+ #
+ # @option options [String] :id
+ # A custom id to reference this menu item with. If empty an id is automatically
+ # generated for you.
+ #
+ # @option options [String, Symbol] :url
+ # A string or symbol representing the url for this item. If it's a symbol, the
+ # view will automatically call the method for you.
+ #
+ # @option options [Integer] :priority
+ # MenuItems are sorted by priority then by label. The lower the priority, the
+ # earlier in the menu the item will be displayed.
+ # Default: 10
+ #
+ # @option options [Proc] :if
+ # A block for the view to call to decide if this menu item should be displayed.
+ # The block should return true of false
+ def initialize(options = {})
+ @label = options[:label]
+ @id = MenuItem.generate_item_id(options[:id] || label)
+ @url = options[:url]
+ @priority = options[:priority] || 10
+ @children = Menu::ItemCollection.new
- @display_if_block = options.delete(:if)
+ @display_if_block = options[:if]
yield(self) if block_given? # Builder style syntax
end
- def add(name, url, priority=10, options = {}, &block)
- item = MenuItem.new(name, url, priority, options, &block)
- item.parent = self
- @children << item
+ def self.generate_item_id(id)
+ id.to_s.downcase.gsub(" ", "_")
+ end
+
+ def label
+ case @label
+ when Proc
+ @label.call
+ else
+ @label.to_s
+ end
+ end
+
+ def add(*menu_items)
+ menu_items.each do |menu_item|
+ menu_item.parent = self
+ @children << menu_item
+ end
end
def children
@@ -28,7 +69,7 @@ def parent?
end
def dom_id
- name.downcase.gsub( " ", '_' ).gsub( /[^a-z0-9_]/, '' )
+ id.gsub( " ", '_' ).gsub( /[^a-z0-9_]/, '' )
end
# Returns an array of the ancestory of this menu item
@@ -40,13 +81,13 @@ def ancestors
# Returns the child item with the name passed in
# @blog_menu["Create New"] => <#MenuItem @name="Create New" >
- def [](name)
- @children.find{ |i| i.name == name }
+ def [](id)
+ @children.find_by_id(id)
end
def <=>(other)
result = priority <=> other.priority
- result = name <=> other.name if result == 0
+ result = label <=> other.label if result == 0
result
end
View
56 lib/active_admin/namespace.rb
@@ -1,5 +1,6 @@
require 'active_admin/helpers/settings'
require 'active_admin/resource_collection'
+require 'active_admin/menu_builder'
module ActiveAdmin
@@ -38,7 +39,6 @@ def initialize(application, name)
@application = application
@name = name.to_s.underscore.to_sym
@resources = ResourceCollection.new
- @menu = Menu.new
register_module unless root?
generate_dashboard_controller
end
@@ -52,7 +52,7 @@ def register(resource_class, options = {}, &block)
# Register the resource
register_resource_controller(config)
parse_registration_block(config, &block) if block_given?
- register_with_menu(config) if config.include_in_menu?
+ reset_menu!
# Ensure that the dashboard is generated
generate_dashboard_controller
@@ -70,7 +70,7 @@ def register_page(name, options = {}, &block)
# Register the resource
register_page_controller(config)
parse_page_registration_block(config, &block) if block_given?
- register_with_menu(config) if config.include_in_menu?
+ reset_menu!
config
end
@@ -100,16 +100,7 @@ def dashboard_controller_name
def unload!
unload_resources!
unload_dashboard!
- unload_menu!
- end
-
- # The menu gets built by Active Admin once all the resources have been
- # loaded. This method gets called to register each resource with the menu system.
- def load_menu!
- register_dashboard
- resources.each do |resource|
- register_with_menu(resource) if resource.include_in_menu?
- end
+ reset_menu!
end
# Returns the first registered ActiveAdmin::Resource instance for a given class
@@ -123,6 +114,14 @@ def read_default_setting(name)
application.send(name)
end
+ def menu
+ @menu ||= MenuBuilder.build_for_namespace(self)
+ end
+
+ def reset_menu!
+ @menu = nil
+ end
+
protected
# Either returns an existing Resource instance or builds a new
@@ -135,7 +134,6 @@ def build_page(name, options)
resources.add Page.new(self, name, options)
end
-
def register_page_controller(config)
eval "class ::#{config.controller_name} < ActiveAdmin::PageController; end"
config.controller.active_admin_config = config
@@ -156,10 +154,6 @@ def unload_dashboard!
Dashboards.clear_all_sections!
end
- def unload_menu!
- @menu = Menu.new
- end
-
# Creates a ruby module to namespace all the classes in if required
def register_module
eval "module ::#{module_name}; end"
@@ -191,31 +185,5 @@ def generate_dashboard_controller
eval "class ::#{dashboard_controller_name} < ActiveAdmin::Dashboards::DashboardController; end"
end
- # Adds the dashboard to the menu
- def register_dashboard
- dashboard_path = root? ? :dashboard_path : "#{name}_dashboard_path".to_sym
- menu.add(I18n.t("active_admin.dashboard"), dashboard_path, 1) unless menu[I18n.t("active_admin.dashboard")]
- end
-
- # Does all the work of registernig a config with the menu system
- def register_with_menu(config)
- # The menu we're going to add this resource to
- add_to = menu
-
- # Adding as a child
- if config.parent_menu_item_name
- # Create the parent if it doesn't exist
- menu.add(config.parent_menu_item_name, '#') unless menu[config.parent_menu_item_name]
- add_to = menu[config.parent_menu_item_name]
- end
-
- # Check if this menu item has already been created
- if add_to[config.menu_item_name]
- # Update the url if it's already been created
- add_to[config.menu_item_name].url = config.route_collection_path
- else
- add_to.add(config.menu_item_name, config.route_collection_path, config.menu_item_priority, { :if => config.menu_item_display_if })
- end
- end
end
end
View
4 lib/active_admin/page.rb
@@ -44,6 +44,10 @@ def resource_name
@resource_name ||= ActiveModel::Name.new(nil, nil, name)
end
+ def default_menu_options
+ super.merge(:id => resource_name)
+ end
+
def controller_name
[namespace.module_name, resource_name + "Controller"].compact.join('::')
end
View
40 lib/active_admin/resource/menu.rb
@@ -5,38 +5,36 @@ module Menu
# Set the menu options. To not add this resource to the menu, just
# call #menu(false)
def menu(options = {})
- options = options == false ? { :display => false } : options
- @menu_options = options
+ if options == false
+ @display_menu = false
+ else
+ options = default_menu_options.merge(options)
+ @parent_menu_item = options.delete(:parent)
+ @menu_item = MenuItem.new(default_menu_options.merge(options))
+ end
end
- # The options to use for the menu
- def menu_options
- @menu_options ||= {}
+ def menu_item
+ @menu_item ||= MenuItem.new(default_menu_options)
end
- # Returns the name to put this resource under in the menu
def parent_menu_item_name
- menu_options[:parent]
+ return nil unless @parent_menu_item
+ ActiveModel::Name.new(nil, nil, @parent_menu_item)
end
- # Returns the name to be displayed in the menu for this resource
- def menu_item_name
- menu_options[:label] || plural_resource_label
- end
-
- # Returns the items priority for altering the default sort order
- def menu_item_priority
- menu_options[:priority] || 10
- end
-
- # Returns a proc for deciding whether to display the menu item or not in the view
- def menu_item_display_if
- menu_options[:if] || proc { true }
+ # The default menu options to pass through to MenuItem.new
+ def default_menu_options
+ {
+ :id => resource_name.plural,
+ :label => proc{ plural_resource_label },
+ :url => route_collection_path
+ }
end
# Should this resource be added to the menu system?
def include_in_menu?
- menu_options[:display] != false
+ @display_menu != false
end
end
View
6 lib/active_admin/views/tabbed_navigation.rb
@@ -46,10 +46,10 @@ def build_menu_item(item)
if item.children.any?
li_element.add_class "has_nested"
- text_node link_to(item.name, link_path)
+ text_node link_to(item.label, link_path)
render_nested_menu(item)
else
- link_to item.name, link_path
+ link_to item.label, link_path
end
end
end
@@ -79,7 +79,7 @@ def default_options
# Returns true if the menu item name is @current_tab (set in controller)
def current?(menu_item)
- assigns[:current_tab].split("/").include?(menu_item.name) unless assigns[:current_tab].blank?
+ assigns[:current_tab] == menu_item || menu_item.children.include?(assigns[:current_tab])
end
# Returns an Array of items to display
View
2  spec/spec_helper.rb
@@ -13,7 +13,7 @@ def load_defaults!
end
def reload_menus!
- ActiveAdmin.application.namespaces.values.each{|n| n.load_menu! }
+ ActiveAdmin.application.namespaces.values.each{|n| n.reset_menu! }
end
# Sometimes we need to reload the routes within
View
9 spec/unit/base_controller_shared_examples.rb
@@ -14,14 +14,11 @@
subject{ controller.instance_variable_get(:@current_tab) }
context "when menu item name is 'Resources' without a parent menu item" do
- let(:resource){ mock(:menu_item_name => "Resources", :parent_menu_item_name => nil, :belongs_to? => false) }
- it { should == "Resources" }
+ let(:menu_item){ stub }
+ let(:resource){ mock(:menu_item => menu_item, :parent_menu_item_name => nil, :belongs_to? => false) }
+ it { should == menu_item }
end
- context "when there is a parent menu item of 'Admin'" do
- let(:resource){ mock(:parent_menu_item_name => "Admin", :menu_item_name => "Resources", :belongs_to? => false) }
- it { should == "Admin/Resources" }
- end
end
end
View
43 spec/unit/config_shared_examples.rb
@@ -31,14 +31,17 @@
end
describe "Menu" do
- describe "menu item name" do
- it "should be the plural resource label when not set" do
- config.menu_item_name.should == config.plural_resource_label
- end
- it "should be settable" do
- config.menu :label => "My Label"
- config.menu_item_name.should == "My Label"
+ describe "menu item" do
+
+ it "initializes a new menu item with defaults" do
+ config.menu_item.label.should == config.plural_resource_label
+ end
+
+ it "initialize a new menu item with custom options" do
+ config.menu :label => "Hello"
+ config.menu_item.label.should == "Hello"
end
+
end
describe "#include_in_menu?" do
@@ -53,35 +56,17 @@
end
describe "parent menu item name" do
+
it "should be nil when not set" do
config.parent_menu_item_name.should == nil
end
+
it "should return the name if set" do
- config.tap do |c|
- c.menu :parent => "Blog"
- end.parent_menu_item_name.should == "Blog"
+ config.menu :parent => "Blog"
+ config.parent_menu_item_name.should == "Blog"
end
- end
- describe "menu item priority" do
- it "should be 10 when not set" do
- config.menu_item_priority.should == 10
- end
- it "should be settable" do
- config.menu :priority => 2
- config.menu_item_priority.should == 2
- end
end
- describe "menu item display if" do
- it "should be a proc always returning true if not set" do
- config.menu_item_display_if.should be_instance_of(Proc)
- config.menu_item_display_if.call.should == true
- end
- it "should be settable" do
- config.menu :if => proc { false }
- config.menu_item_display_if.call.should == false
- end
- end
end
end
View
102 spec/unit/menu_item_spec.rb
@@ -1,75 +1,73 @@
require 'spec_helper_without_rails'
+require 'active_admin/menu'
require 'active_admin/menu_item'
module ActiveAdmin
describe MenuItem do
- it "should have a name" do
- item = MenuItem.new("Dashboard", "/admin")
- item.name.should == "Dashboard"
+ it "should have a label" do
+ item = MenuItem.new(:label => "Dashboard")
+ item.label.should == "Dashboard"
end
it "should have a url" do
- item = MenuItem.new("Dashboard", "/admin")
+ item = MenuItem.new(:url => "/admin")
item.url.should == "/admin"
end
it "should have a priority of 10 by default" do
- item = MenuItem.new("Dashboard", "/admin")
+ item = MenuItem.new
item.priority.should == 10
end
- it "should accept an optional options hash" do
- item = MenuItem.new("Dashboard", "/admin", 10, :if => lambda{ logged_in? } )
- end
-
it "should have a display if block" do
block = lambda{ logged_in? }
- item = MenuItem.new("Dashboard", "/admin", 10, :if => block )
+ item = MenuItem.new(:if => block )
item.display_if_block.should == block
end
it "should have a default display if block always returning true" do
- item = MenuItem.new("Dashboard", "/admin")
+ item = MenuItem.new
item.display_if_block.should be_instance_of(Proc)
item.display_if_block.call(self).should == true
end
context "with no children" do
it "should be empty" do
- item = MenuItem.new("Blog", "/admin/blog")
+ item = MenuItem.new
+ item.children.should be_an_instance_of(Menu::ItemCollection)
item.children.should == []
end
it "should accept new children" do
- item = MenuItem.new("Blog", "/admin/blog")
- item.add "Dashboard", "/admin"
+ item = MenuItem.new
+ item.add MenuItem.new(:label => "Dashboard")
item.children.first.should be_an_instance_of(MenuItem)
- item.children.first.name.should == "Dashboard"
+ item.children.first.label.should == "Dashboard"
end
end
context "with many children" do
let(:item) do
- i = MenuItem.new("Dashboard", "/admin")
- i.add "Blog", "/"
- i.add "Cars", "/"
- i.add "Users", "/", 1
- i.add "Settings", "/", 2
- i.add "Analytics", "/", 44
+ i = MenuItem.new(:label => "Dashboard")
+ i.add MenuItem.new(:label => "Blog")
+ i.add MenuItem.new(:label => "Cars")
+ i.add MenuItem.new(:label => "Users", :priority => 1)
+ i.add MenuItem.new(:label => "Settings", :priority => 2)
+ i.add MenuItem.new(:label => "Analytics", :priority => 44)
i
end
it "should give access to the menu item as an array" do
- item['Blog'].name.should == 'Blog'
+ item['Blog'].label.should == 'Blog'
end
it "should sort items based on priority and name" do
- item.children[0].name.should == 'Users'
- item.children[1].name.should == 'Settings'
- item.children[2].name.should == 'Blog'
- item.children[3].name.should == 'Cars'
- item.children[4].name.should == 'Analytics'
+ item.children[0].label.should == 'Users'
+ item.children[1].label.should == 'Settings'
+ item.children[2].label.should == 'Blog'
+ item.children[3].label.should == 'Cars'
+ item.children[4].label.should == 'Analytics'
end
it "children should hold a reference to their parent" do
@@ -77,27 +75,8 @@ module ActiveAdmin
end
end
- describe "building children using block syntax" do
- let(:item) do
- MenuItem.new("Blog", "/") do |blog|
- blog.add "Create New", "/blog/new"
- blog.add("Comments", "/blog/comments") do |comments|
- comments.add "Approved", "/blog/comments?status=approved"
- end
- end
- end
-
- it "should have 2 children" do
- item.children.size.should == 2
- end
-
- it "should have sub-sub items" do
- item["Comments"]["Approved"].name.should == 'Approved'
- end
- end
-
describe "accessing ancestory" do
- let(:item){ MenuItem.new "Blog", "/blog" }
+ let(:item){ MenuItem.new :label => "Blog" }
context "with no parent" do
it "should return an empty array" do
@@ -107,7 +86,7 @@ module ActiveAdmin
context "with one parent" do
let(:sub_item) do
- item.add "Create New", "/blog/new"
+ item.add MenuItem.new(:label => "Create New")
item["Create New"]
end
it "should return an array with the parent" do
@@ -117,11 +96,15 @@ module ActiveAdmin
context "with many parents" do
before(:each) do
- item.add "C1", "/c1" do |c1|
- c1.add "C2", "/c2" do |c2|
- c2.add "C3", "/c3"
- end
- end
+ c1 = MenuItem.new(:label => "C1")
+ c2 = MenuItem.new(:label => "C2")
+ c3 = MenuItem.new(:label => "C3")
+
+ item.add(c1)
+ c1.add c2
+ c2.add c3
+
+ item
end
let(:sub_item){ item["C1"]["C2"]["C3"] }
it "should return an array with the parents in reverse order" do
@@ -130,5 +113,18 @@ module ActiveAdmin
end
end # accessing ancestory
+
+ describe ".generate_item_id" do
+
+ it "downcases the id" do
+ MenuItem.generate_item_id("Identifier").should == "identifier"
+ end
+
+ it "should set underscore any spaces" do
+ MenuItem.generate_item_id("An Id").should == "an_id"
+ end
+
+ end
+
end
end
View
79 spec/unit/menu_spec.rb
@@ -1,52 +1,67 @@
-require 'spec_helper'
+require 'spec_helper_without_rails'
+require 'active_admin/menu'
+require 'active_admin/menu_item'
+
+include ActiveAdmin
describe ActiveAdmin::Menu do
context "with no items" do
- it "should be empty" do
- ActiveAdmin::Menu.new.items.should == []
+
+ it "should have an empty item collection" do
+ menu = Menu.new
+ menu.items.should be_an_instance_of(Menu::ItemCollection)
+ menu.items.should be_empty
end
-
+
it "should accept new items" do
- menu = ActiveAdmin::Menu.new
- menu.add "Dashboard", "/admin"
- menu.items.first.should be_an_instance_of(ActiveAdmin::MenuItem)
- menu.items.first.name.should == "Dashboard"
- end
-
- it "should default new items to the priority of 10" do
- menu = ActiveAdmin::Menu.new
- menu.add "Dashboard", "/admin"
- menu.items.first.priority.should == 10
+ menu = Menu.new
+ item = MenuItem.new
+ menu.add item
+ menu.items.first.should == item
end
+
end
-
+
context "with many item" do
let(:menu) do
- ActiveAdmin::Menu.new do |m|
- m.add "Dashboard", "/admin"
- m.add "Blog", "/admin/blog"
- m.add "Users", "/admin/users"
- m.add "Settings", "/admin/settings" do |s|
- s.add "Admin Settings", "/admin/settings/admin" do |as|
- s.add "User Settings", "/admin/settings/users"
- end
- end
+ Menu.new do |m|
+ m.add MenuItem.new(:label => "Dashboard")
+ m.add MenuItem.new(:label => "Blog")
end
end
it "should give access to the menu item as an array" do
- menu['Dashboard'].name.should == 'Dashboard'
+ menu['Dashboard'].label.should == 'Dashboard'
end
-
- it "should find the item by a url on the top level" do
- menu.find_by_url("/admin").name.should == "Dashboard"
+ end
+
+ describe Menu::ItemCollection do
+
+ let(:collection) { Menu::ItemCollection.new }
+
+ it "should initialize" do
+ collection.should be_empty
end
-
- it "should find the item deep in the tree" do
- menu.find_by_url("/admin/settings/users").name.should == "User Settings"
+
+ describe "#find_by_id" do
+ let(:menu_item) { MenuItem.new(:id => "an_id") }
+
+ before do
+ collection.push menu_item
+ end
+
+ it "retrieve an item id" do
+ MenuItem.should_receive(:generate_item_id).with("an_id").and_return("an_id")
+ collection.find_by_id("an_id").should == menu_item
+ end
+
+ it "returns nil when no matching ids" do
+ collection.find_by_id("not matching").should == nil
+ end
+
end
-
+
end
end
View
6 spec/unit/namespace/register_page_spec.rb
@@ -20,7 +20,6 @@
end
it "should create a menu item" do
- namespace.load_menu!
namespace.menu["Status"].should be_an_instance_of(ActiveAdmin::MenuItem)
end
end # context "with no configuration"
@@ -39,7 +38,6 @@
describe "adding as a top level item" do
before do
namespace.register_page "Status"
- namespace.load_menu!
end
it "should add a new menu item" do
@@ -52,7 +50,6 @@
namespace.register_page "Status" do
menu :parent => 'Extra'
end
- namespace.load_menu!
end
it "should generate the parent menu item" do
namespace.menu['Extra'].should_not be_nil
@@ -67,7 +64,6 @@
namespace.register_page "Status" do
menu false
end
- namespace.load_menu!
end
it "should not create a menu item" do
namespace.menu["Status"].should be_nil
@@ -79,7 +75,6 @@
namespace.register_page "Status" do
menu :priority => 2
end
- namespace.load_menu!
end
it "should have a custom priority of 2" do
namespace.menu["Status"].priority.should == 2
@@ -91,7 +86,6 @@
namespace.register_page "Status" do
menu :if => proc { false }
end
- namespace.load_menu!
end
it "should have a proc returning false" do
namespace.menu["Status"].display_if_block.should be_instance_of(Proc)
View
7 spec/unit/namespace/register_resource_spec.rb
@@ -20,7 +20,6 @@
defined?(Admin::DashboardController).should be_true
end
it "should create a menu item" do
- namespace.load_menu!
namespace.menu["Categories"].should be_an_instance_of(ActiveAdmin::MenuItem)
namespace.menu["Categories"].url.should == :admin_categories_path
end
@@ -49,7 +48,6 @@ module ::Mock; class Resource; def self.has_many(arg1, arg2); end; end; end
defined?(Admin::MockResourcesController).should be_true
end
it "should create a menu item" do
- namespace.load_menu!
namespace.menu["Mock Resources"].should be_an_instance_of(ActiveAdmin::MenuItem)
end
@@ -88,7 +86,6 @@ module ::Mock; class Resource; def self.has_many(arg1, arg2); end; end; end
describe "adding as a top level item" do
before do
namespace.register Category
- namespace.load_menu!
end
it "should add a new menu item" do
namespace.menu['Categories'].should_not be_nil
@@ -100,7 +97,6 @@ module ::Mock; class Resource; def self.has_many(arg1, arg2); end; end; end
namespace.register Category do
menu :parent => 'Blog'
end
- namespace.load_menu!
end
it "should generate the parent menu item" do
namespace.menu['Blog'].should_not be_nil
@@ -115,7 +111,6 @@ module ::Mock; class Resource; def self.has_many(arg1, arg2); end; end; end
namespace.register Category do
menu false
end
- namespace.load_menu!
end
it "should not create a menu item" do
namespace.menu["Categories"].should be_nil
@@ -127,7 +122,6 @@ module ::Mock; class Resource; def self.has_many(arg1, arg2); end; end; end
namespace.register Category do
menu :priority => 2
end
- namespace.load_menu!
end
it "should have a custom priority of 2" do
namespace.menu["Categories"].priority.should == 2
@@ -139,7 +133,6 @@ module ::Mock; class Resource; def self.has_many(arg1, arg2); end; end; end
namespace.register Category do
menu :if => proc { false }
end
- namespace.load_menu!
end
it "should have a proc returning false" do
namespace.menu["Categories"].display_if_block.should be_instance_of(Proc)
View
4 spec/unit/namespace_spec.rb
@@ -19,8 +19,8 @@
namespace.resources.resources.should be_empty
end
- it "should have an empty menu" do
- namespace.menu.items.should be_empty
+ it "should have one menu item (dashboard)" do
+ namespace.menu.items.size.should == 1
end
end # context "when new"
View
2  spec/unit/page_spec.rb
@@ -11,7 +11,7 @@ module ActiveAdmin
let(:namespace){ Namespace.new(application, :admin) }
def config(options = {})
- @config ||= Page.new(namespace, "Status", options)
+ @config ||= namespace.register_page("Status", options)
end
describe "controller name" do
View
2  spec/unit/resource_registration_spec.rb
@@ -28,7 +28,6 @@
end
it "should generate a menu item for the dashboard" do
application.register Category, :namespace => :hello_world
- application.namespaces[:hello_world].load_menu!
application.namespaces[:hello_world].menu['Dashboard'].instance_variable_get("@url").should == :hello_world_dashboard_path
end
it "should generate a Namespace::RegisterEvent and a Resource::RegisterEvent" do
@@ -49,7 +48,6 @@
it "should generate a menu item for the dashboard" do
application.register Category, :namespace => false
- application.namespaces[:root].load_menu!
application.namespaces[:root].menu['Dashboard'].instance_variable_get("@url").should == :dashboard_path
end
View
42 spec/unit/resource_spec.rb
@@ -62,48 +62,6 @@ def config(options = {})
end
end
- describe "menu item name" do
- it "should be the resource name when not set" do
- config.menu_item_name.should == "Categories"
- end
- it "should be settable" do
- config.menu :label => "My Label"
- config.menu_item_name.should == "My Label"
- end
- end
-
- describe "parent menu item name" do
- it "should be nil when not set" do
- config.parent_menu_item_name.should == nil
- end
- it "should return the name if set" do
- config.tap do |c|
- c.menu :parent => "Blog"
- end.parent_menu_item_name.should == "Blog"
- end
- end
-
- describe "menu item priority" do
- it "should be 10 when not set" do
- config.menu_item_priority.should == 10
- end
- it "should be settable" do
- config.menu :priority => 2
- config.menu_item_priority.should == 2
- end
- end
-
- describe "menu item display if" do
- it "should be a proc always returning true if not set" do
- config.menu_item_display_if.should be_instance_of(Proc)
- config.menu_item_display_if.call.should == true
- end
- it "should be settable" do
- config.menu :if => proc { false }
- config.menu_item_display_if.call.should == false
- end
- end
-
describe "route names" do
it "should return the route prefix" do
config.route_prefix.should == "admin"
View
53 spec/unit/views/tabbed_navigation_spec.rb
@@ -1,5 +1,6 @@
require 'spec_helper'
+include ActiveAdmin
describe ActiveAdmin::Views::TabbedNavigation do
setup_arbre_context!
@@ -16,18 +17,30 @@
describe "rendering a menu" do
before do
- menu.add "Blog Posts", :admin_posts_path
- menu.add "Reports", "/admin/reports"
+ menu.add MenuItem.new(:label => "Blog Posts", :url => :admin_posts_path)
+ menu.add MenuItem.new(:label => "Reports", :url => "/admin/reports")
+ menu.add MenuItem.new(:label => "Administration", :url => "/admin/administration")
+ menu.add MenuItem.new(:label => "Management", :url => "#")
+
reports = menu["Reports"]
- reports.add "A Sub Reports", "/admin/a-sub-reports"
- reports.add "B Sub Reports", "/admin/b-sub-reports"
- menu.add "Administration", "/admin/administration"
+ reports.add MenuItem.new(:label => "A Sub Reports", :url => "/admin/a-sub-reports")
+ reports.add MenuItem.new(:label => "B Sub Reports", :url => "/admin/b-sub-reports")
+
administration = menu["Administration"]
- administration.add "User administration", '/admin/user-administration', 10, :if => proc { false }
- menu.add "Management", "#"
+ administration.add MenuItem.new(:label => "User administration",
+ :url => '/admin/user-administration',
+ :priority => 10,
+ :if => proc { false })
+
management = menu["Management"]
- management.add "Order management", '/admin/order-management', 10, :if => proc { false }
- management.add "Bill management", '/admin/bill-management', 10, :if => :admin_logged_in?
+ management.add MenuItem.new(:label => "Order management",
+ :url => '/admin/order-management',
+ :priority => 10,
+ :if => proc { false })
+ management.add MenuItem.new(:label => "Bill management",
+ :url => '/admin/bill-management',
+ :priority => 10,
+ :if => :admin_logged_in?)
end
it "should generate a ul" do
@@ -74,12 +87,12 @@
describe "marking current item" do
it "should add the 'current' class to the li" do
- assigns[:current_tab] = "Blog Posts"
+ assigns[:current_tab] = menu["Blog Posts"]
html.should have_tag("li", :attributes => { :class => "current" })
end
it "should add the 'current' and 'has_nested' classes to the li and 'current' to the sub li" do
- assigns[:current_tab] = "Reports/A Sub Reports"
+ assigns[:current_tab] = menu["Reports"]["A Sub Reports"]
html.should have_tag("li", :attributes => { :id => "reports", :class => /current/ })
html.should have_tag("li", :attributes => { :id => "reports", :class => /has_nested/ })
html.should have_tag("li", :attributes => { :id => "a_sub_reports", :class => "current" })
@@ -92,32 +105,34 @@
describe "returning the menu items to display" do
it "should be reture one item with no if block" do
- menu.add "Hello World", "/"
+ menu.add MenuItem.new(:label => "Hello World", :url => "/")
tabbed_navigation.menu_items.should == menu.items
end
it "should not include a menu items with an if block that returns false" do
- menu.add "Don't Show", "/", 10, :if => proc{ false }
+ menu.add MenuItem.new(:label => "Don't Show", :url => "/", :priority => 10, :if => proc{ false })
tabbed_navigation.menu_items.should == []
end
it "should not include menu items with an if block that calls a method that returns false" do
- menu.add "Don't Show", "/", 10, :if => :admin_logged_in?
+ menu.add MenuItem.new(:label => "Don't Show", :url => "/", :priority => 10, :if => :admin_logged_in?)
tabbed_navigation.menu_items.should == []
end
it "should not display any items that have no children to display" do
- menu.add "Parent", "#" do |p|
- p.add "Child", "/", 10, :if => proc{ false }
+ item = MenuItem.new(:label => "Parent", :url => "#") do |p|
+ p.add MenuItem.new(:label => "Child", :url => "/", :priority => 10, :if => proc{ false })
end
+ menu.add item
tabbed_navigation.menu_items.should == []
end
it "should display a parent that has a child to display" do
- menu.add "Parent", "#" do |p|
- p.add "Hidden Child", "/", 10, :if => proc{ false }
- p.add "Child", "/"
+ item = MenuItem.new(:label => "Parent", :url => "#") do |p|
+ p.add MenuItem.new(:label => "Hidden Child", :url => "/", :priority => 10, :if => proc{ false })
+ p.add MenuItem.new(:label => "Child", :url => "/")
end
+ menu.add item
tabbed_navigation.should have(1).menu_items
end
Please sign in to comment.
Something went wrong with that request. Please try again.