loaf 0.3.0 → 0.4.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.
- checksums.yaml +7 -0
- data/.gitignore +21 -8
- data/.ruby-version +1 -0
- data/.travis.yml +23 -2
- data/Appraisals +18 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +16 -1
- data/README.md +69 -52
- data/Rakefile +5 -3
- data/bin/setup +7 -0
- data/gemfiles/rails3.2.gemfile +21 -0
- data/gemfiles/rails4.0.gemfile +22 -0
- data/gemfiles/rails4.1.gemfile +21 -0
- data/gemfiles/rails4.2.gemfile +21 -0
- data/lib/loaf.rb +24 -1
- data/lib/loaf/configuration.rb +15 -22
- data/lib/loaf/controller_extensions.rb +25 -12
- data/lib/loaf/crumb.rb +13 -1
- data/lib/loaf/crumb_formatter.rb +14 -13
- data/lib/loaf/options_validator.rb +10 -2
- data/lib/loaf/translation.rb +15 -8
- data/lib/loaf/version.rb +1 -8
- data/lib/loaf/view_extensions.rb +42 -15
- data/loaf.gemspec +10 -17
- data/spec/integration/configuration_spec.rb +7 -8
- data/spec/integration/crumbs_routing_spec.rb +31 -28
- data/spec/rails_app/app/controllers/application_controller.rb +0 -2
- data/spec/rails_app/app/controllers/posts_controller.rb +13 -2
- data/spec/rails_app/app/views/layouts/_breadcrumbs.html.erb +2 -0
- data/spec/rails_app/app/views/posts/index.html.erb +0 -2
- data/spec/rails_app/app/views/posts/new.html.erb +3 -0
- data/spec/rails_app/app/views/posts/show.html.erb +1 -0
- data/spec/rails_app/config/environments/development.rb +2 -0
- data/spec/rails_app/config/environments/production.rb +2 -0
- data/spec/rails_app/config/environments/test.rb +2 -3
- data/spec/rails_app/config/routes.rb +0 -2
- data/spec/rails_app/{app/mailers → log}/.gitkeep +0 -0
- data/spec/spec_helper.rb +42 -4
- data/spec/support/dummy_view.rb +7 -0
- data/spec/unit/controller_extensions_spec.rb +63 -0
- data/spec/unit/crumb_formatter_spec.rb +38 -0
- data/spec/unit/options_validator_spec.rb +17 -0
- data/spec/unit/translation_spec.rb +22 -0
- data/spec/unit/view_extensions/breadcrumb_spec.rb +24 -0
- data/spec/unit/view_extensions/breadcrumbs_spec.rb +128 -0
- data/spec/unit/view_extensions/has_breadcrumbs_spec.rb +12 -0
- data/tasks/console.rake +10 -0
- data/tasks/coverage.rake +11 -0
- data/tasks/spec.rake +29 -0
- metadata +50 -100
- data/.rvmrc +0 -28
- data/Gemfile.lock +0 -132
- data/spec/integration/nested_crumbs_spec.rb +0 -5
- data/spec/loaf/controller_extensions_spec.rb +0 -55
- data/spec/loaf/crumb_formatter_spec.rb +0 -33
- data/spec/loaf/options_validator_spec.rb +0 -29
- data/spec/loaf/translation_spec.rb +0 -23
- data/spec/loaf/view_extensions_spec.rb +0 -114
- data/spec/loaf_spec.rb +0 -5
- data/spec/rails_app/app/assets/images/rails.png +0 -0
- data/spec/rails_app/app/assets/javascripts/application.js +0 -9
- data/spec/rails_app/app/assets/stylesheets/application.css +0 -7
- data/spec/rails_app/app/helpers/application_helper.rb +0 -2
- data/spec/rails_app/app/models/.gitkeep +0 -0
@@ -1,12 +1,23 @@
|
|
1
|
+
class Post < Struct.new(:id); end
|
2
|
+
|
1
3
|
class PostsController < ApplicationController
|
2
4
|
|
3
|
-
|
5
|
+
breadcrumb 'Home', :root_path, only: :index
|
4
6
|
|
5
7
|
def index
|
8
|
+
breadcrumb 'All Posts', posts_path
|
9
|
+
end
|
10
|
+
|
11
|
+
def show
|
12
|
+
@post = ::Post.new(1)
|
6
13
|
end
|
7
14
|
|
8
15
|
def new
|
9
|
-
|
16
|
+
breadcrumb 'New Post', new_post_path
|
10
17
|
end
|
11
18
|
|
19
|
+
def create
|
20
|
+
breadcrumb 'New Post', new_post_path, force: true
|
21
|
+
render action: :new
|
22
|
+
end
|
12
23
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<% breadcrumb 'Show Post in view', post_path(@post.id) %>
|
@@ -11,9 +11,6 @@ RailsApp::Application.configure do
|
|
11
11
|
config.serve_static_assets = true
|
12
12
|
config.static_cache_control = "public, max-age=3600"
|
13
13
|
|
14
|
-
# Log error messages when you accidentally call methods on nil
|
15
|
-
config.whiny_nils = true
|
16
|
-
|
17
14
|
# Show full error reports and disable caching
|
18
15
|
config.consider_all_requests_local = true
|
19
16
|
config.action_controller.perform_caching = false
|
@@ -39,4 +36,6 @@ RailsApp::Application.configure do
|
|
39
36
|
|
40
37
|
# Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets
|
41
38
|
config.assets.allow_debugging = true
|
39
|
+
|
40
|
+
config.eager_load = false
|
42
41
|
end
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
@@ -1,15 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
if RUBY_VERSION > '1.9' and (ENV['COVERAGE'] || ENV['TRAVIS'])
|
4
|
+
require 'simplecov'
|
5
|
+
require 'coveralls'
|
6
|
+
|
7
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
8
|
+
SimpleCov::Formatter::HTMLFormatter,
|
9
|
+
Coveralls::SimpleCov::Formatter
|
10
|
+
]
|
11
|
+
|
12
|
+
SimpleCov.start do
|
13
|
+
command_name 'spec'
|
14
|
+
add_filter 'spec'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
1
18
|
# Configure Rails Environment
|
2
19
|
ENV["RAILS_ENV"] = "test"
|
3
20
|
|
4
21
|
require File.expand_path("../rails_app/config/environment.rb", __FILE__)
|
5
22
|
require 'rspec/rails'
|
6
23
|
|
7
|
-
|
24
|
+
require 'loaf'
|
8
25
|
|
9
|
-
# Load support files
|
10
26
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
11
27
|
|
12
28
|
RSpec.configure do |config|
|
13
|
-
config.
|
14
|
-
|
29
|
+
config.expect_with :rspec do |expectations|
|
30
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
31
|
+
end
|
32
|
+
|
33
|
+
config.mock_with :rspec do |mocks|
|
34
|
+
mocks.verify_partial_doubles = true
|
35
|
+
end
|
36
|
+
|
37
|
+
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
38
|
+
config.disable_monkey_patching!
|
39
|
+
|
40
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
41
|
+
# be too noisy due to issues in dependencies.
|
42
|
+
config.warnings = true
|
43
|
+
|
44
|
+
if config.files_to_run.one?
|
45
|
+
config.default_formatter = 'doc'
|
46
|
+
end
|
47
|
+
|
48
|
+
config.profile_examples = 2
|
49
|
+
|
50
|
+
config.order = :random
|
51
|
+
|
52
|
+
Kernel.srand config.seed
|
15
53
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
class DummyController < ActionController::Base
|
6
|
+
def self.before_filter(options, &block)
|
7
|
+
yield self.new
|
8
|
+
end
|
9
|
+
include Loaf::ControllerExtensions
|
10
|
+
end
|
11
|
+
|
12
|
+
RSpec.describe Loaf::ControllerExtensions do
|
13
|
+
|
14
|
+
context 'when classes extend controller_extensions' do
|
15
|
+
it { expect(DummyController).to respond_to(:add_breadcrumb) }
|
16
|
+
it { expect(DummyController).to respond_to(:breadcrumb) }
|
17
|
+
it { expect(DummyController.new).to respond_to(:add_breadcrumb) }
|
18
|
+
it { expect(DummyController.new).to respond_to(:breadcrumb) }
|
19
|
+
it { expect(DummyController.new).to respond_to(:add_breadcrumbs) }
|
20
|
+
it { expect(DummyController.new).to respond_to(:clear_breadcrumbs) }
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'class methods' do
|
24
|
+
it 'invokes before_filter' do
|
25
|
+
allow(DummyController).to receive(:before_filter)
|
26
|
+
DummyController.breadcrumb('name', 'url_path')
|
27
|
+
expect(DummyController).to have_received(:before_filter)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'delegates to instance' do
|
31
|
+
name = 'List objects'
|
32
|
+
url = :object_path
|
33
|
+
options = {force: true}
|
34
|
+
instance = double(:controller_instance).as_null_object
|
35
|
+
|
36
|
+
allow(DummyController).to receive(:new).and_return(instance)
|
37
|
+
DummyController.breadcrumb(name, url, options)
|
38
|
+
expect(instance).to have_received(:breadcrumb).with(name, url, options)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'instance methods' do
|
43
|
+
it 'instantiates breadcrumbs container' do
|
44
|
+
name = 'List objects'
|
45
|
+
url = :object_path
|
46
|
+
instance = DummyController.new
|
47
|
+
|
48
|
+
allow(Loaf::Crumb).to receive(:new)
|
49
|
+
instance.breadcrumb(name, url)
|
50
|
+
expect(Loaf::Crumb).to have_received(:new).with(name, url, {})
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'adds breadcrumb to collection' do
|
54
|
+
name = 'List objects'
|
55
|
+
url = :object_path
|
56
|
+
instance = DummyController.new
|
57
|
+
|
58
|
+
expect {
|
59
|
+
instance.breadcrumb(name, url)
|
60
|
+
}.to change { instance._breadcrumbs.size }.by(1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Loaf::CrumbFormatter, '.format_name' do
|
6
|
+
let(:formatter) {
|
7
|
+
Class.new do
|
8
|
+
extend Loaf::CrumbFormatter
|
9
|
+
|
10
|
+
def self.truncate(name, options)
|
11
|
+
name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
}
|
15
|
+
|
16
|
+
it 'returns name error if breadcrumb name is nil' do
|
17
|
+
expect(formatter.format_name('')).to eql('')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "doesn't capitalize by default" do
|
21
|
+
name = 'some random name'
|
22
|
+
formatted = formatter.format_name(name)
|
23
|
+
expect(formatted).to eql(name)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'capitalizes crumb name with capitalize option' do
|
27
|
+
name = 'some random name'
|
28
|
+
formatted = formatter.format_name(name, capitalize: true)
|
29
|
+
expect(formatted).to eql('Some random name')
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'shortens crumb to provided length' do
|
33
|
+
name = 'very long name that is more that 30 characters long'
|
34
|
+
allow(formatter).to receive(:truncate).with(name, length: 30).
|
35
|
+
and_return(name[0..30])
|
36
|
+
expect(formatter.format_name(name, crumb_length: 30)).to eql(name[0..30])
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Loaf::OptionsValidator, '.valid?' do
|
6
|
+
let(:klass) { Class.extend Loaf::OptionsValidator }
|
7
|
+
|
8
|
+
it 'validates succesfully known option' do
|
9
|
+
expect(klass.valid?(crumb_length: 10)).to eq(true)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'validates unknown option with an error' do
|
13
|
+
expect {
|
14
|
+
klass.valid?(invalid_param: true)
|
15
|
+
}.to raise_error(Loaf::InvalidOptions)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Loaf::Translation do
|
6
|
+
|
7
|
+
before { I18n.backend = I18n::Backend::Simple.new }
|
8
|
+
|
9
|
+
it 'translates breadcrumb title' do
|
10
|
+
I18n.backend.store_translations 'en', breadcrumbs: { home: 'Home'}
|
11
|
+
expect(described_class.breadcrumb_title('breadcrumbs.home')).to eql('Home')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'translates breadcrumb name with default scope' do
|
15
|
+
I18n.backend.store_translations 'en', breadcrumbs: {home: 'Home'}
|
16
|
+
expect(described_class.breadcrumb_title('home')).to eql('Home')
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'translates breadcrumb name using default option' do
|
20
|
+
expect(described_class.breadcrumb_title('home', default: 'breadcrumb default name')).to eql('breadcrumb default name')
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Loaf::ViewExtensions, '.breadcrumb' do
|
6
|
+
|
7
|
+
it { expect(DummyView.new).to respond_to(:add_breadcrumb) }
|
8
|
+
|
9
|
+
it 'creates crumb instance' do
|
10
|
+
instance = DummyView.new
|
11
|
+
name = 'Home'
|
12
|
+
url = :home_path
|
13
|
+
allow(Loaf::Crumb).to receive(:new).with(name, url, {})
|
14
|
+
instance.breadcrumb name, url
|
15
|
+
expect(Loaf::Crumb).to have_received(:new).with(name, url, {})
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'adds crumb to breadcrumbs storage' do
|
19
|
+
instance = DummyView.new
|
20
|
+
expect {
|
21
|
+
instance.breadcrumb 'Home', :home_path
|
22
|
+
}.to change { instance._breadcrumbs.size }.by(1)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Loaf::ViewExtensions, '.breadcrumbs' do
|
6
|
+
it "yields to block all breadcrumbs" do
|
7
|
+
instance = DummyView.new
|
8
|
+
instance.breadcrumb('home', :home_path)
|
9
|
+
instance.breadcrumb('posts', :posts_path)
|
10
|
+
|
11
|
+
yielded = []
|
12
|
+
block = lambda { |name, url, styles| yielded << [name, url, styles]}
|
13
|
+
expect {
|
14
|
+
instance.breadcrumbs(&block)
|
15
|
+
}.to change { yielded.size }.from(0).to(2)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "resolves breadcrumb paths" do
|
19
|
+
instance = DummyView.new
|
20
|
+
instance.breadcrumb('home', :home_path)
|
21
|
+
instance.breadcrumb('posts', :posts_path)
|
22
|
+
|
23
|
+
allow(instance).to receive(:url_for).with(:home_path).and_return('/home')
|
24
|
+
allow(instance).to receive(:url_for).with(:posts_path).and_return('/posts')
|
25
|
+
yielded = []
|
26
|
+
block = lambda { |name, url, styles| yielded << [name, url, styles]}
|
27
|
+
instance.breadcrumbs(&block)
|
28
|
+
expect(yielded).to eq([
|
29
|
+
['home', '/home', ''],
|
30
|
+
['posts', '/posts', '']
|
31
|
+
])
|
32
|
+
end
|
33
|
+
|
34
|
+
it "checks current path and provides styles" do
|
35
|
+
instance = DummyView.new
|
36
|
+
instance.breadcrumb('home', :home_path)
|
37
|
+
instance.breadcrumb('posts', :posts_path)
|
38
|
+
|
39
|
+
allow(instance).to receive(:url_for).with(:home_path).and_return('/home')
|
40
|
+
allow(instance).to receive(:url_for).with(:posts_path).and_return('/posts')
|
41
|
+
allow(instance).to receive(:current_page?).with('/home').and_return(false)
|
42
|
+
allow(instance).to receive(:current_page?).with('/posts').and_return(true)
|
43
|
+
|
44
|
+
yielded = []
|
45
|
+
block = lambda { |name, url, styles| yielded << [name, url, styles]}
|
46
|
+
instance.breadcrumbs(&block)
|
47
|
+
expect(yielded).to eq([
|
48
|
+
['home', '/home', ''],
|
49
|
+
['posts', '/posts', 'selected']
|
50
|
+
])
|
51
|
+
end
|
52
|
+
|
53
|
+
it "allows to force current path" do
|
54
|
+
instance = DummyView.new
|
55
|
+
instance.breadcrumb('home', :home_path)
|
56
|
+
instance.breadcrumb('posts', :posts_path, force: true)
|
57
|
+
|
58
|
+
allow(instance).to receive(:url_for).with(:home_path).and_return('/home')
|
59
|
+
allow(instance).to receive(:url_for).with(:posts_path).and_return('/posts')
|
60
|
+
allow(instance).to receive(:current_page?).and_return(false)
|
61
|
+
|
62
|
+
yielded = []
|
63
|
+
block = lambda { |name, url, styles| yielded << [name, url, styles]}
|
64
|
+
instance.breadcrumbs(&block)
|
65
|
+
expect(yielded).to eq([
|
66
|
+
['home', '/home', ''],
|
67
|
+
['posts', '/posts', 'selected']
|
68
|
+
])
|
69
|
+
end
|
70
|
+
|
71
|
+
it "returns enumerator without block" do
|
72
|
+
instance = DummyView.new
|
73
|
+
instance.breadcrumb('home', :home_path)
|
74
|
+
instance.breadcrumb('posts', :posts_path)
|
75
|
+
|
76
|
+
allow(instance).to receive(:url_for).with(:home_path).and_return('/home')
|
77
|
+
allow(instance).to receive(:url_for).with(:posts_path).and_return('/posts')
|
78
|
+
|
79
|
+
result = instance.breadcrumbs
|
80
|
+
expect(result).to be_a(Enumerable)
|
81
|
+
expect(result.take(2)).to eq([
|
82
|
+
['home', '/home', ''],
|
83
|
+
['posts', '/posts', '']
|
84
|
+
])
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'validates passed options' do
|
88
|
+
instance = DummyView.new
|
89
|
+
block = lambda { |name, url, styles| }
|
90
|
+
expect {
|
91
|
+
instance.breadcrumbs(unknown: true, &block)
|
92
|
+
}.to raise_error(Loaf::InvalidOptions)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'uses global configuration for crumb formatting' do
|
96
|
+
allow(Loaf.configuration).to receive(:crumb_length).and_return(10)
|
97
|
+
instance = DummyView.new
|
98
|
+
instance.breadcrumb('home-sweet-home', :home_path)
|
99
|
+
instance.breadcrumb('posts-for-everybody', :posts_path)
|
100
|
+
|
101
|
+
allow(instance).to receive(:url_for).with(:home_path).and_return('/home')
|
102
|
+
allow(instance).to receive(:url_for).with(:posts_path).and_return('/posts')
|
103
|
+
yielded = []
|
104
|
+
block = lambda { |name, url, styles| yielded << [name, url, styles]}
|
105
|
+
instance.breadcrumbs(&block)
|
106
|
+
expect(yielded).to eq([
|
107
|
+
['home-sw...', '/home', ''],
|
108
|
+
['posts-f...', '/posts', '']
|
109
|
+
])
|
110
|
+
end
|
111
|
+
|
112
|
+
it "allows to overwrite global configuration" do
|
113
|
+
allow(Loaf.configuration).to receive(:crumb_length).and_return(10)
|
114
|
+
instance = DummyView.new
|
115
|
+
instance.breadcrumb('home-sweet-home', :home_path)
|
116
|
+
instance.breadcrumb('posts-for-everybody', :posts_path)
|
117
|
+
|
118
|
+
allow(instance).to receive(:url_for).with(:home_path).and_return('/home')
|
119
|
+
allow(instance).to receive(:url_for).with(:posts_path).and_return('/posts')
|
120
|
+
yielded = []
|
121
|
+
block = lambda { |name, url, styles| yielded << [name, url, styles]}
|
122
|
+
instance.breadcrumbs(crumb_length: 15, &block)
|
123
|
+
expect(yielded).to eq([
|
124
|
+
['home-sweet-home', '/home', ''],
|
125
|
+
['posts-for-ev...', '/posts', '']
|
126
|
+
])
|
127
|
+
end
|
128
|
+
end
|