quandl_client 2.10.0 → 2.10.1

Sign up to get free protection for your applications and to get access to all the features.
data/UPGRADE.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 2.10.1
2
+
3
+
4
+
5
+
6
+
1
7
  ## 2.10.0
2
8
 
3
9
  * add Quandl::Client::Job
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.10.0
1
+ 2.10.1
@@ -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
@@ -26,7 +26,7 @@ module Model
26
26
  return nil unless request_finished_at.is_a?(Time) && request_started_at.is_a?(Time)
27
27
  @elapsed_request_time ||= (request_finished_at - request_started_at)
28
28
  end
29
-
29
+
30
30
  private
31
31
 
32
32
  def touch_request_started_at
@@ -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,11 @@
1
+ class Quandl::Client::Dataset
2
+ module Benchmark
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ benchmark :data_should_be_valid!, :source_code_should_exist!, :save_dataset_data, :enforce_required_formats, :valid?
8
+ end
9
+
10
+ end
11
+ 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.0
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-05-23 00:00:00.000000000 Z
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: 608725837555586379
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: 608725837555586379
309
+ hash: -2575708082673469562
307
310
  requirements: []
308
311
  rubyforge_project:
309
312
  rubygems_version: 1.8.23