couchrest_model 1.1.2 → 1.2.0.beta
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/README.md +8 -2
- data/VERSION +1 -1
- data/couchrest_model.gemspec +2 -1
- data/history.md +8 -0
- data/lib/couchrest/model/base.rb +0 -20
- data/lib/couchrest/model/configuration.rb +2 -0
- data/lib/couchrest/model/core_extensions/time_parsing.rb +35 -9
- data/lib/couchrest/model/designs/design.rb +182 -0
- data/lib/couchrest/model/designs/view.rb +91 -48
- data/lib/couchrest/model/designs.rb +72 -19
- data/lib/couchrest/model/document_queries.rb +15 -45
- data/lib/couchrest/model/properties.rb +43 -2
- data/lib/couchrest/model/proxyable.rb +20 -54
- data/lib/couchrest/model/typecast.rb +1 -1
- data/lib/couchrest/model/validations/uniqueness.rb +7 -6
- data/lib/couchrest_model.rb +1 -5
- data/spec/fixtures/models/article.rb +22 -20
- data/spec/fixtures/models/base.rb +15 -7
- data/spec/fixtures/models/course.rb +7 -4
- data/spec/fixtures/models/project.rb +4 -1
- data/spec/fixtures/models/sale_entry.rb +5 -3
- data/spec/unit/base_spec.rb +51 -5
- data/spec/unit/core_extensions/time_parsing.rb +41 -0
- data/spec/unit/designs/design_spec.rb +291 -0
- data/spec/unit/designs/view_spec.rb +135 -40
- data/spec/unit/designs_spec.rb +341 -30
- data/spec/unit/dirty_spec.rb +67 -0
- data/spec/unit/inherited_spec.rb +2 -2
- data/spec/unit/property_protection_spec.rb +3 -1
- data/spec/unit/property_spec.rb +43 -3
- data/spec/unit/proxyable_spec.rb +57 -98
- data/spec/unit/subclass_spec.rb +14 -5
- data/spec/unit/validations_spec.rb +14 -12
- metadata +172 -129
- data/lib/couchrest/model/class_proxy.rb +0 -135
- data/lib/couchrest/model/collection.rb +0 -273
- data/lib/couchrest/model/design_doc.rb +0 -115
- data/lib/couchrest/model/support/couchrest_design.rb +0 -33
- data/lib/couchrest/model/views.rb +0 -148
- data/spec/unit/class_proxy_spec.rb +0 -167
- data/spec/unit/collection_spec.rb +0 -86
- data/spec/unit/design_doc_spec.rb +0 -212
- data/spec/unit/view_spec.rb +0 -352
@@ -1,167 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
class UnattachedDoc < CouchRest::Model::Base
|
4
|
-
# Note: no use_database here
|
5
|
-
property :title
|
6
|
-
property :questions
|
7
|
-
property :professor
|
8
|
-
view_by :title
|
9
|
-
end
|
10
|
-
|
11
|
-
|
12
|
-
describe "Proxy Class" do
|
13
|
-
|
14
|
-
before(:all) do
|
15
|
-
reset_test_db!
|
16
|
-
# setup the class default doc to save the design doc
|
17
|
-
UnattachedDoc.use_database nil # just to be sure it is really unattached
|
18
|
-
@us = UnattachedDoc.on(DB)
|
19
|
-
%w{aaa bbb ddd eee}.each do |title|
|
20
|
-
u = @us.new(:title => title)
|
21
|
-
u.save
|
22
|
-
@first_id ||= u.id
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should query all" do
|
27
|
-
rs = @us.all
|
28
|
-
rs.length.should == 4
|
29
|
-
end
|
30
|
-
it "should count" do
|
31
|
-
@us.count.should == 4
|
32
|
-
end
|
33
|
-
it "should make the design doc upon first query" do
|
34
|
-
@us.by_title
|
35
|
-
doc = @us.design_doc
|
36
|
-
doc['views']['all']['map'].should include('UnattachedDoc')
|
37
|
-
end
|
38
|
-
it "should merge query params" do
|
39
|
-
rs = @us.by_title :startkey=>"bbb", :endkey=>"eee"
|
40
|
-
rs.length.should == 3
|
41
|
-
end
|
42
|
-
it "should query via view" do
|
43
|
-
view = @us.view :by_title
|
44
|
-
designed = @us.by_title
|
45
|
-
view.should == designed
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should query via first_from_view" do
|
49
|
-
UnattachedDoc.should_receive(:first_from_view).with('by_title', 'bbb', {:database => DB})
|
50
|
-
@us.first_from_view('by_title', 'bbb')
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should query via first_from_view with complex options" do
|
54
|
-
UnattachedDoc.should_receive(:first_from_view).with('by_title', {:key => 'bbb', :database => DB})
|
55
|
-
@us.first_from_view('by_title', :key => 'bbb')
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should query via first_from_view with complex extra options" do
|
59
|
-
UnattachedDoc.should_receive(:first_from_view).with('by_title', 'bbb', {:limit => 1, :database => DB})
|
60
|
-
@us.first_from_view('by_title', 'bbb', :limit => 1)
|
61
|
-
end
|
62
|
-
|
63
|
-
it "should allow dynamic view matching for single elements" do
|
64
|
-
@us.should_receive(:first_from_view).with('by_title', 'bbb')
|
65
|
-
@us.find_by_title('bbb')
|
66
|
-
end
|
67
|
-
|
68
|
-
it "should yield" do
|
69
|
-
things = []
|
70
|
-
@us.view(:by_title) do |thing|
|
71
|
-
things << thing
|
72
|
-
end
|
73
|
-
things[0]["doc"]["title"].should =='aaa'
|
74
|
-
end
|
75
|
-
it "should yield with by_key method" do
|
76
|
-
things = []
|
77
|
-
@us.by_title do |thing|
|
78
|
-
things << thing
|
79
|
-
end
|
80
|
-
things[0]["doc"]["title"].should =='aaa'
|
81
|
-
end
|
82
|
-
it "should get from specific database" do
|
83
|
-
u = @us.get(@first_id)
|
84
|
-
u.title.should == "aaa"
|
85
|
-
end
|
86
|
-
it "should get first" do
|
87
|
-
u = @us.first
|
88
|
-
u.should == @us.all.first
|
89
|
-
end
|
90
|
-
|
91
|
-
it "should get last" do
|
92
|
-
u = @us.last
|
93
|
-
u.should == @us.all.last
|
94
|
-
end
|
95
|
-
|
96
|
-
it "should set database on first retreived document" do
|
97
|
-
u = @us.first
|
98
|
-
u.database.should === DB
|
99
|
-
end
|
100
|
-
it "should set database on all retreived documents" do
|
101
|
-
@us.all.each do |u|
|
102
|
-
u.database.should === DB
|
103
|
-
end
|
104
|
-
end
|
105
|
-
it "should set database on each retreived document" do
|
106
|
-
rs = @us.by_title :startkey=>"bbb", :endkey=>"eee"
|
107
|
-
rs.length.should == 3
|
108
|
-
rs.each do |u|
|
109
|
-
u.database.should === DB
|
110
|
-
end
|
111
|
-
end
|
112
|
-
it "should set database on document retreived by id" do
|
113
|
-
u = @us.get(@first_id)
|
114
|
-
u.database.should === DB
|
115
|
-
end
|
116
|
-
it "should not attempt to set database on raw results using :all" do
|
117
|
-
@us.all(:raw => true).each do |u|
|
118
|
-
u.respond_to?(:database).should be_false
|
119
|
-
end
|
120
|
-
end
|
121
|
-
it "should not attempt to set database on raw results using view" do
|
122
|
-
@us.by_title(:raw => true).each do |u|
|
123
|
-
u.respond_to?(:database).should be_false
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
describe "#get!" do
|
128
|
-
it "raises exception when passed a nil" do
|
129
|
-
expect { @us.get!(nil)}.to raise_error(CouchRest::Model::DocumentNotFound)
|
130
|
-
end
|
131
|
-
|
132
|
-
it "raises exception when passed an empty string " do
|
133
|
-
expect { @us.get!("")}.to raise_error(CouchRest::Model::DocumentNotFound)
|
134
|
-
end
|
135
|
-
|
136
|
-
it "raises exception when document with provided id does not exist" do
|
137
|
-
expect { @us.get!("thisisnotreallyadocumentid")}.to raise_error(CouchRest::Model::DocumentNotFound)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
describe "#find!" do
|
142
|
-
it "raises exception when passed a nil" do
|
143
|
-
expect { @us.find!(nil)}.to raise_error(CouchRest::Model::DocumentNotFound)
|
144
|
-
end
|
145
|
-
|
146
|
-
it "raises exception when passed an empty string " do
|
147
|
-
expect { @us.find!("")}.to raise_error(CouchRest::Model::DocumentNotFound)
|
148
|
-
end
|
149
|
-
|
150
|
-
it "raises exception when document with provided id does not exist" do
|
151
|
-
expect { @us.find!("thisisnotreallyadocumentid")}.to raise_error(CouchRest::Model::DocumentNotFound)
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
# Sam Lown 2010-04-07
|
156
|
-
# Removed as unclear why this should happen as before my changes
|
157
|
-
# this happend by accident, not explicitly.
|
158
|
-
# If requested, this feature should be added as a specific method.
|
159
|
-
#
|
160
|
-
#it "should clean up design docs left around on specific database" do
|
161
|
-
# @us.by_title
|
162
|
-
# original_id = @us.model_design_doc['_rev']
|
163
|
-
# Unattached.view_by :professor
|
164
|
-
# @us.by_professor
|
165
|
-
# @us.model_design_doc['_rev'].should_not == original_id
|
166
|
-
#end
|
167
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe "Collections" do
|
4
|
-
|
5
|
-
before(:all) do
|
6
|
-
reset_test_db!
|
7
|
-
titles = ["very uniq one", "really interesting", "some fun",
|
8
|
-
"really awesome", "crazy bob", "this rocks", "super rad"]
|
9
|
-
titles.each_with_index do |title,i|
|
10
|
-
a = Article.new(:title => title, :date => Date.today)
|
11
|
-
a.save
|
12
|
-
end
|
13
|
-
|
14
|
-
titles = ["yesterday very uniq one", "yesterday really interesting", "yesterday some fun",
|
15
|
-
"yesterday really awesome", "yesterday crazy bob", "yesterday this rocks"]
|
16
|
-
titles.each_with_index do |title,i|
|
17
|
-
a = Article.new(:title => title, :date => Date.today - 1)
|
18
|
-
a.save
|
19
|
-
end
|
20
|
-
end
|
21
|
-
it "should return a proxy that looks like an array of 7 Article objects" do
|
22
|
-
articles = Article.collection_proxy_for('Article', 'by_date', :descending => true,
|
23
|
-
:key => Date.today, :include_docs => true)
|
24
|
-
articles.class.should == Array
|
25
|
-
articles.size.should == 7
|
26
|
-
end
|
27
|
-
it "should provide a class method for paginate" do
|
28
|
-
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
29
|
-
:per_page => 3, :descending => true, :key => Date.today)
|
30
|
-
articles.size.should == 3
|
31
|
-
|
32
|
-
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
33
|
-
:per_page => 3, :page => 2, :descending => true, :key => Date.today)
|
34
|
-
articles.size.should == 3
|
35
|
-
|
36
|
-
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
37
|
-
:per_page => 3, :page => 3, :descending => true, :key => Date.today)
|
38
|
-
articles.size.should == 1
|
39
|
-
end
|
40
|
-
it "should provide a class method for paginated_each" do
|
41
|
-
options = { :design_doc => 'Article', :view_name => 'by_date',
|
42
|
-
:per_page => 3, :page => 1, :descending => true, :key => Date.today }
|
43
|
-
Article.paginated_each(options) do |a|
|
44
|
-
a.should_not be_nil
|
45
|
-
end
|
46
|
-
end
|
47
|
-
it "should provide a class method to get a collection for a view" do
|
48
|
-
articles = Article.find_all_article_details(:key => Date.today)
|
49
|
-
articles.class.should == Array
|
50
|
-
articles.size.should == 7
|
51
|
-
end
|
52
|
-
it "should get a subset of articles using paginate" do
|
53
|
-
articles = Article.collection_proxy_for('Article', 'by_date', :key => Date.today, :include_docs => true)
|
54
|
-
articles.paginate(:page => 1, :per_page => 3).size.should == 3
|
55
|
-
articles.paginate(:page => 2, :per_page => 3).size.should == 3
|
56
|
-
articles.paginate(:page => 3, :per_page => 3).size.should == 1
|
57
|
-
end
|
58
|
-
it "should get all articles, a few at a time, using paginated each" do
|
59
|
-
articles = Article.collection_proxy_for('Article', 'by_date', :key => Date.today, :include_docs => true)
|
60
|
-
articles.paginated_each(:per_page => 3) do |a|
|
61
|
-
a.should_not be_nil
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should raise an exception if design_doc is not provided" do
|
66
|
-
lambda{Article.collection_proxy_for(nil, 'by_date')}.should raise_error
|
67
|
-
lambda{Article.paginate(:view_name => 'by_date')}.should raise_error
|
68
|
-
end
|
69
|
-
it "should raise an exception if view_name is not provided" do
|
70
|
-
lambda{Article.collection_proxy_for('Article', nil)}.should raise_error
|
71
|
-
lambda{Article.paginate(:design_doc => 'Article')}.should raise_error
|
72
|
-
end
|
73
|
-
it "should be able to span multiple keys" do
|
74
|
-
articles = Article.collection_proxy_for('Article', 'by_date', :startkey => Date.today - 1, :endkey => Date.today, :include_docs => true)
|
75
|
-
articles.paginate(:page => 1, :per_page => 3).size.should == 3
|
76
|
-
articles.paginate(:page => 3, :per_page => 3).size.should == 3
|
77
|
-
articles.paginate(:page => 5, :per_page => 3).size.should == 1
|
78
|
-
end
|
79
|
-
it "should pass database parameter to pager" do
|
80
|
-
proxy = mock(:proxy)
|
81
|
-
proxy.stub!(:paginate)
|
82
|
-
::CouchRest::Model::Collection::CollectionProxy.should_receive(:new).with('database', anything(), anything(), anything(), anything()).and_return(proxy)
|
83
|
-
Article.paginate(:design_doc => 'Article', :view_name => 'by_date', :database => 'database')
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
@@ -1,212 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe CouchRest::Model::DesignDoc do
|
5
|
-
|
6
|
-
before :all do
|
7
|
-
reset_test_db!
|
8
|
-
end
|
9
|
-
|
10
|
-
describe "CouchRest Extension" do
|
11
|
-
|
12
|
-
it "should have created a checksum! method" do
|
13
|
-
::CouchRest::Design.new.should respond_to(:checksum!)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should calculate a consistent checksum for model" do
|
17
|
-
WithTemplateAndUniqueID.design_doc.checksum!.should eql('caa2b4c27abb82b4e37421de76d96ffc')
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should calculate checksum for complex model" do
|
21
|
-
Article.design_doc.checksum!.should eql('70dff8caea143bf40fad09adf0701104')
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should cache the generated checksum value" do
|
25
|
-
Article.design_doc.checksum!
|
26
|
-
Article.design_doc['couchrest-hash'].should_not be_blank
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "class methods" do
|
31
|
-
|
32
|
-
describe ".design_doc" do
|
33
|
-
it "should provide Design document" do
|
34
|
-
Article.design_doc.should be_a(::CouchRest::Design)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe ".design_doc_id" do
|
39
|
-
it "should provide a reasonable id" do
|
40
|
-
Article.design_doc_id.should eql("_design/Article")
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
describe ".design_doc_slug" do
|
45
|
-
it "should provide slug part of design doc" do
|
46
|
-
Article.design_doc_slug.should eql('Article')
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe ".design_doc_uri" do
|
51
|
-
it "should provide complete url" do
|
52
|
-
Article.design_doc_uri.should eql("#{COUCHHOST}/#{TESTDB}/_design/Article")
|
53
|
-
end
|
54
|
-
it "should provide complete url for new DB" do
|
55
|
-
db = mock("Database")
|
56
|
-
db.should_receive(:root).and_return('db')
|
57
|
-
Article.design_doc_uri(db).should eql("db/_design/Article")
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
describe ".stored_design_doc" do
|
62
|
-
it "should load a stored design from the database" do
|
63
|
-
Article.by_date
|
64
|
-
Article.stored_design_doc['_rev'].should_not be_blank
|
65
|
-
end
|
66
|
-
it "should return nil if not already stored" do
|
67
|
-
WithDefaultValues.stored_design_doc.should be_nil
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
describe ".save_design_doc" do
|
72
|
-
it "should call up the design updater" do
|
73
|
-
Article.should_receive(:update_design_doc).with('db', false)
|
74
|
-
Article.save_design_doc('db')
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
describe ".save_design_doc!" do
|
79
|
-
it "should call save_design_doc with force" do
|
80
|
-
Article.should_receive(:save_design_doc).with('db', true)
|
81
|
-
Article.save_design_doc!('db')
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
describe "basics" do
|
88
|
-
|
89
|
-
before :all do
|
90
|
-
reset_test_db!
|
91
|
-
end
|
92
|
-
|
93
|
-
it "should have been instantiated with views" do
|
94
|
-
d = Article.design_doc
|
95
|
-
d['views']['all']['map'].should include('Article')
|
96
|
-
end
|
97
|
-
|
98
|
-
it "should not have been saved yet" do
|
99
|
-
lambda { Article.database.get(Article.design_doc.id) }.should raise_error(RestClient::ResourceNotFound)
|
100
|
-
end
|
101
|
-
|
102
|
-
describe "after requesting a view" do
|
103
|
-
before :each do
|
104
|
-
Article.all
|
105
|
-
end
|
106
|
-
it "should have saved the design doc after view request" do
|
107
|
-
Article.database.get(Article.design_doc.id).should_not be_nil
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
describe "model with simple views" do
|
112
|
-
before(:all) do
|
113
|
-
Article.all.map{|a| a.destroy(true)}
|
114
|
-
Article.database.bulk_delete
|
115
|
-
written_at = Time.now - 24 * 3600 * 7
|
116
|
-
@titles = ["this and that", "also interesting", "more fun", "some junk"]
|
117
|
-
@titles.each do |title|
|
118
|
-
a = Article.new(:title => title)
|
119
|
-
a.date = written_at
|
120
|
-
a.save
|
121
|
-
written_at += 24 * 3600
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
it "will send request for the saved design doc on view request" do
|
126
|
-
reset_test_db!
|
127
|
-
Article.should_receive(:stored_design_doc).and_return(nil)
|
128
|
-
Article.by_date
|
129
|
-
end
|
130
|
-
|
131
|
-
it "should have generated a design doc" do
|
132
|
-
Article.design_doc["views"]["by_date"].should_not be_nil
|
133
|
-
end
|
134
|
-
it "should save the design doc when view requested" do
|
135
|
-
Article.by_date
|
136
|
-
doc = Article.database.get Article.design_doc.id
|
137
|
-
doc['views']['by_date'].should_not be_nil
|
138
|
-
end
|
139
|
-
it "should save design doc if a view changed" do
|
140
|
-
Article.by_date
|
141
|
-
orig = Article.stored_design_doc
|
142
|
-
design = Article.design_doc
|
143
|
-
view = design['views']['by_date']['map']
|
144
|
-
design['views']['by_date']['map'] = view + ' ' # little bit of white space
|
145
|
-
Article.by_date
|
146
|
-
Article.stored_design_doc['_rev'].should_not eql(orig['_rev'])
|
147
|
-
orig['views']['by_date']['map'].should_not eql(Article.design_doc['views']['by_date']['map'])
|
148
|
-
end
|
149
|
-
it "should not save design doc if not changed" do
|
150
|
-
Article.by_date
|
151
|
-
orig = Article.stored_design_doc['_rev']
|
152
|
-
Article.by_date
|
153
|
-
Article.stored_design_doc['_rev'].should eql(orig)
|
154
|
-
end
|
155
|
-
it "should recreate the design doc if database deleted" do
|
156
|
-
Article.database.recreate!
|
157
|
-
lambda { Article.by_date }.should_not raise_error(RestClient::ResourceNotFound)
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
describe "when auto_update_design_doc false" do
|
162
|
-
|
163
|
-
before :all do
|
164
|
-
Article.auto_update_design_doc = false
|
165
|
-
Article.save_design_doc!
|
166
|
-
end
|
167
|
-
|
168
|
-
after :all do
|
169
|
-
Article.auto_update_design_doc = true
|
170
|
-
end
|
171
|
-
|
172
|
-
it "will not send a request for the saved design doc" do
|
173
|
-
Article.should_not_receive(:stored_design_doc)
|
174
|
-
Article.by_date
|
175
|
-
end
|
176
|
-
|
177
|
-
it "will not update stored design doc if view changed" do
|
178
|
-
Article.by_date
|
179
|
-
orig = Article.stored_design_doc
|
180
|
-
design = Article.design_doc
|
181
|
-
view = design['views']['by_date']['map']
|
182
|
-
design['views']['by_date']['map'] = view + ' '
|
183
|
-
Article.by_date
|
184
|
-
Article.stored_design_doc['_rev'].should eql(orig['_rev'])
|
185
|
-
end
|
186
|
-
|
187
|
-
it "will update stored design if forced" do
|
188
|
-
Article.by_date
|
189
|
-
orig = Article.stored_design_doc
|
190
|
-
design = Article.design_doc
|
191
|
-
view = design['views']['by_date']['map']
|
192
|
-
design['views']['by_date']['map'] = view + ' '
|
193
|
-
Article.save_design_doc!
|
194
|
-
Article.stored_design_doc['_rev'].should_not eql(orig['_rev'])
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
describe "lazily refreshing the design document" do
|
200
|
-
before(:all) do
|
201
|
-
@db = reset_test_db!
|
202
|
-
WithTemplateAndUniqueID.new('slug' => '1').save
|
203
|
-
end
|
204
|
-
it "should not save the design doc twice" do
|
205
|
-
WithTemplateAndUniqueID.all
|
206
|
-
rev = WithTemplateAndUniqueID.design_doc['_rev']
|
207
|
-
WithTemplateAndUniqueID.design_doc['_rev'].should eql(rev)
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
|
212
|
-
end
|