From 5d24fd474d6e6bd065039d058ef64c6db4454df9 Mon Sep 17 00:00:00 2001 From: Rufus Pollock Date: Sat, 15 Jun 2013 12:12:15 +0100 Subject: [PATCH] [csv,bugfix][s]: fix to csv backend to correct issue with header row appearing in data in case where fields passed explicitly. * The bug was triggered by change in 4d128af797546e5174537d8ed530a243e444eeab to use model fields if explicitly provided * model.test.js illustrated issue (that new test was failing prior to changes to csv backend in this commit) * Issue was that CSV backend did not pass back fields option. Previously, if no fields provided from backend we extracted fields from first row of the returned records. With change in 4d128af797546e5174537d8ed530a243e444eeab to use model fields if provided we had an issue as we no longer removed first row for fields. * Fixed by having CSV backend explicitly extract fields and pass them back --- src/backend.csv.js | 46 ++++++++++++++++++++++++---------------- test/backend.csv.test.js | 13 ++++++++++++ test/model.test.js | 1 + 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/backend.csv.js b/src/backend.csv.js index 28d58c2b..e5a8a599 100644 --- a/src/backend.csv.js +++ b/src/backend.csv.js @@ -33,37 +33,45 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {}; var reader = new FileReader(); var encoding = dataset.encoding || 'UTF-8'; reader.onload = function(e) { - var rows = my.parseCSV(e.target.result, dataset); - dfd.resolve({ - records: rows, - metadata: { - filename: dataset.file.name - }, - useMemoryStore: true - }); + var out = my.extractFields(my.parseCSV(data, dataset), dataset); + out.useMemoryStore = true; + out.metadata = { + filename: dataset.file.name + } + dfd.resolve(out); }; reader.onerror = function (e) { alert('Failed to load file. Code: ' + e.target.error.code); }; reader.readAsText(dataset.file, encoding); } else if (dataset.data) { - var rows = my.parseCSV(dataset.data, dataset); - dfd.resolve({ - records: rows, - useMemoryStore: true - }); + var out = my.extractFields(my.parseCSV(dataset.data, dataset), dataset); + out.useMemoryStore = true; + dfd.resolve(out); } else if (dataset.url) { jQuery.get(dataset.url).done(function(data) { - var rows = my.parseCSV(data, dataset); - dfd.resolve({ - records: rows, - useMemoryStore: true - }); + var out = my.extractFields(my.parseCSV(data, dataset), dataset); + out.useMemoryStore = true; }); } return dfd.promise(); }; + // Convert array of rows in { records: [ ...] , fields: [ ... ] } + // @param {Boolean} noHeaderRow If true assume that first row is not a header (i.e. list of fields but is data. + my.extractFields = function(rows, noFields) { + if (noFields.noHeaderRow !== true && rows.length > 0) { + return { + fields: rows[0], + records: rows.slice(1) + } + } else { + return { + records: rows + } + } + }; + // ## parseCSV // // Converts a Comma Separated Values string into an array of arrays. @@ -84,6 +92,8 @@ this.recline.Backend.CSV = this.recline.Backend.CSV || {}; // fields containing special characters, such as the delimiter or // quotechar, or which contain new-line characters. It defaults to '"' // + // @param {Integer} skipInitialRows A integer number of rows to skip (default 0) + // // Heavily based on uselesscode's JS CSV parser (MIT Licensed): // http://www.uselesscode.org/javascript/csv/ my.parseCSV= function(s, options) { diff --git a/test/backend.csv.test.js b/test/backend.csv.test.js index c027f097..e7b09b72 100644 --- a/test/backend.csv.test.js +++ b/test/backend.csv.test.js @@ -64,6 +64,19 @@ test("parseCSV - quotechar", function() { }); +test("parseCSV skipInitialRows", function() { + var csv = '"Jones, Jay",10\n' + + '"Xyz ""ABC"" O\'Brien",11:35\n' + + '"Other, AN",12:35\n'; + + var array = recline.Backend.CSV.parseCSV(csv, {skipInitialRows: 1}); + var exp = [ + ['Xyz "ABC" O\'Brien', '11:35' ], + ['Other, AN', '12:35' ] + ]; + deepEqual(exp, array); +}); + test("serializeCSV - Array", function() { var csv = [ ['Jones, Jay', 10], diff --git a/test/model.test.js b/test/model.test.js index 42f9c436..00797ef0 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -194,6 +194,7 @@ test('fetch without and with explicit fields', function () { dataset.fetch(); equal(dataset.fields.at(0).id, 'X'); equal(dataset.fields.at(0).get('type'), 'number'); + equal(dataset.records.at(0).get('X'), 1); }); test('_normalizeRecordsAndFields', function () {