money-rails 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +34 -53
- data/lib/generators/templates/money.rb +7 -4
- data/lib/money-rails/active_model/validator.rb +1 -1
- data/lib/money-rails/active_record/monetizable.rb +23 -7
- data/lib/money-rails/configuration.rb +5 -2
- data/lib/money-rails/money.rb +4 -1
- data/lib/money-rails/mongoid/money.rb +2 -2
- data/lib/money-rails/test_helpers.rb +40 -18
- data/lib/money-rails/version.rb +1 -1
- data/money-rails.gemspec +1 -1
- data/spec/active_record/migration_extensions/schema_statements_spec.rb +8 -8
- data/spec/active_record/migration_extensions/table_spec.rb +8 -8
- data/spec/active_record/monetizable_spec.rb +195 -166
- data/spec/configuration_spec.rb +39 -22
- data/spec/dummy/app/models/dummy_product.rb +1 -0
- data/spec/dummy/app/models/product.rb +4 -0
- data/spec/dummy/config/application.rb +3 -2
- data/spec/dummy/config/locales/en-US.yml +5 -0
- data/spec/dummy/db/migrate/20141005075025_add_aliased_attr_to_products.rb +5 -0
- data/spec/dummy/db/schema.rb +2 -1
- data/spec/helpers/action_view_extension_spec.rb +45 -45
- data/spec/helpers/form_helper_spec.rb +2 -2
- data/spec/mongoid/four_spec.rb +23 -23
- data/spec/mongoid/three_spec.rb +23 -23
- data/spec/mongoid/two_spec.rb +13 -13
- data/spec/spec_helper.rb +0 -2
- data/spec/test_helpers_spec.rb +34 -22
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f7362d98f56cc0f9a7e99d5aae5385d555786dd
|
4
|
+
data.tar.gz: fab18c41c2b15e4916400013a7b60e6b00ae39e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c79ba8f99be3130f51e9b6d2f3092a6c5d4d2247f4325573e07e8e3b00c839a65b471f5937df5085b1cac396c7dbbb9e5f08d1b8aa027f80700fb141f87beb5f
|
7
|
+
data.tar.gz: 452e693682d7f1d45849c14ac44f78ba157cdcd85f9ede1f68a2f419084f666159ac4dd0c439abcf1429303e6256b6e044a04bacf72a15bad1fd0f438649d1fa
|
data/README.md
CHANGED
@@ -259,7 +259,7 @@ object using EUR as their currency, instead of the default USD.
|
|
259
259
|
By passing the option ```:with_currency``` to the ```monetize``` macro call,
|
260
260
|
with a currency code as its value, you can define a currency in a more granular
|
261
261
|
way. This will you attach the given currency only to the specified monetized model
|
262
|
-
attribute (allowing you
|
262
|
+
attribute (allowing you to, for example, monetize different attributes of the same model with different currencies.).
|
263
263
|
|
264
264
|
This allows you to override both the model level and the global
|
265
265
|
default currencies:
|
@@ -321,16 +321,24 @@ MoneyRails.configure do |config|
|
|
321
321
|
|
322
322
|
# To set the default currency
|
323
323
|
#
|
324
|
-
config.default_currency = :usd
|
324
|
+
# config.default_currency = :usd
|
325
|
+
|
326
|
+
# Set default bank object
|
327
|
+
#
|
328
|
+
# Example:
|
329
|
+
# config.default_bank = EuCentralBank.new
|
325
330
|
|
326
|
-
# Add
|
327
|
-
|
328
|
-
|
331
|
+
# Add exchange rates to current money bank object.
|
332
|
+
# (The conversion rate refers to one direction only)
|
333
|
+
#
|
334
|
+
# Example:
|
335
|
+
# config.add_rate "USD", "CAD", 1.24515
|
336
|
+
# config.add_rate "CAD", "USD", 0.803115
|
329
337
|
|
330
338
|
# To handle the inclusion of validations for monetized fields
|
331
339
|
# The default value is true
|
332
340
|
#
|
333
|
-
config.include_validations = true
|
341
|
+
# config.include_validations = true
|
334
342
|
|
335
343
|
# Default ActiveRecord migration configuration values for columns:
|
336
344
|
#
|
@@ -354,6 +362,7 @@ MoneyRails.configure do |config|
|
|
354
362
|
|
355
363
|
# Register a custom currency
|
356
364
|
#
|
365
|
+
# Example:
|
357
366
|
# config.register_currency = {
|
358
367
|
# :priority => 1,
|
359
368
|
# :iso_code => "EU4",
|
@@ -379,15 +388,17 @@ MoneyRails.configure do |config|
|
|
379
388
|
#
|
380
389
|
# set to BigDecimal::ROUND_HALF_EVEN by default
|
381
390
|
#
|
382
|
-
config.rounding_mode = BigDecimal::ROUND_HALF_UP
|
391
|
+
# config.rounding_mode = BigDecimal::ROUND_HALF_UP
|
383
392
|
|
384
|
-
# Set money
|
393
|
+
# Set default money format globally.
|
385
394
|
# Default value is nil meaning "ignore this option".
|
386
|
-
#
|
395
|
+
# Example:
|
387
396
|
#
|
388
|
-
# config.
|
389
|
-
#
|
390
|
-
#
|
397
|
+
# config.default_format = {
|
398
|
+
# :no_cents_if_whole => nil,
|
399
|
+
# :symbol => nil,
|
400
|
+
# :sign_before_symbol => nil
|
401
|
+
# }
|
391
402
|
end
|
392
403
|
```
|
393
404
|
|
@@ -403,56 +414,26 @@ end
|
|
403
414
|
only! This rate is added to the attached bank object.
|
404
415
|
* ```default_bank```: The default bank object holding exchange rates etc.
|
405
416
|
(https://github.com/RubyMoney/money#currency-exchange)
|
406
|
-
* ```
|
407
|
-
* ```symbol```: Use its value as the default for ```symbol``` key in
|
408
|
-
`Money#format` method.
|
409
|
-
* ```sign_before_symbol```: Force `Money#format` to place the negative sign before the currency symbol.
|
417
|
+
* ```default_format```: Force `Money#format` to use these options for formatting.
|
410
418
|
* ```amount_column```: Provide values for the amount column (holding the fractional part of a money object).
|
411
419
|
* ```currency_column```: Provide default values or even disable (`present: false`) the currency column.
|
412
420
|
* ```rounding_mode```: Set Money.rounding_mode to one of the BigDecimal constants
|
413
421
|
|
414
422
|
### Helpers
|
415
423
|
|
416
|
-
|
424
|
+
_For examples below, `@money_object == <Money fractional:650 currency:USD>`_
|
417
425
|
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
```
|
426
|
-
<%= humanized_money @money_object %>
|
427
|
-
```
|
428
|
-
This will render a formatted money value without the currency symbol and
|
429
|
-
without the cents part if it contains only zeros (uses
|
430
|
-
`:no_cents_if_whole flag`).
|
426
|
+
| Helper | Result |
|
427
|
+
|:--- |:--- |
|
428
|
+
| `currency_symbol` | `<span class="currency_symbol">$</span>` |
|
429
|
+
| `humanized_money @money_object` | 6.50 |
|
430
|
+
| `humanized_money_with_symbol @money_object` | $6.50 |
|
431
|
+
| `money_without_cents @money_object` | 6 |
|
432
|
+
| `money_without_cents_and_with_symbol @money_object` | $6 |
|
431
433
|
|
432
|
-
|
434
|
+
#### `no_cents_if_whole`
|
433
435
|
|
434
|
-
|
435
|
-
<%= humanized_money_with_symbol @money_object %>
|
436
|
-
```
|
437
|
-
This will render a formatted money value including the currency symbol and
|
438
|
-
without the cents part if it contains only zeros.
|
439
|
-
|
440
|
-
* get the money value without the cents part
|
441
|
-
|
442
|
-
```
|
443
|
-
<%= money_without_cents @money_object %>
|
444
|
-
```
|
445
|
-
This will render a formatted money value without the currency symbol and
|
446
|
-
without the cents part.
|
447
|
-
|
448
|
-
* get the money value without the cents part and including the currency
|
449
|
-
symbol
|
450
|
-
|
451
|
-
```
|
452
|
-
<%= money_without_cents_and_with_symbol @money_object %>
|
453
|
-
```
|
454
|
-
This will render a formatted money value including the currency symbol and
|
455
|
-
without the cents part.
|
436
|
+
`humanized_money` and `humanized_money_with_symbol` will not render the cents part if it contains only zeros, unless `config.no_cents_if_whole` is set to `false` in the `money.rb` configuration (default: true).
|
456
437
|
|
457
438
|
### Testing
|
458
439
|
|
@@ -58,10 +58,13 @@ MoneyRails.configure do |config|
|
|
58
58
|
# :decimal_mark => ","
|
59
59
|
# }
|
60
60
|
|
61
|
-
# Set money
|
61
|
+
# Set default money format globally.
|
62
62
|
# Default value is nil meaning "ignore this option".
|
63
|
-
#
|
63
|
+
# Example:
|
64
64
|
#
|
65
|
-
# config.
|
66
|
-
#
|
65
|
+
# config.default_format = {
|
66
|
+
# :no_cents_if_whole => nil,
|
67
|
+
# :symbol => nil,
|
68
|
+
# :sign_before_symbol => nil
|
69
|
+
# }
|
67
70
|
end
|
@@ -17,7 +17,7 @@ module MoneyRails
|
|
17
17
|
if options[:field_currency] || options[:target_name] ||
|
18
18
|
options[:model_currency]
|
19
19
|
ActiveSupport::Deprecation.warn("You are using the old " \
|
20
|
-
"argument keys of monetize command! Instead use :as, " \
|
20
|
+
"argument keys of the monetize command! Instead use :as, " \
|
21
21
|
":with_currency or :with_model_currency")
|
22
22
|
end
|
23
23
|
|
@@ -38,7 +38,7 @@ module MoneyRails
|
|
38
38
|
|
39
39
|
# Form target name for the money backed ActiveModel field:
|
40
40
|
# if a target name is provided then use it
|
41
|
-
# if there is a "
|
41
|
+
# if there is a "{column.postfix}" suffix then just remove it to create the target name
|
42
42
|
# if none of the previous is the case then use a default suffix
|
43
43
|
if name
|
44
44
|
name = name.to_s
|
@@ -50,8 +50,11 @@ module MoneyRails
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# Create a reverse mapping of the monetized attributes
|
53
|
-
@monetized_attributes ||= {}
|
54
|
-
@monetized_attributes[name.
|
53
|
+
@monetized_attributes ||= {}.with_indifferent_access
|
54
|
+
if @monetized_attributes[name].present?
|
55
|
+
raise ArgumentError, "#{self} already has a monetized attribute called '#{name}'"
|
56
|
+
end
|
57
|
+
@monetized_attributes[name] = subunit_name
|
55
58
|
class << self
|
56
59
|
def monetized_attributes
|
57
60
|
@monetized_attributes || superclass.monetized_attributes
|
@@ -151,12 +154,25 @@ module MoneyRails
|
|
151
154
|
rescue ArgumentError
|
152
155
|
raise if MoneyRails.raise_error_on_money_parsing
|
153
156
|
return nil
|
157
|
+
rescue Money::Currency::UnknownCurrency
|
158
|
+
raise if MoneyRails.raise_error_on_money_parsing
|
159
|
+
return nil
|
154
160
|
end
|
155
161
|
end
|
156
162
|
end
|
157
163
|
|
158
164
|
# Update cents
|
159
|
-
|
165
|
+
# If the attribute is aliased, make sure we write to the original
|
166
|
+
# attribute name or an error will be raised.
|
167
|
+
# (Note: 'attribute_aliases' doesn't exist in Rails 3.x, so we
|
168
|
+
# can't tell if the attribute was aliased.)
|
169
|
+
if self.class.respond_to?(:attribute_aliases) &&
|
170
|
+
self.class.attribute_aliases.key?(subunit_name)
|
171
|
+
original_name = self.class.attribute_aliases[subunit_name.to_s]
|
172
|
+
write_attribute(original_name, money.try(:cents))
|
173
|
+
else
|
174
|
+
write_attribute(subunit_name, money.try(:cents))
|
175
|
+
end
|
160
176
|
|
161
177
|
money_currency = money.try(:currency)
|
162
178
|
|
@@ -167,7 +183,7 @@ module MoneyRails
|
|
167
183
|
send("#{instance_currency_name}=", money_currency.try(:iso_code))
|
168
184
|
else
|
169
185
|
current_currency = send("currency_for_#{name}")
|
170
|
-
if money_currency && current_currency != money_currency
|
186
|
+
if money_currency && current_currency != money_currency.id
|
171
187
|
raise "Can't change readonly currency '#{current_currency}' to '#{money_currency}' for field '#{name}'"
|
172
188
|
end
|
173
189
|
end
|
@@ -177,7 +193,7 @@ module MoneyRails
|
|
177
193
|
end
|
178
194
|
|
179
195
|
if validation_enabled
|
180
|
-
# Ensure that the before_type_cast value is updated when
|
196
|
+
# Ensure that the before_type_cast value is updated when setting
|
181
197
|
# the subunit value directly
|
182
198
|
define_method "#{subunit_name}=" do |value|
|
183
199
|
before_type_cast = value.to_f / send("currency_for_#{name}").subunit_to_unit
|
@@ -21,12 +21,12 @@ module MoneyRails
|
|
21
21
|
# Configuration parameters
|
22
22
|
|
23
23
|
def default_currency
|
24
|
-
Money.default_currency
|
24
|
+
Money::Currency.new(Money.default_currency)
|
25
25
|
end
|
26
26
|
|
27
27
|
# Set default currency of money library
|
28
28
|
def default_currency=(currency_name)
|
29
|
-
Money.default_currency =
|
29
|
+
Money.default_currency = currency_name
|
30
30
|
set_amount_column_for_default_currency!
|
31
31
|
set_currency_column_for_default_currency!
|
32
32
|
end
|
@@ -90,6 +90,9 @@ module MoneyRails
|
|
90
90
|
mattr_accessor :sign_before_symbol
|
91
91
|
@@sign_before_symbol = nil
|
92
92
|
|
93
|
+
mattr_accessor :default_format
|
94
|
+
@@default_format = nil
|
95
|
+
|
93
96
|
# Configure whether to raise exception when an improper value
|
94
97
|
# is going to be converted to a Money object.
|
95
98
|
mattr_accessor :raise_error_on_money_parsing
|
data/lib/money-rails/money.rb
CHANGED
@@ -7,7 +7,6 @@ class Money
|
|
7
7
|
rules = normalize_formatting_rules(rules)
|
8
8
|
|
9
9
|
# Apply global defaults for money only for non-nil values
|
10
|
-
# TODO: Add here more setting options
|
11
10
|
defaults = {
|
12
11
|
no_cents_if_whole: MoneyRails::Configuration.no_cents_if_whole,
|
13
12
|
symbol: MoneyRails::Configuration.symbol,
|
@@ -16,6 +15,10 @@ class Money
|
|
16
15
|
|
17
16
|
rules.reverse_merge!(defaults)
|
18
17
|
|
18
|
+
unless MoneyRails::Configuration.default_format.nil?
|
19
|
+
rules.reverse_merge!(MoneyRails::Configuration.default_format)
|
20
|
+
end
|
21
|
+
|
19
22
|
format_without_settings(rules)
|
20
23
|
end
|
21
24
|
|
@@ -14,7 +14,7 @@ class Money
|
|
14
14
|
# this custom class from it.
|
15
15
|
def demongoize(object)
|
16
16
|
if object.is_a?(Hash)
|
17
|
-
object = object.
|
17
|
+
object = object.deep_symbolize_keys
|
18
18
|
object.has_key?(:cents) ? ::Money.new(object[:cents], object[:currency_iso]) : nil
|
19
19
|
else
|
20
20
|
nil
|
@@ -27,7 +27,7 @@ class Money
|
|
27
27
|
case
|
28
28
|
when object.is_a?(Money) then object.mongoize
|
29
29
|
when object.is_a?(Hash) then
|
30
|
-
object.
|
30
|
+
object.deep_symbolize_keys! if object.respond_to?(:deep_symbolize_keys!)
|
31
31
|
::Money.new(object[:cents], object[:currency_iso]).mongoize
|
32
32
|
when object.respond_to?(:to_money) then
|
33
33
|
begin
|
@@ -27,29 +27,22 @@ module MoneyRails
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def matches?(actual)
|
30
|
-
|
31
|
-
|
32
|
-
money_attr = @as.presence || @attribute.to_s.sub(/_cents$/, "")
|
33
|
-
|
34
|
-
matched = true
|
35
|
-
|
36
|
-
if actual.respond_to?(money_attr)
|
37
|
-
if @allow_nil
|
38
|
-
matched &&= actual.send(money_attr).nil?
|
39
|
-
actual.send("#{money_attr}=", 0)
|
40
|
-
end
|
41
|
-
matched &&= actual.send(money_attr).instance_of?(Money)
|
42
|
-
|
43
|
-
if @currency_iso
|
44
|
-
matched &&= actual.send(money_attr.to_sym).currency.id == @currency_iso
|
45
|
-
end
|
30
|
+
if actual.is_a?(Class)
|
31
|
+
@actual = actual.new
|
46
32
|
else
|
47
|
-
|
33
|
+
@actual = actual.class.new
|
48
34
|
end
|
49
35
|
|
50
|
-
|
36
|
+
@money_attribute = @as.presence || @attribute.to_s.sub(/_cents$/, "")
|
37
|
+
@money_attribute_setter = "#{@money_attribute}="
|
38
|
+
|
39
|
+
object_responds_to_attributes? &&
|
40
|
+
test_allow_nil &&
|
41
|
+
is_monetized? &&
|
42
|
+
test_currency_iso
|
51
43
|
end
|
52
44
|
|
45
|
+
|
53
46
|
def description
|
54
47
|
desc = "monetize #{@attribute}"
|
55
48
|
desc << " as #{@as}" if @as
|
@@ -73,6 +66,35 @@ module MoneyRails
|
|
73
66
|
end
|
74
67
|
alias_method :failure_message_for_should_not, :failure_message_when_negated # RSpec 1.2, 2.x, and minitest-matchers
|
75
68
|
alias_method :negative_failure_message, :failure_message_when_negated # RSpec 1.1
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def object_responds_to_attributes?
|
73
|
+
@actual.respond_to?(@attribute) && @actual.respond_to?(@money_attribute)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_allow_nil
|
77
|
+
if @allow_nil
|
78
|
+
@actual.send(@money_attribute_setter, "")
|
79
|
+
@actual.send(@money_attribute).nil?
|
80
|
+
else
|
81
|
+
true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def is_monetized?
|
86
|
+
@actual.send(@money_attribute_setter, 1)
|
87
|
+
@actual.send(@money_attribute).instance_of?(Money)
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_currency_iso
|
91
|
+
if @currency_iso
|
92
|
+
@actual.send(@money_attribute).currency.id == @currency_iso
|
93
|
+
else
|
94
|
+
true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
76
98
|
end
|
77
99
|
end
|
78
100
|
end
|
data/lib/money-rails/version.rb
CHANGED
data/money-rails.gemspec
CHANGED
@@ -32,6 +32,6 @@ Gem::Specification.new do |s|
|
|
32
32
|
s.add_dependency "railties", ">= 3.0"
|
33
33
|
|
34
34
|
s.add_development_dependency "rails", ">= 3.0"
|
35
|
-
s.add_development_dependency "rspec-rails", "~>
|
35
|
+
s.add_development_dependency "rspec-rails", "~> 3.0"
|
36
36
|
s.add_development_dependency 'database_cleaner', ['>= 0.8.0']
|
37
37
|
end
|
@@ -53,8 +53,8 @@ if defined? ActiveRecord
|
|
53
53
|
end
|
54
54
|
|
55
55
|
context 'without currency column' do
|
56
|
-
it { Item.columns_hash['price_without_currency_cents'].
|
57
|
-
it { Item.columns_hash['price_without_currency_currency'].
|
56
|
+
it { expect(Item.columns_hash['price_without_currency_cents']).not_to be nil }
|
57
|
+
it { expect(Item.columns_hash['price_without_currency_currency']).to be nil }
|
58
58
|
end
|
59
59
|
|
60
60
|
context 'full options' do
|
@@ -69,7 +69,7 @@ if defined? ActiveRecord
|
|
69
69
|
end
|
70
70
|
|
71
71
|
describe 'currency' do
|
72
|
-
it { Item.columns_hash['currency'].
|
72
|
+
it { expect(Item.columns_hash['currency']).not_to be nil }
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
@@ -87,13 +87,13 @@ if defined? ActiveRecord
|
|
87
87
|
Item.reset_column_information
|
88
88
|
end
|
89
89
|
|
90
|
-
it { Item.columns_hash['price_cents'].
|
91
|
-
it { Item.columns_hash['price_currency'].
|
90
|
+
it { expect(Item.columns_hash['price_cents']).to be nil }
|
91
|
+
it { expect(Item.columns_hash['price_currency']).to be nil }
|
92
92
|
|
93
|
-
it { Item.columns_hash['price_without_currency_cents'].
|
93
|
+
it { expect(Item.columns_hash['price_without_currency_cents']).to be nil }
|
94
94
|
|
95
|
-
it { Item.columns_hash['prefix_price_with_full_options_postfix'].
|
96
|
-
it { Item.columns_hash['currency'].
|
95
|
+
it { expect(Item.columns_hash['prefix_price_with_full_options_postfix']).to be nil }
|
96
|
+
it { expect(Item.columns_hash['currency']).to be nil }
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
@@ -54,8 +54,8 @@ if defined? ActiveRecord
|
|
54
54
|
end
|
55
55
|
|
56
56
|
context 'without currency column' do
|
57
|
-
it { Item.columns_hash['price_without_currency_cents'].
|
58
|
-
it { Item.columns_hash['price_without_currency_currency'].
|
57
|
+
it { expect(Item.columns_hash['price_without_currency_cents']).not_to be nil }
|
58
|
+
it { expect(Item.columns_hash['price_without_currency_currency']).to be nil }
|
59
59
|
end
|
60
60
|
|
61
61
|
context 'full options' do
|
@@ -70,7 +70,7 @@ if defined? ActiveRecord
|
|
70
70
|
end
|
71
71
|
|
72
72
|
describe 'currency' do
|
73
|
-
it { Item.columns_hash['currency'].
|
73
|
+
it { expect(Item.columns_hash['currency']).not_to be nil }
|
74
74
|
end
|
75
75
|
end
|
76
76
|
end
|
@@ -90,13 +90,13 @@ if defined? ActiveRecord
|
|
90
90
|
Item.reset_column_information
|
91
91
|
end
|
92
92
|
|
93
|
-
it { Item.columns_hash['price_cents'].
|
94
|
-
it { Item.columns_hash['price_currency'].
|
93
|
+
it { expect(Item.columns_hash['price_cents']).to be nil }
|
94
|
+
it { expect(Item.columns_hash['price_currency']).to be nil }
|
95
95
|
|
96
|
-
it { Item.columns_hash['price_without_currency_cents'].
|
96
|
+
it { expect(Item.columns_hash['price_without_currency_cents']).to be nil }
|
97
97
|
|
98
|
-
it { Item.columns_hash['prefix_price_with_full_options_postfix'].
|
99
|
-
it { Item.columns_hash['currency'].
|
98
|
+
it { expect(Item.columns_hash['prefix_price_with_full_options_postfix']).to be nil }
|
99
|
+
it { expect(Item.columns_hash['currency']).to be nil }
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|