FasterCSV - illegal quoting error - thought it was correct?

I’m running:
.rvm/gems/ruby-1.8.7-p302/gems/fastercsv-1.5.3

I have a csv file that includes many rows here’s an example snippet
including the header row:

First Name, Last Name, Email, Password, Roles
Sophia, Jackson, [email protected], abc123, UserRole1
Olivia, Davis, [email protected], abc123, User Role2
Alexander, Thomas, [email protected], abc123, “UserRole1, User Role2”

my code is:

fcsv = FasterCSV.open(self.csv_file_name, “rb”, {:headers => true,
:return_headers => false})
fcsv.each do |row|
user = User.new(csv_row_to_user_attributes(row))

I have no problems with any row above Alexander, each user of which only
has 1 role, UserRole1 or User Role2. But on Alexander I get an “Illegal
quoting” error.

I thought that this was the correct way to handle this situation
according to the standard. I do not want the quotes to be returned as
part of my string, i just want the string that is the user roles. One
set of quotes returns me the error illegal quoting, two sets of quotes
returns me the same error. Shouldn’t three sets include the quotes as
part of the string? Well, it still returns me the same error.

What am I doing wrong? thanks.

-Gabe

On Oct 27, 2010, at 5:58 PM, Gabriel S. wrote:

I have a csv file that includes many rows here’s an example snippet
including the header row:

First Name, Last Name, Email, Password, Roles
Sophia, Jackson, [email protected], abc123, UserRole1
Olivia, Davis, [email protected], abc123, User Role2
Alexander, Thomas, [email protected], abc123, “UserRole1, User Role2”

I thought that this was the correct way to handle this situation
according to the standard. I do not want the quotes to be returned as
part of my string, i just want the string that is the user roles. One
set of quotes returns me the error illegal quoting, two sets of quotes
returns me the same error. Shouldn’t three sets include the quotes as
part of the string? Well, it still returns me the same error.

What am I doing wrong? thanks.

The issue is the spaces after your commas. A quoted field must begin
with a quote, not a space. Here’s an example:

require “rubygems”
=> true

require “faster_csv”
=> true

FCSV.parse(‘a, “b, c”’)
FasterCSV::MalformedCSVError: Illegal quoting on line 1.

FCSV.parse(‘a,“b, c”’)
=> [[“a”, “b, c”]]

I hope that helps.

James Edward G. II

On Wed, 27 Oct 2010 19:13:33 -0500, James Edward G. II
[email protected] wrote in
[email protected]:

I thought that this was the correct way to handle this situation
according to the standard. I do not want the quotes to be returned as
part of my string, i just want the string that is the user roles. One
set of quotes returns me the error illegal quoting, two sets of quotes
returns me the same error. Shouldn’t three sets include the quotes as
part of the string? Well, it still returns me the same error.

What am I doing wrong? thanks.

The issue is the spaces after your commas. A quoted field must
begin with a quote, not a space. Here’s an example:

To expand on this, if you check the values returned for other rows,
you’ll find that they’re being returned with the leading space
included:

irb(main):004:0> row = FasterCSV.parse(‘a, b, c’)
=> [[“a”, " b", " c"]]
irb(main):005:0> row[0]
=> [“a”, " b", " c"]
irb(main):006:0> row[0][0].size
=> 1
irb(main):007:0> row[0][1].size
=> 2

Note the difference between the first value and the second and third
values. The latter have leading spaces.

You should eliminate the spaces so that your rows look like this:

First Name,Last Name,Email,Password,Roles
Sophia,Jackson,[email protected],abc123,UserRole1
Olivia,Davis,[email protected],abc123,User Role2
Alexander,Thomas,[email protected],abc123,“UserRole1,User Role2”

It’s less easy for a human to read, but adheres to the RFC
(RFC 4180 - Common Format and MIME Type for Comma-Separated Values (CSV) Files). See section 2.4.

Hi I’m learning Ruby, so I have a beginners question for you:

How Can I sort attributes.values for similar order as csv_header? Just
consider that I already order by csv_header on my query but i did not
work.

@custom_csv = User.find(:all, :select=>"name, lastname, address " :order
=> “name, lastname, address”)

csv_header = [name,lastname,address]

csv_string = FasterCSV.generate do |csv|

csv << csv_header

@custom_csv.each do |v|

csv << v.attributes.values

end

end

Thanks in advance!

Thanks! both for the answer and creating FasterCSV in the first place.

And yeah, that was the issue. I got rid of all the spaces after the
commas and now it works.

-Gabe

On Nov 14, 2010, at 10:48 PM, Francisca Munhoz wrote:

csv_header = [name,lastname,address]

end

Thanks in advance!

Well, since you’ve already limited the attributes that ActiveRecord
will see (assuming by your syntax that User is a model derived from
ActiveRecord::Base), then v.attributes will be a hash that contains
just those three key/value pairs.

Your definition of the headers probably needs to be something like:
csv_header = %w[ name lastname address ]
but then the statement in the inner loop can be:
csv << v.attributes.values_at(*csv_header)
You can lookup the docs for Hash#values_at and the * is the “unary
unarray” operator or the “splat” which places the elements of
csv_header into the argument list separately. This is equivalent to:
csv << v.attributes.values_at(“name”,“lastname”,“address”)

If you have other questions that get more Rails-specific, I’d suggest
jumping over to the rails list.
http://groups.google.com/group/rubyonrails-talk?hl=en

-Rob

Rob B.
[email protected] http://AgileConsultingLLC.com/
[email protected] http://GaslightSoftware.com/

Thanks guys I really appreciate your help, both solutions work
perfectly!

Best regards

Francisca

On Nov 14, 2010, at 9:48 PM, Francisca Munhoz wrote:

csv << csv_header

@custom_csv.each do |v|

csv << v.attributes.values

I think you can replace the above line with:

csv << csv_header.map { |h| v[h] }

end

end

Hope that helps.

James Edward G. II