leanback 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.rdoc +15 -0
- data/README.rdoc +99 -14
- data/VERSION +1 -1
- data/leanback.gemspec +2 -2
- data/lib/leanback.rb +18 -0
- data/test/test_leanback.rb +99 -16
- metadata +4 -4
data/Changelog.rdoc
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
=Leanback 0.2.3
|
2
|
+
July 19, 2011:-
|
3
|
+
* Added better error handling all database operations now raise a CouchdbException when something goes wrong. It's now easy to track exceptions.
|
4
|
+
begin
|
5
|
+
Couchdb.create 'contacts'
|
6
|
+
rescue => e
|
7
|
+
puts "Error message: " + e.to_s
|
8
|
+
puts "Error value: " + e.error
|
9
|
+
end
|
10
|
+
|
11
|
+
# => Error message: CouchDB: Error - file_exists. Reason - The database could not be created, the file already exists.
|
12
|
+
Error value: file_exists
|
13
|
+
|
14
|
+
See README for details
|
15
|
+
|
1
16
|
=Leanback 0.2.2
|
2
17
|
July 13, 2011:-
|
3
18
|
* No need to call add_finder() method directly anymore. find_by() now adds a finder index to the database if one doesn't already exist.
|
data/README.rdoc
CHANGED
@@ -98,10 +98,9 @@ To find all female contacts
|
|
98
98
|
====How it works
|
99
99
|
The method
|
100
100
|
Couchdb.find_by(:database => 'contacts', :email => 'nancy@mail.com')
|
101
|
-
|
102
|
-
It sends a
|
101
|
+
sends a
|
103
102
|
GET http://127.0.0.1:5984/contacts/_design/email_finder/_view/find_by_email?key="nancy@mail.com"
|
104
|
-
This returns all contacts with email = 'nancy@mail.com'. Leanback will parse the native JSON results to return only the data values. If the design_document and view doesn't exist Leanback will create it in the database. See the source
|
103
|
+
This returns all contacts with email = 'nancy@mail.com'. Leanback will parse the native JSON results to return only the data values. If the design_document (_design/email_finder) and the view (find_by_email) doesn't exist, Leanback will create it in the database. See the source for the generated design_document;
|
105
104
|
{
|
106
105
|
"_id": "_design/email_finder",
|
107
106
|
"_rev": "7-da7f3c0bf183f4a36a82013bd0ea6537",
|
@@ -183,20 +182,106 @@ To query the view
|
|
183
182
|
{"Firstname"=>"john", "Lastname"=>"smith", "Email"=>"john@mail.com"}]
|
184
183
|
|
185
184
|
|
186
|
-
===
|
187
|
-
|
188
|
-
|
189
|
-
|
185
|
+
===Create View on the fly if it doesn't already exist
|
186
|
+
Let's say we want to query a view and create it on the fly if it doesn't already exist, and still return the values. In this example we will query a view called get_emails view (which returns emails of all contacts), if this view doesn't already exist it will be added to the database.
|
187
|
+
|
188
|
+
def get_emails
|
189
|
+
begin
|
190
|
+
docs = Couchdb.find(:database => "contacts", :design_doc => 'my_views', :view => 'get_emails')
|
191
|
+
rescue CouchdbException => e
|
192
|
+
doc = { :database => 'contacts', :design_doc => 'my_views', :json_doc => '/path/to/my_views.json' }
|
193
|
+
Couchdb.create_design doc
|
194
|
+
docs = Couchdb.find(:database => "contacts", :design_doc => 'my_views', :view => 'get_emails')
|
195
|
+
end
|
196
|
+
return docs
|
197
|
+
end
|
198
|
+
|
199
|
+
email_list = get_emails()
|
200
|
+
puts email_list.inspect
|
201
|
+
# => [{"Name"=>"Nancy", "Email"=>"nancy@mail.com"}, {"Name"=>"John", "Email"=>"john@mail.com"}]
|
202
|
+
|
203
|
+
In get_emails(),
|
204
|
+
docs = Couchdb.find(:database => "contacts", :design_doc => 'my_views', :view => 'get_emails')
|
205
|
+
sends a request to the design_document (my_views) and view (get_emails). If this view is found in the database, it returns an Array with the name and email of all contacts:
|
206
|
+
[{"Name"=>"Nancy", "Email"=>"nancy@mail.com"}, {"Name"=>"John", "Email"=>"john@mail.com"}]
|
207
|
+
if the view doesn't exist it raises a CouchdbException. It catches this exception
|
208
|
+
rescue CouchdbException => e
|
209
|
+
and then it creates the design_document (my_views) and view (get_emails), since they don't already exist
|
210
|
+
doc = { :database => 'contacts', :design_doc => 'my_views', :json_doc => '/path/to/my_views.json' }
|
211
|
+
Couchdb.create_design doc
|
212
|
+
next it sends a request for the view again.
|
213
|
+
docs = Couchdb.find(:database => "contacts", :design_doc => 'my_views', :view => 'get_emails')
|
214
|
+
Then it returns the email list
|
215
|
+
return docs
|
216
|
+
So the first time the get_emails() method is called, the view will be created on the fly and added to the database.
|
217
|
+
|
218
|
+
Source for the get_emails view:
|
219
|
+
#my_views.json
|
220
|
+
{
|
221
|
+
"language" : "javascript",
|
222
|
+
"views" :{
|
223
|
+
"get_emails" : {
|
224
|
+
"map" : "function(doc){
|
225
|
+
if(doc.firstname && doc.email)
|
226
|
+
emit(doc.id,{Name: doc.firstname, Email: doc.email});
|
227
|
+
}"
|
228
|
+
}
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
190
232
|
|
191
|
-
|
192
|
-
|
193
|
-
# => {"error"=>"not_found", "reason"=>"missing"}
|
233
|
+
===Error handling
|
234
|
+
Every database operation raises a CouchdbException when things go wrong.
|
194
235
|
|
195
|
-
|
236
|
+
Attempting to create a database that already exists
|
237
|
+
begin
|
238
|
+
Couchdb.create 'contacts'
|
239
|
+
rescue CouchdbException => e
|
240
|
+
puts "Error message: " + e.to_s
|
241
|
+
puts "Error value: " + e.error
|
242
|
+
end
|
243
|
+
|
244
|
+
# => Error message: CouchDB: Error - file_exists. Reason - The database could not be created, the file already exists.
|
245
|
+
Error value: file_exists
|
246
|
+
|
247
|
+
|
248
|
+
Attempting to delete a database that doesn't exist
|
249
|
+
begin
|
250
|
+
Couchdb.delete 'buildings'
|
251
|
+
rescue CouchdbException => e
|
252
|
+
puts "Error message: " + e.to_s
|
253
|
+
puts "Error value: " + e.error
|
254
|
+
end
|
255
|
+
|
256
|
+
# => Error message: CouchDB: Error - not_found. Reason - missing
|
257
|
+
Error value: not_found
|
258
|
+
|
259
|
+
Attempting to query a permanent view that doesn't exist
|
260
|
+
begin
|
261
|
+
view = { :database => "contacts", :design_doc => 'more_views', :view => 'get_user_email'}
|
262
|
+
Couchdb.find view
|
263
|
+
rescue CouchdbException => e
|
264
|
+
puts "Error message: " + e.to_s
|
265
|
+
puts "Error value: " + e.error
|
266
|
+
end
|
267
|
+
|
268
|
+
# => Error message: CouchDB: Error - not_found. Reason - missing_named_view
|
269
|
+
Error value: not_found
|
270
|
+
|
271
|
+
You can always check the information passed to the Exception. See example below:
|
272
|
+
begin
|
273
|
+
view = { :database => "contacts", :design_doc => 'more_views', :view => 'get_user_email'}
|
274
|
+
Couchdb.find view
|
275
|
+
rescue CouchdbException => e
|
276
|
+
if e.error == "not_found"
|
277
|
+
doc = { :database => 'contacts', :design_doc => 'more_views', :json_doc => '/path/to/user_email.json' }
|
278
|
+
Couchdb.create_design doc
|
279
|
+
docs = Couchdb.find(:database => "contacts", :design_doc => 'more_views', :view => 'get_user_email')
|
280
|
+
end
|
281
|
+
end
|
196
282
|
|
197
|
-
|
198
|
-
|
199
|
-
puts hash.inspect
|
283
|
+
In the code above, the rescue block will create and request the permanent view if it's not found by the initial request outside the block. e.error is the value of the error returned by CouchDB.
|
284
|
+
|
200
285
|
|
201
286
|
===Bind Address
|
202
287
|
Leanback uses the default Couchdb bind address http://127.0.0.1:5984. To use a different bind address;
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.3
|
data/leanback.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{leanback}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Obi Akubue"]
|
12
|
-
s.date = %q{2011-07-
|
12
|
+
s.date = %q{2011-07-19}
|
13
13
|
s.description = %q{lightweight Ruby interface to CouchDB}
|
14
14
|
s.email = %q{obioraakubue@yahoo.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/leanback.rb
CHANGED
@@ -2,6 +2,14 @@ require 'rest_client'
|
|
2
2
|
require 'yajl'
|
3
3
|
require 'erb'
|
4
4
|
|
5
|
+
class CouchdbException < RuntimeError
|
6
|
+
attr :error
|
7
|
+
def initialize(error)
|
8
|
+
@error = error.values[0]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
|
5
13
|
module Document
|
6
14
|
|
7
15
|
#create a document
|
@@ -16,6 +24,7 @@ module Document
|
|
16
24
|
hash = Yajl::Parser.parse(response.to_str)
|
17
25
|
rescue => e
|
18
26
|
hash = Yajl::Parser.parse(e.response.to_s)
|
27
|
+
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
19
28
|
end
|
20
29
|
end
|
21
30
|
|
@@ -31,6 +40,7 @@ module Document
|
|
31
40
|
hash = Yajl::Parser.parse(response.to_str)
|
32
41
|
rescue => e
|
33
42
|
hash = Yajl::Parser.parse(e.response.to_s)
|
43
|
+
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
34
44
|
end
|
35
45
|
end
|
36
46
|
|
@@ -45,6 +55,7 @@ module Document
|
|
45
55
|
hash = Yajl::Parser.parse(response.to_str)
|
46
56
|
rescue => e
|
47
57
|
hash = Yajl::Parser.parse(e.response.to_s)
|
58
|
+
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
48
59
|
end
|
49
60
|
end
|
50
61
|
|
@@ -69,6 +80,7 @@ module Couchdb
|
|
69
80
|
hash = Yajl::Parser.parse(response.to_str)
|
70
81
|
rescue => e
|
71
82
|
hash = Yajl::Parser.parse(e.response.to_s)
|
83
|
+
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
72
84
|
end
|
73
85
|
end
|
74
86
|
|
@@ -80,6 +92,7 @@ module Couchdb
|
|
80
92
|
hash = Yajl::Parser.parse(response.to_str)
|
81
93
|
rescue => e
|
82
94
|
hash = Yajl::Parser.parse(e.response.to_s)
|
95
|
+
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
83
96
|
end
|
84
97
|
end
|
85
98
|
|
@@ -104,6 +117,7 @@ def self.view(doc)
|
|
104
117
|
hash = Yajl::Parser.parse(response.to_str)
|
105
118
|
rescue => e
|
106
119
|
hash = Yajl::Parser.parse(e.response.to_s)
|
120
|
+
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
107
121
|
end
|
108
122
|
end
|
109
123
|
|
@@ -130,6 +144,7 @@ def self.find(doc,key=nil)
|
|
130
144
|
rescue => e
|
131
145
|
#puts e.inspect
|
132
146
|
hash = Yajl::Parser.parse(e.response.to_s)
|
147
|
+
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
133
148
|
end
|
134
149
|
end
|
135
150
|
|
@@ -154,6 +169,7 @@ def self.create_design(doc)
|
|
154
169
|
hash = Yajl::Parser.parse(response.to_str)
|
155
170
|
rescue => e
|
156
171
|
hash = Yajl::Parser.parse(e.response.to_s)
|
172
|
+
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
157
173
|
end
|
158
174
|
end
|
159
175
|
|
@@ -181,6 +197,7 @@ def self.add_finder(options)
|
|
181
197
|
response = RestClient.put 'http://' + @address + ':' + @port + '/' + db_name + '/_design/' + design_doc_name, view, {:content_type => :json, :accept => :json}
|
182
198
|
rescue => e
|
183
199
|
hash = Yajl::Parser.parse(e.response.to_s)
|
200
|
+
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
184
201
|
end
|
185
202
|
end
|
186
203
|
|
@@ -222,6 +239,7 @@ def self.docs_from(database_name)
|
|
222
239
|
return rows
|
223
240
|
rescue => e
|
224
241
|
hash = Yajl::Parser.parse(e.response.to_s)
|
242
|
+
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
225
243
|
end
|
226
244
|
end
|
227
245
|
|
data/test/test_leanback.rb
CHANGED
@@ -13,47 +13,90 @@ class TestLeanback < Test::Unit::TestCase
|
|
13
13
|
#puts hash.inspect
|
14
14
|
end
|
15
15
|
|
16
|
-
should "create a database if it doesn't already exist" do
|
17
|
-
|
18
|
-
|
16
|
+
should "create a database if it doesn't already exist, and handle exception if it exists" do
|
17
|
+
begin
|
18
|
+
hash = Couchdb.create 'contacts'
|
19
|
+
#puts hash.inspect
|
20
|
+
rescue => e
|
21
|
+
#puts "Error message: " + e.to_s
|
22
|
+
#puts "Error value: " + e.error
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
|
-
should "
|
26
|
+
should "delete a database that doesn't exist and handle the exception" do
|
27
|
+
begin
|
28
|
+
hash = Couchdb.delete 'buildings'
|
29
|
+
#puts hash.inspect
|
30
|
+
rescue CouchdbException => e
|
31
|
+
#puts "Error message: " + e.to_s
|
32
|
+
#puts "Error value: " + e.error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
should "add a finder method to the database or handle exception if a finder already exists" do
|
37
|
+
begin
|
22
38
|
hash = Couchdb.add_finder(:database => 'contacts', :key => 'email')
|
23
39
|
#puts hash.inspect
|
40
|
+
rescue CouchdbException => e
|
41
|
+
#puts e.to_s
|
42
|
+
#puts e.error
|
43
|
+
end
|
24
44
|
end
|
25
45
|
|
26
46
|
should "find items by key" do
|
27
47
|
docs = Couchdb.find_by( :database => 'contacts', :email => 'nancy@mail.com')
|
28
48
|
#docs = Couchdb.find_by( :database => 'contacts', :lastname => 'Smith')
|
29
49
|
#docs = Couchdb.find_by( :database => 'contacts', :gender => 'female')
|
30
|
-
puts docs.inspect
|
50
|
+
#puts docs.inspect
|
31
51
|
end
|
32
52
|
|
33
|
-
should "view document doc" do
|
34
|
-
|
53
|
+
should "view document doc or handle exception" do
|
54
|
+
|
35
55
|
doc = {:database => 'monitors', :doc_id => '3-d71c8ee21d6753896f2d08f57a985e94'}
|
56
|
+
begin
|
36
57
|
hash = Couchdb.view doc
|
37
58
|
#puts hash.inspect
|
59
|
+
rescue CouchdbException => e
|
60
|
+
#puts e.inspect
|
61
|
+
#puts e.error
|
62
|
+
end
|
38
63
|
end
|
39
64
|
|
65
|
+
should "Query a permanent view that doesn't exist and handle exception" do
|
66
|
+
begin
|
67
|
+
#puts 'viewing design doc...'
|
68
|
+
view = { :database => "contacts", :design_doc => 'more_views', :view => 'get_user_email'}
|
69
|
+
hash = Couchdb.find view
|
70
|
+
#puts hash.inspect
|
71
|
+
rescue CouchdbException => e
|
72
|
+
puts "Error message: " + e.to_s
|
73
|
+
puts "Error value: " + e.error
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
40
78
|
should "Query a permanent view" do
|
41
79
|
view = { :database => "contacts", :design_doc => 'more_views', :view => 'get_email'}
|
42
|
-
puts 'viewing design doc...'
|
80
|
+
#puts 'viewing design doc...'
|
43
81
|
hash = Couchdb.find view
|
44
82
|
#puts hash.inspect
|
45
83
|
end
|
46
84
|
|
47
|
-
should "Create a design doc/permanent view" do
|
85
|
+
should "Create a design doc/permanent view or handle exception" do
|
48
86
|
doc = { :database => 'contacts', :design_doc => 'more_views', :json_doc => '/home/obi/bin/leanback/test/my_views.json' }
|
87
|
+
begin
|
49
88
|
hash = Couchdb.create_design doc
|
50
89
|
#puts hash.inspect
|
90
|
+
rescue CouchdbException => e
|
91
|
+
#puts e.to_s
|
92
|
+
#puts e.error
|
93
|
+
end
|
51
94
|
end
|
52
95
|
|
53
96
|
should "return a display a list of all databases" do
|
54
97
|
databases = Couchdb.all
|
55
98
|
databases.each do |db_name|
|
56
|
-
|
99
|
+
# puts db_name
|
57
100
|
end
|
58
101
|
end
|
59
102
|
|
@@ -62,29 +105,55 @@ class TestLeanback < Test::Unit::TestCase
|
|
62
105
|
#puts hash.inspect
|
63
106
|
end
|
64
107
|
|
65
|
-
should "create a document" do
|
108
|
+
should "create a document and handle exception if one occurs" do
|
109
|
+
begin
|
66
110
|
data = {:firstname => 'Nancy', :lastname =>'Lee', :phone => '347-808-3734',:email =>'nancy@mail.com',:gender => 'female'}
|
67
111
|
doc = {:database => 'contacts', :doc_id => 'Nancy', :data => data}
|
68
112
|
hash = Document.create doc
|
69
113
|
#puts hash.inspect
|
114
|
+
rescue CouchdbException => e
|
115
|
+
#puts e.to_s
|
116
|
+
#puts e.error
|
117
|
+
end
|
70
118
|
end
|
71
119
|
|
72
|
-
should "edit a document" do
|
120
|
+
should "edit a document - handle exceptions" do
|
121
|
+
begin
|
73
122
|
data = {:firstname => 'john', :lastname =>'smith', :email => 'john@mail.com',:gender=>'male', :_rev=>'2-e813a0e902e3ac114400ff3959a2adde'}
|
74
123
|
doc = {:database => 'contacts', :doc_id => 'john', :data => data}
|
75
124
|
hash = Document.edit doc
|
76
|
-
#puts hash.inspect
|
125
|
+
#puts hash.inspect
|
126
|
+
rescue CouchdbException => e
|
127
|
+
#puts e.to_s
|
128
|
+
#puts e.error
|
129
|
+
end
|
77
130
|
end
|
78
131
|
|
79
|
-
should "delete a document" do
|
132
|
+
should "delete a document - handle exceptions" do
|
133
|
+
begin
|
80
134
|
doc = {:database => 'contacts', :doc_id => 'john', :rev => '3-be02e80490f8e9e610d9a9e33d752316'}
|
81
135
|
hash = Document.delete doc
|
82
136
|
#puts hash.inspect
|
137
|
+
rescue CouchdbException => e
|
138
|
+
#puts e.to_s
|
139
|
+
#puts e.error
|
140
|
+
end
|
83
141
|
end
|
84
142
|
|
143
|
+
should "display all documents in the database that doesn't exist and handle exception" do
|
144
|
+
begin
|
145
|
+
docs = Couchdb.docs_from 'buildings'
|
146
|
+
rescue CouchdbException => e
|
147
|
+
#puts e.to_s
|
148
|
+
#puts e.error
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
|
85
154
|
should "display all documents in the database" do
|
86
155
|
docs = Couchdb.docs_from 'monitors'
|
87
|
-
puts 'docs = Couchdb.docs_from monitors'
|
156
|
+
#puts 'docs = Couchdb.docs_from monitors'
|
88
157
|
docs.each do |d|
|
89
158
|
# puts "_rev: " + d["_rev"]
|
90
159
|
#puts "_id: " + d["_id"]
|
@@ -98,10 +167,24 @@ class TestLeanback < Test::Unit::TestCase
|
|
98
167
|
end
|
99
168
|
end
|
100
169
|
|
170
|
+
should "create view on the fly if it doesn't already exist" do
|
171
|
+
begin
|
172
|
+
docs = Couchdb.find(:database => "contacts", :design_doc => 'x_my_views', :view => 'get_emails')
|
173
|
+
rescue CouchdbException => e
|
174
|
+
#puts e.to_s
|
175
|
+
doc = { :database => 'contacts', :design_doc => 'x_my_views', :json_doc => '/home/obi/bin/my_views.json' }
|
176
|
+
#doc = { :database => 'contacts', :design_doc => 'my_views', :json_doc => '/path/to/my_views.json' }
|
177
|
+
Couchdb.create_design doc
|
178
|
+
docs = Couchdb.find(:database => "contacts", :design_doc => 'my_views', :view => 'get_emails')
|
179
|
+
end
|
180
|
+
#puts docs.inspect
|
181
|
+
end
|
182
|
+
|
183
|
+
|
101
184
|
should " switch to default bind address" do
|
102
185
|
Couchdb.address = nil
|
103
186
|
Couchdb.port = nil
|
104
|
-
Couchdb.all
|
187
|
+
#Couchdb.all
|
105
188
|
end
|
106
189
|
|
107
190
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 3
|
9
|
+
version: 0.2.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Obi Akubue
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-07-
|
17
|
+
date: 2011-07-19 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -136,7 +136,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
136
136
|
requirements:
|
137
137
|
- - ">="
|
138
138
|
- !ruby/object:Gem::Version
|
139
|
-
hash:
|
139
|
+
hash: 143649905
|
140
140
|
segments:
|
141
141
|
- 0
|
142
142
|
version: "0"
|