money 6.8.4 → 6.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +4 -0
- data/lib/money.rb +0 -13
- data/lib/money/currency/heuristics.rb +1 -144
- data/lib/money/version.rb +1 -1
- data/money.gemspec +0 -1
- data/spec/currency/heuristics_spec.rb +2 -153
- metadata +2 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f268faeee9a1901f8a4e482e8497370697eb436a
|
4
|
+
data.tar.gz: 54f37ca793f33929f7c1dd10de33d58c813495fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9d33bfe048a6ba6fe92391ac9223a92268f31bd6c1f0ef932f2d202fd3a45e7df013c5c96d5ac99b98aacde1ece7a905fda77949aa9e4ad7625698b16b5914f
|
7
|
+
data.tar.gz: b3b255302aec3569a1b7e1b4dc5a7e1a77b1b4129c09eb65f295461eadc48cc342f09de81236a229a6d4139a5038069108fdc53660d09255c9d3fa1130d22a02
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -435,6 +435,10 @@ m = Money.new('123', :gbp) # => #<Money fractional:123 currency:GBP>
|
|
435
435
|
m.format( symbol: m.currency.to_s + ' ') # => "GBP 1.23"
|
436
436
|
```
|
437
437
|
|
438
|
+
## Heuristics
|
439
|
+
|
440
|
+
Prior to v6.9.0 heuristic analysis of string input was part of this gem. Since then it was extracted in to [money-heuristics gem](https://github.com/RubyMoney/money-heuristics).
|
441
|
+
|
438
442
|
## Migration Notes
|
439
443
|
|
440
444
|
#### Version 6.0.0
|
data/lib/money.rb
CHANGED
@@ -2,18 +2,5 @@ require "bigdecimal"
|
|
2
2
|
require "bigdecimal/util"
|
3
3
|
require "set"
|
4
4
|
require "i18n"
|
5
|
-
require "sixarm_ruby_unaccent"
|
6
5
|
require "money/currency"
|
7
6
|
require "money/money"
|
8
|
-
|
9
|
-
# Overwrites unaccent method of sixarm_ruby_unaccent.
|
10
|
-
class String
|
11
|
-
def unaccent
|
12
|
-
accentmap = ACCENTMAP
|
13
|
-
accentmap.delete("\u{0142}") # Delete ł symbol from ACCENTMAP used in PLN currency
|
14
|
-
accentmap.delete("\u{010D}") # Delete č symbol from ACCENTMAP used in CZK currency
|
15
|
-
accentmap.delete("\u{FDFC}") # Delete ﷼ symbol from ACCENTMAP used in IRR, SAR and YER currencies
|
16
|
-
accentmap.delete("\u{20A8}") # Delete ₨ symbol from ACCENTMAP used in INR, LKR, MUR, NPR, PKR and SCR currencies
|
17
|
-
split(//u).map {|c| accentmap[c] || c }.join("")
|
18
|
-
end
|
19
|
-
end
|
@@ -3,152 +3,9 @@
|
|
3
3
|
class Money
|
4
4
|
class Currency
|
5
5
|
module Heuristics
|
6
|
-
|
7
|
-
# An robust and efficient algorithm for finding currencies in
|
8
|
-
# text. Using several algorithms it can find symbols, iso codes and
|
9
|
-
# even names of currencies.
|
10
|
-
# Although not recommendable, it can also attempt to find the given
|
11
|
-
# currency in an entire sentence
|
12
|
-
#
|
13
|
-
# Returns: Array (matched results)
|
14
6
|
def analyze(str)
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
# Build a search tree from the currency database
|
21
|
-
def search_tree
|
22
|
-
@_search_tree ||= {
|
23
|
-
:by_symbol => currencies_by_symbol,
|
24
|
-
:by_iso_code => currencies_by_iso_code,
|
25
|
-
:by_name => currencies_by_name
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
|
-
def currencies_by_symbol
|
30
|
-
{}.tap do |r|
|
31
|
-
table.each do |dummy, c|
|
32
|
-
symbol = (c[:symbol]||"").downcase
|
33
|
-
symbol.chomp!('.')
|
34
|
-
(r[symbol] ||= []) << c
|
35
|
-
|
36
|
-
(c[:alternate_symbols]||[]).each do |ac|
|
37
|
-
ac = ac.downcase
|
38
|
-
ac.chomp!('.')
|
39
|
-
(r[ac] ||= []) << c
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def currencies_by_iso_code
|
46
|
-
{}.tap do |r|
|
47
|
-
table.each do |dummy,c|
|
48
|
-
(r[c[:iso_code].downcase] ||= []) << c
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def currencies_by_name
|
54
|
-
{}.tap do |r|
|
55
|
-
table.each do |dummy,c|
|
56
|
-
name_parts = c[:name].unaccent.downcase.split
|
57
|
-
name_parts.each {|part| part.chomp!('.')}
|
58
|
-
|
59
|
-
# construct one branch per word
|
60
|
-
root = r
|
61
|
-
while name_part = name_parts.shift
|
62
|
-
root = (root[name_part] ||= {})
|
63
|
-
end
|
64
|
-
|
65
|
-
# the leaf is a currency
|
66
|
-
(root[:value] ||= []) << c
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
class Analyzer
|
72
|
-
attr_reader :search_tree, :words
|
73
|
-
attr_accessor :str, :currencies
|
74
|
-
|
75
|
-
def initialize str, search_tree
|
76
|
-
@str = (str||'').dup
|
77
|
-
@search_tree = search_tree
|
78
|
-
@currencies = []
|
79
|
-
end
|
80
|
-
|
81
|
-
def process
|
82
|
-
format
|
83
|
-
return [] if str.empty?
|
84
|
-
|
85
|
-
search_by_symbol
|
86
|
-
search_by_iso_code
|
87
|
-
search_by_name
|
88
|
-
|
89
|
-
prepare_reply
|
90
|
-
end
|
91
|
-
|
92
|
-
def format
|
93
|
-
str.gsub!(/[\r\n\t]/,'')
|
94
|
-
str.gsub!(/[0-9][\.,:0-9]*[0-9]/,'')
|
95
|
-
str.gsub!(/[0-9]/, '')
|
96
|
-
str.downcase!
|
97
|
-
@words = str.unaccent.split
|
98
|
-
@words.each {|word| word.chomp!('.'); word.chomp!(',') }
|
99
|
-
end
|
100
|
-
|
101
|
-
def search_by_symbol
|
102
|
-
words.each do |word|
|
103
|
-
if found = search_tree[:by_symbol][word]
|
104
|
-
currencies.concat(found)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def search_by_iso_code
|
110
|
-
words.each do |word|
|
111
|
-
if found = search_tree[:by_iso_code][word]
|
112
|
-
currencies.concat(found)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def search_by_name
|
118
|
-
# remember, the search tree by name is a construct of branches and leaf!
|
119
|
-
# We need to try every combination of words within the sentence, so we
|
120
|
-
# end up with a x^2 equation, which should be fine as most names are either
|
121
|
-
# one or two words, and this is multiplied with the words of given sentence
|
122
|
-
|
123
|
-
search_words = words.dup
|
124
|
-
|
125
|
-
while search_words.length > 0
|
126
|
-
root = search_tree[:by_name]
|
127
|
-
|
128
|
-
search_words.each do |word|
|
129
|
-
if root = root[word]
|
130
|
-
if root[:value]
|
131
|
-
currencies.concat(root[:value])
|
132
|
-
end
|
133
|
-
else
|
134
|
-
break
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
search_words.delete_at(0)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def prepare_reply
|
143
|
-
codes = currencies.map do |currency|
|
144
|
-
currency[:iso_code]
|
145
|
-
end
|
146
|
-
codes.uniq!
|
147
|
-
codes.sort!
|
148
|
-
codes
|
149
|
-
end
|
7
|
+
raise StandardError, 'Heuristics deprecated, add `gem "money-heuristics"` to Gemfile'
|
150
8
|
end
|
151
9
|
end
|
152
10
|
end
|
153
11
|
end
|
154
|
-
|
data/lib/money/version.rb
CHANGED
data/money.gemspec
CHANGED
@@ -4,159 +4,8 @@ describe Money::Currency::Heuristics do
|
|
4
4
|
describe "#analyze_string" do
|
5
5
|
let(:it) { Money::Currency }
|
6
6
|
|
7
|
-
it "
|
8
|
-
expect
|
9
|
-
expect(it.analyze('\n123 \t')).to eq []
|
10
|
-
end
|
11
|
-
|
12
|
-
it "returns nothing when given nothing" do
|
13
|
-
expect(it.analyze('')).to eq []
|
14
|
-
expect(it.analyze(nil)).to eq []
|
15
|
-
end
|
16
|
-
|
17
|
-
it "finds a currency by use of its symbol" do
|
18
|
-
expect(it.analyze('zł')).to eq ['PLN']
|
19
|
-
end
|
20
|
-
|
21
|
-
it "is not affected by trailing dot" do
|
22
|
-
expect(it.analyze('zł.')).to eq ['PLN']
|
23
|
-
end
|
24
|
-
|
25
|
-
it "finds match even if has numbers after" do
|
26
|
-
expect(it.analyze('zł 123')).to eq ['PLN']
|
27
|
-
end
|
28
|
-
|
29
|
-
it "finds match even if has numbers before" do
|
30
|
-
expect(it.analyze('123 zł')).to eq ['PLN']
|
31
|
-
end
|
32
|
-
|
33
|
-
it "find match even if symbol is next to number" do
|
34
|
-
expect(it.analyze('300zł')).to eq ['PLN']
|
35
|
-
end
|
36
|
-
|
37
|
-
it "finds match even if has numbers with delimiters" do
|
38
|
-
expect(it.analyze('zł 123,000.50')).to eq ['PLN']
|
39
|
-
expect(it.analyze('zł123,000.50')).to eq ['PLN']
|
40
|
-
end
|
41
|
-
|
42
|
-
it "finds currencies with dots in symbols" do
|
43
|
-
expect(it.analyze('L.E.')).to eq ['EGP']
|
44
|
-
end
|
45
|
-
|
46
|
-
it "finds by name" do
|
47
|
-
expect(it.analyze('1900 bulgarian lev')).to eq ['BGN']
|
48
|
-
expect(it.analyze('Swedish Krona')).to eq ['SEK']
|
49
|
-
end
|
50
|
-
|
51
|
-
it "Finds several currencies when several match" do
|
52
|
-
r = it.analyze('$400')
|
53
|
-
expect(r).to include("ARS")
|
54
|
-
expect(r).to include("USD")
|
55
|
-
expect(r).to include("NZD")
|
56
|
-
|
57
|
-
r = it.analyze('9000 £')
|
58
|
-
expect(r).to include("GBP")
|
59
|
-
expect(r).to include("SHP")
|
60
|
-
expect(r).to include("SYP")
|
61
|
-
end
|
62
|
-
|
63
|
-
it "should use alternate symbols" do
|
64
|
-
expect(it.analyze('US$')).to eq ['USD']
|
65
|
-
end
|
66
|
-
|
67
|
-
it "finds a currency by use of its iso code" do
|
68
|
-
expect(it.analyze('USD 200')).to eq ['USD']
|
69
|
-
end
|
70
|
-
|
71
|
-
it "finds currencies in the middle of a sentence!" do
|
72
|
-
expect(it.analyze('It would be nice to have 10000 Albanian lek by tomorrow!')).to eq ['ALL']
|
73
|
-
end
|
74
|
-
|
75
|
-
it "finds several currencies in the same text!" do
|
76
|
-
expect(it.analyze("10EUR is less than 100:- but really, I want US$1")).to eq ['EUR', 'SEK', 'USD']
|
77
|
-
end
|
78
|
-
|
79
|
-
it "find currencies with normal characters in name using unaccent" do
|
80
|
-
expect(it.analyze("10 Nicaraguan Cordoba")).to eq ["NIO"]
|
81
|
-
end
|
82
|
-
|
83
|
-
it "find currencies with special characters in name using unaccent" do
|
84
|
-
expect(it.analyze("10 Nicaraguan Córdoba")).to eq ["NIO"]
|
85
|
-
end
|
86
|
-
|
87
|
-
it "find currencies with special symbols using unaccent" do
|
88
|
-
expect(it.analyze("ل.س")).not_to eq []
|
89
|
-
expect(it.analyze("R₣")).not_to eq []
|
90
|
-
expect(it.analyze("ரூ")).not_to eq []
|
91
|
-
expect(it.analyze("රු")).not_to eq []
|
92
|
-
expect(it.analyze("сом")).not_to eq []
|
93
|
-
expect(it.analyze("圓")).not_to eq []
|
94
|
-
expect(it.analyze("円")).not_to eq []
|
95
|
-
expect(it.analyze("৳")).not_to eq []
|
96
|
-
expect(it.analyze("૱")).not_to eq []
|
97
|
-
expect(it.analyze("௹")).not_to eq []
|
98
|
-
expect(it.analyze("रु")).not_to eq []
|
99
|
-
expect(it.analyze("ש״ח")).not_to eq []
|
100
|
-
expect(it.analyze("元")).not_to eq []
|
101
|
-
expect(it.analyze("¢")).not_to eq []
|
102
|
-
expect(it.analyze("£")).not_to eq []
|
103
|
-
expect(it.analyze("€")).not_to eq []
|
104
|
-
expect(it.analyze("¥")).not_to eq []
|
105
|
-
expect(it.analyze("د.إ")).not_to eq []
|
106
|
-
expect(it.analyze("؋")).not_to eq []
|
107
|
-
expect(it.analyze("դր.")).not_to eq []
|
108
|
-
expect(it.analyze("ƒ")).not_to eq []
|
109
|
-
expect(it.analyze("₼")).not_to eq []
|
110
|
-
expect(it.analyze("৳")).not_to eq []
|
111
|
-
expect(it.analyze("лв")).not_to eq []
|
112
|
-
expect(it.analyze("лев")).not_to eq []
|
113
|
-
expect(it.analyze("дин")).not_to eq []
|
114
|
-
expect(it.analyze("ب.د")).not_to eq []
|
115
|
-
expect(it.analyze("₡")).not_to eq []
|
116
|
-
expect(it.analyze("Kč")).not_to eq []
|
117
|
-
expect(it.analyze("د.ج")).not_to eq []
|
118
|
-
expect(it.analyze("ج.م")).not_to eq []
|
119
|
-
expect(it.analyze("ლ")).not_to eq []
|
120
|
-
expect(it.analyze("₵")).not_to eq []
|
121
|
-
expect(it.analyze("₪")).not_to eq []
|
122
|
-
expect(it.analyze("₹")).not_to eq []
|
123
|
-
expect(it.analyze("ع.د")).not_to eq []
|
124
|
-
expect(it.analyze("﷼")).not_to eq []
|
125
|
-
expect(it.analyze("د.ا")).not_to eq []
|
126
|
-
expect(it.analyze("៛")).not_to eq []
|
127
|
-
expect(it.analyze("₩")).not_to eq []
|
128
|
-
expect(it.analyze("د.ك")).not_to eq []
|
129
|
-
expect(it.analyze("〒")).not_to eq []
|
130
|
-
expect(it.analyze("₭")).not_to eq []
|
131
|
-
expect(it.analyze("ل.ل")).not_to eq []
|
132
|
-
expect(it.analyze("₨")).not_to eq []
|
133
|
-
expect(it.analyze("ل.د")).not_to eq []
|
134
|
-
expect(it.analyze("د.م.")).not_to eq []
|
135
|
-
expect(it.analyze("ден")).not_to eq []
|
136
|
-
expect(it.analyze("₮")).not_to eq []
|
137
|
-
expect(it.analyze("₦")).not_to eq []
|
138
|
-
expect(it.analyze("C$")).not_to eq []
|
139
|
-
expect(it.analyze("ر.ع.")).not_to eq []
|
140
|
-
expect(it.analyze("₱")).not_to eq []
|
141
|
-
expect(it.analyze("zł")).not_to eq []
|
142
|
-
expect(it.analyze("₲")).not_to eq []
|
143
|
-
expect(it.analyze("ر.ق")).not_to eq []
|
144
|
-
expect(it.analyze("РСД")).not_to eq []
|
145
|
-
expect(it.analyze("₽")).not_to eq []
|
146
|
-
expect(it.analyze("ر.س")).not_to eq []
|
147
|
-
expect(it.analyze("฿")).not_to eq []
|
148
|
-
expect(it.analyze("د.ت")).not_to eq []
|
149
|
-
expect(it.analyze("T$")).not_to eq []
|
150
|
-
expect(it.analyze("₺")).not_to eq []
|
151
|
-
expect(it.analyze("₴")).not_to eq []
|
152
|
-
expect(it.analyze("₫")).not_to eq []
|
153
|
-
expect(it.analyze("B⃦")).not_to eq []
|
154
|
-
expect(it.analyze("₤")).not_to eq []
|
155
|
-
expect(it.analyze("ރ")).not_to eq []
|
156
|
-
end
|
157
|
-
|
158
|
-
it "should function with unicode characters" do
|
159
|
-
expect(it.analyze("10 դր.")).to eq ["AMD"]
|
7
|
+
it "it raises deprecation error" do
|
8
|
+
expect{ it.analyze('123') }.to raise_error(StandardError, 'Heuristics deprecated, add `gem "money-heuristics"` to Gemfile')
|
160
9
|
end
|
161
10
|
end
|
162
11
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: money
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane Emmons
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -30,26 +30,6 @@ dependencies:
|
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '0.9'
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: sixarm_ruby_unaccent
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - ">="
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: 1.1.1
|
40
|
-
- - "<"
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: '2'
|
43
|
-
type: :runtime
|
44
|
-
prerelease: false
|
45
|
-
version_requirements: !ruby/object:Gem::Requirement
|
46
|
-
requirements:
|
47
|
-
- - ">="
|
48
|
-
- !ruby/object:Gem::Version
|
49
|
-
version: 1.1.1
|
50
|
-
- - "<"
|
51
|
-
- !ruby/object:Gem::Version
|
52
|
-
version: '2'
|
53
33
|
- !ruby/object:Gem::Dependency
|
54
34
|
name: bundler
|
55
35
|
requirement: !ruby/object:Gem::Requirement
|