navi 0.0.2

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.
Files changed (114) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/.rvmrc +1 -0
  4. data/Gemfile +41 -0
  5. data/Gemfile.lock +196 -0
  6. data/Guardfile +23 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.textile +26 -0
  9. data/Rakefile +50 -0
  10. data/VERSION +1 -0
  11. data/features/create_menu_items.feature +13 -0
  12. data/features/step_definitions/category_steps.rb +3 -0
  13. data/features/step_definitions/menu_item_steps.rb +19 -0
  14. data/features/step_definitions/page_steps.rb +3 -0
  15. data/features/step_definitions/web_steps.rb +211 -0
  16. data/features/support/env.rb +61 -0
  17. data/features/support/paths.rb +33 -0
  18. data/features/support/selectors.rb +39 -0
  19. data/lib/navi/helpers.rb +24 -0
  20. data/lib/navi/navigable/base.rb +16 -0
  21. data/lib/navi/navigable/instance_methods.rb +24 -0
  22. data/lib/navi/navigator/.base.rb.swo +0 -0
  23. data/lib/navi/navigator/base.rb +11 -0
  24. data/lib/navi/navigator/class_methods.rb +27 -0
  25. data/lib/navi/navigator/instance_methods.rb +57 -0
  26. data/lib/navi/railtie.rb +11 -0
  27. data/lib/navi/renderers/base.rb +31 -0
  28. data/lib/navi/renderers/simple_navigation.rb +30 -0
  29. data/lib/navi.rb +29 -0
  30. data/navi.gemspec +281 -0
  31. data/spec/blueprints.rb +16 -0
  32. data/spec/dummy/.gitignore +6 -0
  33. data/spec/dummy/Rakefile +7 -0
  34. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  35. data/spec/dummy/app/controllers/categories_controller.rb +7 -0
  36. data/spec/dummy/app/controllers/menu_items_controller.rb +15 -0
  37. data/spec/dummy/app/controllers/pages_controller.rb +7 -0
  38. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  39. data/spec/dummy/app/models/category.rb +3 -0
  40. data/spec/dummy/app/models/menu_item.rb +2 -0
  41. data/spec/dummy/app/models/page.rb +3 -0
  42. data/spec/dummy/app/views/categories/_form.html.haml +2 -0
  43. data/spec/dummy/app/views/categories/edit.html.haml +5 -0
  44. data/spec/dummy/app/views/categories/index.html.haml +17 -0
  45. data/spec/dummy/app/views/categories/new.html.haml +5 -0
  46. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  47. data/spec/dummy/app/views/menu_items/edit.html.haml +14 -0
  48. data/spec/dummy/app/views/menu_items/index.html.haml +11 -0
  49. data/spec/dummy/app/views/pages/_form.html.haml +2 -0
  50. data/spec/dummy/app/views/pages/edit.html.haml +5 -0
  51. data/spec/dummy/app/views/pages/index.html.haml +17 -0
  52. data/spec/dummy/app/views/pages/new.html.haml +5 -0
  53. data/spec/dummy/app/widgets/menu_editor/category/form/.display.html.haml.swo +0 -0
  54. data/spec/dummy/app/widgets/menu_editor/category/form/display.html.haml +7 -0
  55. data/spec/dummy/app/widgets/menu_editor/category/form_widget.rb +18 -0
  56. data/spec/dummy/app/widgets/menu_editor/display.html.haml +5 -0
  57. data/spec/dummy/app/widgets/menu_editor/page/form/.display.html.haml.swo +0 -0
  58. data/spec/dummy/app/widgets/menu_editor/page/form/display.html.haml +8 -0
  59. data/spec/dummy/app/widgets/menu_editor/page/form_widget.rb +18 -0
  60. data/spec/dummy/app/widgets/menu_editor/tree/display.html.haml +4 -0
  61. data/spec/dummy/app/widgets/menu_editor/tree/item.html.haml +7 -0
  62. data/spec/dummy/app/widgets/menu_editor/tree/items.html.haml +2 -0
  63. data/spec/dummy/app/widgets/menu_editor/tree_widget.rb +48 -0
  64. data/spec/dummy/app/widgets/menu_editor_widget.rb +11 -0
  65. data/spec/dummy/config/application.rb +45 -0
  66. data/spec/dummy/config/boot.rb +10 -0
  67. data/spec/dummy/config/cucumber.yml +8 -0
  68. data/spec/dummy/config/database.yml +19 -0
  69. data/spec/dummy/config/environment.rb +5 -0
  70. data/spec/dummy/config/environments/development.rb +26 -0
  71. data/spec/dummy/config/environments/production.rb +49 -0
  72. data/spec/dummy/config/environments/test.rb +35 -0
  73. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  74. data/spec/dummy/config/initializers/inflections.rb +10 -0
  75. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  76. data/spec/dummy/config/initializers/navigable.rb +1 -0
  77. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  78. data/spec/dummy/config/initializers/session_store.rb +8 -0
  79. data/spec/dummy/config/locales/en.yml +5 -0
  80. data/spec/dummy/config/navigation.rb +7 -0
  81. data/spec/dummy/config/routes.rb +61 -0
  82. data/spec/dummy/config.ru +4 -0
  83. data/spec/dummy/db/migrate/20110607155019_create_menu_items.rb +20 -0
  84. data/spec/dummy/db/migrate/20110607155202_create_categories.rb +13 -0
  85. data/spec/dummy/db/migrate/20110607160052_create_pages.rb +13 -0
  86. data/spec/dummy/db/schema.rb +41 -0
  87. data/spec/dummy/db/seeds.rb +15 -0
  88. data/spec/dummy/lib/tasks/.gitkeep +0 -0
  89. data/spec/dummy/lib/tasks/cucumber.rake +57 -0
  90. data/spec/dummy/public/404.html +26 -0
  91. data/spec/dummy/public/422.html +26 -0
  92. data/spec/dummy/public/500.html +26 -0
  93. data/spec/dummy/public/favicon.ico +0 -0
  94. data/spec/dummy/public/images/rails.png +0 -0
  95. data/spec/dummy/public/index.html +239 -0
  96. data/spec/dummy/public/javascripts/application.js +2 -0
  97. data/spec/dummy/public/javascripts/jquery-ui.js +11603 -0
  98. data/spec/dummy/public/javascripts/jquery-ui.min.js +406 -0
  99. data/spec/dummy/public/javascripts/jquery.js +8936 -0
  100. data/spec/dummy/public/javascripts/jquery.min.js +18 -0
  101. data/spec/dummy/public/javascripts/jquery_ujs.js +315 -0
  102. data/spec/dummy/public/javascripts/menu_items/index.js +40 -0
  103. data/spec/dummy/public/javascripts/rails.js +315 -0
  104. data/spec/dummy/public/robots.txt +5 -0
  105. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  106. data/spec/dummy/script/cucumber +10 -0
  107. data/spec/dummy/script/rails +6 -0
  108. data/spec/dummy/vendor/plugins/.gitkeep +0 -0
  109. data/spec/navi/helpers_spec.rb +5 -0
  110. data/spec/navi/navi_spec.rb +76 -0
  111. data/spec/navi/navigator_spec.rb +204 -0
  112. data/spec/navi/renderers/simple_navigation_spec.rb +49 -0
  113. data/spec/spec_helper.rb +125 -0
  114. metadata +683 -0
@@ -0,0 +1,61 @@
1
+ ENV["RAILS_ENV"] ||= "test"
2
+ require File.expand_path("../../../spec/dummy/config/environment.rb", __FILE__)
3
+ require File.expand_path("../../../spec/blueprints.rb", __FILE__)
4
+
5
+ require 'cucumber/formatter/unicode' # Remove this line if you don't want Cucumber Unicode support
6
+ require 'cucumber/rails/rspec'
7
+
8
+ require 'cucumber/rails/world'
9
+ require 'cucumber/rails3/active_record'
10
+ require 'cucumber/rails3/action_controller'
11
+ require 'cucumber/web/tableish'
12
+
13
+ require 'capybara/rails'
14
+ require 'capybara/cucumber'
15
+ require 'capybara/session'
16
+ require 'cucumber/rails/capybara/javascript_emulation' # Lets you click links with onclick javascript handlers without using @culerity or @javascript
17
+
18
+ # Tell apotomo to use this new view path, since it was looking at app/widgets and app/widgets/layouts
19
+ # It didn't know that the app was being run from inside spec/dummy
20
+ Apotomo::Widget.append_view_path File.join('spec', 'dummy', 'app', 'widgets')
21
+ Apotomo::Widget.append_view_path File.join('spec', 'dummy', 'app', 'widgets', 'layouts')
22
+
23
+ # Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In
24
+ # order to ease the transition to Capybara we set the default here. If you'd
25
+ # prefer to use XPath just remove this line and adjust any selectors in your
26
+ # steps to use the XPath syntax.
27
+ Capybara.default_selector = :css
28
+
29
+ # If you set this to false, any error raised from within your app will bubble
30
+ # up to your step definition and out to cucumber unless you catch it somewhere
31
+ # on the way. You can make Rails rescue errors and render error pages on a
32
+ # per-scenario basis by tagging a scenario or feature with the @allow-rescue tag.
33
+ #
34
+ # If you set this to true, Rails will rescue all errors and render error
35
+ # pages, more or less in the same way your application would behave in the
36
+ # default production environment. It's not recommended to do this for all
37
+ # of your scenarios, as this makes it hard to discover errors in your application.
38
+ ActionController::Base.allow_rescue = false
39
+
40
+ # If you set this to true, each scenario will run in a database transaction.
41
+ # You can still turn off transactions on a per-scenario basis, simply tagging
42
+ # a feature or scenario with the @no-txn tag. If you are using Capybara,
43
+ # tagging with @culerity or @javascript will also turn transactions off.
44
+ #
45
+ # If you set this to false, transactions will be off for all scenarios,
46
+ # regardless of whether you use @no-txn or not.
47
+ #
48
+ # Beware that turning transactions off will leave data in your database
49
+ # after each scenario, which can lead to hard-to-debug failures in
50
+ # subsequent scenarios. If you do this, we recommend you create a Before
51
+ # block that will explicitly put your database in a known state.
52
+
53
+ # How to clean your database when transactions are turned off. See
54
+ # http://github.com/bmabey/database_cleaner for more info.
55
+ if defined?(ActiveRecord::Base)
56
+ begin
57
+ require 'database_cleaner'
58
+ DatabaseCleaner.strategy = :truncation
59
+ rescue LoadError => ignore_if_database_cleaner_not_present
60
+ end
61
+ end
@@ -0,0 +1,33 @@
1
+ module NavigationHelpers
2
+ # Maps a name to a path. Used by the
3
+ #
4
+ # When /^I go to (.+)$/ do |page_name|
5
+ #
6
+ # step definition in web_steps.rb
7
+ #
8
+ def path_to(page_name)
9
+ case page_name
10
+
11
+ when /the home\s?page/
12
+ '/'
13
+
14
+ # Add more mappings here.
15
+ # Here is an example that pulls values out of the Regexp:
16
+ #
17
+ # when /^(.*)'s profile page$/i
18
+ # user_profile_path(User.find_by_login($1))
19
+
20
+ else
21
+ begin
22
+ page_name =~ /the (.*) page/
23
+ path_components = $1.split(/\s+/)
24
+ self.send(path_components.push('path').join('_').to_sym)
25
+ rescue Object => e
26
+ raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
27
+ "Now, go and add a mapping in #{__FILE__}"
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ World(NavigationHelpers)
@@ -0,0 +1,39 @@
1
+ module HtmlSelectorsHelpers
2
+ # Maps a name to a selector. Used primarily by the
3
+ #
4
+ # When /^(.+) within (.+)$/ do |step, scope|
5
+ #
6
+ # step definitions in web_steps.rb
7
+ #
8
+ def selector_for(locator)
9
+ case locator
10
+
11
+ when /the page/
12
+ "html > body"
13
+
14
+ # Add more mappings here.
15
+ # Here is an example that pulls values out of the Regexp:
16
+ #
17
+ # when /the (notice|error|info) flash/
18
+ # ".flash.#{$1}"
19
+
20
+ # You can also return an array to use a different selector
21
+ # type, like:
22
+ #
23
+ # when /the header/
24
+ # [:xpath, "//header"]
25
+
26
+ # This allows you to provide a quoted selector as the scope
27
+ # for "within" steps as was previously the default for the
28
+ # web steps:
29
+ when /"(.+)"/
30
+ $1
31
+
32
+ else
33
+ raise "Can't find mapping from \"#{locator}\" to a selector.\n" +
34
+ "Now, go and add a mapping in #{__FILE__}"
35
+ end
36
+ end
37
+ end
38
+
39
+ World(HtmlSelectorsHelpers)
@@ -0,0 +1,24 @@
1
+ # This helper is a module that will get included into Rails via the
2
+ # lib/navi/railtie class
3
+ #
4
+ # It allows us to be in the context of the controller it is being included
5
+ # into: when this module is included to ActionView and the view/controller
6
+ # calls the render method, "self" will refer to the view or controller
7
+ # context
8
+ module Navi
9
+ module Helpers
10
+ def self.included(base)
11
+ #puts "Navi::Helpers was included into #{base}"
12
+ end
13
+
14
+ def navi_render(collection)
15
+ renderer.render(collection)
16
+ end
17
+
18
+ private
19
+
20
+ def renderer
21
+ @renderer ||= Navi.renderer.new(self)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ require 'navi/navigable/instance_methods'
2
+
3
+ module Navi
4
+ module Navigable
5
+ module Base
6
+ def navigable(options={})
7
+ cattr_accessor :navigable_config
8
+ self.navigable_config = options
9
+ has_one Navi.navigator, :as => :navigable
10
+ include Navi::Navigable::InstanceMethods
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ ActiveRecord::Base.extend Navi::Navigable::Base
@@ -0,0 +1,24 @@
1
+ module Navi
2
+ module Navigable
3
+ module InstanceMethods
4
+ def to_navigator(options={})
5
+ return navigator_instance if navigator_instance
6
+ options.merge!(:navigable => self)
7
+ Navi.navigator_class.new options
8
+ end
9
+
10
+ def to_navigator!(options={})
11
+ navigator = to_navigator(options)
12
+ navigator.save
13
+ navigator
14
+ end
15
+
16
+ private
17
+
18
+ # Easily get the navigator instance based on the Navi.navigator setting
19
+ def navigator_instance
20
+ @navigator_instance ||= send(Navi.navigator)
21
+ end
22
+ end
23
+ end
24
+ end
Binary file
@@ -0,0 +1,11 @@
1
+ require 'navi/navigator/class_methods'
2
+ require 'navi/navigator/instance_methods'
3
+
4
+ module Navi
5
+ module Navigator
6
+ class Base < ActiveRecord::Base
7
+ include Navi::Navigator::ClassMethods
8
+ include Navi::Navigator::InstanceMethods
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ module Navi
2
+ module Navigator
3
+ module ClassMethods
4
+ extend ActiveSupport::Concern
5
+ included do |child|
6
+ # So that Rails won't consider this to be an STI table.
7
+ # The actual project can have a model and inherit it this way:
8
+ # class MyNavItem < Navigable::NavigationItem::Base
9
+ #
10
+ # Then the navigable classes must tell the gem that the name of
11
+ # the nav item is :my_nav_item, this way: navigable :navigator => :my_nav_item
12
+ self.abstract_class = true
13
+
14
+ belongs_to :navigable, :polymorphic => true
15
+
16
+ # Calling ordered_tree on the child is important because
17
+ # of this: http://stackoverflow.com/q/6262033/61018
18
+ # where ordered_tree was picking up the Navi::Navigator::Base's
19
+ # information, rather than whatever inherits Base class
20
+ def self.inherited(child)
21
+ child.send 'ordered_tree'
22
+ super # super, so that Rails can continue to do what it's needs
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,57 @@
1
+ module Navi
2
+ module Navigator
3
+ module InstanceMethods
4
+ def label
5
+ db_value = self.read_attribute :label
6
+ return db_value if db_value
7
+ return navigable.send navigable_config(:label) if navigable && navigable_config(:label)
8
+ nil
9
+ end
10
+
11
+ def link
12
+ db_value = self.read_attribute :link
13
+ return db_value if db_value
14
+ return navigable if navigable
15
+ nil
16
+ end
17
+
18
+ def title
19
+ db_value = self.read_attribute :title
20
+ return db_value if db_value
21
+ if navigable && navigable_config(:title)
22
+ config = navigable_config :title
23
+ return case config
24
+ when Symbol then navigable.send config
25
+ when String then config
26
+ when Proc then config.call navigable
27
+ end
28
+ end
29
+ return self.label
30
+ end
31
+
32
+ def highlights_on
33
+ db_value = self.read_attribute :highlights_on
34
+ value = if db_value
35
+ Regexp.new db_value
36
+ else # db_value.nil?
37
+ if navigable && navigable_config(:highlights_on)
38
+ config = navigable_config(:highlights_on)
39
+ case config
40
+ when Proc then config.call navigable
41
+ else config
42
+ end
43
+ else
44
+ self.link
45
+ end
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def navigable_config(key)
52
+ navigable.class.navigable_config[key]
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,11 @@
1
+ # What is a railtie?
2
+ # tl;dr => Allows us to hook into Rails add add stuff to it
3
+ # http://www.rorexperts.com/what-is-railtie-t1898.html
4
+
5
+ module Navi
6
+ class Railtie < Rails::Railtie
7
+ initializer "navi.helpers" do
8
+ ActionView::Base.send :include, Navi::Helpers
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ module Navi
2
+ module Renderers
3
+ class Base
4
+ attr_accessor :context, :controller, :template
5
+
6
+ def initialize(context)
7
+ @context = context
8
+ @controller = controller_from @context
9
+ @template = template_from @controller
10
+ end
11
+
12
+ def render(collection)
13
+ raise NotImplementedError
14
+ end
15
+
16
+ private
17
+
18
+ # Pretty much lifted from
19
+ # https://github.com/andi/simple-navigation/blob/master/lib/simple_navigation/adapters/rails.rb
20
+ def controller_from(context)
21
+ context.respond_to?(:controller) ? context.controller : context
22
+ end
23
+
24
+ # Pretty much lifted from
25
+ # https://github.com/andi/simple-navigation/blob/master/lib/simple_navigation/adapters/rails.rb
26
+ def template_from(controller)
27
+ controller.respond_to?(:view_context) ? controller.view_context : controller.instance_variable_get(:@template)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,30 @@
1
+ module Navi
2
+ module Renderers
3
+ class SimpleNavigation < Navi::Renderers::Base
4
+
5
+ def render(collection)
6
+ items = create_dynamic_items(collection)
7
+ @template.render_navigation :items => items, :expand_all => true
8
+ end
9
+
10
+ private
11
+
12
+ # Create an array of hashes that can be easily fed into SimpleNavigation
13
+ # like in the following like:
14
+ # https://github.com/andi/simple-navigation/wiki/Dynamic-Navigation-Items
15
+ def create_dynamic_items(collection)
16
+ nav = []
17
+ collection.each do |nav_item|
18
+ nav << {
19
+ :key => @template.dom_id(nav_item).to_sym,
20
+ :name => nav_item.label,
21
+ :url => @template.polymorphic_path(nav_item.link),
22
+ :options => {:title => nav_item.title, :class => nav_item.class.name.underscore},
23
+ :items => create_dynamic_items(nav_item.children)
24
+ }
25
+ end
26
+ nav
27
+ end
28
+ end
29
+ end
30
+ end
data/lib/navi.rb ADDED
@@ -0,0 +1,29 @@
1
+ require 'active_support'
2
+ require "active_support/core_ext/module" # so we can use mattr_accessor
3
+ require 'active_record'
4
+ require 'ordered_tree'
5
+ require 'navi/navigable/base'
6
+ require 'navi/railtie' if defined?(Rails) # so we can include the rendering helper into Rails
7
+
8
+ module Navi
9
+ autoload :Helpers, 'navi/helpers'
10
+
11
+ module Navigator
12
+ autoload :Base, 'navi/navigator/base'
13
+ end
14
+
15
+ module Renderers
16
+ autoload :Base, 'navi/renderers/base'
17
+ autoload :SimpleNavigation, 'navi/renderers/simple_navigation'
18
+ end
19
+
20
+ def self.navigator_class
21
+ self.navigator.to_s.classify.constantize
22
+ end
23
+
24
+ mattr_accessor :navigator
25
+ @@navigator ||= :nav_item
26
+
27
+ mattr_accessor :renderer
28
+ @@renderer ||= Navi::Renderers::SimpleNavigation
29
+ end