data_kitten 1.2.0 → 1.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.
- checksums.yaml +8 -8
- data/lib/data_kitten/dataset.rb +43 -3
- data/lib/data_kitten/distribution.rb +37 -13
- data/lib/data_kitten/distribution_format.rb +2 -0
- data/lib/data_kitten/license.rb +28 -1
- data/lib/data_kitten/publishing_formats/ckan.rb +110 -21
- data/lib/data_kitten/utils/guessable_lookup.rb +38 -0
- data/lib/data_kitten/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MTU4NmQ1MmU2YjJhY2U2NmVjOWE5NTBhOGM2YjNhNGQzMWIxYTU4MQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjNhNWU4NzNlZjI4ODU3ZTRkYTgxZmY4MWM0NTA3OTQyNDNmMmJjMg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZjY0ODMyZmZjODMxNmU4NmNhMmI4N2YxMWMzMThhNGFlMTAxZmQ0ODA1OTcz
|
10
|
+
MjcwOWIwMmYyMmRiNDlmNTEyN2ExMWE4N2E4NWJlMDFlNjI3NDU4ZmZjZWFj
|
11
|
+
Yjk2MWZiZGJmODE5ZDVjMWQ0OTY2ODI4MWRiMzVlZmE5NjM0OGM=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MjY5NDZiZjliNThjZTk5NTQ4YzZlM2M4OGFiOGYzYjFjZDhmYzQ4NmRlMjJm
|
14
|
+
ZmE4MTMxZTMyZmQzNjBhODEyODZhODA3ZjIyMDUzNDFmMWJiMWRhNTBlMTU3
|
15
|
+
MTM2MTU4ZGY4YmZlMjcyM2VkYmM5Y2Q3NzY3YWJmNmNlODdlZTI=
|
data/lib/data_kitten/dataset.rb
CHANGED
@@ -49,7 +49,11 @@ module DataKitten
|
|
49
49
|
def url
|
50
50
|
@access_url.to_s
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
|
+
def source
|
54
|
+
@access_url.as_json if @access_url.ok?
|
55
|
+
end
|
56
|
+
|
53
57
|
# Can metadata be loaded for this Dataset?
|
54
58
|
#
|
55
59
|
# @return [Boolean] true if metadata can be loaded, false if it's
|
@@ -75,7 +79,15 @@ module DataKitten
|
|
75
79
|
def host
|
76
80
|
nil
|
77
81
|
end
|
78
|
-
|
82
|
+
|
83
|
+
# A unique identifier of the dataset.
|
84
|
+
#
|
85
|
+
# @return [String] the identifier of the dataset
|
86
|
+
#
|
87
|
+
def identifier
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
|
79
91
|
# The human-readable title of the dataset.
|
80
92
|
#
|
81
93
|
# @return [String] the title of the dataset.
|
@@ -126,6 +138,13 @@ module DataKitten
|
|
126
138
|
def modified
|
127
139
|
nil
|
128
140
|
end
|
141
|
+
|
142
|
+
# A web page that can be used to gain access to the dataset, its distributions and/or additional information.
|
143
|
+
#
|
144
|
+
# @return [String] The URL to the dataset
|
145
|
+
def landing_page
|
146
|
+
nil
|
147
|
+
end
|
129
148
|
|
130
149
|
# The temporal coverage of the dataset
|
131
150
|
#
|
@@ -191,7 +210,21 @@ module DataKitten
|
|
191
210
|
def contributors
|
192
211
|
[]
|
193
212
|
end
|
194
|
-
|
213
|
+
|
214
|
+
# The language of the dataset.
|
215
|
+
#
|
216
|
+
# @return [String] the language of the dataset
|
217
|
+
def language
|
218
|
+
nil
|
219
|
+
end
|
220
|
+
|
221
|
+
# The main category the dataset belongs to.
|
222
|
+
#
|
223
|
+
# @return [String]
|
224
|
+
def theme
|
225
|
+
nil
|
226
|
+
end
|
227
|
+
|
195
228
|
# Has the data been crowdsourced?
|
196
229
|
#
|
197
230
|
# @return [Boolean] Whether the data has been crowdsourced or not.
|
@@ -229,5 +262,12 @@ module DataKitten
|
|
229
262
|
[]
|
230
263
|
end
|
231
264
|
|
265
|
+
# Spatial coverage of the dataset
|
266
|
+
#
|
267
|
+
# @return [GeoJSON Geometry] A GeoJSON geometry object of the spatial coverage
|
268
|
+
def spatial
|
269
|
+
nil
|
270
|
+
end
|
271
|
+
|
232
272
|
end
|
233
273
|
end
|
@@ -14,8 +14,11 @@ module DataKitten
|
|
14
14
|
# @!attribute access_url
|
15
15
|
# @return [String] a URL to access the distribution.
|
16
16
|
attr_accessor :access_url
|
17
|
-
|
18
|
-
|
17
|
+
|
18
|
+
# @!attribute download_url
|
19
|
+
# @return [String] a URL to the file of the distribution.
|
20
|
+
attr_accessor :download_url
|
21
|
+
alias_method :uri, :download_url
|
19
22
|
|
20
23
|
# @!attribute path
|
21
24
|
# @return [String] the path of the distribution within the source, if appropriate
|
@@ -29,6 +32,22 @@ module DataKitten
|
|
29
32
|
# @return [String] a textual description
|
30
33
|
attr_accessor :description
|
31
34
|
|
35
|
+
# @!attribute issued
|
36
|
+
# @return [Date] date created
|
37
|
+
attr_accessor :issued
|
38
|
+
|
39
|
+
# @!attribute modified
|
40
|
+
# @return [Date] date modified
|
41
|
+
attr_accessor :modified
|
42
|
+
|
43
|
+
# @!attribute byte_size
|
44
|
+
# @return [Integer] size of file in bytes
|
45
|
+
attr_accessor :byte_size
|
46
|
+
|
47
|
+
# @!attribute media_type
|
48
|
+
# @return [String] the IANA media type (MIME type) of the distribution
|
49
|
+
attr_accessor :media_type
|
50
|
+
|
32
51
|
# @!attribute schema
|
33
52
|
# @return [Hash] a hash representing the schema of the data within the distribution. Will
|
34
53
|
# change to a more structured object later.
|
@@ -65,7 +84,7 @@ module DataKitten
|
|
65
84
|
@schema = r['schema']
|
66
85
|
# Get path
|
67
86
|
@path = r['path']
|
68
|
-
@
|
87
|
+
@download_url = r['url']
|
69
88
|
# Set title
|
70
89
|
@title = @path || @uri
|
71
90
|
elsif r = options[:dcat_resource]
|
@@ -73,13 +92,18 @@ module DataKitten
|
|
73
92
|
@description = r[:title]
|
74
93
|
@access_url = r[:accessURL]
|
75
94
|
elsif r = options[:ckan_resource]
|
76
|
-
@title
|
77
|
-
@description
|
78
|
-
@
|
79
|
-
@
|
95
|
+
@title = r[:title]
|
96
|
+
@description = r[:title]
|
97
|
+
@issued = r[:issued]
|
98
|
+
@modified = r[:modified]
|
99
|
+
@access_url = r[:accessURL]
|
100
|
+
@download_url = r[:downloadURL]
|
101
|
+
@byte_size = r[:byteSize]
|
102
|
+
@media_type = r[:mediaType]
|
103
|
+
@extension = r[:format]
|
80
104
|
# Load HTTP Response for further use
|
81
105
|
@format = r[:format] ? DistributionFormat.new(self) : nil
|
82
|
-
|
106
|
+
end
|
83
107
|
# Set default CSV dialect
|
84
108
|
@dialect ||= {
|
85
109
|
"delimiter" => ","
|
@@ -112,7 +136,7 @@ module DataKitten
|
|
112
136
|
#
|
113
137
|
# @return [Boolean] whether the HTTP response returns a success code or not
|
114
138
|
def exists?
|
115
|
-
if @
|
139
|
+
if @download_url
|
116
140
|
http_head.response_code != 404
|
117
141
|
end
|
118
142
|
end
|
@@ -124,8 +148,8 @@ module DataKitten
|
|
124
148
|
@data ||= begin
|
125
149
|
if @path
|
126
150
|
datafile = @dataset.send(:load_file, @path)
|
127
|
-
elsif @
|
128
|
-
datafile = RestClient.get @
|
151
|
+
elsif @download_url
|
152
|
+
datafile = RestClient.get @download_url rescue nil
|
129
153
|
end
|
130
154
|
if datafile
|
131
155
|
case format.extension
|
@@ -147,9 +171,9 @@ module DataKitten
|
|
147
171
|
end
|
148
172
|
|
149
173
|
def http_head
|
150
|
-
if @
|
174
|
+
if @download_url
|
151
175
|
@http_head ||= begin
|
152
|
-
Curl::Easy.http_head(@
|
176
|
+
Curl::Easy.http_head(@download_url) do |c|
|
153
177
|
c.follow_location = true
|
154
178
|
c.useragent = "curb"
|
155
179
|
end
|
@@ -21,6 +21,7 @@ module DataKitten
|
|
21
21
|
@@formats ||= {
|
22
22
|
csv: { structured: true, open: true },
|
23
23
|
xls: { structured: true, open: false },
|
24
|
+
xlsx: { structured: true, open: true },
|
24
25
|
rdf: { structured: true, open: true },
|
25
26
|
xml: { structured: true, open: true },
|
26
27
|
wms: { structured: true, open: true },
|
@@ -33,6 +34,7 @@ module DataKitten
|
|
33
34
|
sparql: { structured: true, open: true },
|
34
35
|
kml: { structured: true, open: true },
|
35
36
|
georss: { structured: true, open: true },
|
37
|
+
geojson: { structured: true, open: true },
|
36
38
|
shp: { structured: true, open: true },
|
37
39
|
html: { structured: false, open: true },
|
38
40
|
doc: { structured: false, open: false },
|
data/lib/data_kitten/license.rb
CHANGED
@@ -3,6 +3,23 @@ module DataKitten
|
|
3
3
|
# A license for a {Dataset} or {Distribution}
|
4
4
|
#
|
5
5
|
class License
|
6
|
+
|
7
|
+
LICENSES = {
|
8
|
+
/opendatacommons.org.*\/by(\/|$)/ => "odc-by",
|
9
|
+
/opendatacommons.org.*\/odbl(\/|$)/ => "odc-odbl",
|
10
|
+
/opendatacommons.org.*\/pddl(\/|$)/ => "odc-pddl",
|
11
|
+
/opendefinition.org.*\/odc-by(\/|$)/ => "odc-by",
|
12
|
+
/opendefinition.org.*\/odc-pddl(\/|$)/ => "odc-pddl",
|
13
|
+
/opendefinition.org.*\/cc-zero(\/|$)/ => "cc-zero",
|
14
|
+
/opendefinition.org.*\/cc-by(\/|$)/ => "cc-by",
|
15
|
+
/opendefinition.org.*\/cc-by-sa(\/|$)/ => "cc-by-sa",
|
16
|
+
/opendefinition.org.*\/gfdl(\/|$)/ => "gfdl",
|
17
|
+
/creativecommons.org.*\/zero(\/|$)/ => "cc-zero",
|
18
|
+
/creativecommons.org.*\/by-sa(\/|$)/ => "cc-by-sa",
|
19
|
+
/creativecommons.org.*\/by(\/|$)/ => "cc-by",
|
20
|
+
/(data|nationalarchives).gov.uk.*\/open-government-licence(\/|$)/ => "ogl-uk",
|
21
|
+
/usa.gov\/publicdomain(\/|$)/ => "us-pd"
|
22
|
+
}
|
6
23
|
|
7
24
|
# @!attribute is
|
8
25
|
# @return [String] a short ID that identifies the license.
|
@@ -19,6 +36,10 @@ module DataKitten
|
|
19
36
|
# @!attribute type
|
20
37
|
# @return [String] the type of information this license applies to. Could be +:data+ or +:content+.
|
21
38
|
attr_accessor :type
|
39
|
+
|
40
|
+
# @!attribute abbr
|
41
|
+
# @return [String] the license abbreviation
|
42
|
+
attr_accessor :abbr
|
22
43
|
|
23
44
|
# Create a new License object.
|
24
45
|
#
|
@@ -32,8 +53,14 @@ module DataKitten
|
|
32
53
|
@name = options[:name]
|
33
54
|
@uri = options[:uri]
|
34
55
|
@type = options[:type]
|
56
|
+
@abbr = get_license_abbr(@uri) if @uri
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_license_abbr(uri)
|
60
|
+
license = LICENSES.find { |regex, abbr| uri =~ regex }
|
61
|
+
license.last if license
|
35
62
|
end
|
36
63
|
|
37
64
|
end
|
38
65
|
|
39
|
-
end
|
66
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'data_kitten/utils/guessable_lookup.rb'
|
2
|
+
|
1
3
|
module DataKitten
|
2
4
|
|
3
5
|
module PublishingFormats
|
@@ -26,6 +28,7 @@ module DataKitten
|
|
26
28
|
@@id = result["result"]["id"] rescue result["id"]
|
27
29
|
end
|
28
30
|
@@metadata = JSON.parse RestClient.get "#{uri.scheme}://#{uri.host}/api/rest/package/#{@@id}"
|
31
|
+
@@metadata.extend(GuessableLookup)
|
29
32
|
rescue
|
30
33
|
false
|
31
34
|
end
|
@@ -43,14 +46,32 @@ module DataKitten
|
|
43
46
|
#
|
44
47
|
# @see Dataset#data_title
|
45
48
|
def data_title
|
46
|
-
metadata
|
49
|
+
metadata.lookup("title")
|
47
50
|
end
|
48
51
|
|
49
52
|
# A brief description of the dataset
|
50
53
|
#
|
51
54
|
# @see Dataset#description
|
52
55
|
def description
|
53
|
-
metadata
|
56
|
+
metadata.lookup("notes") || metadata.lookup("description")
|
57
|
+
rescue
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
|
61
|
+
# An identifier for the dataset
|
62
|
+
#
|
63
|
+
# @see Dataset#identifier
|
64
|
+
def identifier
|
65
|
+
metadata.lookup("name") || @@id
|
66
|
+
end
|
67
|
+
|
68
|
+
# A web page which can be used to gain access to the dataset
|
69
|
+
#
|
70
|
+
# @see Dataset#landing_page
|
71
|
+
def landing_page
|
72
|
+
metadata.lookup("extras", "landing_page") ||
|
73
|
+
metadata.lookup("url") ||
|
74
|
+
metadata.lookup("ckan_url")
|
54
75
|
end
|
55
76
|
|
56
77
|
# Keywords for the dataset
|
@@ -58,7 +79,7 @@ module DataKitten
|
|
58
79
|
# @see Dataset#keywords
|
59
80
|
def keywords
|
60
81
|
keywords = []
|
61
|
-
metadata
|
82
|
+
metadata.lookup("tags").each do |tag|
|
62
83
|
keywords << tag
|
63
84
|
end
|
64
85
|
return keywords
|
@@ -70,7 +91,7 @@ module DataKitten
|
|
70
91
|
#
|
71
92
|
# @see Dataset#publishers
|
72
93
|
def publishers
|
73
|
-
id = metadata
|
94
|
+
id = metadata.lookup('organization', 'id') || metadata.lookup('groups', 0)
|
74
95
|
fetch_publisher(id)
|
75
96
|
rescue
|
76
97
|
[]
|
@@ -88,10 +109,9 @@ module DataKitten
|
|
88
109
|
#
|
89
110
|
# @see Dataset#licenses
|
90
111
|
def licenses
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
name = metadata["license_title"] || extras["licence_url_title"]
|
112
|
+
id = metadata.lookup("license_id")
|
113
|
+
uri = metadata.lookup("license_url") || metadata.lookup("extras", "licence_url")
|
114
|
+
name = metadata.lookup("license_title") || metadata.lookup("extras", "licence_url_title")
|
95
115
|
if [id, uri, name].any?
|
96
116
|
[License.new(:id => id, :uri => uri, :name => name)]
|
97
117
|
else
|
@@ -104,12 +124,17 @@ module DataKitten
|
|
104
124
|
# @see Dataset#distributions
|
105
125
|
def distributions
|
106
126
|
distributions = []
|
107
|
-
metadata
|
127
|
+
metadata.lookup("resources").each do |resource|
|
108
128
|
distribution = {
|
109
129
|
:title => resource["description"],
|
110
|
-
:accessURL =>
|
111
|
-
:
|
130
|
+
:accessURL => landing_page,
|
131
|
+
:downloadURL => resource["url"],
|
132
|
+
:format => resource["format"],
|
133
|
+
:mediaType => resource["mimetype"] || resource["content_type"],
|
112
134
|
}
|
135
|
+
distribution[:issued] = Date.parse(resource["created"]) rescue nil
|
136
|
+
distribution[:modified] = Date.parse(resource["last_modified"] || resource["revision_timestamp"]) rescue nil
|
137
|
+
distribution[:byteSize] = Integer(resource["size"]) rescue nil
|
113
138
|
distributions << Distribution.new(self, ckan_resource: distribution)
|
114
139
|
end
|
115
140
|
return distributions
|
@@ -121,32 +146,68 @@ module DataKitten
|
|
121
146
|
#
|
122
147
|
# @see Dataset#update_frequency
|
123
148
|
def update_frequency
|
124
|
-
metadata
|
149
|
+
metadata.lookup("extras", "update_frequency") ||
|
150
|
+
metadata.lookup("extras", "frequency-of-update") ||
|
151
|
+
metadata.lookup("extras", "accrual_periodicity")
|
152
|
+
rescue
|
153
|
+
nil
|
125
154
|
end
|
126
155
|
|
127
156
|
# Date the dataset was released
|
128
157
|
#
|
129
158
|
# @see Dataset#issued
|
130
159
|
def issued
|
131
|
-
Date.parse metadata
|
160
|
+
Date.parse metadata.lookup("metadata_created") rescue nil
|
132
161
|
end
|
133
162
|
|
134
163
|
# Date the dataset was modified
|
135
164
|
#
|
136
165
|
# @see Dataset#modified
|
137
166
|
def modified
|
138
|
-
Date.parse metadata
|
167
|
+
Date.parse metadata.lookup("metadata_modified") rescue nil
|
139
168
|
end
|
140
169
|
|
141
170
|
# The temporal coverage of the dataset
|
142
171
|
#
|
143
172
|
# @see Dataset#temporal
|
144
173
|
def temporal
|
145
|
-
|
146
|
-
|
174
|
+
from = metadata.lookup("extras", "temporal_coverage-from") ||
|
175
|
+
metadata.lookup("extras", "temporal-extent-begin")
|
176
|
+
to = metadata.lookup("extras", "temporal_coverage-to") ||
|
177
|
+
metadata.lookup("extras", "temporal-extent-end")
|
178
|
+
start_date = Date.parse from rescue nil
|
179
|
+
end_date = Date.parse to rescue nil
|
147
180
|
Temporal.new(:start => start_date, :end => end_date)
|
148
181
|
end
|
149
182
|
|
183
|
+
# The language of the dataset
|
184
|
+
#
|
185
|
+
# @see Dataset#language
|
186
|
+
def language
|
187
|
+
metadata.lookup("language") ||
|
188
|
+
metadata.lookup("metadata_language") ||
|
189
|
+
metadata.lookup("extras", "metadata_language") ||
|
190
|
+
metadata.lookup("extras", "language", 0) ||
|
191
|
+
metadata.lookup("extras", "language")
|
192
|
+
end
|
193
|
+
|
194
|
+
# The main category of the dataset
|
195
|
+
#
|
196
|
+
# @see Dataset#theme
|
197
|
+
def theme
|
198
|
+
metadata.lookup("extras", "theme", 0) ||
|
199
|
+
metadata.lookup("extras", "theme-primary") ||
|
200
|
+
metadata.lookup("groups", 0, "name") ||
|
201
|
+
metadata.lookup("groups", 0)
|
202
|
+
end
|
203
|
+
|
204
|
+
# Spatial coverage of the dataset
|
205
|
+
#
|
206
|
+
# @see Dataset#spatial
|
207
|
+
def spatial
|
208
|
+
extract_spatial || extract_bbox
|
209
|
+
end
|
210
|
+
|
150
211
|
private
|
151
212
|
|
152
213
|
def metadata
|
@@ -161,17 +222,45 @@ module DataKitten
|
|
161
222
|
extra
|
162
223
|
end
|
163
224
|
|
225
|
+
def extract_spatial
|
226
|
+
geometry = JSON.parse metadata.lookup("extras", "spatial")
|
227
|
+
return geometry if !geometry["type"].nil?
|
228
|
+
rescue
|
229
|
+
nil
|
230
|
+
end
|
231
|
+
|
232
|
+
def extract_bbox
|
233
|
+
west = Float(metadata.lookup("extras", "bbox-west-long"))
|
234
|
+
east = Float(metadata.lookup("extras", "bbox-east-long"))
|
235
|
+
north = Float(metadata.lookup("extras", "bbox-north-lat"))
|
236
|
+
south = Float(metadata.lookup("extras", "bbox-south-lat"))
|
237
|
+
|
238
|
+
{ "type" => "Polygon", "coordinates" => [
|
239
|
+
[
|
240
|
+
[west, north],
|
241
|
+
[east, north],
|
242
|
+
[east, south],
|
243
|
+
[west, south],
|
244
|
+
[west, north]
|
245
|
+
]
|
246
|
+
] }
|
247
|
+
rescue
|
248
|
+
nil
|
249
|
+
end
|
250
|
+
|
164
251
|
def fetch_publisher(id)
|
165
252
|
uri = parsed_uri
|
166
253
|
[
|
167
|
-
"#{uri.scheme}://#{uri.host}/api/
|
254
|
+
"#{uri.scheme}://#{uri.host}/api/3/action/organization_show?id=#{id}",
|
168
255
|
"#{uri.scheme}://#{uri.host}/api/3/action/group_show?id=#{id}",
|
169
|
-
"#{uri.scheme}://#{uri.host}/api/
|
256
|
+
"#{uri.scheme}://#{uri.host}/api/rest/group/#{id}"
|
170
257
|
].each do |uri|
|
171
258
|
begin
|
172
259
|
@group = JSON.parse RestClient.get uri
|
173
260
|
break
|
174
|
-
rescue
|
261
|
+
rescue
|
262
|
+
# FakeWeb raises FakeWeb::NetConnectNotAllowedError, whereas
|
263
|
+
# RestClient raises RestClient::ResourceNotFound in the "real world".
|
175
264
|
nil
|
176
265
|
end
|
177
266
|
end
|
@@ -190,8 +279,8 @@ module DataKitten
|
|
190
279
|
end
|
191
280
|
|
192
281
|
def extract_agent(name_field, email_field)
|
193
|
-
name = metadata
|
194
|
-
email = metadata
|
282
|
+
name = metadata.lookup(name_field)
|
283
|
+
email = metadata.lookup(email_field)
|
195
284
|
if [name, email].any?
|
196
285
|
[Agent.new(name: name, mbox: email)]
|
197
286
|
else
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module GuessableLookup
|
2
|
+
|
3
|
+
def lookup(*path)
|
4
|
+
data = self
|
5
|
+
path.each { |key| data = guess_key(data, key) }
|
6
|
+
data
|
7
|
+
rescue
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Guesses which key you want from a hash and returns the value of it.
|
14
|
+
#
|
15
|
+
# It returns the value of the original key if it exists in the hash, otherwise
|
16
|
+
# tries to find a similar key, and if it fails it returns nil.
|
17
|
+
# Similar keys are ones which use '_', '-' or '' as word separators & are
|
18
|
+
# case-insensitive.
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# guess_key({:a_key => true}, 'a_key') # => true
|
22
|
+
# guess_key({:aKey => true}, 'a_key') # => true
|
23
|
+
# guess_key({"a-KEY" => true}, 'a_key') # => true
|
24
|
+
#
|
25
|
+
# @param data [Hash]
|
26
|
+
# @param key [String] The desired key
|
27
|
+
# @return The value of the guessed key
|
28
|
+
#
|
29
|
+
def guess_key(data, key)
|
30
|
+
return data[key] if key.is_a?(Fixnum) || data.keys.include?(key)
|
31
|
+
likeKey = key.gsub(/[\_\-]/, "[\_\-]?")
|
32
|
+
key = data.keys.select { |k| k =~ /^#{likeKey}$/i }.first
|
33
|
+
data[key]
|
34
|
+
rescue
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/lib/data_kitten/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: data_kitten
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Smith
|
@@ -214,6 +214,7 @@ files:
|
|
214
214
|
- lib/data_kitten/rights.rb
|
215
215
|
- lib/data_kitten/source.rb
|
216
216
|
- lib/data_kitten/temporal.rb
|
217
|
+
- lib/data_kitten/utils/guessable_lookup.rb
|
217
218
|
- lib/data_kitten/version.rb
|
218
219
|
homepage: http://github.com/data-kitten
|
219
220
|
licenses:
|