mongous 0.1.4 → 0.2.1
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 +4 -4
- data/README.adoc +156 -37
- data/README.ja.adoc +155 -36
- data/lib/mongous/document.rb +66 -31
- data/lib/mongous/extention.rb +59 -46
- data/lib/mongous/filter.rb +82 -60
- data/lib/mongous/version.rb +1 -1
- data/sample/connect_auto_2.rb +2 -1
- data/sample/connect_default_2.rb +2 -1
- data/sample/connect_environ_2.rb +2 -1
- data/sample/connect_loadfile_2.rb +2 -1
- data/sample/declare_compact_1.rb +4 -3
- data/sample/declare_label_1.rb +5 -3
- data/sample/declare_ndex_1.rb +5 -3
- data/sample/declare_ndex_2.rb +5 -3
- data/sample/declare_strict_1.rb +14 -10
- data/sample/declare_strict_2.rb +5 -3
- data/sample/{multi_docs_1.rb → multi_collection_1.rb} +0 -0
- data/sample/multi_collection_2.rb +63 -0
- data/sample/query_basic_1.rb +3 -1
- data/sample/query_basic_2.rb +5 -3
- data/sample/query_basic_3.rb +2 -3
- data/sample/query_basic_4.rb +3 -4
- data/sample/query_basic_5.rb +2 -3
- data/sample/query_detail_1.rb +1 -0
- data/sample/query_detail_2.rb +1 -0
- data/sample/query_detail_3.rb +5 -3
- data/sample/{query_basic_6.rb → query_filter_1.rb} +8 -5
- data/sample/query_filter_2.rb +50 -0
- data/sample/query_find_1.rb +31 -0
- data/sample/query_projection_1.rb +5 -8
- data/sample/query_skip_limit_1.rb +47 -0
- data/sample/query_skip_limit_2.rb +49 -0
- data/sample/query_sort_order_1.rb +46 -0
- data/sample/save_basic_1.rb +1 -2
- data/sample/save_basic_2.rb +1 -2
- data/sample/save_basic_3.rb +1 -2
- data/sample/save_detail_1.rb +7 -4
- data/sample/save_detail_2.rb +7 -4
- data/sample/save_detail_3.rb +10 -7
- data/sample/save_verify_1.rb +7 -4
- data/sample/save_verify_3.rb +1 -1
- data/sample/save_verify_5.rb +3 -3
- data/sample/save_verify_6.rb +3 -3
- data/sample/save_verify_7.rb +23 -0
- data/sample/update_basic_1.rb +13 -0
- data/sample/zap_basic_2.rb +2 -2
- metadata +12 -11
- data/sample/multi_docs_2.rb +0 -58
- data/sample/query_limit_1.rb +0 -44
- data/sample/query_order_1.rb +0 -49
- data/sample/query_raw_1.rb +0 -33
- data/sample/template_article.rb +0 -5
- data/sample/template_person.rb +0 -12
- data/sample/zap_basic_3.rb +0 -11
data/lib/mongous/document.rb
CHANGED
@@ -26,33 +26,66 @@ module Mongous
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def having?(
|
30
|
-
case
|
29
|
+
def having?( label )
|
30
|
+
case label
|
31
31
|
when NilClass
|
32
32
|
false
|
33
33
|
when String
|
34
|
-
!
|
34
|
+
!label.strip.empty?
|
35
35
|
else
|
36
36
|
true
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
+
def getvalue_or_callproc( value_or_proc )
|
41
|
+
case value_or_proc
|
42
|
+
when Proc
|
43
|
+
value_or_proc.call
|
44
|
+
else
|
45
|
+
value_or_proc
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
40
49
|
def save
|
50
|
+
if @doc["_id"].nil? || self.class.collection.find( { "_id"=> @doc["_id"] } ).count == 0
|
51
|
+
savemode = :create
|
52
|
+
else
|
53
|
+
savemode = :update
|
54
|
+
end
|
55
|
+
|
41
56
|
self.class.fields.each do |label, field|
|
42
|
-
|
57
|
+
default_value = getvalue_or_callproc( field[:default] )
|
58
|
+
_must = field[:_attrs].include?(:must)
|
43
59
|
if @doc.has_key?(label)
|
44
|
-
if
|
45
|
-
|
60
|
+
if !having?( @doc[label] )
|
61
|
+
if default_value
|
62
|
+
self[label] = default_value
|
63
|
+
elsif _must
|
64
|
+
raise Mongous::Error, "must but unassigned field. : #{ label }"
|
65
|
+
elsif self.class.symbols[:strict]
|
66
|
+
self[label] = nil
|
67
|
+
end
|
46
68
|
end
|
47
69
|
else
|
48
|
-
if
|
49
|
-
self[label] =
|
70
|
+
if default_value
|
71
|
+
self[label] = default_value
|
50
72
|
elsif _must
|
51
|
-
raise Mongous::Error, "must
|
73
|
+
raise Mongous::Error, "must but unassigned field. : #{ label }"
|
52
74
|
elsif self.class.symbols[:strict]
|
53
75
|
self[label] = nil
|
54
76
|
end
|
55
77
|
end
|
78
|
+
|
79
|
+
case savemode
|
80
|
+
when :create
|
81
|
+
if create_value = getvalue_or_callproc( field[:create] )
|
82
|
+
self[label] = create_value
|
83
|
+
end
|
84
|
+
when :update
|
85
|
+
if update_value = getvalue_or_callproc( field[:update] )
|
86
|
+
self[label] = update_value
|
87
|
+
end
|
88
|
+
end
|
56
89
|
end
|
57
90
|
|
58
91
|
self.class.blocks.each do |call_from, block|
|
@@ -61,15 +94,13 @@ module Mongous
|
|
61
94
|
end
|
62
95
|
end
|
63
96
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
97
|
+
case savemode
|
98
|
+
when :create
|
99
|
+
self.class.collection.insert_one( @doc )
|
100
|
+
when :update
|
101
|
+
self.class.collection.update_one( { "_id"=> @doc["_id"] }, { '$set' => @doc } )
|
70
102
|
end
|
71
103
|
|
72
|
-
self.class.collection.insert_one( @doc )
|
73
104
|
self
|
74
105
|
end
|
75
106
|
|
@@ -77,7 +108,7 @@ module Mongous
|
|
77
108
|
label = label.to_s
|
78
109
|
|
79
110
|
if self.class.symbols[:strict]
|
80
|
-
if !self.class.fields.keys.include?(label)
|
111
|
+
if !(self.class.fields.keys.include?(label) || (label == "_id"))
|
81
112
|
raise Mongous::Error, "undefined field. : #{ label }"
|
82
113
|
end
|
83
114
|
end
|
@@ -108,18 +139,18 @@ module Mongous
|
|
108
139
|
return @doc[label] = value if field.nil?
|
109
140
|
|
110
141
|
types = []
|
111
|
-
if
|
112
|
-
|
113
|
-
if
|
114
|
-
types <<
|
115
|
-
|
142
|
+
if attrs = field[:_attrs] || []
|
143
|
+
attrs.each do |attr|
|
144
|
+
if attr.class == Class
|
145
|
+
types << attr
|
146
|
+
attrs -= [attr]
|
116
147
|
break
|
117
148
|
end
|
118
149
|
end
|
119
150
|
end
|
120
151
|
|
121
152
|
if !types.empty?
|
122
|
-
if !(
|
153
|
+
if !(attrs & [:must, :not_null]).empty?
|
123
154
|
if !types.include?( value.class )
|
124
155
|
raise Mongous::Error, "invalid type. : #{ label } : #{ value.class }"
|
125
156
|
end
|
@@ -129,7 +160,7 @@ module Mongous
|
|
129
160
|
end
|
130
161
|
end
|
131
162
|
else
|
132
|
-
if !(
|
163
|
+
if !(attrs & [:must, :not_null]).empty?
|
133
164
|
if [NilClass].include?( value.class )
|
134
165
|
raise Mongous::Error, "invalid type. : #{ label } : #{ value.class }"
|
135
166
|
end
|
@@ -138,19 +169,23 @@ module Mongous
|
|
138
169
|
|
139
170
|
@doc[label] = value
|
140
171
|
|
141
|
-
|
142
|
-
case
|
172
|
+
attrs.each do |attr|
|
173
|
+
case attr
|
143
174
|
when Proc
|
144
|
-
if !self.instance_eval( &
|
175
|
+
if !self.instance_eval( &attr )
|
145
176
|
raise Mongous::Error, "violation detected. : #{ label } : #{ value }"
|
146
177
|
end
|
147
178
|
when Array
|
148
|
-
if !
|
149
|
-
raise Mongous::Error, "not include. : #{ label }
|
179
|
+
if !attr.include?( value )
|
180
|
+
raise Mongous::Error, "not include. : #{ label } : #{ value }"
|
150
181
|
end
|
151
182
|
when Range
|
152
|
-
if !
|
153
|
-
raise Mongous::Error, "out of range. : #{ label }
|
183
|
+
if !attr.cover?( value )
|
184
|
+
raise Mongous::Error, "out of range. : #{ label } : #{ value }"
|
185
|
+
end
|
186
|
+
when Regexp
|
187
|
+
if !attr.match( value )
|
188
|
+
raise Mongous::Error, "unmatch regexp. : #{ label } : #{ value }"
|
154
189
|
end
|
155
190
|
end
|
156
191
|
end
|
data/lib/mongous/extention.rb
CHANGED
@@ -10,7 +10,7 @@ module Mongous
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
13
|
+
def client=( _client )
|
14
14
|
m = /(.*?):(\d+)/.match( caller()[0] )
|
15
15
|
call_from = [ m[1], m[2] ].join(":")
|
16
16
|
if !_client.is_a?( Mongo::Client )
|
@@ -28,7 +28,7 @@ module Mongous
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def collection_name=( _collection_name )
|
32
32
|
self.class_variable_set( :@@collection_name, _collection_name )
|
33
33
|
if self.class_variable_defined?( :@@collection )
|
34
34
|
self.remove_class_variable( :@@collection )
|
@@ -60,34 +60,34 @@ module Mongous
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def fields
|
63
|
-
|
64
|
-
self.class_variable_get( :@@fields )
|
65
|
-
else
|
66
|
-
self.class_variable_set( :@@fields, {} )
|
67
|
-
end
|
63
|
+
self_class_variable( :@@fields, {} )
|
68
64
|
end
|
69
65
|
|
70
66
|
def symbols
|
71
|
-
|
72
|
-
self.class_variable_get( :@@symbols )
|
73
|
-
else
|
74
|
-
self.class_variable_set( :@@symbols, {} )
|
75
|
-
end
|
67
|
+
self_class_variable( :@@symbols, {} )
|
76
68
|
end
|
77
69
|
|
78
70
|
def blocks
|
79
|
-
|
80
|
-
self.class_variable_get( :@@blocks )
|
81
|
-
else
|
82
|
-
self.class_variable_set( :@@blocks, {} )
|
83
|
-
end
|
71
|
+
self_class_variable( :@@blocks, {} )
|
84
72
|
end
|
85
73
|
|
86
74
|
def indexes
|
87
|
-
|
88
|
-
|
75
|
+
self_class_variable( :@@indexes, [] )
|
76
|
+
end
|
77
|
+
|
78
|
+
def filters
|
79
|
+
self_class_variable( :@@filters, {} )
|
80
|
+
end
|
81
|
+
|
82
|
+
def defaults
|
83
|
+
self_class_variable( :@@defaults, {} )
|
84
|
+
end
|
85
|
+
|
86
|
+
def self_class_variable( symbol, default )
|
87
|
+
if self.class_variable_defined?( symbol )
|
88
|
+
self.class_variable_get( symbol )
|
89
89
|
else
|
90
|
-
self.class_variable_set(
|
90
|
+
self.class_variable_set( symbol, default )
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
@@ -95,53 +95,66 @@ module Mongous
|
|
95
95
|
self.new( **doc ).save
|
96
96
|
end
|
97
97
|
|
98
|
-
def
|
98
|
+
def find( conditios = {}, options = {} )
|
99
|
+
self.collection.find( conditios, options )
|
100
|
+
end
|
101
|
+
|
102
|
+
def field( symbol, *attrs, **items )
|
99
103
|
m = /(.*?):(\d+)/.match( caller()[0] )
|
100
104
|
call_from = [ m[1], m[2] ].join(":")
|
101
105
|
|
102
|
-
|
103
|
-
if klass =
|
104
|
-
if ![Class, Range, Array, Proc, Symbol].include?(klass)
|
105
|
-
raise Mongous::Error, "field error. :
|
106
|
+
attrs.each do |attr|
|
107
|
+
if klass = attr.class
|
108
|
+
if ![Class, Range, Array, Regexp, Proc, Symbol].include?(klass)
|
109
|
+
raise Mongous::Error, "'field' arguments error. : #{ attr } on #{ symbol } at #{ call_from }"
|
106
110
|
end
|
107
111
|
end
|
108
112
|
end
|
109
113
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
when Proc, String, Numeric
|
115
|
-
else
|
116
|
-
raise Mongous::Error, "field error. : #{key} on #{ label } at #{ call_from }"
|
117
|
-
end
|
118
|
-
end
|
114
|
+
items.each do |key, value|
|
115
|
+
next if [:default, :create, :update].include?(key) && [Proc, String, Numeric].include?(value.class)
|
116
|
+
|
117
|
+
raise Mongous::Error, "'field' options error. : #{key} on #{ symbol } at #{ call_from }"
|
119
118
|
end
|
120
119
|
|
121
|
-
|
122
|
-
|
123
|
-
fields[label.to_s] = opts
|
120
|
+
items[:_attrs] = attrs
|
121
|
+
fields[symbol.to_s] = items
|
124
122
|
end
|
125
123
|
|
126
|
-
def verify( *
|
127
|
-
if !
|
128
|
-
|
129
|
-
symbols[
|
124
|
+
def verify( *directives, &block )
|
125
|
+
if !directives.empty?
|
126
|
+
directives.each do |directive|
|
127
|
+
symbols[directive] = true
|
130
128
|
end
|
131
129
|
elsif block
|
132
130
|
m = /(.*?):(\d+)/.match( caller()[0] )
|
133
131
|
call_from = [ m[1], m[2] ].join(":")
|
134
132
|
blocks[call_from] = block
|
133
|
+
else
|
134
|
+
raise Mongous::Error, "'verify' arguments error. need directives or block."
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
138
|
-
def index( *
|
139
|
-
|
138
|
+
def index( *symbols, **options )
|
139
|
+
options[:background] = true unless options.has_key?(:background)
|
140
140
|
keys = {}
|
141
|
-
|
142
|
-
keys[
|
141
|
+
symbols.each do |symbol|
|
142
|
+
keys[symbol] = 1
|
143
|
+
end
|
144
|
+
indexes.push << [keys, options]
|
145
|
+
end
|
146
|
+
|
147
|
+
def filter( symbol, filter_or_condition )
|
148
|
+
case filter_or_condition
|
149
|
+
when Filter
|
150
|
+
filters[symbol] = filter_or_condition.to_condition
|
151
|
+
when Hash
|
152
|
+
filters[symbol] = filter_or_condition
|
153
|
+
else
|
154
|
+
m = /(.*?):(\d+)/.match( caller()[0] )
|
155
|
+
call_from = [ m[1], m[2] ].join(":")
|
156
|
+
raise Mongous::Error, "'filter' arguments error. : #{symbol}, #{filter_or_condition} at #{ call_from }"
|
143
157
|
end
|
144
|
-
indexes.push << [keys, opts]
|
145
158
|
end
|
146
159
|
end
|
147
160
|
end
|
data/lib/mongous/filter.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
|
2
2
|
module Mongous
|
3
3
|
module Extention
|
4
|
+
def count
|
5
|
+
# self.collection.find.count
|
6
|
+
self.collection.estimated_document_count
|
7
|
+
end
|
8
|
+
|
4
9
|
def first
|
5
10
|
doc = self.collection.find.first
|
6
11
|
self.new( **doc ) if doc
|
@@ -20,55 +25,53 @@ module Mongous
|
|
20
25
|
self.collection.delete_many({})
|
21
26
|
end
|
22
27
|
|
23
|
-
def
|
24
|
-
|
28
|
+
def where( filter = nil, **conditions )
|
29
|
+
condition = normalize( filter, conditions )
|
30
|
+
Filter.new( self ).where( condition )
|
25
31
|
end
|
26
32
|
|
27
33
|
def not( filter = nil, **conditions )
|
28
34
|
raise Mongous::Error, "Unset args for #{self}.not." if filter.nil? && conditions.empty?
|
29
35
|
|
30
|
-
|
31
|
-
condition
|
32
|
-
when Hash
|
33
|
-
filter
|
34
|
-
when Filter
|
35
|
-
filter.to_condition
|
36
|
-
else
|
37
|
-
raise Mongous::Error, "Invalid args for #{self}.not. : #{filter}"
|
38
|
-
end
|
39
|
-
Filter.new( self ).filter({"$nor" => [condition]})
|
36
|
+
condition = normalize( filter, conditions )
|
37
|
+
Filter.new( self ).where({"$nor" => [condition]})
|
40
38
|
end
|
41
39
|
|
42
40
|
def and( *filters )
|
43
41
|
raise Mongous::Error, "Unset args for #{self}.and." if filters.empty?
|
44
42
|
|
45
43
|
conditions = filters.map do |filter|
|
46
|
-
|
47
|
-
when Hash
|
48
|
-
filter
|
49
|
-
when Filter
|
50
|
-
filter.to_condition
|
51
|
-
else
|
52
|
-
raise Mongous::Error, "Invalid args for #{self}.and. : #{filter}"
|
53
|
-
end
|
44
|
+
normalize( filter, {} )
|
54
45
|
end
|
55
|
-
Filter.new( self ).
|
46
|
+
Filter.new( self ).where({"$and" => conditions})
|
56
47
|
end
|
57
48
|
|
58
49
|
def or( *filters )
|
59
50
|
raise Mongous::Error, "Unset args for #{self}.or." if filters.empty?
|
60
51
|
|
61
52
|
conditions = filters.map do |filter|
|
62
|
-
|
63
|
-
|
64
|
-
|
53
|
+
normalize( filter, {} )
|
54
|
+
end
|
55
|
+
Filter.new( self ).where({"$or" => conditions})
|
56
|
+
end
|
57
|
+
|
58
|
+
def normalize( filter, conditions )
|
59
|
+
condition = case filter
|
60
|
+
when Filter
|
61
|
+
filter.to_condition
|
62
|
+
when Symbol
|
63
|
+
case _filter = filters[filter]
|
65
64
|
when Filter
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
_filter.to_condition
|
66
|
+
when Hash
|
67
|
+
_filter
|
69
68
|
end
|
69
|
+
when NilClass
|
70
|
+
Filter.new( self ).where( **conditions ).to_condition
|
71
|
+
else
|
72
|
+
caller_method = /`(.*?)'/.match( caller()[0] )[1]
|
73
|
+
raise Mongous::Error, "Invalid args for #{self}.#{ caller_method }. : #{filter}, #{conditions}"
|
70
74
|
end
|
71
|
-
Filter.new( self ).filter({"$or" => conditions})
|
72
75
|
end
|
73
76
|
end
|
74
77
|
end
|
@@ -81,7 +84,7 @@ module Mongous
|
|
81
84
|
@option = {}
|
82
85
|
end
|
83
86
|
|
84
|
-
def
|
87
|
+
def where( conditions )
|
85
88
|
hash = {}
|
86
89
|
conditions.each do |key, item|
|
87
90
|
case key
|
@@ -126,56 +129,54 @@ module Mongous
|
|
126
129
|
end
|
127
130
|
|
128
131
|
def option( _option )
|
129
|
-
self.option!( _option )
|
130
|
-
self.dup
|
131
|
-
end
|
132
|
-
|
133
|
-
def option!( _option )
|
134
132
|
@option.merge!( _option )
|
133
|
+
self.dup
|
135
134
|
end
|
136
135
|
|
137
136
|
def projection( _projection )
|
138
|
-
|
137
|
+
@projection = _projection
|
139
138
|
self.dup
|
140
139
|
end
|
141
140
|
alias :select :projection
|
142
141
|
|
143
|
-
def projection!( _projection )
|
144
|
-
@projection = _projection
|
145
|
-
end
|
146
|
-
|
147
142
|
def sort( _sort )
|
148
|
-
|
143
|
+
@sort = _sort
|
149
144
|
self.dup
|
150
145
|
end
|
151
146
|
alias :order :sort
|
152
147
|
|
153
|
-
def
|
154
|
-
|
155
|
-
|
148
|
+
def []( nth_or_range, len = nil )
|
149
|
+
case nth_or_range
|
150
|
+
when Integer
|
151
|
+
@skip = nth_or_range
|
156
152
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
alias :offset :skip
|
153
|
+
if len
|
154
|
+
raise Mongous::Error, "invalid len. : #{ len }" if !len.is_a? Integer || len <= 0
|
155
|
+
@limit = len
|
156
|
+
end
|
162
157
|
|
163
|
-
|
164
|
-
|
165
|
-
|
158
|
+
when Range
|
159
|
+
from = nth_or_range.begin
|
160
|
+
raise Mongous::Error, "invalid range. : #{ nth_or_range }" unless from.is_a? Integer
|
166
161
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
162
|
+
to = nth_or_range.end
|
163
|
+
raise Mongous::Error, "invalid range. : #{ nth_or_range }" unless to.is_a? Integer
|
164
|
+
|
165
|
+
to -= 1 if nth_or_range.exclude_end?
|
166
|
+
@skip = from
|
167
|
+
@limit = to - from + 1
|
168
|
+
|
169
|
+
else
|
170
|
+
raise Mongous::Error, "invalid class. : #{ nth_or_range }"
|
171
|
+
|
172
|
+
end
|
171
173
|
|
172
|
-
|
173
|
-
@limit = _limit
|
174
|
+
self.dup
|
174
175
|
end
|
175
176
|
|
176
177
|
def do_find
|
177
178
|
_filter = @filter
|
178
|
-
_option = @option
|
179
|
+
_option = @option.dup
|
179
180
|
_option[:projection] = @projection if @projection
|
180
181
|
found = @klass.collection.find( _filter, _option )
|
181
182
|
found = found.sort( @sort ) if @sort
|
@@ -184,6 +185,28 @@ module Mongous
|
|
184
185
|
found
|
185
186
|
end
|
186
187
|
|
188
|
+
def count
|
189
|
+
found = @klass.collection.find( @filter )
|
190
|
+
found = found.skip( @skip ) if @skip
|
191
|
+
found = found.limit( @limit ) if @limit
|
192
|
+
_count = found.count_documents
|
193
|
+
if @skip
|
194
|
+
if @skip > _count
|
195
|
+
0
|
196
|
+
elsif @limit
|
197
|
+
[_count - @skip, @limit].min
|
198
|
+
else
|
199
|
+
_count - @skip
|
200
|
+
end
|
201
|
+
else
|
202
|
+
if @limit
|
203
|
+
[_count, @limit].min
|
204
|
+
else
|
205
|
+
_count
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
187
210
|
def first
|
188
211
|
doc = do_find.first
|
189
212
|
@klass.new( **doc ) if doc
|
@@ -200,8 +223,7 @@ module Mongous
|
|
200
223
|
end
|
201
224
|
|
202
225
|
def delete
|
203
|
-
|
204
|
-
@klass.collection.delete_many( _filter )
|
226
|
+
@klass.collection.delete_many( @filter )
|
205
227
|
end
|
206
228
|
end
|
207
229
|
end
|