quandl_client 2.10.0 → 2.10.1
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/UPGRADE.md +6 -0
- data/VERSION +1 -1
- data/lib/quandl/client/base.rb +2 -0
- data/lib/quandl/client/base/benchmark.rb +46 -0
- data/lib/quandl/client/base/model.rb +1 -1
- data/lib/quandl/client/models/dataset.rb +5 -126
- data/lib/quandl/client/models/dataset/benchmark.rb +11 -0
- data/lib/quandl/client/models/dataset/validations.rb +133 -0
- metadata +7 -4
data/UPGRADE.md
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.10.
|
1
|
+
2.10.1
|
data/lib/quandl/client/base.rb
CHANGED
@@ -4,6 +4,7 @@ require "active_support/core_ext/hash"
|
|
4
4
|
require "active_support/core_ext/object"
|
5
5
|
|
6
6
|
require 'quandl/client/base/model'
|
7
|
+
require 'quandl/client/base/benchmark'
|
7
8
|
require 'quandl/client/base/attributes'
|
8
9
|
require 'quandl/client/base/validation'
|
9
10
|
require 'quandl/client/base/search'
|
@@ -51,6 +52,7 @@ class Quandl::Client::Base
|
|
51
52
|
# include model behaviour
|
52
53
|
subclass.class_eval do
|
53
54
|
include Quandl::Client::Base::Model
|
55
|
+
include Quandl::Client::Base::Benchmark
|
54
56
|
include Quandl::Client::Base::Attributes
|
55
57
|
include Quandl::Client::Base::Validation
|
56
58
|
include Quandl::Client::Base::Search
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Quandl::Client::Base
|
2
|
+
module Benchmark
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
benchmark(:save)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def benchmark(*names)
|
12
|
+
names.each do |name|
|
13
|
+
def_benchmark(name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def def_benchmark(name)
|
20
|
+
define_method(name) do |*args, &block|
|
21
|
+
benchmark(name) do
|
22
|
+
super(*args, &block) if defined?(super)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def human_benchmarks
|
29
|
+
benchmarks.sort_by{|k,v| v }.reverse.collect{|k,v| "#{k}: #{v.microseconds}ms" }.join(' | ')
|
30
|
+
end
|
31
|
+
|
32
|
+
def benchmarks
|
33
|
+
@benchmarks ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def benchmark(name, &block)
|
39
|
+
timer = Time.now
|
40
|
+
result = block.call
|
41
|
+
self.benchmarks[name.to_sym] ||= timer.elapsed
|
42
|
+
result
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -1,6 +1,11 @@
|
|
1
1
|
class Quandl::Client::Dataset < Quandl::Client::Base
|
2
2
|
|
3
3
|
require 'quandl/client/models/dataset/data'
|
4
|
+
require 'quandl/client/models/dataset/validations'
|
5
|
+
require 'quandl/client/models/dataset/benchmark'
|
6
|
+
|
7
|
+
include Quandl::Client::Dataset::Validations
|
8
|
+
include Quandl::Client::Dataset::Benchmark
|
4
9
|
|
5
10
|
##########
|
6
11
|
# SCOPES #
|
@@ -51,17 +56,6 @@ class Quandl::Client::Dataset < Quandl::Client::Base
|
|
51
56
|
# VALIDATIONS #
|
52
57
|
###############
|
53
58
|
|
54
|
-
validates :code, presence: true, format: { with: Quandl::Pattern.code, message: "is invalid. Expected format: #{Quandl::Pattern.code.to_example}" }
|
55
|
-
validates :display_url, allow_blank: true, url: true
|
56
|
-
validate :data_should_be_valid!
|
57
|
-
validate :dataset_data_should_be_valid!
|
58
|
-
validate :data_row_count_should_match_column_count!
|
59
|
-
validate :data_columns_should_not_exceed_column_names!
|
60
|
-
validate :data_rows_should_have_equal_columns!
|
61
|
-
validate :ambiguous_code_requires_source_code!
|
62
|
-
|
63
|
-
validate :source_code_should_exist!
|
64
|
-
|
65
59
|
|
66
60
|
##############
|
67
61
|
# PROPERTIES #
|
@@ -73,10 +67,6 @@ class Quandl::Client::Dataset < Quandl::Client::Base
|
|
73
67
|
:display_url, :column_spec, :import_spec, :import_url,
|
74
68
|
:locations_attributes, :availability_delay, :refreshed_at
|
75
69
|
|
76
|
-
before_save :enforce_required_formats
|
77
|
-
|
78
|
-
after_save :save_dataset_data
|
79
|
-
|
80
70
|
alias_method :locations, :locations_attributes
|
81
71
|
alias_method :locations=, :locations_attributes=
|
82
72
|
|
@@ -156,115 +146,4 @@ class Quandl::Client::Dataset < Quandl::Client::Base
|
|
156
146
|
@full_code = nil
|
157
147
|
end
|
158
148
|
|
159
|
-
protected
|
160
|
-
|
161
|
-
def data_should_be_valid!
|
162
|
-
if data? && !data.valid?
|
163
|
-
data.errors.each{|k,v| self.errors.add( k,v ) }
|
164
|
-
return false
|
165
|
-
end
|
166
|
-
true
|
167
|
-
end
|
168
|
-
|
169
|
-
def dataset_data_should_be_valid!
|
170
|
-
if dataset_data? && !dataset_data.valid?
|
171
|
-
dataset_data.errors.each{|k,v| self.errors.add( k,v ) }
|
172
|
-
return false
|
173
|
-
end
|
174
|
-
true
|
175
|
-
end
|
176
|
-
|
177
|
-
def source_code_should_exist!
|
178
|
-
if source_code.present?
|
179
|
-
Quandl::Client::Source.cached[source_code] = Quandl::Client::Source.find(source_code) unless Quandl::Client::Source.cached.has_key?(source_code)
|
180
|
-
source = Quandl::Client::Source.cached[source_code]
|
181
|
-
self.errors.add( :source_code, "Could not find a source with the source_code '#{source_code}'" ) if source.blank? || source.code.blank?
|
182
|
-
return false
|
183
|
-
end
|
184
|
-
true
|
185
|
-
end
|
186
|
-
|
187
|
-
def ambiguous_code_requires_source_code!
|
188
|
-
if code.to_s.numeric? && source_code.blank?
|
189
|
-
message = %Q{Pure numerical codes like "#{code}" are not allowed unless you include a source code. Do this:\nsource_code: <USERNAME>\ncode: #{code}}
|
190
|
-
self.errors.add( :data, message )
|
191
|
-
return false
|
192
|
-
end
|
193
|
-
true
|
194
|
-
end
|
195
|
-
|
196
|
-
def data_columns_should_not_exceed_column_names!
|
197
|
-
if errors.size == 0 && data? && data.present? && column_names.present? && data.first.count != column_names.count
|
198
|
-
self.errors.add( :data, "You may not change the number of columns in a dataset. This dataset has #{column_names.count} columns but you tried to send #{data.first.count} columns." )
|
199
|
-
return false
|
200
|
-
end
|
201
|
-
true
|
202
|
-
end
|
203
|
-
|
204
|
-
def data_rows_should_have_equal_columns!
|
205
|
-
# skip validation unless data is present
|
206
|
-
return true unless data? && data.present?
|
207
|
-
# use first row as expected column count
|
208
|
-
column_count = data[0].count
|
209
|
-
# check each row
|
210
|
-
data.each_with_index do |row, index|
|
211
|
-
# the row is valid if it's count matches the first row's count
|
212
|
-
next if row.count == column_count
|
213
|
-
# the row is invalid if the count is mismatched
|
214
|
-
self.errors.add( :data, "Unexpected number of points in this row:\n#{row.join(',')}\nFound #{row.size-1} but expected #{data[0].size-1} based on precedent from the first row (#{data[0].join(',')})" )
|
215
|
-
# return validation failure
|
216
|
-
return false
|
217
|
-
end
|
218
|
-
true
|
219
|
-
end
|
220
|
-
|
221
|
-
def data_row_count_should_match_column_count!
|
222
|
-
# skip validation unless data and column_names present
|
223
|
-
return true unless data? && data.present? && column_names.present?
|
224
|
-
# count the number of expected columns
|
225
|
-
column_count = column_names.count
|
226
|
-
# check each row
|
227
|
-
data.each_with_index do |row, index|
|
228
|
-
# the row is valid if it's count matches the first row's count
|
229
|
-
next if row.count == column_count
|
230
|
-
# the row is invalid if the count is mismatched
|
231
|
-
self.errors.add( :data, "Unexpected number of points in this row:\n#{row.join(',')}\nFound #{row.size-1} but expected #{column_names.count-1} based on precedent from the header row (#{column_names.join(',')})" )
|
232
|
-
# return validation failure
|
233
|
-
return false
|
234
|
-
end
|
235
|
-
true
|
236
|
-
end
|
237
|
-
|
238
|
-
def save_dataset_data
|
239
|
-
return if (!saved? && id.blank?)
|
240
|
-
return if !data? || data.blank?
|
241
|
-
|
242
|
-
dataset_data.id = id
|
243
|
-
dataset_data.data = data.to_csv
|
244
|
-
dataset_data.save
|
245
|
-
# update dataset's attributes with dataset_data's attributes
|
246
|
-
attributes.each{|k,v| attributes[k] = dataset_data.attributes[k] if dataset_data.attributes.has_key?(k) }
|
247
|
-
# update dataset errors with dataset_data
|
248
|
-
@metadata[:status] = dataset_data.status unless dataset_data.saved?
|
249
|
-
# inherit_errors(dataset_data) unless dataset_data.saved?
|
250
|
-
end
|
251
|
-
|
252
|
-
def inherit_errors(object)
|
253
|
-
return unless object.respond_to?(:response_errors) && object.response_errors.respond_to?(:each)
|
254
|
-
object.response_errors.each do |key, messages|
|
255
|
-
if messages.respond_to?(:each)
|
256
|
-
messages.each{|message| errors.add(key, message) }
|
257
|
-
end
|
258
|
-
end
|
259
|
-
@metadata[:status] = object.status
|
260
|
-
object
|
261
|
-
end
|
262
|
-
|
263
|
-
def enforce_required_formats
|
264
|
-
# self.data = Quandl::Data.new(data).to_csv
|
265
|
-
self.source_code = self.source_code.to_s.upcase
|
266
|
-
self.code = self.code.to_s.upcase
|
267
|
-
self.locations_attributes = locations_attributes.to_json if locations_attributes.respond_to?(:to_json) && !locations_attributes.kind_of?(String)
|
268
|
-
end
|
269
|
-
|
270
149
|
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
class Quandl::Client::Dataset
|
2
|
+
module Validations
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
|
8
|
+
validates :code, presence: true, format: { with: Quandl::Pattern.code, message: "is invalid. Expected format: #{Quandl::Pattern.code.to_example}" }
|
9
|
+
validates :display_url, allow_blank: true, url: true
|
10
|
+
validate :data_should_be_valid!
|
11
|
+
validate :dataset_data_should_be_valid!
|
12
|
+
validate :data_row_count_should_match_column_count!
|
13
|
+
validate :data_columns_should_not_exceed_column_names!
|
14
|
+
validate :data_rows_should_have_equal_columns!
|
15
|
+
validate :ambiguous_code_requires_source_code!
|
16
|
+
|
17
|
+
validate :source_code_should_exist!
|
18
|
+
|
19
|
+
before_save :enforce_required_formats
|
20
|
+
after_save :save_dataset_data
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def data_should_be_valid!
|
25
|
+
if data? && !data.valid?
|
26
|
+
data.errors.each{|k,v| self.errors.add( k,v ) }
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def dataset_data_should_be_valid!
|
33
|
+
if dataset_data? && !dataset_data.valid?
|
34
|
+
dataset_data.errors.each{|k,v| self.errors.add( k,v ) }
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def source_code_should_exist!
|
41
|
+
if source_code.present?
|
42
|
+
Quandl::Client::Source.cached[source_code] = Quandl::Client::Source.find(source_code) unless Quandl::Client::Source.cached.has_key?(source_code)
|
43
|
+
source = Quandl::Client::Source.cached[source_code]
|
44
|
+
self.errors.add( :source_code, "Could not find a source with the source_code '#{source_code}'" ) if source.blank? || source.code.blank?
|
45
|
+
return false
|
46
|
+
end
|
47
|
+
true
|
48
|
+
end
|
49
|
+
|
50
|
+
def ambiguous_code_requires_source_code!
|
51
|
+
if code.to_s.numeric? && source_code.blank?
|
52
|
+
message = %Q{Pure numerical codes like "#{code}" are not allowed unless you include a source code. Do this:\nsource_code: <USERNAME>\ncode: #{code}}
|
53
|
+
self.errors.add( :data, message )
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
true
|
57
|
+
end
|
58
|
+
|
59
|
+
def data_columns_should_not_exceed_column_names!
|
60
|
+
if errors.size == 0 && data? && data.present? && column_names.present? && data.first.count != column_names.count
|
61
|
+
self.errors.add( :data, "You may not change the number of columns in a dataset. This dataset has #{column_names.count} columns but you tried to send #{data.first.count} columns." )
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def data_rows_should_have_equal_columns!
|
68
|
+
# skip validation unless data is present
|
69
|
+
return true unless data? && data.present?
|
70
|
+
# use first row as expected column count
|
71
|
+
column_count = data[0].count
|
72
|
+
# check each row
|
73
|
+
data.each_with_index do |row, index|
|
74
|
+
# the row is valid if it's count matches the first row's count
|
75
|
+
next if row.count == column_count
|
76
|
+
# the row is invalid if the count is mismatched
|
77
|
+
self.errors.add( :data, "Unexpected number of points in this row:\n#{row.join(',')}\nFound #{row.size-1} but expected #{data[0].size-1} based on precedent from the first row (#{data[0].join(',')})" )
|
78
|
+
# return validation failure
|
79
|
+
return false
|
80
|
+
end
|
81
|
+
true
|
82
|
+
end
|
83
|
+
|
84
|
+
def data_row_count_should_match_column_count!
|
85
|
+
# skip validation unless data and column_names present
|
86
|
+
return true unless data? && data.present? && column_names.present?
|
87
|
+
# count the number of expected columns
|
88
|
+
column_count = column_names.count
|
89
|
+
# check each row
|
90
|
+
data.each_with_index do |row, index|
|
91
|
+
# the row is valid if it's count matches the first row's count
|
92
|
+
next if row.count == column_count
|
93
|
+
# the row is invalid if the count is mismatched
|
94
|
+
self.errors.add( :data, "Unexpected number of points in this row:\n#{row.join(',')}\nFound #{row.size-1} but expected #{column_names.count-1} based on precedent from the header row (#{column_names.join(',')})" )
|
95
|
+
# return validation failure
|
96
|
+
return false
|
97
|
+
end
|
98
|
+
true
|
99
|
+
end
|
100
|
+
|
101
|
+
def save_dataset_data
|
102
|
+
return if (!saved? && id.blank?)
|
103
|
+
return if !data? || data.blank?
|
104
|
+
dataset_data.id = id
|
105
|
+
dataset_data.data = benchmark('data.to_csv'){ data.to_csv }
|
106
|
+
benchmark('dataset_data.save'){ dataset_data.save }
|
107
|
+
# update dataset's attributes with dataset_data's attributes
|
108
|
+
attributes.each{|k,v| attributes[k] = dataset_data.attributes[k] if dataset_data.attributes.has_key?(k) }
|
109
|
+
# update dataset errors with dataset_data
|
110
|
+
@metadata[:status] = dataset_data.status unless dataset_data.saved?
|
111
|
+
# inherit_errors(dataset_data) unless dataset_data.saved?
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
def inherit_errors(object)
|
116
|
+
return unless object.respond_to?(:response_errors) && object.response_errors.respond_to?(:each)
|
117
|
+
object.response_errors.each do |key, messages|
|
118
|
+
if messages.respond_to?(:each)
|
119
|
+
messages.each{|message| errors.add(key, message) }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
@metadata[:status] = object.status
|
123
|
+
object
|
124
|
+
end
|
125
|
+
|
126
|
+
def enforce_required_formats
|
127
|
+
self.source_code = self.source_code.to_s.upcase
|
128
|
+
self.code = self.code.to_s.upcase
|
129
|
+
self.locations_attributes = locations_attributes.to_json if locations_attributes.respond_to?(:to_json) && !locations_attributes.kind_of?(String)
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quandl_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.10.
|
4
|
+
version: 2.10.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-06-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: quandl_data
|
@@ -240,13 +240,16 @@ files:
|
|
240
240
|
- lib/quandl/client.rb
|
241
241
|
- lib/quandl/client/base.rb
|
242
242
|
- lib/quandl/client/base/attributes.rb
|
243
|
+
- lib/quandl/client/base/benchmark.rb
|
243
244
|
- lib/quandl/client/base/model.rb
|
244
245
|
- lib/quandl/client/base/search.rb
|
245
246
|
- lib/quandl/client/base/validation.rb
|
246
247
|
- lib/quandl/client/middleware.rb
|
247
248
|
- lib/quandl/client/middleware/parse_json.rb
|
248
249
|
- lib/quandl/client/models/dataset.rb
|
250
|
+
- lib/quandl/client/models/dataset/benchmark.rb
|
249
251
|
- lib/quandl/client/models/dataset/data.rb
|
252
|
+
- lib/quandl/client/models/dataset/validations.rb
|
250
253
|
- lib/quandl/client/models/job.rb
|
251
254
|
- lib/quandl/client/models/location.rb
|
252
255
|
- lib/quandl/client/models/report.rb
|
@@ -294,7 +297,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
294
297
|
version: '0'
|
295
298
|
segments:
|
296
299
|
- 0
|
297
|
-
hash:
|
300
|
+
hash: -2575708082673469562
|
298
301
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
299
302
|
none: false
|
300
303
|
requirements:
|
@@ -303,7 +306,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
303
306
|
version: '0'
|
304
307
|
segments:
|
305
308
|
- 0
|
306
|
-
hash:
|
309
|
+
hash: -2575708082673469562
|
307
310
|
requirements: []
|
308
311
|
rubyforge_project:
|
309
312
|
rubygems_version: 1.8.23
|