dao 3.3.0 → 4.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +7 -0
- data/Rakefile +36 -17
- data/b.rb +38 -0
- data/dao.gemspec +41 -13
- data/lib/dao.rb +44 -13
- data/lib/dao/api.rb +1 -1
- data/lib/dao/api/context.rb +35 -45
- data/lib/dao/api/endpoints.rb +225 -91
- data/lib/dao/conducer.rb +437 -0
- data/lib/dao/conducer/attributes.rb +21 -0
- data/lib/dao/conducer/crud.rb +70 -0
- data/lib/dao/current.rb +66 -0
- data/lib/dao/db.rb +44 -5
- data/lib/dao/endpoint.rb +13 -1
- data/lib/dao/errors.rb +74 -59
- data/lib/dao/exceptions.rb +1 -2
- data/lib/dao/extractor.rb +68 -0
- data/lib/dao/form.rb +139 -46
- data/lib/dao/image_cache.rb +193 -0
- data/lib/dao/instance_exec.rb +1 -1
- data/lib/dao/name.rb +7 -0
- data/lib/dao/params.rb +16 -66
- data/lib/dao/rack.rb +3 -0
- data/lib/dao/rack/middleware.rb +5 -0
- data/lib/dao/rack/middleware/params_parser.rb +24 -0
- data/lib/dao/rails.rb +22 -5
- data/lib/dao/rails/lib/generators/dao/USAGE +2 -6
- data/lib/dao/rails/lib/generators/dao/dao_generator.rb +52 -7
- data/lib/dao/rails/lib/generators/dao/templates/api.rb +23 -7
- data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +24 -7
- data/lib/dao/rails/lib/generators/dao/templates/conducer.rb +64 -0
- data/lib/dao/rails/lib/generators/dao/templates/conducer_controller.rb +79 -0
- data/lib/dao/rails/lib/generators/dao/templates/dao.js +13 -6
- data/lib/dao/rails/lib/generators/dao/templates/dao_helper.rb +75 -11
- data/lib/dao/result.rb +1 -26
- data/lib/dao/slug.rb +37 -8
- data/lib/dao/status.rb +4 -0
- data/lib/dao/support.rb +155 -0
- data/lib/dao/validations.rb +48 -157
- data/lib/dao/validations/callback.rb +30 -0
- data/lib/dao/validations/common.rb +322 -320
- data/lib/dao/validations/validator.rb +219 -0
- data/test/active_model_conducer_lint_test.rb +19 -0
- data/test/api_test.rb +261 -0
- data/test/conducer_test.rb +205 -0
- data/test/db.yml +9 -0
- data/test/form_test.rb +42 -0
- data/test/support_test.rb +52 -0
- data/test/testing.rb +145 -24
- data/test/validations_test.rb +156 -0
- metadata +138 -21
- data/TODO +0 -33
- data/a.rb +0 -80
- data/db/dao.yml +0 -5
- data/lib/dao/api/interfaces.rb +0 -306
- data/lib/dao/interface.rb +0 -28
- data/lib/dao/presenter.rb +0 -129
- data/lib/dao/rails/lib/generators/dao/api_generator.rb +0 -3
- data/lib/dao/validations/base.rb +0 -68
- data/test/dao_test.rb +0 -506
@@ -0,0 +1,156 @@
|
|
1
|
+
Testing Dao::Validations do
|
2
|
+
## status
|
3
|
+
#
|
4
|
+
testing 'Status.for' do
|
5
|
+
assert{ Dao::Status.for(:unauthorized).code == 401 }
|
6
|
+
assert{ Dao::Status.for(:UNAUTHORIZED).code == 401 }
|
7
|
+
assert{ Dao::Status.for('unauthorized').code == 401 }
|
8
|
+
assert{ Dao::Status.for('UNAUTHORIZED').code == 401 }
|
9
|
+
assert{ Dao::Status.for('Unauthorized').code == 401 }
|
10
|
+
assert{ Dao::Status.for(:Unauthorized).code == 401 }
|
11
|
+
assert{ Dao::Status.for(:No_Content).code == 204 }
|
12
|
+
assert{ Dao::Status.for(:no_content).code == 204 }
|
13
|
+
end
|
14
|
+
|
15
|
+
testing 'status equality operator' do
|
16
|
+
s = Dao::Status.for(401)
|
17
|
+
assert{ s == :unauthorized }
|
18
|
+
assert{ s == 401 }
|
19
|
+
assert{ s != Array.new }
|
20
|
+
end
|
21
|
+
|
22
|
+
## errors
|
23
|
+
#
|
24
|
+
testing 'that clear does not drop sticky errors' do
|
25
|
+
errors = Dao::Errors.new
|
26
|
+
errors.add! 'sticky', 'error'
|
27
|
+
assert{ errors['sticky'].first.sticky? }
|
28
|
+
errors.add 'not-sticky', 'error'
|
29
|
+
errors.clear
|
30
|
+
assert{ errors['sticky'].first == 'error' }
|
31
|
+
assert{ errors['not-sticky'].to_s.empty? }
|
32
|
+
end
|
33
|
+
|
34
|
+
testing 'that clear! ***does*** drop sticky errors' do
|
35
|
+
errors = Dao::Errors.new
|
36
|
+
errors.add! 'sticky', 'error'
|
37
|
+
errors.add 'not-sticky', 'error'
|
38
|
+
errors.clear!
|
39
|
+
assert{ errors['sticky'].to_s.empty? }
|
40
|
+
assert{ errors['not-sticky'].to_s.empty? }
|
41
|
+
end
|
42
|
+
|
43
|
+
testing 'that global errors are sticky' do
|
44
|
+
errors = Dao::Errors.new
|
45
|
+
global = Dao::Errors::Global
|
46
|
+
errors.add! 'global-error'
|
47
|
+
errors.clear
|
48
|
+
assert{ errors[global].first == 'global-error' }
|
49
|
+
errors.clear!
|
50
|
+
assert{ errors[global].to_s.empty? }
|
51
|
+
end
|
52
|
+
|
53
|
+
## validations
|
54
|
+
#
|
55
|
+
testing 'that simple validations work' do
|
56
|
+
params = Dao::Params.new
|
57
|
+
assert{ params.validates(:password){|password| password=='haxor'} }
|
58
|
+
params.set(:password, 'haxor')
|
59
|
+
assert{ params.valid? }
|
60
|
+
end
|
61
|
+
|
62
|
+
testing 'that validations have some syntax sugar' do
|
63
|
+
return :pending
|
64
|
+
|
65
|
+
assert{
|
66
|
+
api_class =
|
67
|
+
Dao.api do
|
68
|
+
endpoint('/foobar'){
|
69
|
+
validates(:a)
|
70
|
+
validate!
|
71
|
+
}
|
72
|
+
end
|
73
|
+
api = api_class.new
|
74
|
+
|
75
|
+
result = assert{ api.call('/foobar', 'a' => true) }
|
76
|
+
assert{ result.status.ok? }
|
77
|
+
|
78
|
+
result = assert{ api.call('/foobar') }
|
79
|
+
assert{ result.errors.size==1 }
|
80
|
+
assert{ !result.status.ok? }
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
testing 'that validations use instance_exec' do
|
85
|
+
return :pending
|
86
|
+
|
87
|
+
a, b = nil
|
88
|
+
|
89
|
+
api_class =
|
90
|
+
Dao.api do
|
91
|
+
endpoint('/foobar'){
|
92
|
+
params.validate(:a){ b = get(:b) }
|
93
|
+
params.validate(:b){ a = get(:a) }
|
94
|
+
validate!
|
95
|
+
}
|
96
|
+
end
|
97
|
+
api = api_class.new
|
98
|
+
|
99
|
+
result = assert{ api.call('/foobar', 'a' => 40, 'b' => 2) }
|
100
|
+
assert{ result.status.ok? }
|
101
|
+
assert{ a == 40 }
|
102
|
+
assert{ b == 2 }
|
103
|
+
end
|
104
|
+
|
105
|
+
testing 'simple validates_confirmation_of' do
|
106
|
+
return :pending
|
107
|
+
|
108
|
+
api_class =
|
109
|
+
Dao.api do
|
110
|
+
endpoint('/foobar'){
|
111
|
+
params.validates_as_email(:email)
|
112
|
+
params.validates_confirmation_of(:email)
|
113
|
+
validate!
|
114
|
+
}
|
115
|
+
end
|
116
|
+
api = api_class.new
|
117
|
+
|
118
|
+
result = assert{ api.call('/foobar', 'email' => 'ara.t.howard@gmail.com', 'email_confirmation' => 'ara.t.howard@gmail.com') }
|
119
|
+
assert{ result.status.ok? }
|
120
|
+
assert{ result.errors.empty? }
|
121
|
+
|
122
|
+
result = assert{ api.call('/foobar', 'email' => 'ara.t.howard@gmail.com', 'email_confirmation' => 'ara@dojo4.com') }
|
123
|
+
assert{ !result.status.ok? }
|
124
|
+
assert{ !result.errors.empty? }
|
125
|
+
end
|
126
|
+
|
127
|
+
## validating
|
128
|
+
#
|
129
|
+
testing 'that validations can be cleared and do not clobber manually added errors' do
|
130
|
+
params = Dao::Params.new
|
131
|
+
errors = params.errors
|
132
|
+
|
133
|
+
assert{ params.validates(:email){|email| email.to_s.split(/@/).size == 2} }
|
134
|
+
assert{ params.validates(:password){|password| password == 'pa$$w0rd'} }
|
135
|
+
|
136
|
+
params.set(:email => 'ara@dojo4.com', :password => 'pa$$w0rd')
|
137
|
+
assert{ params.valid? }
|
138
|
+
|
139
|
+
params.set(:password => 'haxor')
|
140
|
+
assert{ !params.valid?(:validate => true) }
|
141
|
+
|
142
|
+
errors.add(:name, 'ara')
|
143
|
+
assert{ not params.valid? }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
BEGIN {
|
149
|
+
testdir = File.dirname(File.expand_path(__FILE__))
|
150
|
+
rootdir = File.dirname(testdir)
|
151
|
+
libdir = File.join(rootdir, 'lib')
|
152
|
+
|
153
|
+
require File.join(libdir, 'dao')
|
154
|
+
require File.join(testdir, 'testing')
|
155
|
+
require File.join(testdir, 'helper')
|
156
|
+
}
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dao
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 53
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
|
-
-
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version:
|
7
|
+
- 4
|
8
|
+
- 2
|
9
|
+
- 1
|
10
|
+
version: 4.2.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ara T. Howard
|
@@ -15,10 +15,113 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
date: 2011-10-05 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rails
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 7
|
29
|
+
segments:
|
30
|
+
- 3
|
31
|
+
- 0
|
32
|
+
version: "3.0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: uuidtools
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 1
|
44
|
+
segments:
|
45
|
+
- 2
|
46
|
+
- 1
|
47
|
+
version: "2.1"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: tagz
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ~>
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 47
|
59
|
+
segments:
|
60
|
+
- 9
|
61
|
+
- 0
|
62
|
+
version: "9.0"
|
63
|
+
type: :runtime
|
64
|
+
version_requirements: *id003
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: fattr
|
67
|
+
prerelease: false
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ~>
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 7
|
74
|
+
segments:
|
75
|
+
- 2
|
76
|
+
- 2
|
77
|
+
version: "2.2"
|
78
|
+
type: :runtime
|
79
|
+
version_requirements: *id004
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: map
|
82
|
+
prerelease: false
|
83
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ~>
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 19
|
89
|
+
segments:
|
90
|
+
- 4
|
91
|
+
- 4
|
92
|
+
version: "4.4"
|
93
|
+
type: :runtime
|
94
|
+
version_requirements: *id005
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: unidecode
|
97
|
+
prerelease: false
|
98
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 15
|
104
|
+
segments:
|
105
|
+
- 1
|
106
|
+
- 0
|
107
|
+
version: "1.0"
|
108
|
+
type: :runtime
|
109
|
+
version_requirements: *id006
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: yajl-ruby
|
112
|
+
prerelease: false
|
113
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ~>
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
hash: 27
|
119
|
+
segments:
|
120
|
+
- 0
|
121
|
+
- 8
|
122
|
+
version: "0.8"
|
123
|
+
type: :runtime
|
124
|
+
version_requirements: *id007
|
22
125
|
description: "description: dao kicks the ass"
|
23
126
|
email: ara.t.howard@gmail.com
|
24
127
|
executables: []
|
@@ -30,10 +133,8 @@ extra_rdoc_files: []
|
|
30
133
|
files:
|
31
134
|
- README
|
32
135
|
- Rakefile
|
33
|
-
-
|
34
|
-
- a.rb
|
136
|
+
- b.rb
|
35
137
|
- dao.gemspec
|
36
|
-
- db/dao.yml
|
37
138
|
- lib/dao.rb
|
38
139
|
- lib/dao/active_record.rb
|
39
140
|
- lib/dao/api.rb
|
@@ -41,30 +142,38 @@ files:
|
|
41
142
|
- lib/dao/api/dsl.rb
|
42
143
|
- lib/dao/api/endpoints.rb
|
43
144
|
- lib/dao/api/initializers.rb
|
44
|
-
- lib/dao/api/interfaces.rb
|
45
145
|
- lib/dao/api/modes.rb
|
46
146
|
- lib/dao/api/routes.rb
|
47
147
|
- lib/dao/blankslate.rb
|
148
|
+
- lib/dao/conducer.rb
|
149
|
+
- lib/dao/conducer/attributes.rb
|
150
|
+
- lib/dao/conducer/crud.rb
|
151
|
+
- lib/dao/current.rb
|
48
152
|
- lib/dao/data.rb
|
49
153
|
- lib/dao/db.rb
|
50
154
|
- lib/dao/endpoint.rb
|
51
155
|
- lib/dao/engine.rb
|
52
156
|
- lib/dao/errors.rb
|
53
157
|
- lib/dao/exceptions.rb
|
158
|
+
- lib/dao/extractor.rb
|
54
159
|
- lib/dao/form.rb
|
160
|
+
- lib/dao/image_cache.rb
|
55
161
|
- lib/dao/instance_exec.rb
|
56
|
-
- lib/dao/interface.rb
|
57
162
|
- lib/dao/mode.rb
|
58
163
|
- lib/dao/mongo_mapper.rb
|
164
|
+
- lib/dao/name.rb
|
59
165
|
- lib/dao/params.rb
|
60
166
|
- lib/dao/path.rb
|
61
|
-
- lib/dao/
|
167
|
+
- lib/dao/rack.rb
|
168
|
+
- lib/dao/rack/middleware.rb
|
169
|
+
- lib/dao/rack/middleware/params_parser.rb
|
62
170
|
- lib/dao/rails.rb
|
63
171
|
- lib/dao/rails/lib/generators/dao/USAGE
|
64
|
-
- lib/dao/rails/lib/generators/dao/api_generator.rb
|
65
172
|
- lib/dao/rails/lib/generators/dao/dao_generator.rb
|
66
173
|
- lib/dao/rails/lib/generators/dao/templates/api.rb
|
67
174
|
- lib/dao/rails/lib/generators/dao/templates/api_controller.rb
|
175
|
+
- lib/dao/rails/lib/generators/dao/templates/conducer.rb
|
176
|
+
- lib/dao/rails/lib/generators/dao/templates/conducer_controller.rb
|
68
177
|
- lib/dao/rails/lib/generators/dao/templates/dao.css
|
69
178
|
- lib/dao/rails/lib/generators/dao/templates/dao.js
|
70
179
|
- lib/dao/rails/lib/generators/dao/templates/dao_helper.rb
|
@@ -75,16 +184,24 @@ files:
|
|
75
184
|
- lib/dao/stdext.rb
|
76
185
|
- lib/dao/support.rb
|
77
186
|
- lib/dao/validations.rb
|
78
|
-
- lib/dao/validations/
|
187
|
+
- lib/dao/validations/callback.rb
|
79
188
|
- lib/dao/validations/common.rb
|
80
|
-
-
|
189
|
+
- lib/dao/validations/validator.rb
|
190
|
+
- test/active_model_conducer_lint_test.rb
|
191
|
+
- test/api_test.rb
|
192
|
+
- test/conducer_test.rb
|
193
|
+
- test/db.yml
|
194
|
+
- test/form_test.rb
|
81
195
|
- test/helper.rb
|
82
196
|
- test/leak.rb
|
197
|
+
- test/support_test.rb
|
83
198
|
- test/testing.rb
|
84
|
-
|
199
|
+
- test/validations_test.rb
|
85
200
|
homepage: https://github.com/ahoward/dao
|
86
201
|
licenses: []
|
87
202
|
|
203
|
+
metadata: {}
|
204
|
+
|
88
205
|
post_install_message:
|
89
206
|
rdoc_options: []
|
90
207
|
|
@@ -111,9 +228,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
228
|
requirements: []
|
112
229
|
|
113
230
|
rubyforge_project: codeforpeople
|
114
|
-
rubygems_version: 1.
|
231
|
+
rubygems_version: 1.8.10
|
115
232
|
signing_key:
|
116
|
-
specification_version:
|
233
|
+
specification_version: 4
|
117
234
|
summary: dao
|
118
235
|
test_files: []
|
119
236
|
|
data/TODO
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
todo:
|
2
|
-
- class level nested AR conversions
|
3
|
-
to_dao(:a, :b => [:foo, :bar])
|
4
|
-
|
5
|
-
done:
|
6
|
-
- auto apply?
|
7
|
-
- pre-condition and parameter code
|
8
|
-
- engine-ify the rails stuff? or what
|
9
|
-
- generator api
|
10
|
-
- controller
|
11
|
-
- helper
|
12
|
-
- json/pretty fix baked in? (yajl might simply this...)
|
13
|
-
- description/doc logic
|
14
|
-
- api.index
|
15
|
-
- to_alpo -> to_dao
|
16
|
-
- tests!
|
17
|
-
- #call auto parses data iff appropriate
|
18
|
-
@result = api.read.call('/posts/new(', params) ### check keys for '/posts/new'
|
19
|
-
- re-visit how parameters are parsed, perhaps we just use rack?
|
20
|
-
- next 'data' => {}
|
21
|
-
- check the db layer
|
22
|
-
- make sure one can call route based method (/foo/:bar) methods with params...
|
23
|
-
- Path==Route ??
|
24
|
-
- add result.rb, params.rb
|
25
|
-
- name -> path
|
26
|
-
- tagz for html methods?
|
27
|
-
- data aquires the name/path of the method?
|
28
|
-
- interfaces are objects that respond to call. namespaces respond to call.
|
29
|
-
api responds to call
|
30
|
-
- nested namespaces
|
31
|
-
- routing for path_info + mode
|
32
|
-
route(path_info, :mode => mode, :params => params)
|
33
|
-
- call() on namespaces AND interfaces... why?
|
data/a.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
##
|
2
|
-
#
|
3
|
-
require 'dao'
|
4
|
-
require 'rubygems'
|
5
|
-
gem 'activesupport', '>= 3.0.7'
|
6
|
-
require 'active_support'
|
7
|
-
require 'active_support/dependencies'
|
8
|
-
|
9
|
-
##
|
10
|
-
#
|
11
|
-
leak =
|
12
|
-
lambda do
|
13
|
-
Api =
|
14
|
-
Dao.api do
|
15
|
-
1000.times do |i|
|
16
|
-
call("/foobar-#{ i }") do
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
api = Api.new
|
22
|
-
|
23
|
-
result = api.call('/foobar-1')
|
24
|
-
p result
|
25
|
-
|
26
|
-
ActiveSupport::Dependencies.unloadable(Api)
|
27
|
-
ActiveSupport::Dependencies.remove_unloadable_constants!
|
28
|
-
end
|
29
|
-
|
30
|
-
##
|
31
|
-
#
|
32
|
-
n = 10
|
33
|
-
|
34
|
-
leak.call()
|
35
|
-
|
36
|
-
GC.start
|
37
|
-
leak.call()
|
38
|
-
GC.start
|
39
|
-
|
40
|
-
p :before => Process.size
|
41
|
-
|
42
|
-
|
43
|
-
GC.start
|
44
|
-
leak.call()
|
45
|
-
GC.start
|
46
|
-
|
47
|
-
p :after => Process.size
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
##
|
62
|
-
#
|
63
|
-
BEGIN {
|
64
|
-
|
65
|
-
module Process
|
66
|
-
def self.size pid = Process.pid
|
67
|
-
stdout = `ps wwwux -p #{ pid }`.split(%r/\n/)
|
68
|
-
vsize, rsize = stdout.last.split(%r/\s+/)[4,2]
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.vsize
|
72
|
-
size.first
|
73
|
-
end
|
74
|
-
|
75
|
-
def self.rsize
|
76
|
-
size.last
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
}
|