amrita2 2.0.0 → 2.0.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.
- data/README +1 -1
- data/init.rb +1 -0
- data/lib/amrita2/rails_bridge.rb +92 -7
- data/lib/amrita2/template.rb +12 -127
- data/lib/amrita2/testsupport.rb +0 -25
- data/lib/amrita2/version.rb +1 -1
- data/sample/depot/app/controllers/admin_controller.rb +3 -1
- data/sample/depot/app/helpers/cart_helper.rb +8 -0
- data/sample/depot/app/helpers/price_helper.rb +7 -0
- data/sample/depot/config/environment.rb +0 -14
- data/sample/depot/config/environments/development.rb +2 -2
- data/sample/depot/db/schema.rb +27 -20
- data/sample/depot/test/functional/admin_controller_test.rb +63 -22
- data/sample/depot/test/functional/store_controller_test.rb +30 -18
- data/sample/depot/vendor/plugins/will_paginate/init.rb +4 -0
- data/sample/depot/vendor/plugins/will_paginate/lib/will_paginate.rb +61 -0
- data/sample/depot/vendor/plugins/will_paginate/lib/will_paginate/collection.rb +132 -0
- data/sample/depot/vendor/plugins/will_paginate/lib/will_paginate/core_ext.rb +80 -0
- data/sample/depot/vendor/plugins/will_paginate/lib/will_paginate/finder.rb +181 -0
- data/sample/depot/vendor/plugins/will_paginate/lib/will_paginate/view_helpers.rb +206 -0
- data/sample/depot/vendor/plugins/will_paginate/test/array_pagination_test.rb +131 -0
- data/sample/depot/vendor/plugins/will_paginate/test/boot.rb +23 -0
- data/sample/depot/vendor/plugins/will_paginate/test/finder_test.rb +290 -0
- data/sample/depot/vendor/plugins/will_paginate/test/fixtures/admin.rb +3 -0
- data/sample/depot/vendor/plugins/will_paginate/test/fixtures/company.rb +9 -0
- data/sample/depot/vendor/plugins/will_paginate/test/fixtures/developer.rb +11 -0
- data/sample/depot/vendor/plugins/will_paginate/test/fixtures/project.rb +15 -0
- data/sample/depot/vendor/plugins/will_paginate/test/fixtures/reply.rb +5 -0
- data/sample/depot/vendor/plugins/will_paginate/test/fixtures/schema.rb +38 -0
- data/sample/depot/vendor/plugins/will_paginate/test/fixtures/topic.rb +4 -0
- data/sample/depot/vendor/plugins/will_paginate/test/fixtures/user.rb +2 -0
- data/sample/depot/vendor/plugins/will_paginate/test/helper.rb +25 -0
- data/sample/depot/vendor/plugins/will_paginate/test/lib/activerecord_test_case.rb +23 -0
- data/sample/depot/vendor/plugins/will_paginate/test/lib/activerecord_test_connector.rb +67 -0
- data/sample/depot/vendor/plugins/will_paginate/test/lib/load_fixtures.rb +13 -0
- data/sample/depot/vendor/plugins/will_paginate/test/pagination_test.rb +240 -0
- data/sample/hello/test1.rb +23 -0
- data/sample/login_engine/config/environment.rb +18 -20
- data/sample/login_engine/config/environments/development.rb +2 -2
- data/sample/login_engine/db/schema.rb +24 -17
- data/sample/login_engine/lib/login_engine/authenticated_system.rb +18 -18
- data/sample/login_engine/test/functional/user_controller_test.rb +1 -0
- data/sample/ramaze/ramaise_amrita2.rb +156 -0
- data/specs/attribute.rb +11 -0
- data/specs/datatypes.rb +13 -0
- data/specs/sample.rb +1 -2
- data/specs/sanitize.rb +14 -0
- metadata +28 -7
- data/sample/depot/app/helpers/ar_form.rb +0 -169
- data/sample/depot/app/helpers/form_tag.rb +0 -24
- data/sample/depot/app/helpers/standard_form.rb +0 -73
- data/sample/depot/test/integration/dsl_user_stories_test.rb +0 -126
- data/sample/depot/test/integration/user_stories_test.rb +0 -70
@@ -1,6 +1,6 @@
|
|
1
1
|
#---
|
2
2
|
# Excerpted from "Agile Web Development with Rails, 2nd Ed."
|
3
|
-
# We make no guarantees that this code is fit for any purpose.
|
3
|
+
# We make no guarantees that this code is fit for any purpose.
|
4
4
|
# Visit http://www.pragmaticprogrammer.com/titles/rails2 for more book information.
|
5
5
|
#---
|
6
6
|
# Settings specified here will take precedence over those in config/environment.rb
|
@@ -14,7 +14,7 @@ config.cache_classes = false
|
|
14
14
|
config.whiny_nils = true
|
15
15
|
|
16
16
|
# Enable the breakpoint server that script/breakpointer connects to
|
17
|
-
config.breakpoint_server = true
|
17
|
+
#config.breakpoint_server = true
|
18
18
|
|
19
19
|
# Show full error reports and disable caching
|
20
20
|
config.action_controller.consider_all_requests_local = true
|
data/sample/depot/db/schema.rb
CHANGED
@@ -1,45 +1,52 @@
|
|
1
|
-
# This file is
|
2
|
-
# migrations feature of ActiveRecord to incrementally modify your database, and
|
1
|
+
# This file is auto-generated from the current state of the database. Instead of editing this file,
|
2
|
+
# please use the migrations feature of ActiveRecord to incrementally modify your database, and
|
3
3
|
# then regenerate this schema definition.
|
4
|
+
#
|
5
|
+
# Note that this schema.rb definition is the authoritative source for your database schema. If you need
|
6
|
+
# to create the application database on another system, you should be using db:schema:load, not running
|
7
|
+
# all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
8
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
9
|
+
#
|
10
|
+
# It's strongly recommended to check this file into your version control system.
|
4
11
|
|
5
12
|
ActiveRecord::Schema.define(:version => 7) do
|
6
13
|
|
7
14
|
create_table "line_items", :force => true do |t|
|
8
|
-
t.
|
9
|
-
t.
|
10
|
-
t.
|
11
|
-
t.
|
15
|
+
t.integer "product_id", :null => false
|
16
|
+
t.integer "order_id", :null => false
|
17
|
+
t.integer "quantity", :null => false
|
18
|
+
t.decimal "total_price", :precision => 8, :scale => 2, :null => false
|
12
19
|
end
|
13
20
|
|
14
21
|
add_index "line_items", ["product_id"], :name => "fk_line_item_products"
|
15
22
|
add_index "line_items", ["order_id"], :name => "fk_line_item_orders"
|
16
23
|
|
17
24
|
create_table "orders", :force => true do |t|
|
18
|
-
t.
|
19
|
-
t.
|
20
|
-
t.
|
21
|
-
t.
|
25
|
+
t.string "name"
|
26
|
+
t.text "address"
|
27
|
+
t.string "email"
|
28
|
+
t.string "pay_type", :limit => 10
|
22
29
|
end
|
23
30
|
|
24
31
|
create_table "products", :force => true do |t|
|
25
|
-
t.
|
26
|
-
t.
|
27
|
-
t.
|
28
|
-
t.
|
32
|
+
t.string "title"
|
33
|
+
t.text "description"
|
34
|
+
t.string "image_url"
|
35
|
+
t.decimal "price", :precision => 8, :scale => 2, :default => 0.0
|
29
36
|
end
|
30
37
|
|
31
38
|
create_table "sessions", :force => true do |t|
|
32
|
-
t.
|
33
|
-
t.
|
34
|
-
t.
|
39
|
+
t.string "session_id"
|
40
|
+
t.text "data"
|
41
|
+
t.datetime "updated_at"
|
35
42
|
end
|
36
43
|
|
37
44
|
add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
|
38
45
|
|
39
46
|
create_table "users", :force => true do |t|
|
40
|
-
t.
|
41
|
-
t.
|
42
|
-
t.
|
47
|
+
t.string "name"
|
48
|
+
t.string "hashed_password"
|
49
|
+
t.string "salt"
|
43
50
|
end
|
44
51
|
|
45
52
|
end
|
@@ -7,11 +7,34 @@ require File.dirname(__FILE__) + '/../test_helper'
|
|
7
7
|
require 'admin_controller'
|
8
8
|
require 'amrita2/testsupport'
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
module AdminControllerMixinForTest
|
11
|
+
def new_erb
|
12
|
+
new
|
13
|
+
render :template=>"admin/new.html.erb"
|
14
|
+
end
|
15
|
+
|
16
|
+
def list_erb
|
17
|
+
list
|
18
|
+
render :template=>"admin/list.html.erb"
|
19
|
+
end
|
20
|
+
|
21
|
+
def show_erb
|
22
|
+
show
|
23
|
+
render :template=>"admin/show.html.erb"
|
24
|
+
end
|
25
|
+
|
26
|
+
def edit_erb
|
27
|
+
edit
|
28
|
+
render :template=>"admin/edit.html.erb"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class AdminController
|
33
|
+
include AdminControllerMixinForTest
|
34
|
+
end
|
35
|
+
|
12
36
|
|
13
37
|
class AdminControllerTest < Test::Unit::TestCase
|
14
|
-
include Amrita2::RailsTestHelper
|
15
38
|
fixtures :products
|
16
39
|
|
17
40
|
def setup
|
@@ -20,35 +43,53 @@ class AdminControllerTest < Test::Unit::TestCase
|
|
20
43
|
@controller = AdminController.new
|
21
44
|
@request = ActionController::TestRequest.new
|
22
45
|
@response = ActionController::TestResponse.new
|
46
|
+
ActionView::Base.register_template_handler(:a2, Amrita2View::Base)
|
23
47
|
end
|
24
48
|
|
25
49
|
def test_new
|
50
|
+
login
|
26
51
|
get :new
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
52
|
+
amrita2_result = @response.body
|
53
|
+
get :new_erb
|
54
|
+
erb_result = @response.body
|
55
|
+
#puts amrita2_result
|
56
|
+
#puts erb_result
|
57
|
+
assert_equal_as_xml(erb_result, amrita2_result)
|
33
58
|
end
|
34
59
|
|
35
60
|
def test_list
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
61
|
+
login
|
62
|
+
get :list
|
63
|
+
amrita2_result = @response.body
|
64
|
+
get :list_erb
|
65
|
+
erb_result = @response.body
|
66
|
+
assert_equal_as_xml(erb_result, amrita2_result)
|
43
67
|
end
|
44
68
|
|
45
69
|
def test_show
|
46
|
-
|
70
|
+
login
|
71
|
+
get :show, :id=>1
|
72
|
+
amrita2_result = @response.body
|
73
|
+
get :show_erb, :id=>1
|
74
|
+
erb_result = @response.body
|
75
|
+
assert_equal_as_xml(erb_result, amrita2_result)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_edit
|
79
|
+
login
|
80
|
+
get :edit, :id=>1
|
81
|
+
amrita2_result = @response.body
|
82
|
+
get :edit_erb, :id=>1
|
83
|
+
erb_result = @response.body
|
84
|
+
#puts amrita2_result
|
85
|
+
#puts erb_result
|
86
|
+
assert_equal_as_xml(erb_result, amrita2_result)
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
def login
|
91
|
+
get :new # dummy
|
47
92
|
session[:user_id] = User.find_by_name('u1').id
|
48
|
-
flash[:notice] =
|
49
|
-
compare_result do
|
50
|
-
get :show, :id=>1
|
51
|
-
@response.body
|
52
|
-
end
|
93
|
+
flash[:notice] = nil
|
53
94
|
end
|
54
95
|
end
|
@@ -7,25 +7,40 @@ require File.dirname(__FILE__) + '/../test_helper'
|
|
7
7
|
require 'amrita2/testsupport'
|
8
8
|
require 'store_controller'
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
module StoreControllerMixinForTest
|
11
|
+
def index_erb
|
12
|
+
index
|
13
|
+
render :template=>'store/index.html.erb', :layout=>'store.rhtml'
|
14
|
+
end
|
15
|
+
|
16
|
+
def checkout_erb
|
17
|
+
checkout
|
18
|
+
render :template=>'store/checkout.html.erb', :layout=>'store.rhtml'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class StoreController
|
23
|
+
include StoreControllerMixinForTest
|
24
|
+
end
|
12
25
|
|
13
26
|
class StoreControllerTest < Test::Unit::TestCase
|
14
|
-
include Amrita2::RailsTestHelper
|
15
27
|
fixtures :products
|
16
28
|
|
17
29
|
def setup
|
18
30
|
@controller = StoreController.new
|
19
31
|
@request = ActionController::TestRequest.new
|
20
32
|
@response = ActionController::TestResponse.new
|
33
|
+
ActionView::Base.register_template_handler(:a2, Amrita2View::Base)
|
21
34
|
end
|
22
35
|
|
23
36
|
def test_index
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
37
|
+
get :index_erb
|
38
|
+
erb_result = @response.body
|
39
|
+
#puts erb_result
|
40
|
+
get :index
|
41
|
+
amrita2_result = @response.body
|
42
|
+
#puts amrita2_result
|
43
|
+
assert_equal_as_xml(erb_result, amrita2_result)
|
29
44
|
end
|
30
45
|
|
31
46
|
def test_post_to_add_to_cart
|
@@ -35,11 +50,7 @@ class StoreControllerTest < Test::Unit::TestCase
|
|
35
50
|
|
36
51
|
post :add_to_cart, :id=>ruby_id
|
37
52
|
|
38
|
-
|
39
|
-
get :index
|
40
|
-
assert_response(:success)
|
41
|
-
@response.body
|
42
|
-
end
|
53
|
+
test_index
|
43
54
|
end
|
44
55
|
|
45
56
|
def test_checkout
|
@@ -47,11 +58,12 @@ class StoreControllerTest < Test::Unit::TestCase
|
|
47
58
|
get :index
|
48
59
|
post :add_to_cart, :id=>ruby_id
|
49
60
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
61
|
+
get :checkout
|
62
|
+
amrita2_result = @response.body
|
63
|
+
#puts amrita2_result
|
64
|
+
get :checkout_erb
|
65
|
+
erb_result = @response.body
|
66
|
+
assert_equal_as_xml(erb_result, amrita2_result)
|
55
67
|
end
|
56
68
|
|
57
69
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
# = You *will* paginate!
|
4
|
+
#
|
5
|
+
# First read about WillPaginate::Finder::ClassMethods, then see
|
6
|
+
# WillPaginate::ViewHelpers. The magical array you're handling in-between is
|
7
|
+
# WillPaginate::Collection.
|
8
|
+
#
|
9
|
+
# Happy paginating!
|
10
|
+
module WillPaginate
|
11
|
+
class << self
|
12
|
+
# shortcut for <tt>enable_actionpack; enable_activerecord</tt>
|
13
|
+
def enable
|
14
|
+
enable_actionpack
|
15
|
+
enable_activerecord
|
16
|
+
end
|
17
|
+
|
18
|
+
# mixes in WillPaginate::ViewHelpers in ActionView::Base
|
19
|
+
def enable_actionpack
|
20
|
+
return if ActionView::Base.instance_methods.include? 'will_paginate'
|
21
|
+
require 'will_paginate/view_helpers'
|
22
|
+
ActionView::Base.class_eval { include ViewHelpers }
|
23
|
+
end
|
24
|
+
|
25
|
+
# mixes in WillPaginate::Finder in ActiveRecord::Base and classes that deal
|
26
|
+
# with associations
|
27
|
+
def enable_activerecord
|
28
|
+
return if ActiveRecord::Base.respond_to? :paginate
|
29
|
+
require 'will_paginate/finder'
|
30
|
+
ActiveRecord::Base.class_eval { include Finder }
|
31
|
+
|
32
|
+
associations = ActiveRecord::Associations
|
33
|
+
collection = associations::AssociationCollection
|
34
|
+
|
35
|
+
# to support paginating finders on associations, we have to mix in the
|
36
|
+
# method_missing magic from WillPaginate::Finder::ClassMethods to AssociationProxy
|
37
|
+
# subclasses, but in a different way for Rails 1.2.x and 2.0
|
38
|
+
(collection.instance_methods.include?(:create!) ?
|
39
|
+
collection : collection.subclasses.map(&:constantize)
|
40
|
+
).push(associations::HasManyThroughAssociation).each do |klass|
|
41
|
+
klass.class_eval do
|
42
|
+
include Finder::ClassMethods
|
43
|
+
alias_method_chain :method_missing, :paginate
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module Deprecation #:nodoc:
|
50
|
+
extend ActiveSupport::Deprecation
|
51
|
+
|
52
|
+
def self.warn(message, callstack = caller)
|
53
|
+
message = 'WillPaginate: ' + message.strip.gsub(/ {3,}/, ' ')
|
54
|
+
behavior.call(message, callstack) if behavior && !silenced?
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.silenced?
|
58
|
+
ActiveSupport::Deprecation.silenced?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'will_paginate'
|
2
|
+
|
3
|
+
module WillPaginate
|
4
|
+
# = OMG, invalid page number!
|
5
|
+
# This is an ArgumentError raised in case a page was requested that is either
|
6
|
+
# zero or negative number. You should decide how do deal with such errors in
|
7
|
+
# the controller.
|
8
|
+
#
|
9
|
+
# This error is *not* raised when a page further than the last page is
|
10
|
+
# requested. Use <tt>WillPaginate::Collection#out_of_bounds?</tt> method to
|
11
|
+
# check for those cases and manually deal with them as you see fit.
|
12
|
+
class InvalidPage < ArgumentError
|
13
|
+
def initialize(page, page_num)
|
14
|
+
super "#{page.inspect} given as value, which translates to '#{page_num}' as page number"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Arrays returned from paginating finds are, in fact, instances of this.
|
19
|
+
# You may think of WillPaginate::Collection as an ordinary array with some
|
20
|
+
# extra properties. Those properties are used by view helpers to generate
|
21
|
+
# correct page links.
|
22
|
+
#
|
23
|
+
# WillPaginate::Collection also assists in rolling out your own pagination
|
24
|
+
# solutions: see +create+.
|
25
|
+
#
|
26
|
+
class Collection < Array
|
27
|
+
attr_reader :current_page, :per_page, :total_entries
|
28
|
+
|
29
|
+
# Arguments to this constructor are the current page number, per-page limit
|
30
|
+
# and the total number of entries. The last argument is optional because it
|
31
|
+
# is best to do lazy counting; in other words, count *conditionally* after
|
32
|
+
# populating the collection using the +replace+ method.
|
33
|
+
#
|
34
|
+
def initialize(page, per_page, total = nil)
|
35
|
+
@current_page = page.to_i
|
36
|
+
raise InvalidPage.new(page, @current_page) if @current_page < 1
|
37
|
+
@per_page = per_page.to_i
|
38
|
+
raise ArgumentError, "`per_page` setting cannot be less than 1 (#{@per_page} given)" if @per_page < 1
|
39
|
+
|
40
|
+
self.total_entries = total if total
|
41
|
+
end
|
42
|
+
|
43
|
+
# Just like +new+, but yields the object after instantiation and returns it
|
44
|
+
# afterwards. This is very useful for manual pagination:
|
45
|
+
#
|
46
|
+
# @entries = WillPaginate::Collection.create(1, 10) do |pager|
|
47
|
+
# result = Post.find(:all, :limit => pager.per_page, :offset => pager.offset)
|
48
|
+
# # inject the result array into the paginated collection:
|
49
|
+
# pager.replace(result)
|
50
|
+
#
|
51
|
+
# unless pager.total_entries
|
52
|
+
# # the pager didn't manage to guess the total count, do it manually
|
53
|
+
# pager.total_entries = Post.count
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# The possibilities with this are endless. For another example, here is how
|
58
|
+
# WillPaginate used to define pagination for Array instances:
|
59
|
+
#
|
60
|
+
# Array.class_eval do
|
61
|
+
# def paginate(page = 1, per_page = 15)
|
62
|
+
# WillPaginate::Collection.create(page, per_page, size) do |pager|
|
63
|
+
# pager.replace self[pager.offset, pager.per_page].to_a
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
def self.create(page, per_page, total = nil, &block)
|
69
|
+
pager = new(page, per_page, total)
|
70
|
+
yield pager
|
71
|
+
pager
|
72
|
+
end
|
73
|
+
|
74
|
+
# The total number of pages.
|
75
|
+
def page_count
|
76
|
+
@total_pages
|
77
|
+
end
|
78
|
+
|
79
|
+
# Helper method that is true when someone tries to fetch a page with a
|
80
|
+
# larger number than the last page. Can be used in combination with flashes
|
81
|
+
# and redirecting.
|
82
|
+
def out_of_bounds?
|
83
|
+
current_page > page_count
|
84
|
+
end
|
85
|
+
|
86
|
+
# Current offset of the paginated collection. If we're on the first page,
|
87
|
+
# it is always 0. If we're on the 2nd page and there are 30 entries per page,
|
88
|
+
# the offset is 30. This property is useful if you want to render ordinals
|
89
|
+
# besides your records: simply start with offset + 1.
|
90
|
+
#
|
91
|
+
def offset
|
92
|
+
(current_page - 1) * per_page
|
93
|
+
end
|
94
|
+
|
95
|
+
# current_page - 1 or nil if there is no previous page
|
96
|
+
def previous_page
|
97
|
+
current_page > 1 ? (current_page - 1) : nil
|
98
|
+
end
|
99
|
+
|
100
|
+
# current_page + 1 or nil if there is no next page
|
101
|
+
def next_page
|
102
|
+
current_page < page_count ? (current_page + 1) : nil
|
103
|
+
end
|
104
|
+
|
105
|
+
def total_entries=(number)
|
106
|
+
@total_entries = number.to_i
|
107
|
+
@total_pages = (@total_entries / per_page.to_f).ceil
|
108
|
+
end
|
109
|
+
|
110
|
+
# This is a magic wrapper for the original Array#replace method. It serves
|
111
|
+
# for populating the paginated collection after initialization.
|
112
|
+
#
|
113
|
+
# Why magic? Because it tries to guess the total number of entries judging
|
114
|
+
# by the size of given array. If it is shorter than +per_page+ limit, then we
|
115
|
+
# know we're on the last page. This trick is very useful for avoiding
|
116
|
+
# unnecessary hits to the database to do the counting after we fetched the
|
117
|
+
# data for the current page.
|
118
|
+
#
|
119
|
+
# However, after using +replace+ you should always test the value of
|
120
|
+
# +total_entries+ and set it to a proper value if it's +nil+. See the example
|
121
|
+
# in +create+.
|
122
|
+
def replace(array)
|
123
|
+
returning super do
|
124
|
+
# The collection is shorter then page limit? Rejoice, because
|
125
|
+
# then we know that we are on the last page!
|
126
|
+
if total_entries.nil? and length > 0 and length < per_page
|
127
|
+
self.total_entries = offset + length
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|