crumble 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.md +124 -0
- data/Rakefile +23 -0
- data/VERSION +1 -0
- data/app/helpers/breadcrumbs_helper.rb +89 -0
- data/lib/breadcrumb.rb +91 -0
- data/rails/init.rb +1 -0
- data/spec/breadcrumb_spec.rb +84 -0
- data/spec/breadcrumbs_helper_spec.rb +335 -0
- data/spec/spec_helper.rb +62 -0
- metadata +66 -0
data/.gitignore
ADDED
data/README.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
Crumble - It's like breadcrumbs for your Rails application!
|
2
|
+
|
3
|
+
It's a tiny combination of a helper and a simple configuration class to make breadcrumbs cool, because they're not.
|
4
|
+
|
5
|
+
Installation
|
6
|
+
============
|
7
|
+
|
8
|
+
The gem is hosted on gemcutter, so if you haven’t already, add it as a gem source:
|
9
|
+
|
10
|
+
gem sources -a http://gemcutter.org/
|
11
|
+
|
12
|
+
Then install the Formtastic gem (recommended):
|
13
|
+
|
14
|
+
gem install crumble
|
15
|
+
|
16
|
+
Alternatively you can also install it as a Rails plugin:
|
17
|
+
|
18
|
+
script/plugin install git://github.com/mattmatt/crumble.git
|
19
|
+
|
20
|
+
Requires Rails 2.3.
|
21
|
+
|
22
|
+
Note: If you have configured Rails to reload all plugins in development mode, then putting your breadcrumbs configuration into an initializer won't work, since the classes, and therefore the breadcrumbs configuration will be unloaded after the request, and not be reloaded before the next one.
|
23
|
+
|
24
|
+
This will cause the problem. Either disable it, or let Rails use the default, which is to not reload plugins.
|
25
|
+
|
26
|
+
config.reload_plugins = true
|
27
|
+
|
28
|
+
Usage
|
29
|
+
=====
|
30
|
+
|
31
|
+
I wanted to have a rather simple API to configure breadcrumbs, so I made one. Basically you configure your breadcrumbs in an initializers, e.g. config/initializers/breadcrumbs.rb like so:
|
32
|
+
|
33
|
+
Breadcrumb.configure do
|
34
|
+
# Specify name, link title and the URL to link to
|
35
|
+
crumb :profile, "Your Profile", :account_url
|
36
|
+
crumb :root, "Home", :root_url
|
37
|
+
|
38
|
+
# Specify controller, action, and an array of the crumbs you specified above
|
39
|
+
trail :accounts, :show, [:root, :profile]
|
40
|
+
trail :home, :index, [:root]
|
41
|
+
|
42
|
+
# Specify the delimiter for the crumbs
|
43
|
+
delimit_with "/"
|
44
|
+
end
|
45
|
+
|
46
|
+
You can hand over parameters to the URL generator methods, the parameters are expected to exist as instance variables in your controller/helper:
|
47
|
+
|
48
|
+
crumb :blog_comment, "Your Profile", :blog_comment_url, :blog, :comment
|
49
|
+
|
50
|
+
If you need to fetch a nested object from an existing one, you can do it with nested hashes, nesting knowing now boundaries, as long as a tree of objects conforming to them (in this case @user.blog.name) exists:
|
51
|
+
|
52
|
+
crumb :blog, "Your Blog", :blog_url, :user => {:blog => :name}
|
53
|
+
crumb :blog, "Your Blog", :blog_url, :user => :blog
|
54
|
+
|
55
|
+
If you really need to (only if you really, really need to), you can specify a string to be eval'd at runtime as parameter for the URL method. Brace yourself, it's not pretty:
|
56
|
+
|
57
|
+
crumb :blog, "Your Blog", :blog_url, '@user.blog'
|
58
|
+
|
59
|
+
You can also add URL parameters derived from the parameters of the current request:
|
60
|
+
|
61
|
+
crumb :search, "Search", :new_search_url, :params => :q
|
62
|
+
|
63
|
+
Arrays of parameters work too:
|
64
|
+
|
65
|
+
crumb :search, "Search", :new_search_url, :params => [:q, :country]
|
66
|
+
|
67
|
+
And nested parameters:
|
68
|
+
|
69
|
+
crumb :search, "Search", :new_search_url, :params => {:search => :q}
|
70
|
+
|
71
|
+
If you want to make the link title content dynamic, just use single quotes and rely on interpolation, you just need to ensure the interpolated code exists in the context of your helpers:
|
72
|
+
|
73
|
+
crumb :search, 'Search (Keywords: #{params[:q]})', :new_search_url, :params => :q
|
74
|
+
|
75
|
+
If you don't want to specify any URL method at all, just use :current, it'll just use all the parameters of the current action, of course being aware that you can't have an URL method called current to rely on. But who would do that anyway?
|
76
|
+
|
77
|
+
crumb :search, 'Search (Keywords: #{params[:q]})', :current
|
78
|
+
|
79
|
+
You can base trails on conditions using :unless and :if. Both need to point to a method that exists in the context of the view.
|
80
|
+
|
81
|
+
trail :home, :index, [:root], :unless => :logged_in?
|
82
|
+
trail :home, :index, [:your_account], :if => :logged_in?
|
83
|
+
|
84
|
+
Alternatively you can specify a block that takes the controller as an argument.
|
85
|
+
|
86
|
+
trail :home, :index, [:your_account], :if => lambda {|controller| controller.logged_in?}
|
87
|
+
|
88
|
+
Your trails can also relate to a bunch of actions, just specify an array instead.
|
89
|
+
|
90
|
+
trail :profiles, [:show, :edit], [:profile]
|
91
|
+
|
92
|
+
To keep your breadcrumbs definition neat and tidy, wrap them based on their context with a handy method called, you guessed it, context:
|
93
|
+
|
94
|
+
context "user profile" do
|
95
|
+
trail :home, :index, [:root], :unless => :logged_in?
|
96
|
+
trail :home, :index, [:your_account], :if => :logged_in?
|
97
|
+
end
|
98
|
+
|
99
|
+
Dump your trails and crumbs in there and bask in the glory of an easier readable crumbs definition.
|
100
|
+
|
101
|
+
If you don't want to have the last crumb linked, no problem at all, we can do that too:
|
102
|
+
|
103
|
+
Breadcrumb.configure do
|
104
|
+
dont_link_last_crumb
|
105
|
+
end
|
106
|
+
|
107
|
+
Yep, that's it. Include that in your breadcrumbs definition and you're done.
|
108
|
+
Then, in your views, just insert the following:
|
109
|
+
|
110
|
+
<%= crumbs %>
|
111
|
+
|
112
|
+
If your trails reference non-existing crumbs, the plugin will raise an error telling you where in your configuration the illegal reference was made.
|
113
|
+
|
114
|
+
Future
|
115
|
+
======
|
116
|
+
|
117
|
+
If you think something's missing, let me know at <meyer@paperplanes.de>, or even better, send patches, including tests.
|
118
|
+
|
119
|
+
License
|
120
|
+
=======
|
121
|
+
|
122
|
+
MIT
|
123
|
+
|
124
|
+
(c) 2009 [Mathias Meyer](http://www.paperplanes.de)
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require "spec/rake/spectask"
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = "crumble"
|
9
|
+
gem.summary = %Q{Crumble - It's like breadcrumbs for your Rails application!}
|
10
|
+
gem.description = %Q{How did these breadcrumbs in your Rails application? Oh right, with this plugin!}
|
11
|
+
gem.email = "meyer@paperplanes.de"
|
12
|
+
gem.homepage = "http://github.com/mattmatt/crumble"
|
13
|
+
gem.authors = ["Mathias Meyer"]
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Run all specs"
|
21
|
+
Spec::Rake::SpecTask.new("spec") do |t|
|
22
|
+
t.spec_files = FileList["spec/*.rb"]
|
23
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module BreadcrumbsHelper
|
2
|
+
def crumbs
|
3
|
+
(Breadcrumb.instance.trails || []).each do |trail|
|
4
|
+
if trail.controller.to_sym == params[:controller].to_sym and
|
5
|
+
trail.action.to_sym == params[:action].to_sym
|
6
|
+
next unless trail.condition_met?(self)
|
7
|
+
return calculate_breadcrumb_trail(trail.trail)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
""
|
11
|
+
end
|
12
|
+
|
13
|
+
def calculate_breadcrumb_trail(trail)
|
14
|
+
breadcrumb_trail = []
|
15
|
+
trail.each do |crummy|
|
16
|
+
crumb = Breadcrumb.instance.crumbs[crummy]
|
17
|
+
if not Breadcrumb.instance.last_crumb_linked? and crummy == trail.last
|
18
|
+
breadcrumb_trail << eval(%Q{"#{crumb.title}"})
|
19
|
+
else
|
20
|
+
breadcrumb_trail << link_to(eval(%Q{"#{crumb.title}"}), fetch_crumb_url(crumb))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
breadcrumb_trail.join(Breadcrumb.instance.delimiter)
|
24
|
+
end
|
25
|
+
|
26
|
+
def fetch_parameterized_crumb_url(crumb)
|
27
|
+
case crumb.params
|
28
|
+
when Hash
|
29
|
+
if crumb.params[:params]
|
30
|
+
send(crumb.url, fetch_parameters_recursive(crumb.params[:params]))
|
31
|
+
else
|
32
|
+
result = instance_eval("@#{assemble_crumb_url_parameter(crumb.params).join(".")}")
|
33
|
+
send(crumb.url, result)
|
34
|
+
end
|
35
|
+
else
|
36
|
+
if crumb.url == :current
|
37
|
+
params
|
38
|
+
else
|
39
|
+
prams = crumb.params.collect do |name|
|
40
|
+
case name
|
41
|
+
when Symbol
|
42
|
+
instance_variable_get("@#{name}")
|
43
|
+
when String
|
44
|
+
instance_eval(name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
send(crumb.url, *prams)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def fetch_crumb_url(crumb)
|
53
|
+
if crumb.params
|
54
|
+
fetch_parameterized_crumb_url(crumb)
|
55
|
+
else
|
56
|
+
send(crumb.url)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def fetch_parameters_recursive(params_hash, parent = nil)
|
61
|
+
parameters = {}
|
62
|
+
case params_hash
|
63
|
+
when Symbol
|
64
|
+
parameters[params_hash] = (parent || params)[params_hash]
|
65
|
+
when Array
|
66
|
+
params_hash.each do |pram|
|
67
|
+
parameter = (parent || params)[pram]
|
68
|
+
parameters[pram] = parameter unless parameter.blank?
|
69
|
+
end
|
70
|
+
when Hash
|
71
|
+
params_hash.each do |pram, nested|
|
72
|
+
parameters[pram] = fetch_parameters_recursive(nested, params[pram])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
parameters
|
76
|
+
end
|
77
|
+
|
78
|
+
def assemble_crumb_url_parameter(params)
|
79
|
+
result = []
|
80
|
+
params.to_a.flatten.collect do |step|
|
81
|
+
result << if step.is_a?(Hash)
|
82
|
+
assemble_crumb_url_parameter(step)
|
83
|
+
else
|
84
|
+
step
|
85
|
+
end
|
86
|
+
end
|
87
|
+
result
|
88
|
+
end
|
89
|
+
end
|
data/lib/breadcrumb.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
class Breadcrumb
|
4
|
+
include Singleton
|
5
|
+
Trail = Struct.new(:controller, :action, :trail, :options, :line) do
|
6
|
+
def condition_met?(obj)
|
7
|
+
if options[:if]
|
8
|
+
evaluate(obj, options[:if])
|
9
|
+
elsif options[:unless]
|
10
|
+
!evaluate(obj, options[:unless])
|
11
|
+
else
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def evaluate(obj, condition)
|
17
|
+
if condition.respond_to?(:call)
|
18
|
+
condition.call(obj.controller)
|
19
|
+
else
|
20
|
+
obj.send(condition)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Crumb = Struct.new(:name, :title, :url, :params)
|
26
|
+
|
27
|
+
attr_accessor :trails, :crumbs, :delimiter
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@last_crumb_linked = true
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.configure(&blk)
|
34
|
+
instance.crumbs = {}
|
35
|
+
instance.trails = []
|
36
|
+
instance.instance_eval &blk
|
37
|
+
instance.validate
|
38
|
+
end
|
39
|
+
|
40
|
+
def trail(controller, actions, trail, options = {})
|
41
|
+
@trails ||= []
|
42
|
+
actions = Array(actions)
|
43
|
+
actions.each do |action|
|
44
|
+
@trails << Trail.new(controller, action, trail, options, caller[2].split(":")[1])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def crumb(name, title, url, *params)
|
49
|
+
params = params.first if params.any? && params.first.is_a?(Hash)
|
50
|
+
@crumbs ||= {}
|
51
|
+
@crumbs[name] = Crumb.new(name, title, url, params)
|
52
|
+
end
|
53
|
+
|
54
|
+
def context(name)
|
55
|
+
yield
|
56
|
+
end
|
57
|
+
|
58
|
+
def delimit_with(delimiter)
|
59
|
+
@delimiter = delimiter
|
60
|
+
end
|
61
|
+
|
62
|
+
def dont_link_last_crumb
|
63
|
+
@last_crumb_linked = false
|
64
|
+
end
|
65
|
+
|
66
|
+
def link_last_crumb
|
67
|
+
@last_crumb_linked = true
|
68
|
+
end
|
69
|
+
|
70
|
+
def last_crumb_linked?
|
71
|
+
@last_crumb_linked
|
72
|
+
end
|
73
|
+
|
74
|
+
def validate
|
75
|
+
invalid_trails = []
|
76
|
+
trails.each do |trail|
|
77
|
+
trail.trail.collect do |t|
|
78
|
+
invalid_trails << [trail, t] if crumbs[t].nil?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
if invalid_trails.any?
|
83
|
+
messages = []
|
84
|
+
invalid_trails.each do |trail|
|
85
|
+
messages << "Trail for #{trail.first.controller}/#{trail.first.action} references non-existing crumb '#{trail.last}' (configuration file line: #{trail.first.line})"
|
86
|
+
end
|
87
|
+
raise messages.join("\n")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), *%w[.. lib breadcrumb])
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe Breadcrumb do
|
4
|
+
describe "when configuring the instance" do
|
5
|
+
it "should add trails" do
|
6
|
+
Breadcrumb.configure do
|
7
|
+
crumb :profile, "Public Profile", :user_url, :user
|
8
|
+
crumb :your_account, "Public Profile", :user_url, :user
|
9
|
+
|
10
|
+
trail :accounts, :edit, [:profile, :your_account]
|
11
|
+
end
|
12
|
+
|
13
|
+
trail = Breadcrumb.instance.trails.last
|
14
|
+
trail.controller.should == :accounts
|
15
|
+
trail.action.should == :edit
|
16
|
+
trail.trail.should == [:profile, :your_account]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should add crumbs" do
|
20
|
+
Breadcrumb.configure do
|
21
|
+
crumb :profile, "Public Profile", :user_url, :user
|
22
|
+
end
|
23
|
+
|
24
|
+
profile = Breadcrumb.instance.crumbs[:profile]
|
25
|
+
profile.title.should == "Public Profile"
|
26
|
+
profile.url.should == :user_url
|
27
|
+
profile.params.should == [:user]
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should store the delimiter" do
|
31
|
+
Breadcrumb.configure do
|
32
|
+
delimit_with "/"
|
33
|
+
end
|
34
|
+
|
35
|
+
Breadcrumb.instance.delimiter.should == "/"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should set the flag not to link the last crumb" do
|
39
|
+
Breadcrumb.configure do
|
40
|
+
dont_link_last_crumb
|
41
|
+
end
|
42
|
+
|
43
|
+
Breadcrumb.instance.last_crumb_linked?.should == false
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should unset the flag not to link the last crumb" do
|
47
|
+
Breadcrumb.configure do
|
48
|
+
link_last_crumb
|
49
|
+
end
|
50
|
+
|
51
|
+
Breadcrumb.instance.last_crumb_linked?.should == true
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should support contexts" do
|
55
|
+
Breadcrumb.configure do
|
56
|
+
context "user profile" do
|
57
|
+
crumb :profile, "Public Profile", :user_url, :user
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
profile = Breadcrumb.instance.crumbs[:profile]
|
62
|
+
profile.title.should == "Public Profile"
|
63
|
+
profile.url.should == :user_url
|
64
|
+
profile.params.should == [:user]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should not accept non-existing trails in crumb definitions" do
|
68
|
+
lambda {
|
69
|
+
Breadcrumb.configure do
|
70
|
+
trail :accounts, :edit, [:profile]
|
71
|
+
end
|
72
|
+
}.should raise_error(RuntimeError, "Trail for accounts/edit references non-existing crumb 'profile' (configuration file line: 70)")
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should include errors for multiple missing crumb definitions" do
|
76
|
+
lambda {
|
77
|
+
Breadcrumb.configure do
|
78
|
+
trail :accounts, :edit, [:profile]
|
79
|
+
trail :accounts, :show, [:profile]
|
80
|
+
end
|
81
|
+
}.should raise_error(RuntimeError, "Trail for accounts/edit references non-existing crumb 'profile' (configuration file line: 78)\nTrail for accounts/show references non-existing crumb 'profile' (configuration file line: 79)")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,335 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'action_view/helpers/url_helper'
|
5
|
+
|
6
|
+
describe BreadcrumbsHelper do
|
7
|
+
include ActionView::Helpers::UrlHelper
|
8
|
+
include ActionView::Helpers::TagHelper
|
9
|
+
include BreadcrumbsHelper
|
10
|
+
|
11
|
+
attr_accessor :params
|
12
|
+
|
13
|
+
def controller
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
@params = {}
|
19
|
+
@user = User.new("jonathan")
|
20
|
+
@article = Article.new(1)
|
21
|
+
Breadcrumb.configure do
|
22
|
+
delimit_with " / "
|
23
|
+
link_last_crumb
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "when getting the breadcrumbs" do
|
28
|
+
before(:each) do
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should calculate the urls in the breadcrumbs" do
|
32
|
+
Breadcrumb.configure do
|
33
|
+
crumb :your_account, "Your Account", :edit_account_url
|
34
|
+
trail :accounts, :index, [:your_account]
|
35
|
+
end
|
36
|
+
params[:controller] = 'accounts'
|
37
|
+
params[:action] = 'index'
|
38
|
+
crumbs.should == %Q{<a href="http://test.host/account/edit">Your Account</a>}
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should support fetching an instance variable" do
|
42
|
+
Breadcrumb.configure do
|
43
|
+
crumb :profile, "Public Profile", :user_url, :user
|
44
|
+
trail :accounts, :edit, [:profile]
|
45
|
+
end
|
46
|
+
params[:controller] = 'accounts'
|
47
|
+
params[:action] = 'edit'
|
48
|
+
crumbs.should == %Q{<a href="http://test.host/f/jonathan">Public Profile</a>}
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should support fetching multiple instance variables" do
|
52
|
+
Breadcrumb.configure do
|
53
|
+
trail :accounts, :profile, [:your_article]
|
54
|
+
crumb :your_article, "Your Article", :user_article_url, :user, :article
|
55
|
+
end
|
56
|
+
|
57
|
+
params[:controller] = 'accounts'
|
58
|
+
params[:action] = 'profile'
|
59
|
+
crumbs.should == %Q{<a href="http://test.host/f/jonathan/articles/1">Your Article</a>}
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should join multiple crumbs with a /" do
|
63
|
+
Breadcrumb.configure do
|
64
|
+
trail :accounts, :show, [:profile, :your_account]
|
65
|
+
crumb :profile, "Public Profile", :user_url, :user
|
66
|
+
crumb :your_account, "Your Account", :edit_account_url
|
67
|
+
end
|
68
|
+
|
69
|
+
params[:controller] = 'accounts'
|
70
|
+
params[:action] = 'show'
|
71
|
+
crumbs.should == %Q{<a href="http://test.host/f/jonathan">Public Profile</a> / <a href="http://test.host/account/edit">Your Account</a>}
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should return an empty string for no matches" do
|
75
|
+
Breadcrumb.configure do
|
76
|
+
end
|
77
|
+
params[:controller] = 'accounts'
|
78
|
+
params[:action] = 'sho'
|
79
|
+
crumbs.should == ""
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should add parameters to the url" do
|
83
|
+
Breadcrumb.configure do
|
84
|
+
crumb :search, "Search", :search_url, :params => :q
|
85
|
+
trail :search, :new, [:search]
|
86
|
+
end
|
87
|
+
|
88
|
+
params[:controller] = 'search'
|
89
|
+
params[:action] = 'new'
|
90
|
+
params[:q] = 'google'
|
91
|
+
crumbs.should == %Q{<a href="http://test.host/search?q=google">Search</a>}
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should add multiple parameters to the url" do
|
95
|
+
Breadcrumb.configure do
|
96
|
+
crumb :search, "Search", :search_url, :params => [:q, :country]
|
97
|
+
trail :search, :new, [:search]
|
98
|
+
end
|
99
|
+
|
100
|
+
params[:controller] = 'search'
|
101
|
+
params[:action] = 'new'
|
102
|
+
params[:country] = 'Germany'
|
103
|
+
params[:q] = 'google'
|
104
|
+
crumbs.should == %Q{<a href="http://test.host/search?q=google&country=Germany">Search</a>}
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should eval single quoted title strings and interpolate them" do
|
108
|
+
Breadcrumb.configure do
|
109
|
+
crumb :search_results, 'Search Results (#{@query})', :search_url, :query
|
110
|
+
trail :search, :create, [:search_results]
|
111
|
+
end
|
112
|
+
|
113
|
+
params[:controller] = 'search'
|
114
|
+
params[:action] = 'create'
|
115
|
+
|
116
|
+
@query = 'google'
|
117
|
+
crumbs.should == %Q{<a href="http://test.host/search/google">Search Results (google)</a>}
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should support a list of actions to configure a trail" do
|
121
|
+
Breadcrumb.configure do
|
122
|
+
crumb :search_results, 'Search Results (#{@query})', :search_url
|
123
|
+
trail :search, [:create, :new], [:search_results]
|
124
|
+
end
|
125
|
+
|
126
|
+
params[:controller] = 'search'
|
127
|
+
params[:action] = 'create'
|
128
|
+
crumbs.should == %Q{<a href="http://test.host/search/">Search Results ()</a>}
|
129
|
+
|
130
|
+
params[:action] = 'new'
|
131
|
+
crumbs.should == %Q{<a href="http://test.host/search/">Search Results ()</a>}
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should support using the current url instead of a predefined one" do
|
135
|
+
Breadcrumb.configure do
|
136
|
+
crumb :search_results, 'Search Results (#{@query})', :current
|
137
|
+
trail :search, [:create, :new], [:search_results]
|
138
|
+
end
|
139
|
+
|
140
|
+
params[:controller] = 'search'
|
141
|
+
params[:action] = 'new'
|
142
|
+
crumbs.should == %Q{<a href="http://test.host/search/new">Search Results ()</a>}
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should not consider a trail when it has an :if condition and it's not met" do
|
146
|
+
Breadcrumb.configure do
|
147
|
+
crumb :search_results, 'Search Results', :current
|
148
|
+
trail :search, [:create, :new], [:search_results], :if => :is_it_false?
|
149
|
+
end
|
150
|
+
|
151
|
+
params[:controller] = 'search'
|
152
|
+
params[:action] = 'new'
|
153
|
+
crumbs.should == ""
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should consider a trail when it has an :if condition and it's met" do
|
157
|
+
Breadcrumb.configure do
|
158
|
+
crumb :search_results, 'Search Results', :current
|
159
|
+
trail :search, [:create, :new], [:search_results], :if => :its_true!
|
160
|
+
end
|
161
|
+
|
162
|
+
params[:controller] = 'search'
|
163
|
+
params[:action] = 'new'
|
164
|
+
crumbs.should == %Q{<a href="http://test.host/search/new">Search Results</a>}
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should not consider a trail when it has an :unless condition and it's not met" do
|
168
|
+
Breadcrumb.configure do
|
169
|
+
crumb :search_results, 'Search Results', :current
|
170
|
+
trail :search, [:create, :new], [:search_results], :unless => :its_true!
|
171
|
+
end
|
172
|
+
|
173
|
+
params[:controller] = 'search'
|
174
|
+
params[:action] = 'new'
|
175
|
+
crumbs.should == ""
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should consider a trail when it has an :unless condition and it's met" do
|
179
|
+
Breadcrumb.configure do
|
180
|
+
crumb :search_results, 'Search Results', :current
|
181
|
+
trail :search, [:create, :new], [:search_results], :unless => :is_it_false?
|
182
|
+
end
|
183
|
+
|
184
|
+
params[:controller] = 'search'
|
185
|
+
params[:action] = 'new'
|
186
|
+
crumbs.should == %Q{<a href="http://test.host/search/new">Search Results</a>}
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should call blocks as :unless parameters" do
|
190
|
+
Breadcrumb.configure do
|
191
|
+
crumb :search_results, 'Search Results', :current
|
192
|
+
trail :search, [:create, :new], [:search_results], :unless => lambda {|controller| controller.its_true!}
|
193
|
+
end
|
194
|
+
|
195
|
+
params[:controller] = 'search'
|
196
|
+
params[:action] = 'new'
|
197
|
+
crumbs.should == ""
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should call blocks as :if parameters" do
|
201
|
+
Breadcrumb.configure do
|
202
|
+
crumb :search_results, 'Search Results', :current
|
203
|
+
trail :search, [:create, :new], [:search_results], :if => lambda {|controller| controller.its_true!}
|
204
|
+
end
|
205
|
+
|
206
|
+
params[:controller] = 'search'
|
207
|
+
params[:action] = 'new'
|
208
|
+
crumbs.should == "<a href=\"http://test.host/search/new\">Search Results</a>"
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should support resolving parameters for url methods derived from a string" do
|
212
|
+
Breadcrumb.configure do
|
213
|
+
crumb :search_results, 'Search Results', :search_url, "@user.login"
|
214
|
+
trail :search, [:create, :new], [:search_results]
|
215
|
+
end
|
216
|
+
|
217
|
+
params[:controller] = 'search'
|
218
|
+
params[:action] = 'new'
|
219
|
+
crumbs.should == %Q{<a href="http://test.host/search/jonathan">Search Results</a>}
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should support resolving parameters for url methods derived from a hash pointing to an object hierarchy" do
|
223
|
+
Breadcrumb.configure do
|
224
|
+
crumb :search_results, 'Search Results', :search_url, :user => :login
|
225
|
+
trail :search, [:create, :new], [:search_results]
|
226
|
+
end
|
227
|
+
|
228
|
+
params[:controller] = 'search'
|
229
|
+
params[:action] = 'new'
|
230
|
+
crumbs.should == %Q{<a href="http://test.host/search/jonathan">Search Results</a>}
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should support resolving parameters for url methods derived from a hash pointing to a nested object hierarchy" do
|
234
|
+
Breadcrumb.configure do
|
235
|
+
crumb :search_results, 'Search Results', :search_url, :user => {:login => :to_s}
|
236
|
+
trail :search, [:create, :new], [:search_results]
|
237
|
+
end
|
238
|
+
|
239
|
+
params[:controller] = 'search'
|
240
|
+
params[:action] = 'new'
|
241
|
+
crumbs.should == %Q{<a href="http://test.host/search/jonathan">Search Results</a>}
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should return the same breadcrumbs on subsequent calls" do
|
245
|
+
Breadcrumb.configure do
|
246
|
+
crumb :your_account, "Your Account", :edit_account_url
|
247
|
+
trail :accounts, :index, [:your_account]
|
248
|
+
end
|
249
|
+
params[:controller] = 'accounts'
|
250
|
+
params[:action] = 'index'
|
251
|
+
once = crumbs
|
252
|
+
twice = crumbs
|
253
|
+
once.should == twice
|
254
|
+
end
|
255
|
+
|
256
|
+
it "should not link the last link when the option was specified" do
|
257
|
+
Breadcrumb.configure do
|
258
|
+
trail :accounts, :show, [:profile, :your_account]
|
259
|
+
crumb :profile, "Public Profile", :user_url, :user
|
260
|
+
crumb :your_account, "Your Account", :edit_account_url
|
261
|
+
dont_link_last_crumb
|
262
|
+
end
|
263
|
+
|
264
|
+
params[:controller] = 'accounts'
|
265
|
+
params[:action] = 'show'
|
266
|
+
crumbs.should == %Q{<a href="http://test.host/f/jonathan">Public Profile</a> / Your Account}
|
267
|
+
end
|
268
|
+
|
269
|
+
it "should not link the last link when the option was specified and only one crumb is in the trail" do
|
270
|
+
Breadcrumb.configure do
|
271
|
+
trail :accounts, :show, [:profile]
|
272
|
+
crumb :profile, "Public Profile", :user_url, :user
|
273
|
+
dont_link_last_crumb
|
274
|
+
end
|
275
|
+
|
276
|
+
params[:controller] = 'accounts'
|
277
|
+
params[:action] = 'show'
|
278
|
+
crumbs.should == %Q{Public Profile}
|
279
|
+
end
|
280
|
+
|
281
|
+
describe "when fetching parameters" do
|
282
|
+
it "should support nested parameter attributes" do
|
283
|
+
Breadcrumb.configure do
|
284
|
+
crumb :nested_search, "Search", :search_url, :params => {:search => :q}
|
285
|
+
trail :search, :new, [:nested_search]
|
286
|
+
end
|
287
|
+
|
288
|
+
params[:controller] = "search"
|
289
|
+
params[:action] = 'new'
|
290
|
+
params[:search] = {:q => "google", :country => "Germany"}
|
291
|
+
|
292
|
+
fetch_parameters_recursive({:search => [:q, :country]}).should == {:search => {:q => "google", :country => "Germany"}}
|
293
|
+
end
|
294
|
+
|
295
|
+
it "should support nested array parameters" do
|
296
|
+
Breadcrumb.configure do
|
297
|
+
crumb :nested_search, "Search", :search_url, :params => {:search => :q}
|
298
|
+
trail :search, :new, [:nested_search]
|
299
|
+
end
|
300
|
+
|
301
|
+
params[:controller] = "search"
|
302
|
+
params[:action] = 'new'
|
303
|
+
params[:search] = {:q => "google", :country => ["Germany", "Australia"]}
|
304
|
+
|
305
|
+
fetch_parameters_recursive({:search => [:q, :country]}).should == {:search => {:q => "google", :country => ["Germany", "Australia"]}}
|
306
|
+
end
|
307
|
+
|
308
|
+
it "should not include empty parameters" do
|
309
|
+
Breadcrumb.configure do
|
310
|
+
crumb :nested_search, "Search", :search_url, :params => {:search => :q}
|
311
|
+
trail :search, :new, [:nested_search]
|
312
|
+
end
|
313
|
+
|
314
|
+
params[:controller] = "search"
|
315
|
+
params[:action] = 'new'
|
316
|
+
params[:search] = {:q => ""}
|
317
|
+
|
318
|
+
fetch_parameters_recursive({:search => [:q, :country]}).should == {:search => {}}
|
319
|
+
end
|
320
|
+
|
321
|
+
it "should not include empty parameters with nested hashes" do
|
322
|
+
Breadcrumb.configure do
|
323
|
+
crumb :nested_search, "Search", :search_url, :params => {:search => :q}
|
324
|
+
trail :search, :new, [:nested_search]
|
325
|
+
end
|
326
|
+
|
327
|
+
params[:controller] = "search"
|
328
|
+
params[:action] = 'new'
|
329
|
+
params[:search] = {:q => "google", :country => []}
|
330
|
+
|
331
|
+
fetch_parameters_recursive({:search => [:q, :country]}).should == {:search => {:q => "google"}}
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'rspec'
|
3
|
+
|
4
|
+
require "#{File.dirname(__FILE__)}/../app/helpers/breadcrumbs_helper"
|
5
|
+
require "#{File.dirname(__FILE__)}/../lib/breadcrumb"
|
6
|
+
|
7
|
+
Spec::Runner.configure do |config|
|
8
|
+
|
9
|
+
config.before(:each) do
|
10
|
+
@old_trails = Breadcrumb.instance.trails
|
11
|
+
Breadcrumb.instance.trails = nil
|
12
|
+
|
13
|
+
@old_crumbs = Breadcrumb.instance.crumbs
|
14
|
+
Breadcrumb.instance.crumbs = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
config.after(:each) do
|
18
|
+
Breadcrumb.instance.crumbs = @old_crumbs
|
19
|
+
Breadcrumb.instance.trails = @old_trails
|
20
|
+
end
|
21
|
+
|
22
|
+
public
|
23
|
+
|
24
|
+
def edit_account_url
|
25
|
+
"http://test.host/account/edit"
|
26
|
+
end
|
27
|
+
|
28
|
+
def user_url(user)
|
29
|
+
"http://test.host/f/#{user.login}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def user_article_url(user, article)
|
33
|
+
"http://test.host/f/#{user.login}/articles/#{article.id}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def search_url(params = nil)
|
37
|
+
if params.is_a?(Hash)
|
38
|
+
"http://test.host/search?#{params.collect{|key, value| "#{key.to_s}=#{value}"}.join('&')}"
|
39
|
+
else
|
40
|
+
"http://test.host/search/#{params}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def url_for(params)
|
45
|
+
if params.is_a?(Hash)
|
46
|
+
"http://test.host/#{params[:controller]}/#{params[:action]}"
|
47
|
+
else
|
48
|
+
super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def is_it_false?
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
56
|
+
def its_true!
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
User = Struct.new(:login)
|
61
|
+
Article = Struct.new(:id)
|
62
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: crumble
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mathias Meyer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-18 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: How did these breadcrumbs in your Rails application? Oh right, with this plugin!
|
17
|
+
email: meyer@paperplanes.de
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.md
|
24
|
+
files:
|
25
|
+
- .gitignore
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- VERSION
|
29
|
+
- app/helpers/breadcrumbs_helper.rb
|
30
|
+
- lib/breadcrumb.rb
|
31
|
+
- rails/init.rb
|
32
|
+
- spec/breadcrumb_spec.rb
|
33
|
+
- spec/breadcrumbs_helper_spec.rb
|
34
|
+
- spec/spec_helper.rb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/mattmatt/crumble
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --charset=UTF-8
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: Crumble - It's like breadcrumbs for your Rails application!
|
63
|
+
test_files:
|
64
|
+
- spec/breadcrumb_spec.rb
|
65
|
+
- spec/breadcrumbs_helper_spec.rb
|
66
|
+
- spec/spec_helper.rb
|