easycrumbs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Stanisław Kolarzowski
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,22 @@
1
+ = easycrumbs
2
+
3
+ Easy breadcrumbs for your site
4
+
5
+ * gemcutter[not yet]
6
+ * repository[http://github.com/staszek/easycrumbs]
7
+
8
+ == Installation
9
+
10
+ If you don't have the {Gemcutter sources}[http://gemcutter.org/pages/gem_docs] yet:
11
+ gem sources -a http://gemcutter.org
12
+
13
+ To install the gem type:
14
+ gem install easycrumbs
15
+
16
+ == Usage
17
+
18
+ It does not work yet.
19
+
20
+ == Copyright
21
+
22
+ Copyright (c) 2010 Stanisław Kolarzowski. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "easycrumbs"
8
+ gem.summary = %Q{Easy breadcrumbs}
9
+ gem.description = %Q{Easy breadcrumbs for your website}
10
+ gem.email = "stanislaw.kolarzowski@gmail.com"
11
+ gem.homepage = "http://github.com/staszek/easycrumbs"
12
+ gem.authors = ["Stanisław Kolarzowski"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ task :test => :check_dependencies
29
+
30
+ task :default => :test
31
+
32
+ require 'rake/rdoctask'
33
+ Rake::RDocTask.new do |rdoc|
34
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
35
+
36
+ rdoc.rdoc_dir = 'rdoc'
37
+ rdoc.title = "easycrumbs #{version}"
38
+ rdoc.rdoc_files.include('README*')
39
+ rdoc.rdoc_files.include('lib/**/*.rb')
40
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,60 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{easycrumbs}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Stanis\305\202aw Kolarzowski"]
12
+ s.date = %q{2010-08-08}
13
+ s.description = %q{Easy breadcrumbs for your website}
14
+ s.email = %q{stanislaw.kolarzowski@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "easycrumbs.gemspec",
27
+ "lib/easycrumbs.rb",
28
+ "lib/easycrumbs/breadcrumb.rb",
29
+ "lib/easycrumbs/collection.rb",
30
+ "lib/easycrumbs/errors.rb",
31
+ "lib/easycrumbs/view_helpers.rb",
32
+ "test/helper.rb",
33
+ "test/routes.rb",
34
+ "test/test_easycrumbs.rb"
35
+ ]
36
+ s.homepage = %q{http://github.com/staszek/easycrumbs}
37
+ s.rdoc_options = ["--charset=UTF-8"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = %q{1.3.7}
40
+ s.summary = %q{Easy breadcrumbs}
41
+ s.test_files = [
42
+ "test/helper.rb",
43
+ "test/routes.rb",
44
+ "test/test_easycrumbs.rb"
45
+ ]
46
+
47
+ if s.respond_to? :specification_version then
48
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
53
+ else
54
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
55
+ end
56
+ else
57
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
58
+ end
59
+ end
60
+
data/lib/easycrumbs.rb ADDED
@@ -0,0 +1,4 @@
1
+ require "easycrumbs/collection"
2
+ require "easycrumbs/view_helpers"
3
+ require "easycrumbs/breadcrumb"
4
+ require "easycrumbs/errors"
@@ -0,0 +1,95 @@
1
+ module EasyCrumbs
2
+ class Breadcrumb
3
+ attr_reader :object, :name, :path
4
+
5
+ # Breadcrumb object:
6
+ # object - just object from application. Could be a model or controller
7
+ # name - printed name
8
+ # path - path to this object
9
+ def initialize(object, options = {})
10
+ @object = set_object(object)
11
+ @name = set_name(options)
12
+ @path = set_path(options[:path], options[:blank_links])
13
+ end
14
+
15
+
16
+ # Object from application must be a model or controller
17
+ def set_object(object)
18
+ raise EasyCrumbs::InvalidObject unless object.is_a?(ActionController::Base) || object.is_a?(ActiveRecord::Base)
19
+ object
20
+ end
21
+
22
+ # Set name for model or controller
23
+ def set_name(options = {})
24
+ if object.is_a?(ActiveRecord::Base)
25
+ options[:name_column] ||= "breadcrumb"
26
+ name = name_for_model(options[:name_column], options[:i18n])
27
+ else
28
+ name = name_for_controller(options[:i18n])
29
+ end
30
+ add_prefix(name, options[:action], options[:prefix], options[:i18n])
31
+ end
32
+
33
+ # Set name for model
34
+ # Model has to have column equal to name_column
35
+ def name_for_model(name_column, i18n)
36
+ raise EasyCrumbs::NoName.new(@object.class, name_column) unless @object.respond_to? name_column
37
+ name = @object.send name_column
38
+ name.nil? ? name_for_nil(@object, i18n) : name
39
+ end
40
+
41
+ # Set name for object if it is nil
42
+ def name_for_nil(object, i18n)
43
+ i18n == true ? I18n.t("breadcrumbs.models.#{object.class.to_s.downcase}") : @object.class.to_s
44
+ end
45
+
46
+ # Set name for controller
47
+ def name_for_controller(i18n)
48
+ if @object.respond_to? :breadcrumb
49
+ @object.breadcrumb
50
+ else
51
+ i18n == true ? I18n.t("breadcrumbs.controllers.#{@object.controller_name}") : @object.controller_name.titlecase
52
+ end
53
+ end
54
+
55
+ # Add specyfic prefix if action is passed
56
+ # prefix =
57
+ # :every - add prefix for every action
58
+ # :none - do not add prefix
59
+ # [array of symbols] - add prefix only for actions in array
60
+ #
61
+ # Example
62
+ # [:show, :new] - add prefix only for show and new
63
+ def add_prefix(object_name, action, prefix, i18n)
64
+ name = object_name
65
+ unless action.nil?
66
+ prefix = case prefix
67
+ when :every
68
+ [action.to_sym]
69
+ when :none
70
+ []
71
+ else
72
+ prefix || [:new, :edit]
73
+ end
74
+ name = action_name(action, i18n, name) if prefix.include?(action.to_sym)
75
+ end
76
+ name
77
+ end
78
+
79
+ # Return name of action.
80
+ def action_name(action, i18n, name)
81
+ i18n == true ? I18n.t("breadcrumbs.actions.#{action}", :name => name) : "#{action.titlecase} #{name}"
82
+ end
83
+
84
+ # Set path using hash from ActionController::Routing::Routes.recognize_path
85
+ # Example looks like:
86
+ # {:country_id => "1", :movie_id => "1", :id => "1", :action => "show", :controller => "movies"}
87
+ def set_path(path, blank_links)
88
+ path.nil? || path.empty? ? "/" : ActionController::Routing::Routes.generate_extras(path).first
89
+ rescue ActionController::RoutingError => e
90
+ raise EasyCrumbs::NoPath.new(e.message) unless blank_links == true
91
+ nil
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,172 @@
1
+ module EasyCrumbs
2
+ class Collection
3
+ attr_reader :breadcrumbs, :route, :path
4
+
5
+ def initialize(request, options = {})
6
+ @request = request
7
+
8
+ @route = find_route
9
+ @path = find_path
10
+ @controller = @path[:controller]
11
+ @action = @path[:action]
12
+
13
+ @pathes = make_pathes
14
+ @breadcrumbs = make_breadcrumbs(options)
15
+ end
16
+
17
+ # Finding route with given path and method
18
+ # Return ActionController:Routing::Route object
19
+ def find_route
20
+ routes = ActionController::Routing::Routes.routes.select do |route|
21
+ route.recognize(request_path, :method => request_method) != nil
22
+ end
23
+ raise EasyCrumbs::NotRecognized if routes.empty?
24
+ routes.first
25
+ end
26
+
27
+ # Return hash with path parameter
28
+ # for example:
29
+ # { :controller => 'movies', :action => 'show', :country_id => '23', :id => '12' }
30
+ def find_path
31
+ @route.recognize(request_path, :method => request_method)
32
+ end
33
+
34
+ # Select only static and dynamic segments from route. Static segments points at controllers and dynamic points at models.
35
+ # It is given in right order
36
+ # If last segment is equal to member action then it should be deleted. for example movies/123/edit should not return "edit" segment
37
+ def segments
38
+ segments = @route.segments.select do |segment|
39
+ [ActionController::Routing::DynamicSegment, ActionController::Routing::StaticSegment].include? segment.class
40
+ end
41
+ segments.pop if segments.last.is_a?(ActionController::Routing::StaticSegment) && segments.last.value == @action && segments.last.value != 'new'
42
+ segments
43
+ end
44
+
45
+ # Returning controller object from static segment
46
+ def pick_controller(segment)
47
+ segment = last_controller_segment if segment.value == "new"
48
+ "#{segment.value.titlecase}Controller".constantize.new
49
+ end
50
+
51
+ # Returns last controller segment in segments
52
+ def last_controller_segment
53
+ segments.select{ |seg| seg.is_a?(ActionController::Routing::StaticSegment) && seg.value != "new"}.last
54
+ end
55
+
56
+ # Retrung model object from dynamic segment
57
+ # If key has not model name then it is taken from current controller(it is taken from path)
58
+ def pick_model(segment)
59
+ key = segment.key
60
+ if key == :id
61
+ model = @controller.singularize
62
+ else
63
+ model = key.to_s[0..-4] # model_id without last 3 signs = model
64
+ end
65
+ model = model.titlecase.constantize
66
+ model.find(@path[key])
67
+ end
68
+
69
+ # Retruning array of controllers and models objects from right segments
70
+ # for example
71
+ # [#<CountriesController:0x001>, #<Country:0x001 @name="usa">, #<MoviesController:0x001>, #<Movie:0x001 @name="titanic">]
72
+ def objects
73
+ segments.map do |segment|
74
+ if segment.is_a? ActionController::Routing::DynamicSegment
75
+ pick_model(segment)
76
+ else
77
+ pick_controller(segment)
78
+ end
79
+ end
80
+ end
81
+
82
+ # Return array of breadcrumbs object in right order
83
+ def make_breadcrumbs(options = {})
84
+ breadcrumbs = [Breadcrumb.new(ApplicationController.new, options)]
85
+ objects.each_with_index do |object, index|
86
+ options.merge!({:action => @action}) if index == objects.size - 1
87
+ options.merge!({:path => @pathes[index]})
88
+ breadcrumbs << Breadcrumb.new(object, options)
89
+ end
90
+ breadcrumbs
91
+ end
92
+
93
+ # Retrurn parameters for path of model
94
+ # If it is last object then action is equal to request action
95
+ def path_for_model(segment)
96
+ key = segment.key
97
+ if key == :id
98
+ {:action => @action, :id => @path[key]}
99
+ else
100
+ {:action => 'show', key => @path[key]}
101
+ end
102
+ end
103
+
104
+ # Retrun parameters for path of controller
105
+ def path_for_controller(segment)
106
+ if segment.value == "new"
107
+ {:action => "new", :controller => last_controller_segment.value}
108
+ else
109
+ {:action => 'index', :controller => segment.value}
110
+ end
111
+ end
112
+
113
+ # If controller name is connected with object then parameter should be :id instead of :object_id
114
+ # {:controller => 'movies', :movie_id => 1} will be {:controller => 'movies', :id => 1}
115
+ def repaired_model_path(path)
116
+ path = path.dup
117
+ object_param = "#{path[:controller].singularize}_id".to_sym
118
+ id = path.delete(object_param)
119
+ id.nil? ? path : path.merge({:id => id})
120
+ end
121
+
122
+ # Retrun array of pathes for every segment
123
+ # for example:
124
+ # countries > 1 > movies > 2 > actors> 3
125
+ #
126
+ # {:action => 'index', :controller => 'countries'},
127
+ # {:action => 'show', :controller => 'countries', :id => 1},
128
+ # {:action => 'index', :controller => 'movies', :country_id => 1},
129
+ # {:action => 'show', :controller => 'movies', :country_id => 1, :id => 2},
130
+ # {:action => 'index', :controller => 'actors', :country_id => 1, :movie_id => 2},
131
+ # {:action => 'update', :controller => 'actors', :country_id => 1, :movie_id => 2, :id => 3}
132
+ def make_pathes
133
+ path = {}
134
+ segments.map do |segment|
135
+ if segment.is_a? ActionController::Routing::DynamicSegment
136
+ path.merge! path_for_model(segment)
137
+ result = repaired_model_path(path)
138
+ else
139
+ result = path.merge! path_for_controller(segment)
140
+ end
141
+ result.dup
142
+ end
143
+ end
144
+
145
+ def render(options = {})
146
+ options[:separator] ||= " > "
147
+ options[:last_link] = true if options[:last_link].nil?
148
+
149
+ elements = @breadcrumbs.map do |breadcrumb|
150
+ if options[:last_link] == false && breadcrumb == @breadcrumbs.last
151
+ breadcrumb.name
152
+ else
153
+ link_to breadcrumb.name, breadcrumb.path
154
+ end
155
+ end
156
+ elements.join(options[:separator])
157
+ end
158
+ private
159
+
160
+ def request_path
161
+ @request.path
162
+ end
163
+
164
+ def request_method
165
+ @request.method
166
+ end
167
+
168
+ def link_to(name, path)
169
+ "<a href=\"#{path}\">#{name}</a>"
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,34 @@
1
+ module EasyCrumbs
2
+ class InvalidObject < StandardError
3
+ def message
4
+ "object should be Controller(ActionController::Base) or Model(ActiveRecord::Base)"
5
+ end
6
+ end
7
+
8
+ class NoName < StandardError
9
+ def initialize(object_class, column)
10
+ @object_class = object_class
11
+ @column = column
12
+ end
13
+
14
+ def message
15
+ "Can not set name. Model #{@object_class} does not have column \"#{@column}\". Try change column name or create \"#{@column}\" method"
16
+ end
17
+ end
18
+
19
+ class NoPath < StandardError
20
+ def initialize(routing_error)
21
+ @routing_error = routing_error
22
+ end
23
+
24
+ def message
25
+ "Can not set path. You can use :blank_links to return nil for no-recognized pathes. RoutingError: #{@routing_error}"
26
+ end
27
+ end
28
+
29
+ class NotRecognized < StandardError
30
+ def message
31
+ "Can not recognize main path."
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,7 @@
1
+ module ActionView
2
+ class Base
3
+ def breadcrumbs(options = {})
4
+ EasyCrumbs::Collection.new(request, options).render(options)
5
+ end
6
+ end
7
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require "mocha"
5
+ require 'active_record'
6
+ require "action_view"
7
+ require "action_controller"
8
+ require "routes"
9
+
10
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
12
+ require 'easycrumbs'
13
+
14
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
15
+ ActiveRecord::Base.configurations = true
16
+
17
+ ActiveRecord::Schema.verbose = false
18
+ ActiveRecord::Schema.define(:version => 1) do
19
+ create_table :countries do |t|
20
+ t.string :name
21
+ t.string :breadcrumb
22
+ end
23
+
24
+ create_table :movies do |t|
25
+ t.string :name
26
+ t.integer :country_id
27
+ t.string :breadcrumb
28
+ end
29
+
30
+ create_table :actors do |t|
31
+ t.string :first_name
32
+ t.string :last_name
33
+ t.integer :movie_id
34
+ end
35
+ end
36
+
37
+
38
+ # =========== Rails Classes and Objects ===========
39
+
40
+ include EasyCrumbs
41
+
42
+ class Country < ActiveRecord::Base
43
+ has_many :movies
44
+ end
45
+
46
+ class Movie < ActiveRecord::Base
47
+ has_many :actors
48
+ belongs_to :country
49
+ end
50
+
51
+ class Actor < ActiveRecord::Base
52
+ belongs_to :movie
53
+
54
+ def breadcrumb
55
+ "#{first_name} #{last_name}"
56
+ end
57
+ end
58
+
59
+ class ApplicationController < ActionController::Base
60
+ end
61
+
62
+ class CountriesController < ApplicationController
63
+ def breadcrumb
64
+ "Countries list"
65
+ end
66
+ end
67
+
68
+ class MoviesController < ApplicationController
69
+ end
70
+
71
+ class ActorsController < ApplicationController
72
+ end
data/test/routes.rb ADDED
@@ -0,0 +1,9 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+
3
+ map.resources :countries do |country|
4
+ country.resources :movies do |movie|
5
+ movie.resources :actors
6
+ end
7
+ end
8
+
9
+ end
@@ -0,0 +1,337 @@
1
+ require 'helper'
2
+
3
+ class TestEasycrumbs < Test::Unit::TestCase
4
+ context "EasyCrumbs tests" do
5
+ setup do
6
+ @usa = Country.create(:name => "USA", :breadcrumb => "United States of America")
7
+ @titanic = @usa.movies.create(:name => "Titanic", :breadcrumb => "Titanic")
8
+ @leo = @titanic.actors.create(:first_name => "Leonardo", :last_name => "Di Caprio")
9
+ end
10
+
11
+ context "Models testing" do
12
+ should "Leo play in Titanic" do
13
+ assert_equal(@titanic, @leo.movie)
14
+ end
15
+
16
+ should "Titanic be produced in Usa" do
17
+ assert_equal(@usa, @titanic.country)
18
+ end
19
+ end
20
+
21
+ context "Breadcrumb model" do
22
+ context "set object" do
23
+ should "model object be ok" do
24
+ assert_equal(@usa, Breadcrumb.new(@usa).object)
25
+ end
26
+
27
+ should "controller object be ok" do
28
+ @controller = MoviesController.new
29
+ assert_equal(@controller, Breadcrumb.new(@controller).object)
30
+ end
31
+
32
+ should "raise exception for String object" do
33
+ assert_raise(InvalidObject) { Breadcrumb.new("Some string") }
34
+ end
35
+ end
36
+
37
+ context "set name" do
38
+ context "for model" do
39
+ should "return breadcrumb column by default" do
40
+ assert_equal("United States of America", Breadcrumb.new(@usa).name)
41
+ end
42
+
43
+ should "return name column if someone set it" do
44
+ assert_equal(@titanic.name, Breadcrumb.new(@titanic, :name_column => "name").name)
45
+ end
46
+
47
+ should "return specyfic name using breadcrumb method" do
48
+ assert_equal("Leonardo Di Caprio", Breadcrumb.new(@leo).name)
49
+ end
50
+
51
+ should "raise exception if can not find name" do
52
+ assert_raise(NoName) { Breadcrumb.new(@leo, :name_column => "wrong_column")}
53
+ end
54
+
55
+ should "return model name if column return nil" do
56
+ assert_equal("Movie", Breadcrumb.new(Movie.new).name)
57
+ end
58
+
59
+ should "return model name from i18n if column return nil" do
60
+ I18n.expects(:t).with("breadcrumbs.models.movie").returns("Das film")
61
+ assert_equal("Das film", Breadcrumb.new(Movie.new, :i18n => true).name)
62
+ end
63
+ end
64
+
65
+ context "for controller" do
66
+ should "return controller name" do
67
+ assert_equal("Movies", Breadcrumb.new(MoviesController.new).name)
68
+ end
69
+
70
+ should "return breadcrumb method from controller" do
71
+ assert_equal("Countries list", Breadcrumb.new(CountriesController.new).name)
72
+ end
73
+ end
74
+
75
+ context "with prefix option" do
76
+ should "return name with prefix if action is passed by parameter and it is one of defaults(new or edit)" do
77
+ assert_equal("Edit Leonardo Di Caprio", Breadcrumb.new(@leo, :action => "edit").name)
78
+ end
79
+
80
+ should "return only name if it is set to :none" do
81
+ assert_equal("Leonardo Di Caprio", Breadcrumb.new(@leo, :action => "edit", :prefix => :none).name)
82
+ end
83
+
84
+ should "return prefix and name for every action if it is set to :every" do
85
+ assert_equal("Show Leonardo Di Caprio", Breadcrumb.new(@leo, :action => "show", :prefix => :every).name)
86
+ end
87
+
88
+ should "return prefix and name if action is in prefix array" do
89
+ assert_equal("Destroy Leonardo Di Caprio", Breadcrumb.new(@leo, :action => "destroy", :prefix => [:destroy, :edit]).name)
90
+ end
91
+
92
+ should "return only name if action is not in prefix array" do
93
+ assert_equal("Leonardo Di Caprio", Breadcrumb.new(@leo, :action => "show", :prefix => [:destroy, :edit]).name)
94
+ end
95
+ end
96
+
97
+ context "with i18n enable" do
98
+ should "return transalted name for controller" do
99
+ I18n.expects(:t).with("breadcrumbs.controllers.movies").returns("la movies")
100
+ assert_equal("la movies", Breadcrumb.new(MoviesController.new, :i18n => true).name)
101
+ end
102
+
103
+ should "return transalted action as a prefix" do
104
+ name = "Leonardo Di Caprio"
105
+ I18n.expects(:t).with("breadcrumbs.actions.edit", {:name => name}).returns("Editzione #{name}")
106
+ assert_equal("Editzione Leonardo Di Caprio", Breadcrumb.new(@leo, :i18n => true, :action => "edit").name)
107
+ end
108
+ end
109
+
110
+ context "set path" do
111
+ should "return path if it exist" do
112
+ assert_equal("/countries/1/movies/1/actors/1", Breadcrumb.new(@leo, :path => {:country_id => "1", :movie_id => "1", :id => "1", :action => "show", :controller => "actors"}).path)
113
+ end
114
+
115
+ should "raise RoutingError when can not find path" do
116
+ assert_raise(EasyCrumbs::NoPath) { Breadcrumb.new(@leo, :path => {:country_id => "1", :movie_id => "1", :id => "1", :action => "no_action", :controller => "actors"}) }
117
+ end
118
+
119
+ should "retrun nil when can not find path and blank_links is on" do
120
+ assert_equal(nil, Breadcrumb.new(@leo, :path => {:country_id => "1", :movie_id => "1", :id => "1", :action => "no_action", :controller => "actors"}, :blank_links => true).path)
121
+ end
122
+
123
+ should "return root path for empty path" do
124
+ assert_equal("/", Breadcrumb.new(@leo, :path => {}).path)
125
+ end
126
+
127
+ should "return root path for nil path" do
128
+ assert_equal("/", Breadcrumb.new(@leo).path)
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ context "Collection" do
135
+ setup do
136
+ Collection.any_instance.stubs(:request_path => "/countries/#{@usa.id}/movies/#{@titanic.id}/actors/#{@leo.id}", :request_method => :put)
137
+ @collection = Collection.new("request object")
138
+ end
139
+
140
+ context "finding route" do
141
+ should "return route if it can find it" do
142
+ assert_equal(ActionController::Routing::Route, @collection.route.class)
143
+ end
144
+
145
+ should "raise error when it can not find route" do
146
+ assert_raise(EasyCrumbs::NotRecognized) do
147
+ @collection.stubs(:request_path => "/countres/1/videos/1")
148
+ @collection.find_route
149
+ end
150
+ end
151
+ end
152
+
153
+ context "find path" do
154
+ should "retrun path hash" do
155
+ assert_equal({:action => "update", :controller => "actors", :country_id => @usa.id.to_s, :movie_id => @titanic.id.to_s, :id => @leo.id.to_s}, @collection.path)
156
+ end
157
+ end
158
+
159
+ context "selecting right segments" do
160
+ should "select only static and dynamic segments" do
161
+ results = @collection.segments
162
+ results = results.map(&:class).uniq
163
+ results.delete(ActionController::Routing::StaticSegment)
164
+ results.delete(ActionController::Routing::DynamicSegment)
165
+ assert_equal(true, results.empty?)
166
+ end
167
+
168
+ should "return proper segments for member action" do
169
+ Collection.any_instance.stubs(:request_path => "/countries/#{@usa.id}/movies/#{@titanic.id}/actors/#{@leo.id}/edit", :request_method => :get)
170
+ collection = Collection.new("request object")
171
+ assert_equal(6, collection.segments.size)
172
+ end
173
+
174
+ should "return proper segments for new action" do
175
+ Collection.any_instance.stubs(:request_path => "/countries/#{@usa.id}/movies/#{@titanic.id}/actors/new", :request_method => :get)
176
+ collection = Collection.new("request object")
177
+ assert_equal(6, collection.segments.size)
178
+ end
179
+ end
180
+
181
+ context "pick_controller" do
182
+ should "return controller object" do
183
+ assert_equal(MoviesController, @collection.pick_controller(ActionController::Routing::StaticSegment.new("movies")).class)
184
+ end
185
+
186
+ should "return controller object if action is new" do
187
+ assert_equal(ActorsController, @collection.pick_controller(ActionController::Routing::StaticSegment.new("new")).class)
188
+ end
189
+ end
190
+
191
+ context "last controller" do
192
+ should "return last controller object if last segment is dynamic" do
193
+ assert_equal("actors", @collection.last_controller_segment.value)
194
+ end
195
+
196
+ should "return last controller object if last segment is static" do
197
+ Collection.any_instance.stubs(:request_path => "/countries/#{@usa.id}/movies/#{@titanic.id}/actors", :request_method => :get)
198
+ collection = Collection.new("request object")
199
+ assert_equal("actors", collection.last_controller_segment.value)
200
+ end
201
+
202
+ should "return last controller object if last segment is new action" do
203
+ Collection.any_instance.stubs(:request_path => "/countries/#{@usa.id}/movies/#{@titanic.id}/actors/new", :request_method => :get)
204
+ collection = Collection.new("request object")
205
+ assert_equal("actors", collection.last_controller_segment.value)
206
+ end
207
+ end
208
+
209
+ context "pick_model" do
210
+ should "return model object when key has model name" do
211
+ segment = ActionController::Routing::DynamicSegment.new(:movie_id)
212
+ assert_equal(@titanic, @collection.pick_model(segment))
213
+ end
214
+
215
+ should "return model object when key has not model name"do
216
+ segment = ActionController::Routing::DynamicSegment.new(:id)
217
+ assert_equal(@leo, @collection.pick_model(segment))
218
+ end
219
+ end
220
+
221
+ context "objects" do
222
+ should "change segments into objects" do
223
+ assert_equal([CountriesController, Country, MoviesController, Movie, ActorsController, Actor], @collection.objects.map(&:class))
224
+ end
225
+ end
226
+
227
+ context "path_for_model" do
228
+ should "return id and current action for last object" do
229
+ segment = ActionController::Routing::DynamicSegment.new(:id)
230
+ assert_equal({:action => 'update', :id => @leo.id.to_s}, @collection.path_for_model(segment))
231
+ end
232
+
233
+ should "return show action and object id for not last object" do
234
+ segment = ActionController::Routing::DynamicSegment.new(:movie_id)
235
+ assert_equal({:action => 'show', :movie_id => @titanic.id.to_s}, @collection.path_for_model(segment))
236
+ end
237
+ end
238
+
239
+ context "path_for_controller" do
240
+ should "return index action and controller name" do
241
+ segment = ActionController::Routing::StaticSegment.new("movies")
242
+ assert_equal({:action => 'index', :controller => 'movies'}, @collection.path_for_controller(segment))
243
+ end
244
+
245
+ should "return new action and controller name for new action segment" do
246
+ segment = ActionController::Routing::StaticSegment.new("new")
247
+ assert_equal({:action => 'new', :controller => 'actors'}, @collection.path_for_controller(segment))
248
+ end
249
+ end
250
+
251
+ context "repaired_model_path" do
252
+ should "return repaired path if model is connected with controller" do
253
+ path = {:action => "show", :controller => "movies", :movie_id => 3}
254
+ assert_equal({:action => "show", :controller => "movies", :id => 3}, @collection.repaired_model_path(path))
255
+ end
256
+
257
+ should "return same path if model is not connected with controller" do
258
+ path = {:action => "show", :controller => "actors", :movie_id => 3}
259
+ assert_equal(path, @collection.repaired_model_path(path))
260
+ end
261
+ end
262
+
263
+ context "make_pathes" do
264
+ should "return patches array for objects" do
265
+ assert_equal([
266
+ {:action => 'index', :controller => 'countries'},
267
+ {:action => 'show', :controller => 'countries', :id => @usa.id.to_s},
268
+ {:action => 'index', :controller => 'movies', :country_id => @usa.id.to_s},
269
+ {:action => 'show', :controller => 'movies', :country_id => @usa.id.to_s, :id => @titanic.id.to_s},
270
+ {:action => 'index', :controller => 'actors', :country_id => @usa.id.to_s, :movie_id => @titanic.id.to_s},
271
+ {:action => 'update', :controller => 'actors', :country_id => @usa.id.to_s, :movie_id => @titanic.id.to_s, :id => @leo.id.to_s}
272
+ ], @collection.make_pathes)
273
+ end
274
+
275
+ should "return patches array for objects for new action" do
276
+ Collection.any_instance.stubs(:request_path => "/countries/#{@usa.id}/movies/#{@titanic.id}/actors/new", :request_method => :get)
277
+ collection = Collection.new("request_object")
278
+ assert_equal([
279
+ {:action => 'index', :controller => 'countries'},
280
+ {:action => 'show', :controller => 'countries', :id => @usa.id.to_s},
281
+ {:action => 'index', :controller => 'movies', :country_id => @usa.id.to_s},
282
+ {:action => 'show', :controller => 'movies', :country_id => @usa.id.to_s, :id => @titanic.id.to_s},
283
+ {:action => 'index', :controller => 'actors', :country_id => @usa.id.to_s, :movie_id => @titanic.id.to_s},
284
+ {:action => 'new', :controller => 'actors', :country_id => @usa.id.to_s, :movie_id => @titanic.id.to_s}
285
+ ], collection.make_pathes)
286
+ end
287
+ end
288
+
289
+ context "make_breadcrumbs" do
290
+ setup do
291
+ @results = @collection.make_breadcrumbs({:prefix => :every})
292
+ end
293
+
294
+ should "return array of breadcrumbs objects" do
295
+ assert_equal(@collection.objects.size + 1, @results.size)
296
+ results = @results.map(&:class).uniq
297
+ assert_equal(1, results.size)
298
+ assert_equal(EasyCrumbs::Breadcrumb, results.first)
299
+ end
300
+
301
+ should "last breadcrumb have name with action prefix" do
302
+ assert_equal("Update Leonardo Di Caprio", @results.last.name)
303
+ end
304
+ end
305
+
306
+ context "render" do
307
+ setup do
308
+ @results = [ "<a href=\"/\">Application</a>",
309
+ "<a href=\"/countries\">Countries list</a>",
310
+ "<a href=\"/countries/#{@usa.id}\">United States of America</a>",
311
+ "<a href=\"/countries/#{@usa.id}/movies\">Movies</a>",
312
+ "<a href=\"/countries/#{@usa.id}/movies/#{@titanic.id}\">Titanic</a>",
313
+ "<a href=\"/countries/#{@usa.id}/movies/#{@titanic.id}/actors\">Actors</a>",
314
+ "<a href=\"/countries/#{@usa.id}/movies/#{@titanic.id}/actors/#{@leo.id}\">Leonardo Di Caprio</a>"]
315
+ end
316
+
317
+ context "separator" do
318
+ should "render all breadcrumbs with links and standard separator" do
319
+ assert_equal(@results.join(" > "), @collection.render)
320
+ end
321
+
322
+ should "render custom separator" do
323
+ assert_equal(@results.join(" | "), @collection.render(:separator => " | "))
324
+ end
325
+ end
326
+
327
+ context "last item not link" do
328
+ should "last item not be link when last_link option is false" do
329
+ @results = @results[0..-2] << "Leonardo Di Caprio"
330
+ assert_equal(@results.join(" > "), @collection.render(:last_link => false))
331
+ end
332
+ end
333
+ end
334
+
335
+ end
336
+ end
337
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: easycrumbs
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - "Stanis\xC5\x82aw Kolarzowski"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-08 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: thoughtbot-shoulda
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ description: Easy breadcrumbs for your website
36
+ email: stanislaw.kolarzowski@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.rdoc
44
+ files:
45
+ - .document
46
+ - .gitignore
47
+ - LICENSE
48
+ - README.rdoc
49
+ - Rakefile
50
+ - VERSION
51
+ - easycrumbs.gemspec
52
+ - lib/easycrumbs.rb
53
+ - lib/easycrumbs/breadcrumb.rb
54
+ - lib/easycrumbs/collection.rb
55
+ - lib/easycrumbs/errors.rb
56
+ - lib/easycrumbs/view_helpers.rb
57
+ - test/helper.rb
58
+ - test/routes.rb
59
+ - test/test_easycrumbs.rb
60
+ has_rdoc: true
61
+ homepage: http://github.com/staszek/easycrumbs
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options:
66
+ - --charset=UTF-8
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ requirements: []
88
+
89
+ rubyforge_project:
90
+ rubygems_version: 1.3.7
91
+ signing_key:
92
+ specification_version: 3
93
+ summary: Easy breadcrumbs
94
+ test_files:
95
+ - test/helper.rb
96
+ - test/routes.rb
97
+ - test/test_easycrumbs.rb