Ruby View CSV Data

How can i read csv file datas from csv files in ruby on rails

Here goes a working example of reading CSV, instantiating Person object and printing.

# following the directory tree:
# ./
# ./tasks/main.rb
# ./csv/department.csv
#
# csv file example
#
# name,surname,department
# John,Doe,IT
# Bill,Doe,IT
#
# running this code:
# ruby tasks/main.rb
require 'csv'

class Person
def initialize(name, surname, department)
@name = name
@surname = surname
@department = department
end

def print_full_name
puts "#{@name} #{@surname}"
end
end

### main
filepath = "#{__dir__}/../csv/department.csv"
CSV.foreach(filepath, headers: true) do |row|
person = Person.new(
row["name"],
row["surname"],
row["department"]
)

person.print_full_name
end

Your code in the question wasn't written in ruby way. I recommend you to read this ruby styleguide to follow some practices on our community

Ruby view csv data

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.

Fetch the data from the CSV files in ruby and Order the Data in DESC?

You need column names in the CSV if you want to use the row["COL"] csv syntax.
Additionally you need to use += not = to add them up. Right now you're just overwriting the value every time.

Name,Sales
Randy, 200
Robin, 502
Randy, 200
Raj, 502
Randy, 500
Robin, 102
Mano, 220
Raj, 502
Randy, 285
Robin, 385
Randy, 295
Raj, 596
require 'csv'
cust = Hash.new

CSV.foreach(("./data.csv"), headers: true, col_sep: ",") do |row|
# if key isn't in hash start it at 0
unless cust.keys.include?(row["Name"])
cust[row["Name"]] = 0
end
# add the sales (.to_i converts to integer)
cust[row["Name"]] += row["Sales"].to_i
end

puts "Name Sales Rank"
# Sort by the value not the key. Make it negative so it's descending
# not ascending.
# each_with_index is just a nice way to count them
cust.sort_by{|k,v| -v}.each_with_index do |(name, sales), i|
puts "#{name} #{sales} #{i+1}"
end

Produces:

Raj 1600 1
Randy 1480 2
Robin 989 3
Mano 220 4

How to read the filename of a csv file in ruby

You can list all the CSV files in the dropbox folder and check if they match the pattern. Then extract the information you need and create the test:

Dir.glob('yourdropboxfolder/*.csv').each do |filename|
name = File.basename(filename, '.csv')
if (match = /(\d+)_(.*).csv/.match(name))
student_id = match[1]
test_name = match[2]
create_test_for(student_id, test_name, File.read(filename))
end
end

Not sure if you need to extract the values from the filename or if this information is also in the file.



Related Topics



Leave a reply



Submit