quandl_client 2.7.3 → 2.7.4

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.
Files changed (56) hide show
  1. data/.gitignore +7 -6
  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 +35 -35
  10. data/UPGRADE.md +210 -207
  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 +245 -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 +40 -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 +5 -27
@@ -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,246 @@
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
+
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
+
246
246
  end