mattetti-couchrest 0.2.1.0 → 0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/README.md +6 -31
  2. data/Rakefile +1 -1
  3. data/examples/model/example.rb +13 -19
  4. data/lib/couchrest/core/database.rb +4 -3
  5. data/lib/couchrest/core/model.rb +615 -0
  6. data/lib/couchrest/core/response.rb +4 -5
  7. data/lib/couchrest/core/server.rb +1 -1
  8. data/lib/couchrest/mixins/callbacks.rb +33 -74
  9. data/lib/couchrest/mixins/design_doc.rb +1 -2
  10. data/lib/couchrest/mixins/document_queries.rb +1 -1
  11. data/lib/couchrest/mixins/extended_document_mixins.rb +1 -2
  12. data/lib/couchrest/mixins/properties.rb +3 -8
  13. data/lib/couchrest/mixins/validation.rb +1 -2
  14. data/lib/couchrest/mixins/views.rb +5 -5
  15. data/lib/couchrest/monkeypatches.rb +48 -65
  16. data/lib/couchrest/more/extended_document.rb +8 -75
  17. data/lib/couchrest/more/property.rb +1 -12
  18. data/lib/couchrest/support/class.rb +132 -148
  19. data/lib/couchrest.rb +8 -33
  20. data/spec/couchrest/core/database_spec.rb +23 -28
  21. data/spec/couchrest/core/model_spec.rb +856 -0
  22. data/spec/couchrest/more/casted_model_spec.rb +0 -14
  23. data/spec/couchrest/more/extended_doc_spec.rb +4 -450
  24. data/spec/couchrest/more/property_spec.rb +5 -16
  25. data/spec/spec_helper.rb +0 -4
  26. metadata +3 -16
  27. data/lib/couchrest/mixins/extended_attachments.rb +0 -68
  28. data/lib/couchrest/validation/validators/confirmation_validator.rb +0 -99
  29. data/spec/couchrest/more/casted_extended_doc_spec.rb +0 -40
  30. data/spec/couchrest/more/extended_doc_attachment_spec.rb +0 -129
  31. data/spec/couchrest/more/extended_doc_view_spec.rb +0 -206
  32. data/spec/couchrest/support/class_spec.rb +0 -59
  33. data/spec/fixtures/more/article.rb +0 -34
  34. data/spec/fixtures/more/course.rb +0 -14
  35. data/spec/fixtures/more/event.rb +0 -6
  36. data/spec/fixtures/more/person.rb +0 -8
  37. data/spec/fixtures/more/question.rb +0 -6
@@ -25,167 +25,151 @@
25
25
  # example, an array without those additions being shared with either their
26
26
  # parent, siblings, or children, which is unlike the regular class-level
27
27
  # attributes that are shared across the entire hierarchy.
28
- module CouchRest
29
- module ClassExtension
30
- def self.included(base)
31
- if CouchRest::ClassExtension::InstanceMethods.instance_methods.all? {|m| base.respond_to?(m)}
32
- # do nothing
33
- elsif CouchRest::ClassExtension::InstanceMethods.instance_methods.any? {|m| base.respond_to?(m)}
34
- raise RuntimeError, "Conflicting extentions to Class, work it out"
35
- else
36
- base.send(:include, CouchRest::ClassExtension::InstanceMethods)
37
- end
38
- end
39
-
40
- module InstanceMethods
41
- # Defines class-level and instance-level attribute reader.
42
- #
43
- # @param *syms<Array> Array of attributes to define reader for.
44
- # @return <Array[#to_s]> List of attributes that were made into cattr_readers
45
- #
46
- # @api public
47
- #
48
- # @todo Is this inconsistent in that it does not allow you to prevent
49
- # an instance_reader via :instance_reader => false
50
- def cattr_reader(*syms)
51
- syms.flatten.each do |sym|
52
- next if sym.is_a?(Hash)
53
- class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
54
- unless defined? @@#{sym}
55
- @@#{sym} = nil
56
- end
28
+ class Class
29
+ # Defines class-level and instance-level attribute reader.
30
+ #
31
+ # @param *syms<Array> Array of attributes to define reader for.
32
+ # @return <Array[#to_s]> List of attributes that were made into cattr_readers
33
+ #
34
+ # @api public
35
+ #
36
+ # @todo Is this inconsistent in that it does not allow you to prevent
37
+ # an instance_reader via :instance_reader => false
38
+ def cattr_reader(*syms)
39
+ syms.flatten.each do |sym|
40
+ next if sym.is_a?(Hash)
41
+ class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
42
+ unless defined? @@#{sym}
43
+ @@#{sym} = nil
44
+ end
57
45
 
58
- def self.#{sym}
59
- @@#{sym}
60
- end
46
+ def self.#{sym}
47
+ @@#{sym}
48
+ end
61
49
 
62
- def #{sym}
63
- @@#{sym}
50
+ def #{sym}
51
+ @@#{sym}
52
+ end
53
+ RUBY
64
54
  end
65
- RUBY
66
- end
67
- end
55
+ end
68
56
 
69
- # Defines class-level (and optionally instance-level) attribute writer.
70
- #
71
- # @param <Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to define writer for.
72
- # @option syms :instance_writer<Boolean> if true, instance-level attribute writer is defined.
73
- # @return <Array[#to_s]> List of attributes that were made into cattr_writers
74
- #
75
- # @api public
76
- def cattr_writer(*syms)
77
- options = syms.last.is_a?(Hash) ? syms.pop : {}
78
- syms.flatten.each do |sym|
79
- class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
80
- unless defined? @@#{sym}
81
- @@#{sym} = nil
82
- end
57
+ # Defines class-level (and optionally instance-level) attribute writer.
58
+ #
59
+ # @param <Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to define writer for.
60
+ # @option syms :instance_writer<Boolean> if true, instance-level attribute writer is defined.
61
+ # @return <Array[#to_s]> List of attributes that were made into cattr_writers
62
+ #
63
+ # @api public
64
+ def cattr_writer(*syms)
65
+ options = syms.last.is_a?(Hash) ? syms.pop : {}
66
+ syms.flatten.each do |sym|
67
+ class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
68
+ unless defined? @@#{sym}
69
+ @@#{sym} = nil
70
+ end
83
71
 
84
- def self.#{sym}=(obj)
85
- @@#{sym} = obj
86
- end
87
- RUBY
72
+ def self.#{sym}=(obj)
73
+ @@#{sym} = obj
74
+ end
75
+ RUBY
88
76
 
89
- unless options[:instance_writer] == false
90
- class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
91
- def #{sym}=(obj)
92
- @@#{sym} = obj
93
- end
94
- RUBY
95
- end
96
- end
77
+ unless options[:instance_writer] == false
78
+ class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
79
+ def #{sym}=(obj)
80
+ @@#{sym} = obj
81
+ end
82
+ RUBY
97
83
  end
84
+ end
85
+ end
98
86
 
99
- # Defines class-level (and optionally instance-level) attribute accessor.
100
- #
101
- # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to define accessor for.
102
- # @option syms :instance_writer<Boolean> if true, instance-level attribute writer is defined.
103
- # @return <Array[#to_s]> List of attributes that were made into accessors
104
- #
105
- # @api public
106
- def cattr_accessor(*syms)
107
- cattr_reader(*syms)
108
- cattr_writer(*syms)
109
- end
87
+ # Defines class-level (and optionally instance-level) attribute accessor.
88
+ #
89
+ # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to define accessor for.
90
+ # @option syms :instance_writer<Boolean> if true, instance-level attribute writer is defined.
91
+ # @return <Array[#to_s]> List of attributes that were made into accessors
92
+ #
93
+ # @api public
94
+ def cattr_accessor(*syms)
95
+ cattr_reader(*syms)
96
+ cattr_writer(*syms)
97
+ end
110
98
 
111
- # Defines class-level inheritable attribute reader. Attributes are available to subclasses,
112
- # each subclass has a copy of parent's attribute.
113
- #
114
- # @param *syms<Array[#to_s]> Array of attributes to define inheritable reader for.
115
- # @return <Array[#to_s]> Array of attributes converted into inheritable_readers.
116
- #
117
- # @api public
118
- #
119
- # @todo Do we want to block instance_reader via :instance_reader => false
120
- # @todo It would be preferable that we do something with a Hash passed in
121
- # (error out or do the same as other methods above) instead of silently
122
- # moving on). In particular, this makes the return value of this function
123
- # less useful.
124
- def class_inheritable_reader(*ivars)
125
- instance_reader = ivars.pop[:reader] if ivars.last.is_a?(Hash)
99
+ # Defines class-level inheritable attribute reader. Attributes are available to subclasses,
100
+ # each subclass has a copy of parent's attribute.
101
+ #
102
+ # @param *syms<Array[#to_s]> Array of attributes to define inheritable reader for.
103
+ # @return <Array[#to_s]> Array of attributes converted into inheritable_readers.
104
+ #
105
+ # @api public
106
+ #
107
+ # @todo Do we want to block instance_reader via :instance_reader => false
108
+ # @todo It would be preferable that we do something with a Hash passed in
109
+ # (error out or do the same as other methods above) instead of silently
110
+ # moving on). In particular, this makes the return value of this function
111
+ # less useful.
112
+ def class_inheritable_reader(*ivars)
113
+ instance_reader = ivars.pop[:reader] if ivars.last.is_a?(Hash)
126
114
 
127
- ivars.each do |ivar|
128
- self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
129
- def self.#{ivar}
130
- return @#{ivar} if self.object_id == #{self.object_id} || defined?(@#{ivar})
131
- ivar = superclass.#{ivar}
132
- return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}")
133
- @#{ivar} = ivar && !ivar.is_a?(Module) && !ivar.is_a?(Numeric) && !ivar.is_a?(TrueClass) && !ivar.is_a?(FalseClass) && !ivar.is_a?(Symbol) ? ivar.dup : ivar
134
- end
135
- RUBY
136
- unless instance_reader == false
137
- self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
138
- def #{ivar}
139
- self.class.#{ivar}
140
- end
141
- RUBY
142
- end
143
- end
115
+ ivars.each do |ivar|
116
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
117
+ def self.#{ivar}
118
+ return @#{ivar} if self.object_id == #{self.object_id} || defined?(@#{ivar})
119
+ ivar = superclass.#{ivar}
120
+ return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}")
121
+ @#{ivar} = ivar && !ivar.is_a?(Module) && !ivar.is_a?(Numeric) && !ivar.is_a?(TrueClass) && !ivar.is_a?(FalseClass) && !ivar.is_a?(Symbol) ? ivar.dup : ivar
122
+ end
123
+ RUBY
124
+ unless instance_reader == false
125
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
126
+ def #{ivar}
127
+ self.class.#{ivar}
128
+ end
129
+ RUBY
144
130
  end
145
-
146
- # Defines class-level inheritable attribute writer. Attributes are available to subclasses,
147
- # each subclass has a copy of parent's attribute.
148
- #
149
- # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
150
- # define inheritable writer for.
151
- # @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
152
- # @return <Array[#to_s]> An Array of the attributes that were made into inheritable writers.
153
- #
154
- # @api public
155
- #
156
- # @todo We need a style for class_eval <<-HEREDOC. I'd like to make it
157
- # class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere.
158
- def class_inheritable_writer(*ivars)
159
- instance_writer = ivars.pop[:instance_writer] if ivars.last.is_a?(Hash)
160
- ivars.each do |ivar|
161
- self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
162
- def self.#{ivar}=(obj)
163
- @#{ivar} = obj
164
131
  end
165
- RUBY
166
- unless instance_writer == false
167
- self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
168
- def #{ivar}=(obj) self.class.#{ivar} = obj end
169
- RUBY
170
- end
171
- end
172
- end
132
+ end
173
133
 
174
- # Defines class-level inheritable attribute accessor. Attributes are available to subclasses,
175
- # each subclass has a copy of parent's attribute.
176
- #
177
- # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
178
- # define inheritable accessor for.
179
- # @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
180
- # @return <Array[#to_s]> An Array of attributes turned into inheritable accessors.
181
- #
182
- # @api public
183
- def class_inheritable_accessor(*syms)
184
- class_inheritable_reader(*syms)
185
- class_inheritable_writer(*syms)
134
+ # Defines class-level inheritable attribute writer. Attributes are available to subclasses,
135
+ # each subclass has a copy of parent's attribute.
136
+ #
137
+ # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
138
+ # define inheritable writer for.
139
+ # @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
140
+ # @return <Array[#to_s]> An Array of the attributes that were made into inheritable writers.
141
+ #
142
+ # @api public
143
+ #
144
+ # @todo We need a style for class_eval <<-HEREDOC. I'd like to make it
145
+ # class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere.
146
+ def class_inheritable_writer(*ivars)
147
+ instance_writer = ivars.pop[:instance_writer] if ivars.last.is_a?(Hash)
148
+ ivars.each do |ivar|
149
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
150
+ def self.#{ivar}=(obj)
151
+ @#{ivar} = obj
152
+ end
153
+ RUBY
154
+ unless instance_writer == false
155
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
156
+ def #{ivar}=(obj) self.class.#{ivar} = obj end
157
+ RUBY
186
158
  end
187
159
  end
188
160
  end
189
- end
190
-
191
- Class.send(:include, CouchRest::ClassExtension)
161
+
162
+ # Defines class-level inheritable attribute accessor. Attributes are available to subclasses,
163
+ # each subclass has a copy of parent's attribute.
164
+ #
165
+ # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
166
+ # define inheritable accessor for.
167
+ # @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
168
+ # @return <Array[#to_s]> An Array of attributes turned into inheritable accessors.
169
+ #
170
+ # @api public
171
+ def class_inheritable_accessor(*syms)
172
+ class_inheritable_reader(*syms)
173
+ class_inheritable_writer(*syms)
174
+ end
175
+ end
data/lib/couchrest.rb CHANGED
@@ -22,19 +22,18 @@ $:.unshift File.dirname(__FILE__) unless
22
22
  $:.include?(File.dirname(__FILE__)) ||
23
23
  $:.include?(File.expand_path(File.dirname(__FILE__)))
24
24
 
25
- $COUCHREST_DEBUG ||= false
26
25
 
27
26
  require 'couchrest/monkeypatches'
28
27
 
29
28
  # = CouchDB, close to the metal
30
29
  module CouchRest
31
- VERSION = '0.2.1' unless self.const_defined?("VERSION")
30
+ VERSION = '0.13'
32
31
 
33
32
  autoload :Server, 'couchrest/core/server'
34
33
  autoload :Database, 'couchrest/core/database'
35
- autoload :Response, 'couchrest/core/response'
34
+ autoload :Response, 'couchrest/core/response'
36
35
  autoload :Document, 'couchrest/core/document'
37
- autoload :Design, 'couchrest/core/design'
36
+ autoload :Design, 'couchrest/core/design'
38
37
  autoload :View, 'couchrest/core/view'
39
38
  autoload :Model, 'couchrest/core/model'
40
39
  autoload :Pager, 'couchrest/helper/pager'
@@ -125,42 +124,18 @@ module CouchRest
125
124
  cr.database(parsed[:database])
126
125
  end
127
126
 
128
- def put(uri, doc = nil)
127
+ def put uri, doc = nil
129
128
  payload = doc.to_json if doc
130
- begin
131
- JSON.parse(RestClient.put(uri, payload))
132
- rescue Exception => e
133
- if $COUCHREST_DEBUG == true
134
- raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}"
135
- else
136
- raise e
137
- end
138
- end
129
+ JSON.parse(RestClient.put(uri, payload))
139
130
  end
140
131
 
141
- def get(uri)
142
- begin
143
- JSON.parse(RestClient.get(uri), :max_nesting => false)
144
- rescue => e
145
- if $COUCHREST_DEBUG == true
146
- raise "Error while sending a GET request #{uri}\n: #{e}"
147
- else
148
- raise e
149
- end
150
- end
132
+ def get uri
133
+ JSON.parse(RestClient.get(uri), :max_nesting => false)
151
134
  end
152
135
 
153
136
  def post uri, doc = nil
154
137
  payload = doc.to_json if doc
155
- begin
156
- JSON.parse(RestClient.post(uri, payload))
157
- rescue Exception => e
158
- if $COUCHREST_DEBUG == true
159
- raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}"
160
- else
161
- raise e
162
- end
163
- end
138
+ JSON.parse(RestClient.post(uri, payload))
164
139
  end
165
140
 
166
141
  def delete uri
@@ -247,11 +247,9 @@ describe CouchRest::Database do
247
247
  @db.save_doc(@doc)
248
248
  end
249
249
 
250
- # Depreacated
251
- # it "should get the attachment with the doc's _id" do
252
- # @db.fetch_attachment("mydocwithattachment", "test.html").should == @attach
253
- # end
254
-
250
+ it "should get the attachment with the doc's _id" do
251
+ @db.fetch_attachment("mydocwithattachment", "test.html").should == @attach
252
+ end
255
253
  it "should get the attachment with the doc itself" do
256
254
  @db.fetch_attachment(@db.get('mydocwithattachment'), 'test.html').should == @attach
257
255
  end
@@ -268,8 +266,7 @@ describe CouchRest::Database do
268
266
  it "should save the attachment to a new doc" do
269
267
  r = @db.put_attachment({'_id' => 'attach-this'}, 'couchdb.png', image = @file.read, {:content_type => 'image/png'})
270
268
  r['ok'].should == true
271
- doc = @db.get("attach-this")
272
- attachment = @db.fetch_attachment(doc,"couchdb.png")
269
+ attachment = @db.fetch_attachment("attach-this","couchdb.png")
273
270
  attachment.should == image
274
271
  end
275
272
  end
@@ -277,7 +274,7 @@ describe CouchRest::Database do
277
274
  describe "PUT document with attachment" do
278
275
  before(:each) do
279
276
  @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
280
- doc = {
277
+ @doc = {
281
278
  "_id" => "mydocwithattachment",
282
279
  "field" => ["some value"],
283
280
  "_attachments" => {
@@ -287,14 +284,14 @@ describe CouchRest::Database do
287
284
  }
288
285
  }
289
286
  }
290
- @db.save_doc(doc)
291
- @doc = @db.get("mydocwithattachment")
287
+ @db.save_doc(@doc)
292
288
  end
293
289
  it "should save and be indicated" do
294
- @doc['_attachments']['test.html']['length'].should == @attach.length
290
+ doc = @db.get("mydocwithattachment")
291
+ doc['_attachments']['test.html']['length'].should == @attach.length
295
292
  end
296
293
  it "should be there" do
297
- attachment = @db.fetch_attachment(@doc,"test.html")
294
+ attachment = @db.fetch_attachment("mydocwithattachment","test.html")
298
295
  attachment.should == @attach
299
296
  end
300
297
  end
@@ -312,15 +309,14 @@ describe CouchRest::Database do
312
309
  }
313
310
  }
314
311
  @db.save_doc(doc)
315
- doc['_rev'].should_not be_nil
312
+ doc = @db.get('mydocwithattachment')
316
313
  doc['field'] << 'another value'
317
- @db.save_doc(doc)["ok"].should be_true
314
+ @db.save_doc(doc)
318
315
  end
319
316
 
320
317
  it 'should be there' do
321
- doc = @db.get('mydocwithattachment')
322
- attachment = @db.fetch_attachment(doc, 'test.html')
323
- Base64.decode64(attachment).should == @attach
318
+ attachment = @db.fetch_attachment('mydocwithattachment', 'test.html')
319
+ attachment.should == @attach
324
320
  end
325
321
  end
326
322
 
@@ -343,18 +339,18 @@ describe CouchRest::Database do
343
339
  }
344
340
  }
345
341
  @db.save_doc(@doc)
346
- @doc = @db.get("mydocwithattachment")
347
342
  end
348
343
  it "should save and be indicated" do
349
- @doc['_attachments']['test.html']['length'].should == @attach.length
350
- @doc['_attachments']['other.html']['length'].should == @attach2.length
344
+ doc = @db.get("mydocwithattachment")
345
+ doc['_attachments']['test.html']['length'].should == @attach.length
346
+ doc['_attachments']['other.html']['length'].should == @attach2.length
351
347
  end
352
348
  it "should be there" do
353
- attachment = @db.fetch_attachment(@doc,"test.html")
349
+ attachment = @db.fetch_attachment("mydocwithattachment","test.html")
354
350
  attachment.should == @attach
355
351
  end
356
352
  it "should be there" do
357
- attachment = @db.fetch_attachment(@doc,"other.html")
353
+ attachment = @db.fetch_attachment("mydocwithattachment","other.html")
358
354
  attachment.should == @attach2
359
355
  end
360
356
  end
@@ -374,9 +370,9 @@ describe CouchRest::Database do
374
370
  @doc = @db.get('mydocwithattachment')
375
371
  end
376
372
  it "should delete the attachment" do
377
- lambda { @db.fetch_attachment(@doc,'test.html') }.should_not raise_error
373
+ lambda { @db.fetch_attachment('mydocwithattachment','test.html') }.should_not raise_error
378
374
  @db.delete_attachment(@doc, "test.html")
379
- lambda { @db.fetch_attachment(@doc,'test.html') }.should raise_error(RestClient::ResourceNotFound)
375
+ lambda { @db.fetch_attachment('mydocwithattachment','test.html') }.should raise_error(RestClient::ResourceNotFound)
380
376
  end
381
377
  end
382
378
 
@@ -399,8 +395,7 @@ describe CouchRest::Database do
399
395
  doc['_attachments']['http://example.com/stuff.cgi?things=and%20stuff']['length'].should == @attach.length
400
396
  end
401
397
  it "should be there" do
402
- doc = @db.get(@docid)
403
- attachment = @db.fetch_attachment(doc,"http://example.com/stuff.cgi?things=and%20stuff")
398
+ attachment = @db.fetch_attachment(@docid,"http://example.com/stuff.cgi?things=and%20stuff")
404
399
  attachment.should == @attach
405
400
  end
406
401
  end
@@ -709,7 +704,7 @@ describe CouchRest::Database do
709
704
  describe "creating a database" do
710
705
  before(:each) do
711
706
  @db = @cr.database('couchrest-test-db_to_create')
712
- @db.delete! if @cr.databases.include?('couchrest-test-db_to_create')
707
+ @db.delete!
713
708
  end
714
709
 
715
710
  it "should just work fine" do
@@ -742,4 +737,4 @@ describe CouchRest::Database do
742
737
  end
743
738
 
744
739
 
745
- end
740
+ end