money 2.2.0 → 2.3.0
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/CHANGELOG.rdoc +9 -0
- data/README.rdoc +92 -10
- data/Rakefile +7 -2
- data/VERSION +1 -1
- data/lib/money/core_extensions.rb +7 -1
- data/lib/money/currency.rb +289 -0
- data/lib/money/defaults.rb +55 -29
- data/lib/money/money.rb +58 -24
- data/lib/money/variable_exchange_bank.rb +1 -1
- data/money.gemspec +9 -4
- data/test/core_extensions_spec.rb +18 -6
- data/test/currency_spec.rb +113 -0
- data/test/money_spec.rb +80 -19
- metadata +33 -13
data/lib/money/defaults.rb
CHANGED
@@ -1,31 +1,57 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
}
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
#
|
31
|
-
|
3
|
+
class Money
|
4
|
+
|
5
|
+
class DeprecatedHash < Hash
|
6
|
+
|
7
|
+
def initialize(hash, message)
|
8
|
+
@message = message
|
9
|
+
replace(hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](key)
|
13
|
+
deprecate
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def []=(value)
|
18
|
+
deprecate
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def deprecate
|
25
|
+
warn "DEPRECATION MESSAGE: #{@message}"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
# @deprecated See Money::Currency#symbol
|
31
|
+
SYMBOLS = DeprecatedHash.new({
|
32
|
+
"GBP" => "£",
|
33
|
+
"JPY" => "¥",
|
34
|
+
"EUR" => "€",
|
35
|
+
"ZWD" => "Z$",
|
36
|
+
"CNY" => "¥",
|
37
|
+
"INR" => "₨",
|
38
|
+
"NPR" => "₨",
|
39
|
+
"SCR" => "₨",
|
40
|
+
"LKR" => "₨",
|
41
|
+
"SEK" => "kr",
|
42
|
+
"GHC" => "¢",
|
43
|
+
"BRL" => "R$ ",
|
44
|
+
# Everything else defaults to '$'
|
45
|
+
}, "Money::SYMBOLS has no longer effect. See Money::Currency#symbol.")
|
46
|
+
|
47
|
+
SEPARATORS = {
|
48
|
+
"BRL" => ",",
|
49
|
+
# Everything else defaults to '.'
|
50
|
+
}
|
51
|
+
|
52
|
+
DELIMITERS = {
|
53
|
+
"BRL" => ".",
|
54
|
+
# Everything else defaults to ","
|
55
|
+
}
|
56
|
+
|
57
|
+
end
|
data/lib/money/money.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'money/currency'
|
1
3
|
require 'money/variable_exchange_bank'
|
2
4
|
|
3
5
|
# Represents an amount of money in a certain currency.
|
@@ -5,7 +7,7 @@ class Money
|
|
5
7
|
include Comparable
|
6
8
|
|
7
9
|
attr_reader :cents, :currency, :bank
|
8
|
-
|
10
|
+
|
9
11
|
class << self
|
10
12
|
# Each Money object is associated to a bank object, which is responsible
|
11
13
|
# for currency exchange. This property allows one to specify the default
|
@@ -33,12 +35,13 @@ class Money
|
|
33
35
|
attr_accessor :default_bank
|
34
36
|
|
35
37
|
# The default currency, which is used when <tt>Money.new</tt> is called
|
36
|
-
# without an explicit currency argument. The default value is "USD".
|
38
|
+
# without an explicit currency argument. The default value is Currency.new("USD").
|
39
|
+
# The value must be a valid <tt>Money::Currency</tt> instance.
|
37
40
|
attr_accessor :default_currency
|
38
41
|
end
|
39
42
|
|
40
43
|
self.default_bank = VariableExchangeBank.instance
|
41
|
-
self.default_currency = "USD"
|
44
|
+
self.default_currency = Currency.new("USD")
|
42
45
|
|
43
46
|
|
44
47
|
# Create a new money object with value 0.
|
@@ -80,9 +83,9 @@ class Money
|
|
80
83
|
# Money.new(50, :currency => "USD")
|
81
84
|
#
|
82
85
|
# We retain compatibility here.
|
83
|
-
@currency = currency[:currency] || Money.default_currency
|
86
|
+
@currency = Currency.wrap(currency[:currency] || Money.default_currency)
|
84
87
|
else
|
85
|
-
@currency = currency
|
88
|
+
@currency = Currency.wrap(currency)
|
86
89
|
end
|
87
90
|
@bank = bank
|
88
91
|
end
|
@@ -165,6 +168,30 @@ class Money
|
|
165
168
|
end
|
166
169
|
|
167
170
|
|
171
|
+
# Attempts to pick a symbol that's suitable for the given currency
|
172
|
+
# looking up the Currency::TABLE hashtable.
|
173
|
+
# If the symbol for the given currency isn't known,
|
174
|
+
# then it will default to "$".
|
175
|
+
def symbol
|
176
|
+
currency.symbol || "$"
|
177
|
+
end
|
178
|
+
|
179
|
+
# Attempts to pick a delimiter that's suitable for the given currency
|
180
|
+
# looking up the Money::DELIMITERS hashtable.
|
181
|
+
# If the symbol for the given currency isn't known,
|
182
|
+
# then it will default to ",".
|
183
|
+
def delimiter
|
184
|
+
DELIMITERS[currency.to_s] || ","
|
185
|
+
end
|
186
|
+
|
187
|
+
# Attempts to pick a separator for <tt>cents</tt> that's suitable for the given currency
|
188
|
+
# looking up the Money::DELIMITERS hashtable.
|
189
|
+
# If the separator for the given currency isn't known,
|
190
|
+
# then it will default to ".".
|
191
|
+
def separator
|
192
|
+
SEPARATORS[currency.to_s] || "."
|
193
|
+
end
|
194
|
+
|
168
195
|
# Creates a formatted price string according to several rules. The following
|
169
196
|
# options are supported: :display_free, :with_currency, :no_cents, :symbol,
|
170
197
|
# :separator, :delimiter and :html.
|
@@ -279,52 +306,52 @@ class Money
|
|
279
306
|
|
280
307
|
if rules.has_key?(:symbol)
|
281
308
|
if rules[:symbol] === true
|
282
|
-
|
309
|
+
symbol_value = symbol
|
283
310
|
elsif rules[:symbol]
|
284
|
-
|
311
|
+
symbol_value = rules[:symbol]
|
285
312
|
else
|
286
|
-
|
313
|
+
symbol_value = ""
|
287
314
|
end
|
288
315
|
else
|
289
|
-
|
316
|
+
symbol_value = symbol
|
290
317
|
end
|
291
318
|
|
292
319
|
if rules[:no_cents]
|
293
|
-
formatted = sprintf("#{
|
320
|
+
formatted = sprintf("#{symbol_value}%d", cents.to_f / 100)
|
294
321
|
else
|
295
|
-
formatted = sprintf("#{
|
322
|
+
formatted = sprintf("#{symbol_value}%.2f", cents.to_f / 100)
|
296
323
|
end
|
297
324
|
|
298
|
-
|
325
|
+
delimiter_value = delimiter
|
299
326
|
# Determine delimiter
|
300
327
|
if rules.has_key?(:delimiter)
|
301
328
|
if rules[:delimiter] === false or rules[:delimiter].nil?
|
302
|
-
|
329
|
+
delimiter_value = ""
|
303
330
|
elsif rules[:delimiter]
|
304
|
-
|
331
|
+
delimiter_value = rules[:delimiter]
|
305
332
|
end
|
306
333
|
end
|
307
334
|
|
308
335
|
# Apply delimiter
|
309
|
-
formatted.gsub!(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/, "\\1#{
|
336
|
+
formatted.gsub!(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/, "\\1#{delimiter_value}\\2")
|
310
337
|
|
311
|
-
|
338
|
+
separator_value = separator
|
312
339
|
# Determine separator
|
313
340
|
if rules.has_key?(:separator) and rules[:separator]
|
314
|
-
|
341
|
+
separator_value = rules[:separator]
|
315
342
|
end
|
316
343
|
|
317
344
|
# Apply separator
|
318
|
-
formatted.sub!(/\.(\d{2})$/, "#{
|
345
|
+
formatted.sub!(/\.(\d{2})$/, "#{separator_value}\\1")
|
319
346
|
|
320
347
|
if rules[:with_currency]
|
321
348
|
formatted << " "
|
322
349
|
formatted << '<span class="currency">' if rules[:html]
|
323
|
-
formatted << currency
|
350
|
+
formatted << currency.to_s
|
324
351
|
formatted << '</span>' if rules[:html]
|
325
352
|
end
|
326
353
|
formatted
|
327
|
-
end
|
354
|
+
end
|
328
355
|
|
329
356
|
# Returns the amount of money as a string.
|
330
357
|
#
|
@@ -342,12 +369,19 @@ class Money
|
|
342
369
|
def to_f
|
343
370
|
cents / 100.0
|
344
371
|
end
|
345
|
-
|
346
|
-
# Recieve the amount of this money object in another
|
372
|
+
|
373
|
+
# Recieve the amount of this money object in another Currency.
|
374
|
+
# <tt>other_currency</tt> can be either a <tt>String</tt>
|
375
|
+
# or a <tt>Currency</tt> instance.
|
376
|
+
#
|
377
|
+
# Money.new(2000, "USD").exchange_to("EUR")
|
378
|
+
# Money.new(2000, "USD").exchange_to(Currency.new("EUR"))
|
379
|
+
#
|
347
380
|
def exchange_to(other_currency)
|
381
|
+
other_currency = Currency.wrap(other_currency)
|
348
382
|
Money.new(@bank.exchange(self.cents, currency, other_currency), other_currency)
|
349
|
-
end
|
350
|
-
|
383
|
+
end
|
384
|
+
|
351
385
|
# Recieve a money object with the same amount as the current Money object
|
352
386
|
# in american dollar
|
353
387
|
def as_us_dollar
|
@@ -52,7 +52,7 @@ class Money
|
|
52
52
|
# bank.same_currency?("usd", "USD") # => true
|
53
53
|
# bank.same_currency?("usd", "EUR") # => false
|
54
54
|
def same_currency?(currency1, currency2)
|
55
|
-
currency1
|
55
|
+
Currency.wrap(currency1) == Currency.wrap(currency2)
|
56
56
|
end
|
57
57
|
|
58
58
|
# Exchange the given amount of cents in +from_currency+ to +to_currency+.
|
data/money.gemspec
CHANGED
@@ -5,32 +5,36 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{money}
|
8
|
-
s.version = "2.
|
8
|
+
s.version = "2.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Tobias Luetke", "Hongli Lai", "Jeremy McNevin", "Shane Emmons"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-04-16}
|
13
13
|
s.description = %q{Money and currency exchange support library.}
|
14
14
|
s.email = %q{hongli@phusion.nl}
|
15
15
|
s.extra_rdoc_files = [
|
16
|
-
"
|
16
|
+
"CHANGELOG.rdoc",
|
17
|
+
"LICENSE",
|
17
18
|
"README.rdoc"
|
18
19
|
]
|
19
20
|
s.files = [
|
20
21
|
".document",
|
21
22
|
".gitignore",
|
23
|
+
"CHANGELOG.rdoc",
|
22
24
|
"LICENSE",
|
23
25
|
"README.rdoc",
|
24
26
|
"Rakefile",
|
25
27
|
"VERSION",
|
26
28
|
"lib/money.rb",
|
27
29
|
"lib/money/core_extensions.rb",
|
30
|
+
"lib/money/currency.rb",
|
28
31
|
"lib/money/defaults.rb",
|
29
32
|
"lib/money/errors.rb",
|
30
33
|
"lib/money/money.rb",
|
31
34
|
"lib/money/variable_exchange_bank.rb",
|
32
35
|
"money.gemspec",
|
33
36
|
"test/core_extensions_spec.rb",
|
37
|
+
"test/currency_spec.rb",
|
34
38
|
"test/exchange_bank_spec.rb",
|
35
39
|
"test/money_spec.rb"
|
36
40
|
]
|
@@ -38,10 +42,11 @@ Gem::Specification.new do |s|
|
|
38
42
|
s.rdoc_options = ["--charset=UTF-8"]
|
39
43
|
s.require_paths = ["lib"]
|
40
44
|
s.rubyforge_project = %q{money}
|
41
|
-
s.rubygems_version = %q{1.3.
|
45
|
+
s.rubygems_version = %q{1.3.6}
|
42
46
|
s.summary = %q{Money and currency exchange support library}
|
43
47
|
s.test_files = [
|
44
48
|
"test/core_extensions_spec.rb",
|
49
|
+
"test/currency_spec.rb",
|
45
50
|
"test/exchange_bank_spec.rb",
|
46
51
|
"test/money_spec.rb"
|
47
52
|
]
|
@@ -1,4 +1,5 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
|
2
|
+
|
2
3
|
require 'money/core_extensions'
|
3
4
|
|
4
5
|
describe "Money core extensions" do
|
@@ -6,12 +7,12 @@ describe "Money core extensions" do
|
|
6
7
|
money = 1234.to_money
|
7
8
|
money.cents.should == 1234_00
|
8
9
|
money.currency.should == Money.default_currency
|
9
|
-
|
10
|
+
|
10
11
|
money = 100.37.to_money
|
11
12
|
money.cents.should == 100_37
|
12
13
|
money.currency.should == Money.default_currency
|
13
14
|
end
|
14
|
-
|
15
|
+
|
15
16
|
specify "String#to_money works" do
|
16
17
|
"20.15".to_money.should == Money.new(20_15)
|
17
18
|
"100".to_money.should == Money.new(100_00)
|
@@ -31,7 +32,7 @@ describe "Money core extensions" do
|
|
31
32
|
"1.550".to_money.should == Money.new(1_55)
|
32
33
|
"25.".to_money.should == Money.new(25_00)
|
33
34
|
".75".to_money.should == Money.new(75)
|
34
|
-
|
35
|
+
|
35
36
|
"100 USD".to_money.should == Money.new(100_00, "USD")
|
36
37
|
"-100 USD".to_money.should == Money.new(-100_00, "USD")
|
37
38
|
"100 EUR".to_money.should == Money.new(100_00, "EUR")
|
@@ -44,7 +45,7 @@ describe "Money core extensions" do
|
|
44
45
|
"1,000.5500 USD".to_money.should == Money.new(1_000_55, "USD")
|
45
46
|
"-1,000.6500 USD".to_money.should == Money.new(-1_000_65, "USD")
|
46
47
|
"1.550 USD".to_money.should == Money.new(1_55, "USD")
|
47
|
-
|
48
|
+
|
48
49
|
"USD 100".to_money.should == Money.new(100_00, "USD")
|
49
50
|
"EUR 100".to_money.should == Money.new(100_00, "EUR")
|
50
51
|
"EUR 100.37".to_money.should == Money.new(100_37, "EUR")
|
@@ -58,7 +59,7 @@ describe "Money core extensions" do
|
|
58
59
|
"USD 1,000.9000".to_money.should == Money.new(1_000_90, "USD")
|
59
60
|
"USD -1,000.090".to_money.should == Money.new(-1_000_09, "USD")
|
60
61
|
"USD 1.5500".to_money.should == Money.new(1_55, "USD")
|
61
|
-
|
62
|
+
|
62
63
|
"$100 USD".to_money.should == Money.new(100_00, "USD")
|
63
64
|
"$1,194.59 USD".to_money.should == Money.new(1_194_59, "USD")
|
64
65
|
"$-1,955 USD".to_money.should == Money.new(-1_955_00, "USD")
|
@@ -66,8 +67,19 @@ describe "Money core extensions" do
|
|
66
67
|
"$-1,955.000 USD".to_money.should == Money.new(-1_955_00, "USD")
|
67
68
|
"$1.99000 USD".to_money.should == Money.new(1_99, "USD")
|
68
69
|
end
|
69
|
-
|
70
|
+
|
70
71
|
specify "String#to_money ignores unrecognized data" do
|
71
72
|
"hello 2000 world".to_money.should == Money.new(2000_00)
|
72
73
|
end
|
74
|
+
|
75
|
+
specify "String#to_currency convert string to Currency" do
|
76
|
+
"USD".to_currency.should == Money::Currency.new(:usd)
|
77
|
+
"EUR".to_currency.should == Money::Currency.new(:eur)
|
78
|
+
end
|
79
|
+
|
80
|
+
specify "String#to_currency should raise Currency::UnknownCurrency with unkwnown Currency" do
|
81
|
+
lambda { "XXX".to_currency }.should raise_error(Money::Currency::UnknownCurrency)
|
82
|
+
lambda { " ".to_currency }.should raise_error(Money::Currency::UnknownCurrency)
|
83
|
+
end
|
84
|
+
|
73
85
|
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
|
4
|
+
|
5
|
+
require 'money/money'
|
6
|
+
require 'money/currency'
|
7
|
+
require 'money/defaults'
|
8
|
+
|
9
|
+
describe Money::Currency do
|
10
|
+
|
11
|
+
specify "#initialize should lookup data from TABLE" do
|
12
|
+
with_custom_definitions do
|
13
|
+
Money::Currency::TABLE[:usd] = { :priority => 1, :iso_code => "USD", :name => "United States Dollar", :symbol => "$", :subunit => "Cent", :subunit_to_unit => "100" }
|
14
|
+
Money::Currency::TABLE[:eur] = { :priority => 2, :iso_code => "EUR", :name => "Euro", :symbol => "€", :subunit => "Cent", :subunit_to_unit => "100" }
|
15
|
+
|
16
|
+
currency = Money::Currency.new("USD")
|
17
|
+
currency.id.should == :usd
|
18
|
+
currency.priority.should == 1
|
19
|
+
currency.iso_code.should == "USD"
|
20
|
+
currency.name.should == "United States Dollar"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
specify "#initialize should raise UnknownMoney::Currency with unknown currency" do
|
25
|
+
lambda { Money::Currency.new("xxx") }.should raise_error(Money::Currency::UnknownCurrency, /xxx/)
|
26
|
+
end
|
27
|
+
|
28
|
+
specify "#== should return true if self === other" do
|
29
|
+
currency = Money::Currency.new(:eur)
|
30
|
+
currency.should == currency
|
31
|
+
end
|
32
|
+
|
33
|
+
specify "#== should return true if the id is equal" do
|
34
|
+
Money::Currency.new(:eur).should == Money::Currency.new(:eur)
|
35
|
+
Money::Currency.new(:eur).should_not == Money::Currency.new(:usd)
|
36
|
+
end
|
37
|
+
|
38
|
+
specify "#<=> should compare objects by priority" do
|
39
|
+
Money::Currency.new(:cad).should > Money::Currency.new(:usd)
|
40
|
+
Money::Currency.new(:usd).should < Money::Currency.new(:eur)
|
41
|
+
end
|
42
|
+
|
43
|
+
specify "#to_s" do
|
44
|
+
Money::Currency.new(:usd).to_s.should == "USD"
|
45
|
+
Money::Currency.new(:eur).to_s.should == "EUR"
|
46
|
+
end
|
47
|
+
|
48
|
+
specify "#inspect" do
|
49
|
+
Money::Currency.new(:usd).inspect.should ==
|
50
|
+
%Q{#<Money::Currency id: usd priority: 1, iso_code: USD, name: United States Dollar, symbol: $, subunit: Cent, subunit_to_unit: 100>}
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
specify "#self.find should return currency matching given id" do
|
55
|
+
with_custom_definitions do
|
56
|
+
Money::Currency::TABLE[:usd] = { :priority => 1, :iso_code => "USD", :name => "United States Dollar", :symbol => "$", :subunit => "Cent", :subunit_to_unit => "100" }
|
57
|
+
Money::Currency::TABLE[:eur] = { :priority => 2, :iso_code => "EUR", :name => "Euro", :symbol => "€", :subunit => "Cent", :subunit_to_unit => "100" }
|
58
|
+
|
59
|
+
expected = Money::Currency.new(:eur)
|
60
|
+
Money::Currency.find(:eur).should == expected
|
61
|
+
Money::Currency.find(:EUR).should == expected
|
62
|
+
Money::Currency.find("eur").should == expected
|
63
|
+
Money::Currency.find("EUR").should == expected
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
specify "#self.find should return nil unless currency matching given id" do
|
68
|
+
with_custom_definitions do
|
69
|
+
Money::Currency::TABLE[:usd] = { :position => 1, :iso_code => "USD", :name => "United States Dollar", :symbol => "$", :subunit => "Cent", :subunit_to_unit => "100" }
|
70
|
+
Money::Currency::TABLE[:eur] = { :position => 2, :iso_code => "EUR", :name => "Euro", :symbol => "€", :subunit => "Cent", :subunit_to_unit => "100" }
|
71
|
+
|
72
|
+
expected = Money::Currency.new(:eur)
|
73
|
+
Money::Currency.find(:eur).should == expected
|
74
|
+
Money::Currency.find(:EUR).should == expected
|
75
|
+
Money::Currency.find("eur").should == expected
|
76
|
+
Money::Currency.find("EUR").should == expected
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
specify "#self.wrap should return nil if object is nil" do
|
81
|
+
Money::Currency.wrap(nil).should == nil
|
82
|
+
Money::Currency.wrap(Money::Currency.new(:usd)).should == Money::Currency.new(:usd)
|
83
|
+
Money::Currency.wrap(:usd).should == Money::Currency.new(:usd)
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def with_custom_definitions(&block)
|
88
|
+
begin
|
89
|
+
old = Money::Currency::TABLE.dup
|
90
|
+
Money::Currency::TABLE.clear
|
91
|
+
yield
|
92
|
+
ensure
|
93
|
+
silence_warnings do
|
94
|
+
Money::Currency.const_set("TABLE", old)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.
|
100
|
+
#
|
101
|
+
# silence_warnings do
|
102
|
+
# value = noisy_call # no warning voiced
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
# noisy_call # warning voiced
|
106
|
+
def silence_warnings
|
107
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
108
|
+
yield
|
109
|
+
ensure
|
110
|
+
$VERBOSE = old_verbose
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|