navi 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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