storage_room 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/README.rdoc +10 -4
- data/Rakefile +3 -1
- data/TODO +7 -2
- data/VERSION +1 -1
- data/examples/authentication.rb +5 -3
- data/examples/create_entry.rb +8 -5
- data/examples/destroy_entry.rb +2 -2
- data/examples/get_collections.rb +2 -2
- data/examples/import_csv.rb +4 -4
- data/examples/search_entries.rb +2 -2
- data/examples/update_entry.rb +2 -2
- data/lib/console.rb +12 -0
- data/lib/storage_room.rb +73 -34
- data/lib/storage_room/accessors.rb +190 -0
- data/lib/storage_room/array.rb +3 -23
- data/lib/storage_room/embedded.rb +1 -1
- data/lib/storage_room/embeddeds/field.rb +28 -0
- data/lib/storage_room/embeddeds/fields/association_field.rb +17 -0
- data/lib/storage_room/embeddeds/fields/associations/many_association_field.rb +9 -0
- data/lib/storage_room/embeddeds/fields/associations/one_association_field.rb +9 -0
- data/lib/storage_room/embeddeds/fields/atomic/boolean_field.rb +6 -0
- data/lib/storage_room/embeddeds/fields/atomic/date_field.rb +6 -0
- data/lib/storage_room/embeddeds/fields/atomic/float_field.rb +6 -0
- data/lib/storage_room/embeddeds/fields/atomic/integer_field.rb +6 -0
- data/lib/storage_room/embeddeds/fields/atomic/string_field.rb +6 -0
- data/lib/storage_room/embeddeds/fields/atomic/time_field.rb +6 -0
- data/lib/storage_room/embeddeds/fields/atomic_field.rb +15 -0
- data/lib/storage_room/embeddeds/fields/compound/attachment_field.rb +6 -0
- data/lib/storage_room/embeddeds/fields/compound/file_field.rb +6 -0
- data/lib/storage_room/embeddeds/fields/compound/image_field.rb +6 -0
- data/lib/storage_room/embeddeds/fields/compound/location_field.rb +6 -0
- data/lib/storage_room/embeddeds/fields/compound_field.rb +10 -0
- data/lib/storage_room/embeddeds/file.rb +1 -1
- data/lib/storage_room/embeddeds/image.rb +6 -0
- data/lib/storage_room/embeddeds/location.rb +2 -1
- data/lib/storage_room/extensions/const_defined.rb +12 -0
- data/lib/storage_room/identity_map.rb +117 -0
- data/lib/storage_room/model.rb +19 -23
- data/lib/storage_room/models/collection.rb +76 -11
- data/lib/storage_room/models/entry.rb +6 -32
- data/lib/storage_room/plugins.rb +22 -0
- data/lib/storage_room/proxy.rb +49 -0
- data/lib/storage_room/{base.rb → resource.rb} +13 -36
- data/spec/fixtures/collection.json +0 -16
- data/spec/spec_helper.rb +1 -0
- data/spec/storage_room/accessors_spec.rb +107 -0
- data/spec/storage_room/array_spec.rb +13 -9
- data/spec/storage_room/embedded_spec.rb +5 -1
- data/spec/storage_room/embeddeds/field_spec.rb +25 -0
- data/spec/storage_room/embeddeds/fields/association_field_spec.rb +29 -0
- data/spec/storage_room/embeddeds/fields/associations/many_association_field_spec.rb +21 -0
- data/spec/storage_room/embeddeds/fields/associations/one_association_field_spec.rb +19 -0
- data/spec/storage_room/embeddeds/fields/atomic/boolean_field_spec.rb +5 -0
- data/spec/storage_room/embeddeds/fields/atomic/date_field_spec.rb +5 -0
- data/spec/storage_room/embeddeds/fields/atomic/float_field_spec.rb +5 -0
- data/spec/storage_room/embeddeds/fields/atomic/integer_field_spec.rb +5 -0
- data/spec/storage_room/embeddeds/fields/atomic/string_field_spec.rb +5 -0
- data/spec/storage_room/embeddeds/fields/atomic/time_field_spec.rb +5 -0
- data/spec/storage_room/embeddeds/fields/atomic_field_spec.rb +27 -0
- data/spec/storage_room/embeddeds/fields/compound/attachment_field_spec.rb +5 -0
- data/spec/storage_room/embeddeds/fields/compound/file_field_spec.rb +5 -0
- data/spec/storage_room/embeddeds/fields/compound/image_field_spec.rb +5 -0
- data/spec/storage_room/embeddeds/fields/compound/location_field_spec.rb +5 -0
- data/spec/storage_room/embeddeds/fields/compound_field_spec.rb +17 -0
- data/spec/storage_room/embeddeds/location_spec.rb +13 -1
- data/spec/storage_room/identity_map_spec.rb +53 -0
- data/spec/storage_room/model_spec.rb +70 -50
- data/spec/storage_room/models/collection_spec.rb +57 -14
- data/spec/storage_room/models/entry_spec.rb +16 -20
- data/spec/storage_room/proxy_spec.rb +58 -0
- data/spec/storage_room/resource_spec.rb +98 -0
- data/spec/storage_room_spec.rb +45 -9
- data/storage_room.gemspec +48 -9
- data/tasks/storage_room.rake +3 -0
- metadata +49 -10
- data/lib/storage_room/attributes.rb +0 -46
- data/lib/storage_room/field.rb +0 -8
- data/spec/storage_room/attributes_spec.rb +0 -82
- data/spec/storage_room/base_spec.rb +0 -118
- data/spec/storage_room/field_spec.rb +0 -5
@@ -1,23 +1,26 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
2
|
|
3
3
|
describe StorageRoom::Collection do
|
4
|
+
before(:each) do
|
5
|
+
@field = StorageRoom::StringField.new(:name => 'Name', :identifier => 'name')
|
6
|
+
@collection = StorageRoom::Collection.new(:name => 'Restaurant', :fields => [@field])
|
7
|
+
@collection.response_data[:@version] = 1
|
8
|
+
@collection.response_data[:@url] = "URL"
|
9
|
+
|
10
|
+
@collection2 = StorageRoom::Collection.new
|
11
|
+
end
|
12
|
+
|
4
13
|
context "Class" do
|
5
14
|
context "Methods" do
|
6
15
|
describe "#show_path" do
|
7
16
|
it "should be defined" do
|
8
|
-
StorageRoom::Collection.show_path(1).should ==
|
17
|
+
StorageRoom::Collection.show_path(1).should == "#{StorageRoom::Resource.base_uri}/collections/1"
|
9
18
|
end
|
10
19
|
end
|
11
20
|
|
12
21
|
describe "#index_path" do
|
13
22
|
it "should be defined" do
|
14
|
-
StorageRoom::Collection.index_path.should ==
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
describe "#entries_path" do
|
19
|
-
it "should be defined" do
|
20
|
-
StorageRoom::Collection.entries_path(1).should == '/collections/1/entries'
|
23
|
+
StorageRoom::Collection.index_path.should == "#{StorageRoom::Resource.base_uri}/collections"
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
@@ -31,24 +34,64 @@ describe StorageRoom::Collection do
|
|
31
34
|
end
|
32
35
|
|
33
36
|
context "Instance" do
|
34
|
-
before(:each) do
|
35
|
-
@collection = StorageRoom::Collection.new
|
36
|
-
end
|
37
|
-
|
38
37
|
describe "#entries" do
|
39
38
|
it "should load" do
|
40
39
|
StorageRoom::Array.should_receive(:load)
|
41
40
|
@collection.entries
|
42
41
|
end
|
42
|
+
|
43
|
+
it "should have an error if not loaded" do
|
44
|
+
lambda { @collection2.entries }.should raise_error(StorageRoom::ResourceNotLoaded)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#entry_class_name" do
|
49
|
+
it "should return string" do
|
50
|
+
@collection.entry_class_name.should == 'Restaurant'
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should have an error if not loaded" do
|
54
|
+
lambda { @collection2.entry_class_name }.should raise_error(StorageRoom::ResourceNotLoaded)
|
55
|
+
end
|
43
56
|
end
|
44
57
|
|
45
58
|
describe "#entry_class" do
|
46
59
|
it "should return class" do
|
47
|
-
@collection
|
60
|
+
@collection.entry_class.should == Restaurant
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should have an error if not loaded" do
|
64
|
+
lambda { @collection2.entry_class }.should raise_error(StorageRoom::ResourceNotLoaded)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#field" do
|
69
|
+
it "should return existing field" do
|
70
|
+
@collection.field('name').should == @field
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should return nil for non-existant field" do
|
74
|
+
@collection.field('undefined').should be_nil
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should have an error if not loaded" do
|
78
|
+
lambda { @collection2.field('name') }.should raise_error(StorageRoom::ResourceNotLoaded)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "Private Methods" do
|
84
|
+
describe "#initialize_entry_class" do
|
85
|
+
it "should create class" do
|
48
86
|
klass = @collection.entry_class
|
49
|
-
klass.should ==
|
87
|
+
klass.collection.should == @collection
|
88
|
+
|
89
|
+
guidebook = klass.new(:name => 'NAME')
|
90
|
+
guidebook.name.should == 'NAME'
|
50
91
|
end
|
92
|
+
|
51
93
|
end
|
52
94
|
|
95
|
+
|
53
96
|
end
|
54
97
|
end
|
@@ -1,40 +1,37 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
2
|
|
3
3
|
describe StorageRoom::Entry do
|
4
|
+
before(:each) do
|
5
|
+
@string_field = StorageRoom::StringField.new(:name => 'Name', :identifier => 'name')
|
6
|
+
@collection = StorageRoom::Collection.new(:name => 'Report', :fields => [@string_field])
|
7
|
+
@collection.response_data[:@url] = '/collections/COLLECTION_ID'
|
8
|
+
@collection.entry_class
|
9
|
+
end
|
10
|
+
|
4
11
|
context "Class" do
|
5
|
-
context "Methods" do
|
6
|
-
before(:each) do
|
7
|
-
StorageRoom::Entry.class_with_options('Guidebook', :collection_path => '/collections/4ddaf68b4d085d374a000003')
|
8
|
-
end
|
9
|
-
|
12
|
+
context "Methods" do
|
10
13
|
describe "#show_path" do
|
11
14
|
it "should be defined" do
|
12
|
-
|
15
|
+
Report.show_path(1).should == '/collections/COLLECTION_ID/entries/1'
|
13
16
|
end
|
14
17
|
end
|
15
18
|
|
16
19
|
describe "#index_path" do
|
17
20
|
it "should be defined" do
|
18
|
-
|
21
|
+
Report.index_path.should == '/collections/COLLECTION_ID/entries'
|
19
22
|
end
|
20
23
|
end
|
21
|
-
|
22
|
-
describe "#collection_path" do
|
23
|
-
it "should be defined" do
|
24
|
-
Guidebook.collection_path.should == '/collections/4ddaf68b4d085d374a000003'
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
24
|
+
|
28
25
|
describe "#search_path" do
|
29
26
|
it "should be defined" do
|
30
|
-
|
27
|
+
Report.search_path(:test =>1).should == '/collections/COLLECTION_ID/entries?test=1'
|
31
28
|
end
|
32
29
|
end
|
33
30
|
|
34
31
|
describe "#json_name" do
|
35
32
|
it "should be defined" do
|
36
33
|
StorageRoom::Entry.json_name.should == 'entry'
|
37
|
-
|
34
|
+
Report.json_name.should == 'entry'
|
38
35
|
end
|
39
36
|
end
|
40
37
|
|
@@ -49,13 +46,12 @@ describe StorageRoom::Entry do
|
|
49
46
|
|
50
47
|
context "Instance" do
|
51
48
|
before(:each) do
|
52
|
-
@entry =
|
49
|
+
@entry = Report.new
|
53
50
|
end
|
54
51
|
|
55
52
|
describe "#collection" do
|
56
|
-
it "should
|
57
|
-
|
58
|
-
@entry.collection
|
53
|
+
it "should return collection" do
|
54
|
+
@entry.collection.should == @collection
|
59
55
|
end
|
60
56
|
end
|
61
57
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Post < StorageRoom::Entry
|
4
|
+
key :name
|
5
|
+
end
|
6
|
+
|
7
|
+
describe StorageRoom::Proxy do
|
8
|
+
before(:each) do
|
9
|
+
@hash_unloaded = {'@type' => 'Post', 'url' => 'URL'}
|
10
|
+
@object_unloaded = Post.new
|
11
|
+
|
12
|
+
@hash_loaded = {'@type' => 'Post', '@url' => 'URL', 'name' => 'NAME'}
|
13
|
+
@object_loaded = Post.new_from_response_data(@hash_loaded)
|
14
|
+
|
15
|
+
@proxy_unloaded = StorageRoom::Proxy.new(@object_unloaded)
|
16
|
+
@proxy_loaded = StorageRoom::Proxy.new(@object_loaded)
|
17
|
+
end
|
18
|
+
|
19
|
+
context "Methods" do
|
20
|
+
describe "#proxy" do
|
21
|
+
it "should return true" do
|
22
|
+
@proxy_unloaded.proxy?.should be_true
|
23
|
+
@proxy_loaded.proxy?.should be_true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#response_data" do
|
28
|
+
it "should return from object" do
|
29
|
+
@proxy_unloaded.response_data.should == {}
|
30
|
+
@proxy_loaded.response_data.should == @object_loaded.response_data
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#loaded?" do
|
35
|
+
it "should return false" do
|
36
|
+
@proxy_unloaded.loaded?.should be_false
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return true" do
|
40
|
+
@proxy_loaded.loaded?.should be_true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#method_missing" do
|
45
|
+
it "should forward to object" do
|
46
|
+
@proxy_loaded.name.should == 'NAME'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should reload if missing" do
|
50
|
+
@object_unloaded.response_data = @hash_unloaded
|
51
|
+
@object_unloaded.stub(:reload)
|
52
|
+
@object_unloaded.should_receive(:reload).with(@hash_unloaded['url'], {})
|
53
|
+
|
54
|
+
@proxy_unloaded.name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe StorageRoom::Resource do
|
4
|
+
context "Class" do
|
5
|
+
context "Configuration" do
|
6
|
+
describe "Headers" do
|
7
|
+
it "should have User-Agent" do
|
8
|
+
StorageRoom::Resource.headers['User-Agent'].should be_present
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should set Content Type" do
|
12
|
+
StorageRoom::Resource.headers['Content-Type'].should == 'application/json'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should set Accept" do
|
16
|
+
StorageRoom::Resource.headers['Accept'].should == 'application/json'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not have base_uri" do
|
21
|
+
StorageRoom::Resource.base_uri.should be_present
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should have format" do
|
25
|
+
StorageRoom::Resource.default_options[:format].should == :json
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should include Accessors" do
|
29
|
+
StorageRoom::Embedded.should include(StorageRoom::Accessors)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "Methods" do
|
34
|
+
describe "#load" do
|
35
|
+
it "should load" do
|
36
|
+
stub_request(:get, stub_url('/collections')).to_return(:body => fixture_file('collections.json'), :status => 200)
|
37
|
+
|
38
|
+
array = StorageRoom::Array.load('/collections')
|
39
|
+
array[:@type].should == 'Array'
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should raise on error" do
|
43
|
+
stub_request(:get, stub_url('/collections')).to_return(:status => 500)
|
44
|
+
|
45
|
+
lambda {
|
46
|
+
StorageRoom::Array.load('/collections')
|
47
|
+
}.should raise_error(StorageRoom::RequestFailed)
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#loaded?" do
|
53
|
+
before(:each) do
|
54
|
+
@resource = StorageRoom::Resource.new
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should return true" do
|
58
|
+
@resource.response_data['@url'] = 'URL'
|
59
|
+
@resource.should be_loaded
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should return false" do
|
63
|
+
@resource.should_not be_loaded
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#handle_critical_response_errors" do
|
68
|
+
it "should handle no error" do
|
69
|
+
httparty = mock_httparty(200)
|
70
|
+
StorageRoom::Resource.handle_critical_response_errors(httparty).should be_true
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should raise error" do
|
74
|
+
lambda {
|
75
|
+
StorageRoom::Resource.handle_critical_response_errors(mock_httparty(500))
|
76
|
+
}.should raise_error(StorageRoom::RequestFailed)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#meta_data?" do
|
81
|
+
it "should detect" do
|
82
|
+
StorageRoom::Resource.meta_data?('@test').should be_true
|
83
|
+
StorageRoom::Resource.meta_data?('test').should be_false
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "Instance" do
|
91
|
+
before(:each) do
|
92
|
+
@base = StorageRoom::Resource.new(:test => 1, :@attr => 2)
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
data/spec/storage_room_spec.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
|
+
class Client < StorageRoom::Entry
|
4
|
+
key :name
|
5
|
+
end
|
6
|
+
|
3
7
|
describe StorageRoom do
|
4
8
|
describe "#authenticate" do
|
5
9
|
before(:each) do
|
@@ -7,7 +11,7 @@ describe StorageRoom do
|
|
7
11
|
end
|
8
12
|
|
9
13
|
it "should set basic auth" do
|
10
|
-
StorageRoom::
|
14
|
+
StorageRoom::Resource.default_options[:basic_auth].should == {:username => 'api_key', :password => 'X'}
|
11
15
|
end
|
12
16
|
|
13
17
|
it "should set variables" do
|
@@ -16,7 +20,7 @@ describe StorageRoom do
|
|
16
20
|
end
|
17
21
|
|
18
22
|
it "should update uri" do
|
19
|
-
StorageRoom::
|
23
|
+
StorageRoom::Resource.base_uri.should include('account_id')
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
@@ -26,7 +30,7 @@ describe StorageRoom do
|
|
26
30
|
end
|
27
31
|
|
28
32
|
it "should set user agent" do
|
29
|
-
StorageRoom::
|
33
|
+
StorageRoom::Resource.headers['User-Agent'].should == 'agent'
|
30
34
|
end
|
31
35
|
|
32
36
|
it "should set variables" do
|
@@ -40,7 +44,7 @@ describe StorageRoom do
|
|
40
44
|
end
|
41
45
|
|
42
46
|
it "should update uri" do
|
43
|
-
StorageRoom::
|
47
|
+
StorageRoom::Resource.base_uri.should include('server')
|
44
48
|
end
|
45
49
|
|
46
50
|
it "should set variables" do
|
@@ -59,7 +63,7 @@ describe StorageRoom do
|
|
59
63
|
end
|
60
64
|
|
61
65
|
it "should update uri" do
|
62
|
-
StorageRoom::
|
66
|
+
StorageRoom::Resource.base_uri.should include('https://')
|
63
67
|
end
|
64
68
|
|
65
69
|
it "should set variables" do
|
@@ -73,8 +77,8 @@ describe StorageRoom do
|
|
73
77
|
end
|
74
78
|
|
75
79
|
it "should set proxy" do
|
76
|
-
StorageRoom::
|
77
|
-
StorageRoom::
|
80
|
+
StorageRoom::Resource.default_options[:http_proxyaddr].should == 'http_proxy'
|
81
|
+
StorageRoom::Resource.default_options[:http_proxyport].should == 123
|
78
82
|
end
|
79
83
|
|
80
84
|
it "should set variables" do
|
@@ -83,11 +87,35 @@ describe StorageRoom do
|
|
83
87
|
end
|
84
88
|
end
|
85
89
|
|
90
|
+
describe "#entry_class_mappings" do
|
91
|
+
it "should return hash" do
|
92
|
+
StorageRoom.entry_class_mappings.should == {}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#add_entry_class_mapping" do
|
97
|
+
it "should add to hash" do
|
98
|
+
StorageRoom.add_entry_class_mapping('Recipes List', 'List')
|
99
|
+
StorageRoom.entry_class_mappings.should include('Recipes List' => 'List')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "#entry_class_for_name" do
|
104
|
+
it "should return with mapping" do
|
105
|
+
StorageRoom.add_entry_class_mapping('Recipes List', 'List')
|
106
|
+
StorageRoom.entry_class_for_name('Recipes List').should == 'List'
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return without mapping" do
|
110
|
+
StorageRoom.entry_class_for_name('Restaurant Visits').should == 'RestaurantVisit'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
86
114
|
describe "#class_for_name" do
|
87
115
|
it "should get class" do
|
88
|
-
klass = StorageRoom.class_for_name('
|
116
|
+
klass = StorageRoom.class_for_name('Client')
|
89
117
|
klass.should be_an_instance_of(Class)
|
90
|
-
klass.name.should == '
|
118
|
+
klass.name.should == 'Client'
|
91
119
|
end
|
92
120
|
|
93
121
|
it "should get StorageRoom class" do
|
@@ -95,5 +123,13 @@ describe StorageRoom do
|
|
95
123
|
klass.should be_an_instance_of(Class)
|
96
124
|
klass.should == StorageRoom::Entry
|
97
125
|
end
|
126
|
+
|
127
|
+
it "should raise an error for unknown classes" do
|
128
|
+
lambda {
|
129
|
+
StorageRoom.class_for_name("Unknown")
|
130
|
+
}.should raise_error(StorageRoom::ClassNotFound)
|
131
|
+
|
132
|
+
end
|
98
133
|
end
|
134
|
+
|
99
135
|
end
|