sportdb-catalogs 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/Rakefile +3 -3
- data/lib/sportdb/catalogs/country.rb +67 -30
- data/lib/sportdb/catalogs/league.rb +104 -21
- data/lib/sportdb/catalogs/version.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4615353b8720394e2c0edcd97de249822923718bf9d7703e4ce2f93f4411b372
|
4
|
+
data.tar.gz: ac4536c29d15caf8bf5c3de62539785f17fbad3e6098c5e0d18282c1e5cccb2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93dc76f6a2dd70d04a9ebb6700e66bbcd41a98cd517a9f1ed24b6a2ad667806963ffd2fda6991a02600c3aa4d61c45431201b4f350a37b4a080e53bf664866ec
|
7
|
+
data.tar.gz: f0cc52b6590c598ec8ae40abdb7b8238a647617b10825b76d4c910bcd01ca7facde765cf977e0abb807312fa7fa55ffa83a239446962b209c8a747004e43e03a
|
data/CHANGELOG.md
CHANGED
data/Rakefile
CHANGED
@@ -20,13 +20,13 @@ Hoe.spec 'sportdb-catalogs' do
|
|
20
20
|
self.licenses = ['Public Domain']
|
21
21
|
|
22
22
|
self.extra_deps = [
|
23
|
-
['sportdb-formats'],
|
23
|
+
['sportdb-formats', '>= 2.0.0'],
|
24
24
|
['sqlite3'], ## add sqlite for "metal" use (no activerecord etc.)
|
25
|
-
['footballdb-data'] ## add builtin default db
|
25
|
+
['footballdb-data'] ## add builtin default db
|
26
26
|
]
|
27
27
|
|
28
28
|
self.spec_extras = {
|
29
|
-
required_ruby_version: '>=
|
29
|
+
required_ruby_version: '>= 3.1.0'
|
30
30
|
}
|
31
31
|
|
32
32
|
end
|
@@ -5,8 +5,8 @@ module Metal
|
|
5
5
|
class Country < Record
|
6
6
|
self.tablename = 'countries'
|
7
7
|
|
8
|
-
self.columns = ['key',
|
9
|
-
'name',
|
8
|
+
self.columns = ['key',
|
9
|
+
'name',
|
10
10
|
'code',
|
11
11
|
'tags',
|
12
12
|
'alt_names']
|
@@ -20,42 +20,42 @@ class Country < Record
|
|
20
20
|
else ## query and cache and return
|
21
21
|
rows = execute( <<-SQL )
|
22
22
|
SELECT #{self.columns.join(', ')}
|
23
|
-
FROM countries
|
24
|
-
WHERE countries.key = '#{key}'
|
23
|
+
FROM countries
|
24
|
+
WHERE countries.key = '#{key}'
|
25
25
|
SQL
|
26
|
-
|
26
|
+
|
27
27
|
## todo/fix: also assert for rows == 1 AND NOT MULTIPLE records - why? why not?
|
28
|
-
if rows.empty?
|
29
|
-
raise ArgumentError, "country record with key #{key} not found"
|
30
|
-
else
|
28
|
+
if rows.empty?
|
29
|
+
raise ArgumentError, "country record with key #{key} not found"
|
30
|
+
else
|
31
31
|
_build_country( rows[0] )
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
|
36
|
+
|
37
37
|
def self._build_country( row )
|
38
38
|
## note: cache structs by key (do NOT rebuild duplicates; reuse)
|
39
39
|
cache[ row[0] ] ||= begin
|
40
40
|
## note: split tags & alt names (PLUS remove leading//trailing spaces)
|
41
41
|
tags = row[3].split(',').map {|tag| tag.strip }
|
42
|
-
alt_names = row[4].split('|').map {|alt_name| alt_name.strip }
|
42
|
+
alt_names = row[4].split('|').map {|alt_name| alt_name.strip }
|
43
43
|
country = Sports::Country.new(
|
44
44
|
key: row[0],
|
45
45
|
name: row[1],
|
46
46
|
code: row[2],
|
47
|
-
tags: tags
|
47
|
+
tags: tags
|
48
48
|
)
|
49
49
|
country.alt_names = alt_names
|
50
50
|
country
|
51
51
|
end
|
52
|
-
end
|
53
|
-
|
52
|
+
end
|
53
|
+
|
54
54
|
|
55
55
|
## fix/todo: add find_by (alias for find_by_name/find_by_code)
|
56
56
|
def self.find_by_code( code )
|
57
57
|
q = code.to_s.downcase ## allow symbols (and always downcase e.g. AUT to aut etc.)
|
58
|
-
|
58
|
+
|
59
59
|
## note: results in
|
60
60
|
## Côte d'Ivoire => côte d'ivoire
|
61
61
|
## quote will break sql!!!
|
@@ -69,15 +69,16 @@ SQL
|
|
69
69
|
|
70
70
|
rows = execute( <<-SQL )
|
71
71
|
SELECT #{self.columns.join(', ')}
|
72
|
-
FROM countries
|
72
|
+
FROM countries
|
73
73
|
INNER JOIN country_codes ON countries.key = country_codes.key
|
74
|
-
WHERE country_codes.code = '#{q}'
|
74
|
+
WHERE country_codes.code = '#{q}'
|
75
75
|
SQL
|
76
|
-
|
77
|
-
if rows.empty?
|
78
|
-
nil
|
79
|
-
else
|
80
|
-
|
76
|
+
|
77
|
+
if rows.empty?
|
78
|
+
nil
|
79
|
+
else
|
80
|
+
## todo/fix - raise error if more than once record found!!!
|
81
|
+
_build_country( rows[0] )
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
@@ -85,26 +86,62 @@ SQL
|
|
85
86
|
##
|
86
87
|
##
|
87
88
|
## note - need to escape name ?
|
88
|
-
## e.g. Côte d'Ivoire
|
89
|
+
## e.g. Côte d'Ivoire
|
89
90
|
## make sure normalize removes single quotes (')!!!
|
90
91
|
|
91
92
|
def self.find_by_name( name )
|
92
93
|
q = normalize( unaccent( name.to_s )) ## allow symbols too (e.g. use to.s first)
|
93
|
-
|
94
|
+
|
94
95
|
rows = execute( <<-SQL )
|
95
96
|
SELECT #{self.columns.join(', ')}
|
96
|
-
FROM countries
|
97
|
+
FROM countries
|
97
98
|
INNER JOIN country_names ON countries.key = country_names.key
|
98
|
-
WHERE country_names.name = '#{q}'
|
99
|
+
WHERE country_names.name = '#{q}'
|
99
100
|
SQL
|
100
101
|
|
101
|
-
if rows.empty?
|
102
|
-
nil
|
103
|
-
else
|
102
|
+
if rows.empty?
|
103
|
+
nil
|
104
|
+
else
|
105
|
+
## todo/fix - raise error if more than once record found!!!
|
104
106
|
_build_country( rows[0] )
|
105
|
-
end
|
107
|
+
end
|
106
108
|
end
|
109
|
+
|
110
|
+
|
111
|
+
def self.find_by_name_or_code( q )
|
112
|
+
name = normalize( unaccent( q.to_s )) ## allow symbols too (e.g. use to.s first)
|
113
|
+
|
114
|
+
code = q.to_s.downcase ## allow symbols (and always downcase e.g. AUT to aut etc.)
|
115
|
+
## note: results in
|
116
|
+
## Côte d'Ivoire => côte d'ivoire
|
117
|
+
## quote will break sql!!!
|
118
|
+
## remove - spaces etc.
|
119
|
+
## for now remove only single quote (will break sql) - add more?
|
120
|
+
##
|
121
|
+
## or use escape_sql_string - possible??
|
122
|
+
code = code.gsub( /[']/, '' )
|
123
|
+
|
124
|
+
|
125
|
+
rows = execute( <<-SQL )
|
126
|
+
SELECT #{self.columns.join(', ')}
|
127
|
+
FROM countries
|
128
|
+
INNER JOIN country_names ON countries.key = country_names.key
|
129
|
+
WHERE country_names.name = '#{name}'
|
130
|
+
UNION
|
131
|
+
SELECT #{self.columns.join(', ')}
|
132
|
+
FROM countries
|
133
|
+
INNER JOIN country_codes ON countries.key = country_codes.key
|
134
|
+
WHERE country_codes.code = '#{code}'
|
135
|
+
SQL
|
136
|
+
|
137
|
+
if rows.empty?
|
138
|
+
nil
|
139
|
+
else
|
140
|
+
## todo/fix - raise error if more than once record found!!!
|
141
|
+
_build_country( rows[0] )
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
107
145
|
end # class Country
|
108
146
|
end # module Metal
|
109
147
|
end # module CatalogDb
|
110
|
-
|
@@ -4,12 +4,12 @@ module Metal
|
|
4
4
|
class League < Record
|
5
5
|
self.tablename = 'leagues'
|
6
6
|
|
7
|
-
self.columns = ['key',
|
8
|
-
'name',
|
7
|
+
self.columns = ['key',
|
8
|
+
'name',
|
9
9
|
'intl', # international tournament?
|
10
|
-
'clubs', # clubs or national teams?
|
10
|
+
'clubs', # clubs or national teams?
|
11
11
|
'country_key']
|
12
|
-
|
12
|
+
|
13
13
|
|
14
14
|
def self.cache() @cache ||= Hash.new; end
|
15
15
|
|
@@ -20,14 +20,14 @@ class League < Record
|
|
20
20
|
else ## query and cache and return
|
21
21
|
rows = execute( <<-SQL )
|
22
22
|
SELECT #{self.columns.join(', ')}
|
23
|
-
FROM leagues
|
24
|
-
WHERE leagues.key = '#{key}'
|
23
|
+
FROM leagues
|
24
|
+
WHERE leagues.key = '#{key}'
|
25
25
|
SQL
|
26
|
-
|
26
|
+
|
27
27
|
## todo/fix: also assert for rows == 1 AND NOT MULTIPLE records - why? why not?
|
28
|
-
if rows.empty?
|
29
|
-
raise ArgumentError, "league record with key #{key} not found"
|
30
|
-
else
|
28
|
+
if rows.empty?
|
29
|
+
raise ArgumentError, "league record with key #{key} not found"
|
30
|
+
else
|
31
31
|
_build_league( rows[0] )
|
32
32
|
end
|
33
33
|
end
|
@@ -38,37 +38,74 @@ SQL
|
|
38
38
|
cache[ row[0] ] ||= Sports::League.new(
|
39
39
|
key: row[0],
|
40
40
|
name: row[1],
|
41
|
-
intl: _to_bool( row[2] ),
|
41
|
+
intl: _to_bool( row[2] ),
|
42
42
|
clubs: _to_bool( row[3] ),
|
43
43
|
country: row[4] ? _to_country( row[4] ) : nil,
|
44
44
|
)
|
45
|
-
end
|
46
|
-
|
45
|
+
end
|
47
46
|
|
48
|
-
def self.
|
49
|
-
|
47
|
+
def self.match_by_code( code,
|
48
|
+
country: nil )
|
49
|
+
## note: match must for now always include name
|
50
|
+
### todo/fix: allow special normalize formula for
|
51
|
+
## code - why? why not?
|
52
|
+
## e.g. allow ö1 or ö or such - why? why not?
|
53
|
+
code = normalize( unaccent(code) )
|
54
|
+
|
55
|
+
rows = nil
|
56
|
+
if country.nil?
|
57
|
+
## note: returns empty array if no match and NOT nil
|
58
|
+
rows = execute( <<-SQL )
|
59
|
+
SELECT #{self.columns.join(', ')}
|
60
|
+
FROM leagues
|
61
|
+
INNER JOIN league_codes ON leagues.key = league_codes.key
|
62
|
+
WHERE league_codes.code = '#{code}'
|
63
|
+
SQL
|
64
|
+
else ## filter by country
|
65
|
+
## note: also skip international leagues & cups (e.g. champions league etc.) for now - why? why not?
|
66
|
+
|
67
|
+
## note: country assumes / allows the country key or fifa code for now
|
68
|
+
## note: allow passing in of country struct too
|
69
|
+
country_rec = _country( country )
|
70
|
+
|
71
|
+
rows = execute( <<-SQL )
|
72
|
+
SELECT #{self.columns.join(', ')}
|
73
|
+
FROM leagues
|
74
|
+
INNER JOIN league_codes ON leagues.key = league_codes.key
|
75
|
+
WHERE league_codes.code = '#{code}' AND
|
76
|
+
leagues.country_key = '#{country_rec.key}'
|
77
|
+
|
78
|
+
SQL
|
79
|
+
end
|
80
|
+
|
81
|
+
## wrap results array into struct records
|
82
|
+
rows.map {|row| _build_league( row )}
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.match_by_name( name,
|
86
|
+
country: nil )
|
50
87
|
## note: match must for now always include name
|
51
88
|
name = normalize( unaccent(name) )
|
52
89
|
|
53
|
-
rows = nil
|
54
|
-
if country.nil?
|
90
|
+
rows = nil
|
91
|
+
if country.nil?
|
55
92
|
## note: returns empty array if no match and NOT nil
|
56
93
|
rows = execute( <<-SQL )
|
57
94
|
SELECT #{self.columns.join(', ')}
|
58
|
-
FROM leagues
|
95
|
+
FROM leagues
|
59
96
|
INNER JOIN league_names ON leagues.key = league_names.key
|
60
|
-
WHERE league_names.name = '#{name}'
|
97
|
+
WHERE league_names.name = '#{name}'
|
61
98
|
SQL
|
62
99
|
else ## filter by country
|
63
100
|
## note: also skip international leagues & cups (e.g. champions league etc.) for now - why? why not?
|
64
|
-
|
101
|
+
|
65
102
|
## note: country assumes / allows the country key or fifa code for now
|
66
103
|
## note: allow passing in of country struct too
|
67
104
|
country_rec = _country( country )
|
68
105
|
|
69
106
|
rows = execute( <<-SQL )
|
70
107
|
SELECT #{self.columns.join(', ')}
|
71
|
-
FROM leagues
|
108
|
+
FROM leagues
|
72
109
|
INNER JOIN league_names ON leagues.key = league_names.key
|
73
110
|
WHERE league_names.name = '#{name}' AND
|
74
111
|
leagues.country_key = '#{country_rec.key}'
|
@@ -80,6 +117,52 @@ SQL
|
|
80
117
|
rows.map {|row| _build_league( row )}
|
81
118
|
end
|
82
119
|
|
120
|
+
def self.match_by_name_or_code( q,
|
121
|
+
country: nil )
|
122
|
+
name = normalize( unaccent(q) )
|
123
|
+
code = normalize( unaccent(q) )
|
124
|
+
|
125
|
+
rows = nil
|
126
|
+
if country.nil?
|
127
|
+
## note: returns empty array if no match and NOT nil
|
128
|
+
rows = execute( <<-SQL )
|
129
|
+
SELECT #{self.columns.join(', ')}
|
130
|
+
FROM leagues
|
131
|
+
INNER JOIN league_names ON leagues.key = league_names.key
|
132
|
+
WHERE league_names.name = '#{name}'
|
133
|
+
UNION
|
134
|
+
SELECT #{self.columns.join(', ')}
|
135
|
+
FROM leagues
|
136
|
+
INNER JOIN league_codes ON leagues.key = league_codes.key
|
137
|
+
WHERE league_codes.code = '#{code}'
|
138
|
+
SQL
|
139
|
+
else ## filter by country
|
140
|
+
## note: also skip international leagues & cups (e.g. champions league etc.) for now - why? why not?
|
141
|
+
|
142
|
+
## note: country assumes / allows the country key or fifa code for now
|
143
|
+
## note: allow passing in of country struct too
|
144
|
+
country_rec = _country( country )
|
145
|
+
|
146
|
+
rows = execute( <<-SQL )
|
147
|
+
SELECT #{self.columns.join(', ')}
|
148
|
+
FROM leagues
|
149
|
+
INNER JOIN league_names ON leagues.key = league_names.key
|
150
|
+
WHERE league_names.name = '#{name}' AND
|
151
|
+
leagues.country_key = '#{country_rec.key}'
|
152
|
+
UNION
|
153
|
+
SELECT #{self.columns.join(', ')}
|
154
|
+
FROM leagues
|
155
|
+
INNER JOIN league_codes ON leagues.key = league_codes.key
|
156
|
+
WHERE league_codes.code = '#{code}' AND
|
157
|
+
leagues.country_key = '#{country_rec.key}'
|
158
|
+
SQL
|
159
|
+
end
|
160
|
+
|
161
|
+
## wrap results array into struct records
|
162
|
+
rows.map {|row| _build_league( row )}
|
163
|
+
end
|
164
|
+
|
165
|
+
|
83
166
|
end # class League
|
84
167
|
end # module Metal
|
85
168
|
end # module CatalogDb
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sportdb-catalogs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sportdb-formats
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 2.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 2.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: sqlite3
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -125,7 +125,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
125
125
|
requirements:
|
126
126
|
- - ">="
|
127
127
|
- !ruby/object:Gem::Version
|
128
|
-
version:
|
128
|
+
version: 3.1.0
|
129
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
130
|
requirements:
|
131
131
|
- - ">="
|