quandl_client 2.7.5 → 2.7.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +7 -7
  2. data/.rspec +1 -1
  3. data/.travis.yml +20 -20
  4. data/.yardopts +2 -2
  5. data/Gemfile +12 -12
  6. data/Guardfile +8 -8
  7. data/LICENSE +7 -7
  8. data/README.md +303 -303
  9. data/Rakefile +31 -35
  10. data/UPGRADE.md +190 -213
  11. data/VERSION +1 -1
  12. data/examples/create.rb +32 -32
  13. data/examples/find.rb +17 -17
  14. data/examples/login.rb +12 -12
  15. data/examples/search.rb +12 -12
  16. data/examples/trims.rb +15 -15
  17. data/lib/quandl/client.rb +49 -49
  18. data/lib/quandl/client/base.rb +91 -91
  19. data/lib/quandl/client/base/attributes.rb +15 -15
  20. data/lib/quandl/client/base/model.rb +40 -40
  21. data/lib/quandl/client/base/search.rb +74 -74
  22. data/lib/quandl/client/base/validation.rb +101 -101
  23. data/lib/quandl/client/middleware.rb +9 -9
  24. data/lib/quandl/client/middleware/parse_json.rb +85 -85
  25. data/lib/quandl/client/models/dataset.rb +261 -245
  26. data/lib/quandl/client/models/dataset/data.rb +57 -57
  27. data/lib/quandl/client/models/location.rb +10 -10
  28. data/lib/quandl/client/models/report.rb +14 -14
  29. data/lib/quandl/client/models/scraper.rb +16 -16
  30. data/lib/quandl/client/models/sheet.rb +50 -50
  31. data/lib/quandl/client/models/source.rb +48 -40
  32. data/lib/quandl/client/models/superset.rb +59 -59
  33. data/lib/quandl/client/models/user.rb +7 -7
  34. data/lib/quandl/client/version.rb +14 -14
  35. data/lib/quandl/her/remove_method_data.rb +8 -8
  36. data/lib/quandl/pattern.rb +37 -37
  37. data/lib/quandl/pattern/client.rb +8 -8
  38. data/quandl_client.gemspec +33 -33
  39. data/spec/factories/dataset.rb +10 -10
  40. data/spec/factories/sheet.rb +7 -7
  41. data/spec/factories/source.rb +9 -9
  42. data/spec/fixtures/scraper.rb +5 -5
  43. data/spec/lib/quandl/client/dataset/attributes_spec.rb +63 -63
  44. data/spec/lib/quandl/client/dataset/data_spec.rb +92 -92
  45. data/spec/lib/quandl/client/dataset/location_spec.rb +65 -65
  46. data/spec/lib/quandl/client/dataset/persistence_spec.rb +104 -104
  47. data/spec/lib/quandl/client/dataset/search_spec.rb +19 -19
  48. data/spec/lib/quandl/client/dataset/source_spec.rb +47 -47
  49. data/spec/lib/quandl/client/dataset/trim_spec.rb +35 -35
  50. data/spec/lib/quandl/client/dataset/validation_spec.rb +68 -68
  51. data/spec/lib/quandl/client/dataset_spec.rb +57 -57
  52. data/spec/lib/quandl/client/scraper_spec.rb +71 -71
  53. data/spec/lib/quandl/client/sheet_spec.rb +37 -37
  54. data/spec/lib/quandl/client/source_spec.rb +51 -51
  55. data/spec/spec_helper.rb +30 -30
  56. metadata +27 -5
@@ -1,10 +1,10 @@
1
- require 'faraday'
2
- require 'quandl/client/middleware/parse_json'
3
-
4
- module Quandl
5
- module Client
6
- module Middleware
7
-
8
- end
9
- end
1
+ require 'faraday'
2
+ require 'quandl/client/middleware/parse_json'
3
+
4
+ module Quandl
5
+ module Client
6
+ module Middleware
7
+
8
+ end
9
+ end
10
10
  end
@@ -1,86 +1,86 @@
1
- require 'json'
2
-
3
- module Quandl
4
- module Client
5
- module Middleware
6
-
7
- class ParseJSON < Faraday::Response::Middleware
8
-
9
- def on_complete(env)
10
- env[:body] = case env[:status]
11
- when 204
12
- parse('{}', env)
13
- else
14
- parse(env[:body], env)
15
- end
16
- end
17
-
18
- def parse(body, env)
19
- json = parse_json(body, env)
20
- json.has_key?(:docs) ? format_collection( json, env ) : format_record( json, env )
21
- end
22
-
23
- def format_record(json, env)
24
- errors = json.delete(:errors) || {}
25
- metadata = json.delete(:metadata) || {}
26
- # collect some response data
27
- metadata.merge!({
28
- status: env[:status],
29
- headers: env[:response_headers],
30
- })
31
- # return object
32
- object = {
33
- :data => json,
34
- :errors => errors,
35
- :metadata => metadata
36
- }
37
- env[:status] = 200
38
- object
39
- end
40
-
41
- def format_collection(json, env)
42
- errors = json.delete(:errors) || {}
43
- metadata = json.delete(:metadata) || {}
44
- docs = json.delete(:docs)
45
- # collect some response data
46
- metadata.merge!(json).merge!({
47
- status: env[:status],
48
- headers: env[:response_headers],
49
- })
50
- # each doc metadata references metadata
51
- docs.each{|d| d[:metadata] = metadata }
52
- # return object
53
- object = {
54
- :data => docs,
55
- :errors => errors,
56
- :metadata => metadata
57
- }
58
- env[:status] = 200
59
- object
60
- end
61
-
62
- def parse_json(body = nil, env)
63
- body ||= '{}'
64
- json = begin
65
- JSON.parse(body).symbolize_keys!
66
- rescue JSON::ParserError
67
- nil
68
- end
69
- # invalid json body?
70
- if json.blank?
71
- # fallback to error message
72
- json = {
73
- id: 1,
74
- errors: {
75
- parse_errors: [ "Quandl::Client::ParseJSON error. status: #{env[:status]}, body: #{body.inspect}" ]
76
- }
77
- }
78
- end
79
- json
80
- end
81
-
82
- end
83
-
84
- end
85
- end
1
+ require 'json'
2
+
3
+ module Quandl
4
+ module Client
5
+ module Middleware
6
+
7
+ class ParseJSON < Faraday::Response::Middleware
8
+
9
+ def on_complete(env)
10
+ env[:body] = case env[:status]
11
+ when 204
12
+ parse('{}', env)
13
+ else
14
+ parse(env[:body], env)
15
+ end
16
+ end
17
+
18
+ def parse(body, env)
19
+ json = parse_json(body, env)
20
+ json.has_key?(:docs) ? format_collection( json, env ) : format_record( json, env )
21
+ end
22
+
23
+ def format_record(json, env)
24
+ errors = json.delete(:errors) || {}
25
+ metadata = json.delete(:metadata) || {}
26
+ # collect some response data
27
+ metadata.merge!({
28
+ status: env[:status],
29
+ headers: env[:response_headers],
30
+ })
31
+ # return object
32
+ object = {
33
+ :data => json,
34
+ :errors => errors,
35
+ :metadata => metadata
36
+ }
37
+ env[:status] = 200
38
+ object
39
+ end
40
+
41
+ def format_collection(json, env)
42
+ errors = json.delete(:errors) || {}
43
+ metadata = json.delete(:metadata) || {}
44
+ docs = json.delete(:docs)
45
+ # collect some response data
46
+ metadata.merge!(json).merge!({
47
+ status: env[:status],
48
+ headers: env[:response_headers],
49
+ })
50
+ # each doc metadata references metadata
51
+ docs.each{|d| d[:metadata] = metadata }
52
+ # return object
53
+ object = {
54
+ :data => docs,
55
+ :errors => errors,
56
+ :metadata => metadata
57
+ }
58
+ env[:status] = 200
59
+ object
60
+ end
61
+
62
+ def parse_json(body = nil, env)
63
+ body ||= '{}'
64
+ json = begin
65
+ JSON.parse(body).symbolize_keys!
66
+ rescue JSON::ParserError
67
+ nil
68
+ end
69
+ # invalid json body?
70
+ if json.blank?
71
+ # fallback to error message
72
+ json = {
73
+ id: 1,
74
+ errors: {
75
+ parse_errors: [ "Quandl::Client::ParseJSON error. status: #{env[:status]}, body: #{body.inspect}" ]
76
+ }
77
+ }
78
+ end
79
+ json
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
86
86
  end
@@ -1,246 +1,262 @@
1
- class Quandl::Client::Dataset < Quandl::Client::Base
2
-
3
- require 'quandl/client/models/dataset/data'
4
-
5
- ##########
6
- # SCOPES #
7
- ##########
8
- class << self
9
- def touch_existing(id)
10
- put(File.join(Quandl::Client::Base.url_with_version, "datasets/#{id}/touch")).exists?
11
- end
12
-
13
- def find(value)
14
- # preformat
15
- value = format_id(value)
16
- # short-circuit if value is illegal
17
- return nil unless value.is_a?(Integer) || value.to_s =~ %r{^#{Quandl::Pattern.full_code}$}
18
- # search
19
- super(value)
20
- end
21
-
22
- def format_id(value)
23
- # enforce code formatting
24
- if value.is_a?(String)
25
- # strip extra whitespace
26
- value = value.strip.rstrip
27
- # ensure slashes are forward facing
28
- value = value.gsub("\\","/").gsub(".","/")
29
- # ensure uppercase
30
- value = value.upcase
31
- end
32
- value
33
- end
34
-
35
- end
36
-
37
- # SEARCH
38
- scope :query, :rows, :owner
39
- scope :page, ->(p){ where( page: p.to_i )}
40
- scope :source_code, ->(c){ where( code: c.to_s.upcase )}
41
-
42
- ###############
43
- # ASSOCIATIONS #
44
- ###############
45
-
46
- def source
47
- @source ||= Quandl::Client::Source.find(self.source_code)
48
- end
49
-
50
- ###############
51
- # VALIDATIONS #
52
- ###############
53
-
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
-
64
- ##############
65
- # PROPERTIES #
66
- ##############
67
-
68
- attributes :source_code, :code, :name, :urlize_name,
69
- :description, :updated_at, :frequency,
70
- :from_date, :to_date, :column_names, :private, :type,
71
- :display_url, :column_spec, :import_spec, :import_url,
72
- :locations_attributes, :availability_delay, :refreshed_at
73
-
74
- before_save :enforce_required_formats
75
-
76
- after_save :save_dataset_data
77
-
78
- alias_method :locations, :locations_attributes
79
- alias_method :locations=, :locations_attributes=
80
-
81
- def reference_url
82
- self.display_url
83
- end
84
- def reference_url=(value)
85
- value = "http://#{value}" if value.present? && !(value =~ /:\/\//)
86
- self.display_url = value
87
- end
88
-
89
- def full_url
90
- File.join(Quandl::Client::Base.url.gsub(/api\/?/, ''), full_code)
91
- end
92
-
93
- def full_code
94
- File.join(self.source_code.to_s, self.code.to_s)
95
- end
96
-
97
- # DATA
98
-
99
- def data
100
- defined?(@data) ? @data : data_scope
101
- end
102
-
103
- def data=(value)
104
- @data = Quandl::Data.new(value).sort_descending
105
- end
106
-
107
- def data?
108
- @data.is_a?(Quandl::Data)
109
- end
110
-
111
- def delete_data
112
- # cant delete unsaved records
113
- return false if new_record?
114
- # delete and return success / failure
115
- self.class.destroy_existing("#{id}/data").saved?
116
- end
117
-
118
- def delete_rows(*dates)
119
- # cant delete unsaved records
120
- return false if new_record?
121
- # collect dates
122
- query = { dates: Array(dates).flatten }.to_query
123
- # delete and return success / failure
124
- self.class.destroy_existing("#{id}/data/rows?#{query}").saved?
125
- end
126
-
127
- def data_scope
128
- @data_scope ||= Quandl::Client::Dataset::Data.with_id(id)
129
- end
130
-
131
- def dataset_data
132
- @dataset_data ||= Quandl::Client::Dataset::Data.new( id: id )
133
- end
134
-
135
- def dataset_data?
136
- @dataset_data.is_a?(Quandl::Client::Dataset::Data)
137
- end
138
-
139
- def reload
140
- @dataset_data = nil
141
- @data_scope = nil
142
- @full_code = nil
143
- end
144
-
145
- protected
146
-
147
- def data_should_be_valid!
148
- if data? && !data.valid?
149
- data.errors.each{|k,v| self.errors.add( k,v ) }
150
- return false
151
- end
152
- true
153
- end
154
-
155
- def dataset_data_should_be_valid!
156
- if dataset_data? && !dataset_data.valid?
157
- dataset_data.errors.each{|k,v| self.errors.add( k,v ) }
158
- return false
159
- end
160
- true
161
- end
162
-
163
- def ambiguous_code_requires_source_code!
164
- if code.to_s.numeric? && source_code.blank?
165
- message = %Q{Pure numerical codes like "#{code}" are not allowed unless you include a source code. Do this:\nsource_code: <USERNAME>\ncode: #{code}}
166
- self.errors.add( :data, message )
167
- return false
168
- end
169
- true
170
- end
171
-
172
- def data_columns_should_not_exceed_column_names!
173
- if errors.size == 0 && data? && data.present? && column_names.present? && data.first.count != column_names.count
174
- 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." )
175
- return false
176
- end
177
- true
178
- end
179
-
180
- def data_rows_should_have_equal_columns!
181
- # skip validation unless data is present
182
- return true unless data? && data.present?
183
- # use first row as expected column count
184
- column_count = data[0].count
185
- # check each row
186
- data.each_with_index do |row, index|
187
- # the row is valid if it's count matches the first row's count
188
- next if row.count == column_count
189
- # the row is invalid if the count is mismatched
190
- 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(',')})" )
191
- # return validation failure
192
- return false
193
- end
194
- true
195
- end
196
-
197
- def data_row_count_should_match_column_count!
198
- # skip validation unless data and column_names present
199
- return true unless data? && data.present? && column_names.present?
200
- # count the number of expected columns
201
- column_count = column_names.count
202
- # check each row
203
- data.each_with_index do |row, index|
204
- # the row is valid if it's count matches the first row's count
205
- next if row.count == column_count
206
- # the row is invalid if the count is mismatched
207
- 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(',')})" )
208
- # return validation failure
209
- return false
210
- end
211
- true
212
- end
213
-
214
- def save_dataset_data
215
- return if (!saved? && id.blank?)
216
- return if !data? || data.blank?
217
-
218
- dataset_data.id = id
219
- dataset_data.data = data.to_csv
220
- dataset_data.save
221
- # update dataset's attributes with dataset_data's attributes
222
- attributes.each{|k,v| attributes[k] = dataset_data.attributes[k] if dataset_data.attributes.has_key?(k) }
223
- # update dataset errors with dataset_data
224
- @metadata[:status] = dataset_data.status unless dataset_data.saved?
225
- # inherit_errors(dataset_data) unless dataset_data.saved?
226
- end
227
-
228
- def inherit_errors(object)
229
- return unless object.respond_to?(:response_errors) && object.response_errors.respond_to?(:each)
230
- object.response_errors.each do |key, messages|
231
- if messages.respond_to?(:each)
232
- messages.each{|message| errors.add(key, message) }
233
- end
234
- end
235
- @metadata[:status] = object.status
236
- object
237
- end
238
-
239
- def enforce_required_formats
240
- # self.data = Quandl::Data.new(data).to_csv
241
- self.source_code = self.source_code.to_s.upcase
242
- self.code = self.code.to_s.upcase
243
- self.locations_attributes = locations_attributes.to_json if locations_attributes.respond_to?(:to_json) && !locations_attributes.kind_of?(String)
244
- end
245
-
1
+ class Quandl::Client::Dataset < Quandl::Client::Base
2
+
3
+ require 'quandl/client/models/dataset/data'
4
+
5
+ ##########
6
+ # SCOPES #
7
+ ##########
8
+ class << self
9
+ def touch_existing(id)
10
+ put(File.join(Quandl::Client::Base.url_with_version, "datasets/#{id}/touch")).exists?
11
+ end
12
+
13
+ def find(value)
14
+ # preformat
15
+ value = format_id(value)
16
+ # short-circuit if value is illegal
17
+ return nil unless value.is_a?(Integer) || value.to_s =~ %r{^#{Quandl::Pattern.full_code}$}
18
+ # search
19
+ super(value)
20
+ end
21
+
22
+ def format_id(value)
23
+ # enforce code formatting
24
+ if value.is_a?(String)
25
+ # strip extra whitespace
26
+ value = value.strip.rstrip
27
+ # ensure slashes are forward facing
28
+ value = value.gsub("\\","/").gsub(".","/")
29
+ # ensure uppercase
30
+ value = value.upcase
31
+ end
32
+ value
33
+ end
34
+
35
+ end
36
+
37
+ # SEARCH
38
+ scope :query, :rows, :owner
39
+ scope :page, ->(p){ where( page: p.to_i )}
40
+ scope :source_code, ->(c){ where( code: c.to_s.upcase )}
41
+
42
+ ###############
43
+ # ASSOCIATIONS #
44
+ ###############
45
+
46
+ def source
47
+ @source ||= Quandl::Client::Source.find(self.source_code)
48
+ end
49
+
50
+ ###############
51
+ # VALIDATIONS #
52
+ ###############
53
+
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
+
66
+ ##############
67
+ # PROPERTIES #
68
+ ##############
69
+
70
+ attributes :source_code, :code, :name, :urlize_name,
71
+ :description, :updated_at, :frequency,
72
+ :from_date, :to_date, :column_names, :private, :type,
73
+ :display_url, :column_spec, :import_spec, :import_url,
74
+ :locations_attributes, :availability_delay, :refreshed_at
75
+
76
+ before_save :enforce_required_formats
77
+
78
+ after_save :save_dataset_data
79
+
80
+ alias_method :locations, :locations_attributes
81
+ alias_method :locations=, :locations_attributes=
82
+
83
+ def reference_url
84
+ self.display_url
85
+ end
86
+ def reference_url=(value)
87
+ value = "http://#{value}" if value.present? && !(value =~ /:\/\//)
88
+ self.display_url = value
89
+ end
90
+
91
+ def full_url
92
+ File.join(Quandl::Client::Base.url.gsub(/api\/?/, ''), full_code)
93
+ end
94
+
95
+ def full_code
96
+ File.join(self.source_code.to_s, self.code.to_s)
97
+ end
98
+
99
+ # DATA
100
+
101
+ def data
102
+ defined?(@data) ? @data : data_scope
103
+ end
104
+
105
+ def data=(value)
106
+ @data = Quandl::Data.new(value).sort_descending
107
+ end
108
+
109
+ def data?
110
+ @data.is_a?(Quandl::Data)
111
+ end
112
+
113
+ def source_code=(v)
114
+ write_attribute(:source_code, v.to_s.upcase)
115
+ end
116
+
117
+ def delete_data
118
+ # cant delete unsaved records
119
+ return false if new_record?
120
+ # delete and return success / failure
121
+ self.class.destroy_existing("#{id}/data").saved?
122
+ end
123
+
124
+ def delete_rows(*dates)
125
+ # cant delete unsaved records
126
+ return false if new_record?
127
+ # collect dates
128
+ query = { dates: Array(dates).flatten }.to_query
129
+ # delete and return success / failure
130
+ self.class.destroy_existing("#{id}/data/rows?#{query}").saved?
131
+ end
132
+
133
+ def data_scope
134
+ @data_scope ||= Quandl::Client::Dataset::Data.with_id(id)
135
+ end
136
+
137
+ def dataset_data
138
+ @dataset_data ||= Quandl::Client::Dataset::Data.new( id: id )
139
+ end
140
+
141
+ def dataset_data?
142
+ @dataset_data.is_a?(Quandl::Client::Dataset::Data)
143
+ end
144
+
145
+ def reload
146
+ @dataset_data = nil
147
+ @data_scope = nil
148
+ @full_code = nil
149
+ end
150
+
151
+ protected
152
+
153
+ def data_should_be_valid!
154
+ if data? && !data.valid?
155
+ data.errors.each{|k,v| self.errors.add( k,v ) }
156
+ return false
157
+ end
158
+ true
159
+ end
160
+
161
+ def dataset_data_should_be_valid!
162
+ if dataset_data? && !dataset_data.valid?
163
+ dataset_data.errors.each{|k,v| self.errors.add( k,v ) }
164
+ return false
165
+ end
166
+ true
167
+ end
168
+
169
+ def source_code_should_exist!
170
+ if source_code.present?
171
+ Source.cached[source_code] = Source.find(source_code) unless Source.cached.has_key?(source_code)
172
+ source = Source.cached[source_code]
173
+ self.errors.add( :source_code, "Could not find a source with the source_code '#{source_code}'" ) if source.blank? || source.code.blank?
174
+ return false
175
+ end
176
+ true
177
+ end
178
+
179
+ def ambiguous_code_requires_source_code!
180
+ if code.to_s.numeric? && source_code.blank?
181
+ message = %Q{Pure numerical codes like "#{code}" are not allowed unless you include a source code. Do this:\nsource_code: <USERNAME>\ncode: #{code}}
182
+ self.errors.add( :data, message )
183
+ return false
184
+ end
185
+ true
186
+ end
187
+
188
+ def data_columns_should_not_exceed_column_names!
189
+ if errors.size == 0 && data? && data.present? && column_names.present? && data.first.count != column_names.count
190
+ 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." )
191
+ return false
192
+ end
193
+ true
194
+ end
195
+
196
+ def data_rows_should_have_equal_columns!
197
+ # skip validation unless data is present
198
+ return true unless data? && data.present?
199
+ # use first row as expected column count
200
+ column_count = data[0].count
201
+ # check each row
202
+ data.each_with_index do |row, index|
203
+ # the row is valid if it's count matches the first row's count
204
+ next if row.count == column_count
205
+ # the row is invalid if the count is mismatched
206
+ 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(',')})" )
207
+ # return validation failure
208
+ return false
209
+ end
210
+ true
211
+ end
212
+
213
+ def data_row_count_should_match_column_count!
214
+ # skip validation unless data and column_names present
215
+ return true unless data? && data.present? && column_names.present?
216
+ # count the number of expected columns
217
+ column_count = column_names.count
218
+ # check each row
219
+ data.each_with_index do |row, index|
220
+ # the row is valid if it's count matches the first row's count
221
+ next if row.count == column_count
222
+ # the row is invalid if the count is mismatched
223
+ 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(',')})" )
224
+ # return validation failure
225
+ return false
226
+ end
227
+ true
228
+ end
229
+
230
+ def save_dataset_data
231
+ return if (!saved? && id.blank?)
232
+ return if !data? || data.blank?
233
+
234
+ dataset_data.id = id
235
+ dataset_data.data = data.to_csv
236
+ dataset_data.save
237
+ # update dataset's attributes with dataset_data's attributes
238
+ attributes.each{|k,v| attributes[k] = dataset_data.attributes[k] if dataset_data.attributes.has_key?(k) }
239
+ # update dataset errors with dataset_data
240
+ @metadata[:status] = dataset_data.status unless dataset_data.saved?
241
+ # inherit_errors(dataset_data) unless dataset_data.saved?
242
+ end
243
+
244
+ def inherit_errors(object)
245
+ return unless object.respond_to?(:response_errors) && object.response_errors.respond_to?(:each)
246
+ object.response_errors.each do |key, messages|
247
+ if messages.respond_to?(:each)
248
+ messages.each{|message| errors.add(key, message) }
249
+ end
250
+ end
251
+ @metadata[:status] = object.status
252
+ object
253
+ end
254
+
255
+ def enforce_required_formats
256
+ # self.data = Quandl::Data.new(data).to_csv
257
+ self.source_code = self.source_code.to_s.upcase
258
+ self.code = self.code.to_s.upcase
259
+ self.locations_attributes = locations_attributes.to_json if locations_attributes.respond_to?(:to_json) && !locations_attributes.kind_of?(String)
260
+ end
261
+
246
262
  end