easycrumbs 0.1.0

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.
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