jordanyeo-simple-navigation 3.11.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/CHANGELOG +265 -0
- data/Gemfile +17 -0
- data/README +22 -0
- data/Rakefile +47 -0
- data/VERSION +1 -0
- data/generators/navigation_config/USAGE +1 -0
- data/generators/navigation_config/navigation_config_generator.rb +8 -0
- data/generators/navigation_config/templates/config/navigation.rb +76 -0
- data/lib/generators/navigation_config/navigation_config_generator.rb +12 -0
- data/lib/simple-navigation.rb +1 -0
- data/lib/simple_navigation.rb +167 -0
- data/lib/simple_navigation/adapters.rb +10 -0
- data/lib/simple_navigation/adapters/base.rb +37 -0
- data/lib/simple_navigation/adapters/nanoc.rb +45 -0
- data/lib/simple_navigation/adapters/padrino.rb +20 -0
- data/lib/simple_navigation/adapters/rails.rb +93 -0
- data/lib/simple_navigation/adapters/sinatra.rb +69 -0
- data/lib/simple_navigation/core.rb +5 -0
- data/lib/simple_navigation/core/configuration.rb +72 -0
- data/lib/simple_navigation/core/item.rb +144 -0
- data/lib/simple_navigation/core/item_adapter.rb +63 -0
- data/lib/simple_navigation/core/item_container.rb +147 -0
- data/lib/simple_navigation/core/items_provider.rb +35 -0
- data/lib/simple_navigation/rails_controller_methods.rb +144 -0
- data/lib/simple_navigation/rendering.rb +12 -0
- data/lib/simple_navigation/rendering/helpers.rb +123 -0
- data/lib/simple_navigation/rendering/renderer/base.rb +107 -0
- data/lib/simple_navigation/rendering/renderer/breadcrumbs.rb +59 -0
- data/lib/simple_navigation/rendering/renderer/json.rb +29 -0
- data/lib/simple_navigation/rendering/renderer/links.rb +32 -0
- data/lib/simple_navigation/rendering/renderer/list.rb +29 -0
- data/lib/simple_navigation/rendering/renderer/text.rb +26 -0
- data/rails/init.rb +1 -0
- data/spec/lib/simple_navigation/adapters/padrino_spec.rb +31 -0
- data/spec/lib/simple_navigation/adapters/rails_spec.rb +287 -0
- data/spec/lib/simple_navigation/adapters/sinatra_spec.rb +80 -0
- data/spec/lib/simple_navigation/core/configuration_spec.rb +128 -0
- data/spec/lib/simple_navigation/core/item_adapter_spec.rb +212 -0
- data/spec/lib/simple_navigation/core/item_container_spec.rb +451 -0
- data/spec/lib/simple_navigation/core/item_spec.rb +566 -0
- data/spec/lib/simple_navigation/core/items_provider_spec.rb +60 -0
- data/spec/lib/simple_navigation/rails_controller_methods_spec.rb +249 -0
- data/spec/lib/simple_navigation/rendering/helpers_spec.rb +276 -0
- data/spec/lib/simple_navigation/rendering/renderer/base_spec.rb +199 -0
- data/spec/lib/simple_navigation/rendering/renderer/breadcrumbs_spec.rb +101 -0
- data/spec/lib/simple_navigation/rendering/renderer/json_spec.rb +48 -0
- data/spec/lib/simple_navigation/rendering/renderer/links_spec.rb +64 -0
- data/spec/lib/simple_navigation/rendering/renderer/list_spec.rb +211 -0
- data/spec/lib/simple_navigation/rendering/renderer/text_spec.rb +41 -0
- data/spec/lib/simple_navigation_spec.rb +307 -0
- data/spec/spec_helper.rb +108 -0
- metadata +199 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleNavigation::Renderer::Text do
|
4
|
+
|
5
|
+
describe 'render' do
|
6
|
+
|
7
|
+
def render(current_nav=nil, options={:level => :all})
|
8
|
+
primary_navigation = primary_container
|
9
|
+
select_item(current_nav)
|
10
|
+
setup_renderer_for SimpleNavigation::Renderer::Text, :rails, options
|
11
|
+
@renderer.render(primary_navigation)
|
12
|
+
end
|
13
|
+
context 'regarding result' do
|
14
|
+
|
15
|
+
it "should render the selected page" do
|
16
|
+
render(:invoices).should == "invoices"
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'nested sub_navigation' do
|
20
|
+
it "should add an entry for each selected item" do
|
21
|
+
render(:subnav1).should == "invoices subnav1"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'with a custom seperator specified' do
|
26
|
+
it "should separate the items with the separator" do
|
27
|
+
render(:subnav1, :join_with => " | ").should == "invoices | subnav1"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'custom name generator is set' do
|
32
|
+
before(:each) do
|
33
|
+
SimpleNavigation.config.stub!(:name_generator => Proc.new {|name| "<span>name</span>"})
|
34
|
+
end
|
35
|
+
it "should not apply the name generator (since it is text only)" do
|
36
|
+
render(:subnav1, :join_with => " | ").should == "invoices | subnav1"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,307 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleNavigation do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
SimpleNavigation.config_file_path = 'path_to_config'
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'config_file_name' do
|
10
|
+
context 'for :default navigation_context' do
|
11
|
+
it "should return the name of the default config file" do
|
12
|
+
SimpleNavigation.config_file_name.should == 'navigation.rb'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
context 'for other navigation_context' do
|
16
|
+
it "should return the name of the config file matching the specified context" do
|
17
|
+
SimpleNavigation.config_file_name(:my_other_context).should == 'my_other_context_navigation.rb'
|
18
|
+
end
|
19
|
+
it "should convert camelcase-contexts to underscore" do
|
20
|
+
SimpleNavigation.config_file_name(:WhyWouldYouDoThis).should == 'why_would_you_do_this_navigation.rb'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'config_file_path=' do
|
26
|
+
before(:each) do
|
27
|
+
SimpleNavigation.config_file_paths = ['existing_path']
|
28
|
+
end
|
29
|
+
it "should override the config_file_paths" do
|
30
|
+
SimpleNavigation.config_file_path = 'new_path'
|
31
|
+
SimpleNavigation.config_file_paths.should == ['new_path']
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'config_file' do
|
36
|
+
context 'no config_file_paths are set' do
|
37
|
+
before(:each) do
|
38
|
+
SimpleNavigation.config_file_paths = []
|
39
|
+
end
|
40
|
+
it "should return nil" do
|
41
|
+
SimpleNavigation.config_file.should be_nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
context 'one config_file_path is set' do
|
45
|
+
before(:each) do
|
46
|
+
SimpleNavigation.config_file_paths = ['my_config_file_path']
|
47
|
+
end
|
48
|
+
context 'requested config file does exist' do
|
49
|
+
before(:each) do
|
50
|
+
File.stub!(:exists? => true)
|
51
|
+
end
|
52
|
+
it "should return the path to the config_file" do
|
53
|
+
SimpleNavigation.config_file.should == 'my_config_file_path/navigation.rb'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
context 'requested config file does not exist' do
|
57
|
+
before(:each) do
|
58
|
+
File.stub!(:exists? => false)
|
59
|
+
end
|
60
|
+
it "should return nil" do
|
61
|
+
SimpleNavigation.config_file.should be_nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
context 'multiple config_file_paths are set' do
|
66
|
+
before(:each) do
|
67
|
+
SimpleNavigation.config_file_paths = ['first_path', 'second_path']
|
68
|
+
end
|
69
|
+
context 'requested config file does exist' do
|
70
|
+
before(:each) do
|
71
|
+
File.stub!(:exists? => true)
|
72
|
+
end
|
73
|
+
it "should return the path to the first matching config_file" do
|
74
|
+
SimpleNavigation.config_file.should == 'first_path/navigation.rb'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
context 'requested config file does not exist' do
|
78
|
+
before(:each) do
|
79
|
+
File.stub!(:exists? => false)
|
80
|
+
end
|
81
|
+
it "should return nil" do
|
82
|
+
SimpleNavigation.config_file.should be_nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'config_file?' do
|
89
|
+
context 'config_file present' do
|
90
|
+
before(:each) do
|
91
|
+
SimpleNavigation.stub!(:config_file => 'file')
|
92
|
+
end
|
93
|
+
it {SimpleNavigation.config_file?.should be_true}
|
94
|
+
end
|
95
|
+
context 'config_file not present' do
|
96
|
+
before(:each) do
|
97
|
+
SimpleNavigation.stub!(:config_file => nil)
|
98
|
+
end
|
99
|
+
it {SimpleNavigation.config_file?.should be_false}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe 'self.default_config_file_path' do
|
104
|
+
before(:each) do
|
105
|
+
SimpleNavigation.stub!(:root => 'root')
|
106
|
+
end
|
107
|
+
it {SimpleNavigation.default_config_file_path.should == 'root/config'}
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'regarding renderers' do
|
111
|
+
it "should have registered the builtin renderers by default" do
|
112
|
+
SimpleNavigation.registered_renderers.should_not be_empty
|
113
|
+
end
|
114
|
+
|
115
|
+
describe 'register_renderer' do
|
116
|
+
before(:each) do
|
117
|
+
@renderer = stub(:renderer)
|
118
|
+
end
|
119
|
+
it "should add the specified renderer to the list of renderers" do
|
120
|
+
SimpleNavigation.register_renderer(:my_renderer => @renderer)
|
121
|
+
SimpleNavigation.registered_renderers[:my_renderer].should == @renderer
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
describe 'set_env' do
|
128
|
+
before(:each) do
|
129
|
+
SimpleNavigation.config_file_paths = []
|
130
|
+
SimpleNavigation.stub!(:default_config_file_path => 'default_path')
|
131
|
+
SimpleNavigation.set_env('root', 'my_env')
|
132
|
+
end
|
133
|
+
it "should set the root" do
|
134
|
+
SimpleNavigation.root.should == 'root'
|
135
|
+
end
|
136
|
+
it "should set the environment" do
|
137
|
+
SimpleNavigation.environment.should == 'my_env'
|
138
|
+
end
|
139
|
+
it "should add the default-config path to the list of config_file_paths" do
|
140
|
+
SimpleNavigation.config_file_paths.should == ['default_path']
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe 'load_config' do
|
145
|
+
context 'config_file_path is set' do
|
146
|
+
before(:each) do
|
147
|
+
SimpleNavigation.stub!(:config_file => 'path_to_config_file')
|
148
|
+
end
|
149
|
+
context 'config_file does exist' do
|
150
|
+
before(:each) do
|
151
|
+
SimpleNavigation.stub!(:config_file? => true)
|
152
|
+
IO.stub!(:read => 'file_content')
|
153
|
+
end
|
154
|
+
it "should not raise an error" do
|
155
|
+
lambda{SimpleNavigation.load_config}.should_not raise_error
|
156
|
+
end
|
157
|
+
it "should read the specified config file from disc" do
|
158
|
+
IO.should_receive(:read).with('path_to_config_file')
|
159
|
+
SimpleNavigation.load_config
|
160
|
+
end
|
161
|
+
it "should store the read content in the module (default context)" do
|
162
|
+
SimpleNavigation.should_receive(:config_file).with(:default)
|
163
|
+
SimpleNavigation.load_config
|
164
|
+
SimpleNavigation.config_files[:default].should == 'file_content'
|
165
|
+
end
|
166
|
+
it "should store the content in the module (non default context)" do
|
167
|
+
SimpleNavigation.should_receive(:config_file).with(:my_context)
|
168
|
+
SimpleNavigation.load_config(:my_context)
|
169
|
+
SimpleNavigation.config_files[:my_context].should == 'file_content'
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'config_file does not exist' do
|
174
|
+
before(:each) do
|
175
|
+
SimpleNavigation.stub!(:config_file? => false)
|
176
|
+
end
|
177
|
+
it {lambda{SimpleNavigation.load_config}.should raise_error}
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context 'config_file_path is not set' do
|
182
|
+
before(:each) do
|
183
|
+
SimpleNavigation.config_file_path = nil
|
184
|
+
end
|
185
|
+
it {lambda{SimpleNavigation.load_config}.should raise_error}
|
186
|
+
end
|
187
|
+
|
188
|
+
describe 'regarding caching of the config-files' do
|
189
|
+
before(:each) do
|
190
|
+
IO.stub!(:read).and_return('file_content')
|
191
|
+
SimpleNavigation.config_file_path = 'path_to_config'
|
192
|
+
File.stub!(:exists? => true)
|
193
|
+
end
|
194
|
+
context "environment undefined" do
|
195
|
+
before(:each) do
|
196
|
+
SimpleNavigation.stub!(:environment => nil)
|
197
|
+
end
|
198
|
+
it "should load the config file twice" do
|
199
|
+
IO.should_receive(:read).twice
|
200
|
+
SimpleNavigation.load_config
|
201
|
+
SimpleNavigation.load_config
|
202
|
+
end
|
203
|
+
end
|
204
|
+
context "environment defined" do
|
205
|
+
before(:each) do
|
206
|
+
SimpleNavigation.stub!(:environment => 'production')
|
207
|
+
end
|
208
|
+
context "environment=production" do
|
209
|
+
it "should load the config file only once" do
|
210
|
+
IO.should_receive(:read).once
|
211
|
+
SimpleNavigation.load_config
|
212
|
+
SimpleNavigation.load_config
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context "environment=development" do
|
217
|
+
before(:each) do
|
218
|
+
SimpleNavigation.stub!(:environment => 'development')
|
219
|
+
end
|
220
|
+
it "should load the config file twice" do
|
221
|
+
IO.should_receive(:read).twice
|
222
|
+
SimpleNavigation.load_config
|
223
|
+
SimpleNavigation.load_config
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
context "environment=test" do
|
228
|
+
before(:each) do
|
229
|
+
SimpleNavigation.stub!(:environment => 'test')
|
230
|
+
end
|
231
|
+
it "should load the config file twice" do
|
232
|
+
IO.should_receive(:read).twice
|
233
|
+
SimpleNavigation.load_config
|
234
|
+
SimpleNavigation.load_config
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
after(:each) do
|
239
|
+
SimpleNavigation.config_files = {}
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
describe 'config' do
|
245
|
+
it {SimpleNavigation.config.should == SimpleNavigation::Configuration.instance}
|
246
|
+
end
|
247
|
+
|
248
|
+
describe 'active_item_container_for' do
|
249
|
+
before(:each) do
|
250
|
+
@primary = stub(:primary)
|
251
|
+
SimpleNavigation.config.stub!(:primary_navigation => @primary)
|
252
|
+
end
|
253
|
+
context 'level is :all' do
|
254
|
+
it "should return the primary_navigation" do
|
255
|
+
SimpleNavigation.active_item_container_for(:all).should == @primary
|
256
|
+
end
|
257
|
+
end
|
258
|
+
context 'level is :leaves' do
|
259
|
+
it "should return the currently active leaf-container" do
|
260
|
+
@primary.should_receive(:active_leaf_container)
|
261
|
+
SimpleNavigation.active_item_container_for(:leaves)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
context 'level is a Range' do
|
265
|
+
it "should take the min of the range to lookup the active container" do
|
266
|
+
@primary.should_receive(:active_item_container_for).with(2)
|
267
|
+
SimpleNavigation.active_item_container_for(2..3)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
context 'level is an Integer' do
|
271
|
+
it "should consider the Integer to lookup the active container" do
|
272
|
+
@primary.should_receive(:active_item_container_for).with(1)
|
273
|
+
SimpleNavigation.active_item_container_for(1)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
context 'level is something else' do
|
277
|
+
it "should raise an ArgumentError" do
|
278
|
+
lambda {SimpleNavigation.active_item_container_for('something else')}.should raise_error(ArgumentError)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
describe 'load_adapter' do
|
284
|
+
context 'Rails' do
|
285
|
+
before(:each) do
|
286
|
+
SimpleNavigation.stub!(:framework => :rails)
|
287
|
+
SimpleNavigation.load_adapter
|
288
|
+
end
|
289
|
+
it {SimpleNavigation.adapter_class.should == SimpleNavigation::Adapters::Rails}
|
290
|
+
end
|
291
|
+
context 'Padrino' do
|
292
|
+
before(:each) do
|
293
|
+
SimpleNavigation.stub!(:framework => :padrino)
|
294
|
+
SimpleNavigation.load_adapter
|
295
|
+
end
|
296
|
+
it {SimpleNavigation.adapter_class.should == SimpleNavigation::Adapters::Padrino}
|
297
|
+
end
|
298
|
+
context 'Sinatra' do
|
299
|
+
before(:each) do
|
300
|
+
SimpleNavigation.stub!(:framework => :sinatra)
|
301
|
+
SimpleNavigation.load_adapter
|
302
|
+
end
|
303
|
+
it {SimpleNavigation.adapter_class.should == SimpleNavigation::Adapters::Sinatra}
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
ENV["RAILS_ENV"] = "test"
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rspec'
|
4
|
+
require 'json_spec'
|
5
|
+
require 'action_controller'
|
6
|
+
|
7
|
+
module Rails
|
8
|
+
module VERSION
|
9
|
+
MAJOR = 2
|
10
|
+
end
|
11
|
+
end unless defined? Rails
|
12
|
+
|
13
|
+
$:.unshift File.dirname(__FILE__)
|
14
|
+
$:.unshift File.join(File.dirname(__FILE__), '../lib')
|
15
|
+
|
16
|
+
require 'simple_navigation'
|
17
|
+
|
18
|
+
# SimpleNavigation.root = './'
|
19
|
+
RAILS_ROOT = './' unless defined?(RAILS_ROOT)
|
20
|
+
RAILS_ENV = 'test' unless defined?(RAILS_ENV)
|
21
|
+
|
22
|
+
|
23
|
+
RSpec.configure do |config|
|
24
|
+
# == Mock Framework
|
25
|
+
#
|
26
|
+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
27
|
+
#
|
28
|
+
# config.mock_with :mocha
|
29
|
+
# config.mock_with :flexmock
|
30
|
+
# config.mock_with :rr
|
31
|
+
config.mock_with :rspec
|
32
|
+
config.include JsonSpec::Helpers
|
33
|
+
end
|
34
|
+
|
35
|
+
# spec helper methods
|
36
|
+
def sub_items
|
37
|
+
[
|
38
|
+
[:subnav1, 'subnav1', 'subnav1_url'],
|
39
|
+
[:subnav2, 'subnav2', 'subnav2_url']
|
40
|
+
]
|
41
|
+
end
|
42
|
+
|
43
|
+
def primary_items
|
44
|
+
[
|
45
|
+
[:users, 'users', 'first_url', {:id => 'my_id', :link => {:id => 'my_link_id'}}],
|
46
|
+
[:invoices, 'invoices', 'second_url'],
|
47
|
+
[:accounts, 'accounts', 'third_url', {:style => 'float:right', :link => {:style => 'float:left'}}],
|
48
|
+
[:miscellany, 'miscellany']
|
49
|
+
]
|
50
|
+
end
|
51
|
+
|
52
|
+
def primary_container
|
53
|
+
containers.first
|
54
|
+
end
|
55
|
+
|
56
|
+
def containers
|
57
|
+
container = SimpleNavigation::ItemContainer.new(1)
|
58
|
+
container.dom_id = 'nav_dom_id'
|
59
|
+
container.dom_class = 'nav_dom_class'
|
60
|
+
@items = primary_items.map {|params| SimpleNavigation::Item.new(container, *params)}
|
61
|
+
@items.each {|i| i.stub!(:selected? => false, :selected_by_condition? => false)}
|
62
|
+
container.instance_variable_set(:@items, @items)
|
63
|
+
sub_container = subnav_container
|
64
|
+
primary_item(:invoices) {|item| item.instance_variable_set(:@sub_navigation, sub_container)}
|
65
|
+
[container,sub_container]
|
66
|
+
end
|
67
|
+
|
68
|
+
def primary_item(key)
|
69
|
+
item = @items.find {|i| i.key == key}
|
70
|
+
block_given? ? yield(item) : item
|
71
|
+
end
|
72
|
+
|
73
|
+
def sub_item(key)
|
74
|
+
primary_item(:invoices).instance_variable_get(:@sub_navigation).items.find { |i| i.key == key}
|
75
|
+
end
|
76
|
+
|
77
|
+
def select_item(key)
|
78
|
+
if(key == :subnav1)
|
79
|
+
select_item(:invoices)
|
80
|
+
primary_item(:invoices) do |item|
|
81
|
+
item.instance_variable_get(:@sub_navigation).items.find { |i| i.key == key}.stub!(:selected? => true, :selected_by_condition? => true)
|
82
|
+
end
|
83
|
+
else
|
84
|
+
primary_item(key) {|item| item.stub!(:selected? => true) unless item.frozen?}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def subnav_container
|
89
|
+
container = SimpleNavigation::ItemContainer.new(2)
|
90
|
+
items = sub_items.map {|params| SimpleNavigation::Item.new(container, *params)}
|
91
|
+
items.each {|i| i.stub!(:selected? => false, :selected_by_condition? => false)}
|
92
|
+
container.instance_variable_set(:@items, items)
|
93
|
+
container
|
94
|
+
end
|
95
|
+
|
96
|
+
def setup_renderer_for(renderer_class, framework, options)
|
97
|
+
setup_adapter_for framework
|
98
|
+
@renderer = renderer_class.new(options)
|
99
|
+
end
|
100
|
+
|
101
|
+
def setup_adapter_for(framework)
|
102
|
+
adapter = case framework
|
103
|
+
when :rails
|
104
|
+
SimpleNavigation::Adapters::Rails.new(stub(:context, :view_context => ActionView::Base.new))
|
105
|
+
end
|
106
|
+
SimpleNavigation.stub!(:adapter => adapter)
|
107
|
+
adapter
|
108
|
+
end
|