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, sjackson@example.com, abc123, UserRole1
Olivia, Davis, odavis@example.com, abc123, User Role2
Alexander, Thomas, athomas@example.com, 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

···

--
Posted via http://www.ruby-forum.com/.

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, sjackson@example.com, abc123, UserRole1
Olivia, Davis, odavis@example.com, abc123, User Role2
Alexander, Thomas, athomas@example.com, 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 Gray II

···

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

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!

···

--
Posted via http://www.ruby-forum.com/.

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

Best regards

Francisca

···

--
Posted via http://www.ruby-forum.com/.

On Wed, 27 Oct 2010 19:13:33 -0500, James Edward Gray II
<james@graysoftinc.com> wrote in
<E79F065E-636F-4545-99AC-9D5F04E5A752@graysoftinc.com>:

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, sjackson@example.com, abc123, UserRole1
Olivia, Davis, odavis@example.com, abc123, User Role2
Alexander, Thomas, athomas@example.com, 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:

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,sjackson@example.com,abc123,UserRole1
Olivia,Davis,odavis@example.com,abc123,User Role2
Alexander,Thomas,athomas@example.com,abc123,"UserRole1,User Role2"

It's less easy for a human to read, but adheres to the RFC
(http://tools.ietf.org/html/rfc4180#page-2). See section 2.4.

···

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

--
Charles Calvert | Software Design/Development
Celtic Wolf, Inc. | Project Management
http://www.celticwolf.com/ | Technical Writing
(703) 580-0210 | Research

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

···

--
Posted via http://www.ruby-forum.com/.

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 Biedenharn
Rob@AgileConsultingLLC.com http://AgileConsultingLLC.com/
rab@GaslightSoftware.com http://GaslightSoftware.com/

···

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

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!

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

I think you can replace the above line with:

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

end

end

Hope that helps.

James Edward Gray II

···

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