simple-navigation 3.12.0 → 3.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. data/CHANGELOG +4 -0
  2. data/generators/navigation_config/navigation_config_generator.rb +3 -3
  3. data/generators/navigation_config/templates/config/navigation.rb +9 -10
  4. data/init.rb +1 -1
  5. data/lib/generators/navigation_config/navigation_config_generator.rb +11 -6
  6. data/lib/simple-navigation.rb +1 -1
  7. data/lib/simple_navigation.rb +93 -65
  8. data/lib/simple_navigation/adapters/base.rb +16 -16
  9. data/lib/simple_navigation/adapters/nanoc.rb +7 -6
  10. data/lib/simple_navigation/adapters/padrino.rb +5 -7
  11. data/lib/simple_navigation/adapters/rails.rb +52 -39
  12. data/lib/simple_navigation/adapters/sinatra.rb +14 -17
  13. data/lib/simple_navigation/core/configuration.rb +73 -34
  14. data/lib/simple_navigation/core/item.rb +110 -54
  15. data/lib/simple_navigation/core/item_adapter.rb +18 -13
  16. data/lib/simple_navigation/core/item_container.rb +93 -66
  17. data/lib/simple_navigation/core/items_provider.rb +12 -10
  18. data/lib/simple_navigation/rails_controller_methods.rb +98 -78
  19. data/lib/simple_navigation/rendering/helpers.rb +130 -68
  20. data/lib/simple_navigation/rendering/renderer/base.rb +30 -25
  21. data/lib/simple_navigation/rendering/renderer/breadcrumbs.rb +26 -19
  22. data/lib/simple_navigation/rendering/renderer/json.rb +11 -13
  23. data/lib/simple_navigation/rendering/renderer/links.rb +18 -13
  24. data/lib/simple_navigation/rendering/renderer/list.rb +28 -15
  25. data/lib/simple_navigation/rendering/renderer/text.rb +7 -12
  26. data/lib/simple_navigation/version.rb +1 -1
  27. data/spec/lib/simple_navigation/core/item_adapter_spec.rb +1 -1
  28. data/spec/lib/simple_navigation/core/item_container_spec.rb +118 -68
  29. data/spec/lib/simple_navigation_spec.rb +16 -5
  30. metadata +2 -2
@@ -1,31 +1,36 @@
1
1
  module SimpleNavigation
2
2
  module Renderer
3
-
4
- # Renders an ItemContainer as a <div> element and its containing items as <a> elements.
3
+ # Renders an ItemContainer as a <div> element and its containing items as
4
+ # <a> elements.
5
5
  # It adds the 'selected' class to the <a> element that is currently active.
6
6
  #
7
- # The Links renderer cannot be used to render nested navigations. If you would like it to use with nested navigations, you have to render each level separately.
8
- #
9
- # By default, the renderer sets the item's key as dom_id for the rendered <a> element unless the config option <tt>autogenerate_item_ids</tt> is set to false.
10
- # The id can also be explicitely specified by setting the id in the html-options of the 'item' method in the config/navigation.rb file.
11
- # The ItemContainer's dom_attributes are applied to the surrounding <div> element.
7
+ # The Links renderer cannot be used to render nested navigations. If you
8
+ # would like it to use with nested navigations, you have to render each
9
+ # level separately.
12
10
  #
11
+ # By default, the renderer sets the item's key as dom_id for the rendered
12
+ # <a> element unless the config option <tt>autogenerate_item_ids</tt> is set
13
+ # to false.
14
+ # The id can also be explicitely specified by setting the id in the
15
+ # html-options of the 'item' method in the config/navigation.rb file.
16
+ # The ItemContainer's dom_attributes are applied to the surrounding <div>
17
+ # element.
13
18
  class Links < SimpleNavigation::Renderer::Base
14
19
  def render(item_container)
15
- div_content = item_container.items.inject([]) do |list, item|
16
- list << tag_for(item)
17
- end.join(join_with)
18
- content_tag(:div, div_content, item_container.dom_attributes)
20
+ div_content = item_container.items
21
+ .map { |item| tag_for(item) }
22
+ .join(join_with)
23
+ content_tag :div, div_content, item_container.dom_attributes
19
24
  end
20
25
 
21
26
  protected
22
27
 
23
28
  def join_with
24
- @join_with ||= options[:join_with] || ""
29
+ @join_with ||= options[:join_with] || ''
25
30
  end
26
31
 
27
32
  def options_for(item)
28
- {:method => item.method}.merge(item.html_options)
33
+ { method: item.method }.merge(item.html_options)
29
34
  end
30
35
  end
31
36
  end
@@ -1,28 +1,41 @@
1
1
  module SimpleNavigation
2
2
  module Renderer
3
-
4
- # Renders an ItemContainer as a <ul> element and its containing items as <li> elements.
5
- # It adds the 'selected' class to li element AND the link inside the li element that is currently active.
3
+ # Renders an ItemContainer as a <ul> element and its containing items as
4
+ # <li> elements.
5
+ # It adds the 'selected' class to li element AND the link inside the li
6
+ # element that is currently active.
6
7
  #
7
- # If the sub navigation should be included (based on the level and expand_all options), it renders another <ul> containing the sub navigation inside the active <li> element.
8
+ # If the sub navigation should be included (based on the level and
9
+ # expand_all options), it renders another <ul> containing the sub navigation
10
+ # inside the active <li> element.
8
11
  #
9
- # By default, the renderer sets the item's key as dom_id for the rendered <li> element unless the config option <tt>autogenerate_item_ids</tt> is set to false.
10
- # The id can also be explicitely specified by setting the id in the html-options of the 'item' method in the config/navigation.rb file.
12
+ # By default, the renderer sets the item's key as dom_id for the rendered
13
+ # <li> element unless the config option <tt>autogenerate_item_ids</tt> is
14
+ # set to false.
15
+ # The id can also be explicitely specified by setting the id in the
16
+ # html-options of the 'item' method in the config/navigation.rb file.
11
17
  class List < SimpleNavigation::Renderer::Base
12
18
  def render(item_container)
13
- list_content = item_container.items.inject([]) do |list, item|
14
- li_options = item.html_options.reject {|k, v| k == :link}
19
+ if skip_if_empty? && item_container.empty?
20
+ ''
21
+ else
22
+ tag = options[:ordered] ? :ol : :ul
23
+ content = list_content(item_container)
24
+ content_tag(tag, content, item_container.dom_attributes)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def list_content(item_container)
31
+ item_container.items.map { |item|
32
+ li_options = item.html_options.except(:link)
15
33
  li_content = tag_for(item)
16
34
  if include_sub_navigation?(item)
17
35
  li_content << render_sub_navigation_for(item)
18
36
  end
19
- list << content_tag(:li, li_content, li_options)
20
- end.join
21
- if skip_if_empty? && item_container.empty?
22
- ''
23
- else
24
- content_tag((options[:ordered] ? :ol : :ul), list_content, item_container.dom_attributes)
25
- end
37
+ content_tag(:li, li_content, li_options)
38
+ }.join
26
39
  end
27
40
  end
28
41
  end
@@ -1,26 +1,21 @@
1
1
  module SimpleNavigation
2
2
  module Renderer
3
-
4
- # Renders the 'chain' of selected navigation items as simple text items, joined with an optional separator (similar to breadcrumbs, but without markup).
5
- #
3
+ # Renders the 'chain' of selected navigation items as simple text items,
4
+ # joined with an optional separator (similar to breadcrumbs, but without
5
+ # markup).
6
6
  class Text < SimpleNavigation::Renderer::Base
7
-
8
7
  def render(item_container)
9
- list(item_container).compact.join(options[:join_with] || " ")
8
+ list(item_container).compact.join(options[:join_with] || ' ')
10
9
  end
11
10
 
12
11
  private
13
12
 
14
13
  def list(item_container)
15
- item_container.items.inject([]) do |array, item|
16
- if item.selected?
17
- array + [item.name(:apply_generator => false)] + (include_sub_navigation?(item) ? list(item.sub_navigation) : [])
18
- else
19
- array
20
- end
14
+ item_container.items.keep_if(&:selected?).map do |item|
15
+ [item.name(apply_generator: false)] +
16
+ (include_sub_navigation?(item) ? list(item.sub_navigation) : [])
21
17
  end
22
18
  end
23
-
24
19
  end
25
20
  end
26
21
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleNavigation
2
- VERSION = '3.12.0'
2
+ VERSION = '3.12.1'
3
3
  end
@@ -62,7 +62,7 @@ module SimpleNavigation
62
62
  end
63
63
 
64
64
  context 'and items is not empty' do
65
- let(:items) { double(:items, empty?: false) }
65
+ let(:items) { [true] }
66
66
 
67
67
  before { item.stub(items: items) }
68
68
 
@@ -2,19 +2,72 @@ require 'spec_helper'
2
2
 
3
3
  module SimpleNavigation
4
4
  describe ItemContainer do
5
- let(:item_container) { ItemContainer.new }
5
+ subject(:item_container) { ItemContainer.new }
6
6
 
7
- describe '#initialize' do
8
- it 'sets the renderer to the globally-configured renderer per default' do
9
- expect(Configuration.instance).to receive(:renderer)
10
- ItemContainer.new
7
+ shared_examples 'adding the item to the list' do
8
+ it 'adds the item to the list' do
9
+ Item.stub(:new).and_return(item)
10
+ item_container.item(*args)
11
+ expect(item_container.items).to include(item)
12
+ end
13
+ end
14
+
15
+ shared_examples 'not adding the item to the list' do
16
+ it "doesn't add the item to the list" do
17
+ Item.stub(:new).and_return(item)
18
+ item_container.item(*args)
19
+ expect(item_container.items).not_to include(item)
11
20
  end
21
+ end
12
22
 
13
- it "sets an empty items array" do
23
+ describe '#initialize' do
24
+ it 'sets an empty items array' do
14
25
  expect(item_container.items).to be_empty
15
26
  end
16
27
  end
17
28
 
29
+ describe '#dom_attributes' do
30
+ let(:dom_attributes) {{ id: 'test_id', class: 'test_class' }}
31
+
32
+ before { item_container.dom_attributes = dom_attributes }
33
+
34
+ it "returns the container's dom_attributes" do
35
+ expect(item_container.dom_attributes).to eq dom_attributes
36
+ end
37
+
38
+ context 'when the dom_attributes do not contain any id or class' do
39
+ let(:dom_attributes) {{ test: 'test' }}
40
+
41
+ context "and the container hasn't any dom_id" do
42
+ it "returns the contaier's dom_attributes without any id" do
43
+ expect(item_container.dom_attributes).not_to include(:id)
44
+ end
45
+ end
46
+
47
+ context 'and the container has a dom_id' do
48
+ before { item_container.dom_id = 'test_id' }
49
+
50
+ it "returns the contaier's dom_attributes including the #dom_id" do
51
+ expect(item_container.dom_attributes).to include(id: 'test_id')
52
+ end
53
+ end
54
+
55
+ context "and the container hasn't any dom_class" do
56
+ it "returns the contaier's dom_attributes without any class" do
57
+ expect(item_container.dom_attributes).not_to include(:class)
58
+ end
59
+ end
60
+
61
+ context 'and the container has a dom_class' do
62
+ before { item_container.dom_class = 'test_class' }
63
+
64
+ it "returns the contaier's dom_attributes including the #dom_class" do
65
+ expect(item_container.dom_attributes).to include(class: 'test_class')
66
+ end
67
+ end
68
+ end
69
+ end
70
+
18
71
  describe '#items=' do
19
72
  let(:item) { double(:item) }
20
73
  let(:items) { [item] }
@@ -31,23 +84,13 @@ module SimpleNavigation
31
84
  end
32
85
 
33
86
  context 'when item should be added' do
34
- let(:simple_navigation_item) { double(:simple_navigation_item) }
87
+ let(:wrapped_item) { double(:wrapped_item).as_null_object }
35
88
 
36
- before do
37
- item_container.stub(should_add_item?: true)
38
- item_adapter.stub(to_simple_navigation_item: simple_navigation_item)
39
- end
89
+ before { ItemAdapter.stub(:new).with(item).and_return(wrapped_item) }
40
90
 
41
- it 'converts the item to an Item' do
42
- expect(item_adapter).to receive(:to_simple_navigation_item)
43
- .with(item_container)
44
- item_container.items = items
45
- end
46
-
47
- it 'adds the item to the items-collection' do
48
- expect(item_container.items).to receive(:<<)
49
- .with(simple_navigation_item)
91
+ it 'converts item to an Item and adds it to the items collection' do
50
92
  item_container.items = items
93
+ expect(item_container.items).to include(wrapped_item)
51
94
  end
52
95
  end
53
96
 
@@ -177,65 +220,54 @@ module SimpleNavigation
177
220
  end
178
221
 
179
222
  describe '#item' do
180
- context 'when the item has no :if or :unless option' do
181
- let(:options) { Hash.new }
182
-
183
- before { item_container.stub(:should_add_item?).and_return(true) }
184
-
185
- context 'when a block is given' do
186
- let(:sub_container) { double(:sub_container) }
187
- let(:block) { proc{} }
188
-
189
- before { ItemContainer.stub(:new).with(2).and_return(sub_container) }
223
+ let(:options) { Hash.new }
224
+ let(:item) { double(:item) }
190
225
 
191
- it 'yields a new ItemContainer' do
192
- expect{ |blk|
193
- item_container.item('key', 'name', 'url', options, &blk)
194
- }.to yield_with_args(sub_container)
195
- end
226
+ context 'when a block is given' do
227
+ let(:block) { proc{} }
228
+ let(:sub_container) { double(:sub_container) }
196
229
 
197
- it "creates a new Navigation-Item with the given params and block" do
198
- expect(Item).to receive(:new)
199
- .with(item_container, 'key', 'name', 'url',
200
- options, nil, &block)
201
- item_container.item('key', 'name', 'url', options, &block)
202
- end
230
+ it 'yields a new ItemContainer' do
231
+ Item.any_instance
232
+ .stub(:sub_navigation)
233
+ .and_return(sub_container)
203
234
 
204
- it 'adds the created item to the list of items' do
205
- expect(item_container.items).to receive(:<<)
206
- item_container.item('key', 'name', 'url', options) {}
207
- end
235
+ expect{ |blk|
236
+ item_container.item('key', 'name', 'url', options, &blk)
237
+ }.to yield_with_args(sub_container)
208
238
  end
209
239
 
210
- context 'when no block is given' do
211
- it "creates a new Navigation_item with the given params and nil as sub_navigation" do
212
- expect(Item).to receive(:new)
213
- .with(item_container, 'key', 'name', 'url', options, nil)
214
- item_container.item('key', 'name', 'url', options)
215
- end
240
+ it "creates a new Item with the given params and block" do
241
+ Item.stub(:new)
242
+ .with(item_container, 'key', 'name', 'url', options, nil, &block)
243
+ .and_return(item)
244
+ item_container.item('key', 'name', 'url', options, &block)
245
+ expect(item_container.items).to include(item)
246
+ end
216
247
 
217
- it 'adds the created item to the list of items' do
218
- expect(item_container.items).to receive(:<<)
219
- item_container.item('key', 'name', 'url', options)
220
- end
248
+ it 'adds the created item to the list of items' do
249
+ item_container.item('key', 'name', 'url', options) {}
250
+ expect(item_container.items).not_to include(item)
221
251
  end
222
252
  end
223
253
 
224
- describe 'Optional url and optional options' do
225
- shared_examples 'adding the item to the list' do
226
- it 'adds the item to the list' do
227
- expect(item_container.items).to receive(:<<)
228
- item_container.item(*args)
229
- end
254
+ context 'when no block is given' do
255
+ it 'creates a new Item with the given params and no sub navigation' do
256
+ Item.stub(:new)
257
+ .with(item_container, 'key', 'name', 'url', options, nil)
258
+ .and_return(item)
259
+ item_container.item('key', 'name', 'url', options)
260
+ expect(item_container.items).to include(item)
230
261
  end
231
262
 
232
- shared_examples 'not adding the item to the list' do
233
- it "doesn't add the item to the list" do
234
- expect(item_container.items).not_to receive(:<<)
235
- item_container.item(*args)
236
- end
263
+ it 'adds the created item to the list of items' do
264
+ Item.stub(:new).and_return(item)
265
+ item_container.item('key', 'name', 'url', options) {}
266
+ expect(item_container.items).to include(item)
237
267
  end
268
+ end
238
269
 
270
+ describe 'Optional url and optional options' do
239
271
  context 'when item specifed without url or options' do
240
272
  it_behaves_like 'adding the item to the list' do
241
273
  let(:args) { ['key', 'name'] }
@@ -302,7 +334,7 @@ module SimpleNavigation
302
334
  context 'and it evals to true' do
303
335
  let(:condition) { true }
304
336
 
305
- it 'creates a new Navigation-Item' do
337
+ it 'creates a new Item' do
306
338
  expect(Item).to receive(:new)
307
339
  item_container.item('key', 'name', 'url', options)
308
340
  end
@@ -311,7 +343,7 @@ module SimpleNavigation
311
343
  context 'and it evals to false' do
312
344
  let(:condition) { false }
313
345
 
314
- it "doesn't create a new Navigation-Item" do
346
+ it "doesn't create a new Item" do
315
347
  expect(Item).not_to receive(:new)
316
348
  item_container.item('key', 'name', 'url', options)
317
349
  end
@@ -429,6 +461,24 @@ module SimpleNavigation
429
461
  end
430
462
  end
431
463
 
464
+ describe '#renderer' do
465
+ context 'when no renderer is set explicitly' do
466
+ it 'returns globally-configured renderer' do
467
+ expect(item_container.renderer).to be Configuration.instance.renderer
468
+ end
469
+ end
470
+
471
+ context 'when a renderer is set explicitly' do
472
+ let(:renderer) { double(:renderer) }
473
+
474
+ before { item_container.renderer = renderer }
475
+
476
+ it 'returns the specified renderer' do
477
+ expect(item_container.renderer).to be renderer
478
+ end
479
+ end
480
+ end
481
+
432
482
  describe '#level_for_item' do
433
483
  before(:each) do
434
484
  item_container.item(:p1, 'p1', 'p1')
@@ -45,7 +45,7 @@ describe SimpleNavigation do
45
45
  before { subject.config_file_paths = ['my_config_file_path'] }
46
46
 
47
47
  context 'and the requested config file exists' do
48
- before { File.stub(exists?: true) }
48
+ before { File.stub(exist?: true) }
49
49
 
50
50
  it 'returns the path to the config_file' do
51
51
  expect(subject.config_file).to eq 'my_config_file_path/navigation.rb'
@@ -53,7 +53,7 @@ describe SimpleNavigation do
53
53
  end
54
54
 
55
55
  context 'and the requested config file does not exist' do
56
- before { File.stub(exists?: false) }
56
+ before { File.stub(exist?: false) }
57
57
 
58
58
  it 'returns nil' do
59
59
  expect(subject.config_file).to be_nil
@@ -65,7 +65,7 @@ describe SimpleNavigation do
65
65
  before { subject.config_file_paths = ['first_path', 'second_path'] }
66
66
 
67
67
  context 'and the requested config file exists' do
68
- before { File.stub(exists?: true) }
68
+ before { File.stub(exist?: true) }
69
69
 
70
70
  it 'returns the path to the first matching config_file' do
71
71
  expect(subject.config_file).to eq 'first_path/navigation.rb'
@@ -73,7 +73,7 @@ describe SimpleNavigation do
73
73
  end
74
74
 
75
75
  context 'and the requested config file does not exist' do
76
- before { File.stub(exists?: false) }
76
+ before { File.stub(exist?: false) }
77
77
 
78
78
  it 'returns nil' do
79
79
  expect(subject.config_file).to be_nil
@@ -196,7 +196,7 @@ describe SimpleNavigation do
196
196
  before do
197
197
  subject.config_file_path = 'path_to_config'
198
198
  IO.stub(:read).and_return('file_content')
199
- File.stub(exists?: true)
199
+ File.stub(exist?: true)
200
200
  end
201
201
 
202
202
  after { subject.config_files = {} }
@@ -286,4 +286,15 @@ describe SimpleNavigation do
286
286
  it_behaves_like 'loading the right adapter', :padrino, :Padrino
287
287
  it_behaves_like 'loading the right adapter', :sinatra, :Sinatra
288
288
  end
289
+
290
+ describe '.init_adapter_from' do
291
+ let(:adapter) { double(:adapter) }
292
+ let(:adapter_class) { double(:adapter_class, new: adapter) }
293
+
294
+ it 'sets the adapter to a new instance of adapter_class' do
295
+ subject.adapter_class = adapter_class
296
+ subject.init_adapter_from(:default)
297
+ expect(subject.adapter).to be adapter
298
+ end
299
+ end
289
300
  end