2

I'm getting from csv file some data (also how to select first 20 in csv?), for example:

A B C
D E F

also method:

def common_uploader
    require 'csv'
    arr = CSV.read("/#{Rails.public_path}/uploads_prices/"+params[:file], {:encoding => "CP1251:UTF-8", :col_sep => ";", :row_sep => :auto, :headers => :none})  
    @csv = []
    @csv << arr
  end

so it is array of arrays... But how can i view it normaly in haml view? How can i view array of arrays? i tried something like (also in each file i have different count of columns): view:

= @csv.first.each do |a|
 = a[:1]

Help me please to view csv data.

3
  • 1
    You are asking several questions making your question ambiguous. Stack Overflow prefers you restrict yourself to one or two questions to keep the answers focused. Commented Jan 2, 2013 at 0:36
  • Define "view it normaly in haml view". As a table? As <ol><li><li> or <ul><li><li>? Commented Jan 2, 2013 at 4:18
  • @theTinMan as <table><tr><td>... Commented Jan 2, 2013 at 9:30

3 Answers 3

6

There are several ways you can read a set number of records, and you need to pick which to use based on the anticipated size of your data source.

Starting with a CSV file:

A1,A2,A3
B1,B2,B3
C1,C2,C3
D1,D2,D3
E1,E2,E3
F1,F2,F3

The simplest ways to read a fixed number of records would be one of these:

require 'csv'

array = CSV.read('test.csv')[0, 2]

Which returns an array of two sub-arrays:

[
    [0] [
        [0] "A1",
        [1] "A2",
        [2] "A3"
    ],
    [1] [
        [0] "B1",
        [1] "B2",
        [2] "B3"
    ]
]

An alternate is:

File.new('test.csv').readlines[0, 2].map{ |l| CSV.parse(l).flatten }

Which returns the same result, an array of two sub-arrays:

[
    [0] [
        [0] "A1",
        [1] "A2",
        [2] "A3"
    ],
    [1] [
        [0] "B1",
        [1] "B2",
        [2] "B3"
    ]
]

Both of these are fine for small input files, but will have problems if you are reading a few lines from a big input file. They will force Ruby to read the entire file into memory and create an intermediate array before slicing off the number of records you want. Where I work it's nothing for us to get gigabyte file sizes, so grabbing a small section of those files would make Ruby and the system do an inordinate amount of work building the intermediate array then throwing it away.

You are better off to only read the minimum number of records needed. Sometimes lines need to be skipped before reading; This demonstrates that idea, along with handling EOFError if the input file's EOF is encountered unexpectedly:

File.open('test.csv') do |fi|
  array = []
  begin  
    5.times { fi.readline }    
    2.times.each{ array += CSV.parse(fi.readline) }    
  rescue EOFError    
  end    
end  

Replace 5 with the number of records to skip, and 2 with the number to read. For that example I deliberately read off the end of the file to show how to skip lines, read some and then handle the EOF situation cleanly.

The data looks like:

[
    [0] [
        [0] "F1",
        [1] "F2",
        [2] "F3"
    ]
]

Because I'm using File.open with a block, the file is closed automatically after the block exists, avoiding leaving an open filehandle hanging around.

The HAML output section of your question isn't well defined at all, but this is one way to output the data:

array = []
File.open('test.csv') do |fi|
  begin  
    0.times { fi.readline }    
    2.times.each{ array += CSV.parse(fi.readline) }    
  rescue EOFError    
  end    
end  

require 'haml'

engine = Haml::Engine.new(<<EOT)
%html
  %body
    %table
      - array.each do |r|
        %tr
          - r.each do |c|
            %td= c
EOT
puts engine.render(Object.new, :array => array)

Which results in this output of a simple HTML table:

<html>
  <body>
    <table>
      <tr>
        <td>A1</td>
        <td>A2</td>
        <td>A3</td>
      </tr>
      <tr>
        <td>B1</td>
        <td>B2</td>
        <td>B3</td>
      </tr>
    </table>
  </body>
</html>

EDIT:

and my test file: dl.dropbox.com/u/59666091/qnt_small.csv i want to see this 7 columns in browser (via haml view)

Using this as my test data:

a1,a2,a3,a4,a5,a6,a7
b1,b2,b3,b4,b5,b6,b7
c1,c2,c3,c4,c5,c6,c7
d1,d2,d3,d4,d5,d6,d7
e1,e2,e3,e4,e5,e6,e7

and this code:

require 'csv'

array = []
File.open('test.csv') do |fi|
  begin
    0.times { fi.readline }
    2.times.each{ array += CSV.parse(fi.readline) }
  rescue EOFError
  end
end

require 'haml'

engine = Haml::Engine.new(<<EOT)
%html
  %body
    %table
      - array.each do |r|
        %tr
          - r.each do |c|
            %td= c
EOT
puts engine.render(Object.new, :array => array)

I get this output:

<html>
  <body>
    <table>
      <tr>
        <td>a1</td>
        <td>a2</td>
        <td>a3</td>
        <td>a4</td>
        <td>a5</td>
        <td>a6</td>
        <td>a7</td>
      </tr>
      <tr>
        <td>b1</td>
        <td>b2</td>
        <td>b3</td>
        <td>b4</td>
        <td>b5</td>
        <td>b6</td>
        <td>b7</td>
      </tr>
    </table>
  </body>
</html>

I made a minor change to move array outside the File.open block, nothing else is different.

Sign up to request clarification or add additional context in comments.

8 Comments

"is not working" doesn't help. What is it doing? Returning an error? The examples in my answer are right out of IRB and PRY using Ruby 1.9.3-p362 so I know they work.
and my test file: dl.dropbox.com/u/59666091/qnt_small.csv i want to see this 7 columns in browser (via haml view)
for first case (in my case @csv = CSV.read("/#{Rails.public_path}/uploads_prices/"+params[:file], {:encoding => "CP1251:UTF-8", :col_sep => ";", :row_sep => :auto, :headers => :none})[0,5]) it returns: wrong number of arguments (2 for 1)
re: seeing seven columns in browser, the code doesn't care how many columns there are. If yours doesn't automatically show them the problem is in your implementation of the code.
Re: wrong number of arguments, the problem is in your code somewhere as the example doesn't return an error.
|
0

You can do sth like that:

arr = CSV.read("/data.csv", {:encoding => "CP1251:UTF-8", :col_sep => ",", :row_sep => :auto, :headers => :none})

i = 0
arr.each do |row|
  if i == 20
    break
  else
    i += 1
  end

  # do  sth
  puts row
end

But I think it's not a beautiful solution. Edit: I don't understand why you put a instance of CSV into array, you wouldn't get a each row of csv file into array

1 Comment

alsO! how to open and view then csv file in better way?
-1
require 'csv'
def parser
  CSV.open('data.csv', 'r', ';') do |row|
  puts row
end

1 Comment

how display it as table in haml? question is orientied on html view, but not just putting row

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.