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 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