CSV.open(..) block does not execute, and ends immediately - ruby-on-rails

I am opening a CSV file for writing with the following code, as indicated in CSV documentation here (http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html):
CSV.open( csv_file_out, 'wb' ) { |csv_line_out|
#stuff happens here
}
the block does not execute, i.e. after the CSV.open command debugger goes directly to the end of block.
thinking "just in case", I try the same with IO modes w+b wt w+t ab a+b. I also tried creating the file before the in case there was a problem with opening it. nothing changes.
when I stop the debugger at the CSV.open line, I am able to execute a block manually and create a csv file myself. I can also create the file frmo the exact same command from console. But it won't work when executed in the server.
Any ideas on what's going on are very welcome. Thanks in advance!

You don't need the {} brackets before your |csv_line_out|

Your trying to iterate sth. (the files content) that does not exist so its logical that it ends imediatly! Try it this way:
CSV.open(csv_file_out, "wb") do |csv|
csv << [column1, column2,...]
end

Related

Rails FTP OPEN CSV

I have the following code to connect my rails app to my FTP. This works great. However, I want to use open-uri to open the csv file so I can parse it. Any ideas how to do this? I think it's an easy thing to do but I'm missing something.
require 'net/ftp'
ftp = Net::FTP.new
ftp.connect("xxx.xxx.xx.xxx",21)
ftp.login("xxxxx","xxxx")
ftp.chdir("/")
ftp.passive = true
puts ftp.list("TEST.csv")
You'll need to use #gettextfile.
A) Get the file to a local temporary file and read its content
# Creating a tmp file can be done differently as well.
# It may also be omitted, in which case `gettextfile`
# will create a file in the current directory.
Dir::Tmpname.create(['TEST', ['.csv']) do |file_name|
ftp.gettextfile('TEST.csv', file_name)
content = File.read(file_name)
end
B) Pass a block to gettextfile and get the content one line at a time
content = ''
ftp.gettextfile('TEST.csv') do |line|
content << line
end

Lua io.write() not working

I am using a luvit Lua environment to run my lua code through my control panel. I am looking to write to a .txt file, but with the simple code that i am running, its not working.
The reason I wish to write to a .txt file is to log notices from my Discord Bot I am working on in the Discordia library.
I have a folder called MezzaBOT. In this file i have a write.lua file and also a log.txt file. I have this simple code in my write.lua file:
io.output('log.txt')
io.write('hello\n')
io.close()
I then run in my command promt with Luvit environment:
>luvit Desktop\mezzabot\write.lua
I don't get any errors but the log.txt file continues to stay empty. Am I missing a line in my code, or do i need to access log.txt differently?
edit: my new code is the following
file = io.open('log.txt')
file:write('hello', '\n')
file:close()
and it is not making a new line for each time with \n
edit B:
Ok, i found my problem, its creating a log.txt in my C:\Users\PC.
One other problem is when writing, its not making a new line with the \n. Can someone please help me?
Lua, by default, opens files in read mode. You need to explicitly open a file in write mode if you want to write to it (see manual)
file = io.open('log.txt', 'w')
file:write('hello', '\n')
file:close()
Should work :)

Read next line during file IO in Ruby

I am trying to import a file using ruby and parse it. Is there a way to read the next line once inside the file import? Basically I want to see if a specific line is within x lines of another important line. Like does "x phrase" Come within 10 lines of "y phrase". I don't see a way to do this -- I know its simple with Java.
Thanks!
You can also try:
web_contents = "c:\\path\\to\\your\\file.txt"
File.open(web_contents).each_with_index do |line, i|
line.chomp!
puts "line #{line}, i #{i}" # Do whatever you want to here
end
The .each_with_index method gives you an index, i, which you can use to keep track of where on what line in your file you are. Simple maths can then yield the offset as required.
To read lines of a file
lines_array = IO.readlines('testfile')
lines_array.each { |l| #Do your stuff with your line }
VoilĂ 
Ruby Docs on IO

reading large csv files in a rails app takes up a lot of memory - Strategy to reduce memory consumption?

I have a rails app which allows users to upload csv files and schedule the reading of multiple csv files with help of delayed_job gem. The problem is the app reads each file in its entirity into memory and then writes to the database. If its just 1 file being read its fine, but when multiple files are read the RAM on the server gets full and causes the app to hang.
I am trying to find a solution for this problem.
One solution I researched is to break the csv file into smaller parts and save them on the server, and read the smaller files. see this link
example: split -b 40k myfile segment
Not my preferred solution. Are there any other approaches to solve this where I dont have to break the file. Solutions must be ruby code.
Thanks,
You can make use of CSV.foreach to read just chunks of your CSV file:
path = Rails.root.join('data/uploads/.../upload.csv') # or, whatever
CSV.foreach(path) do |row|
# process row[i] here
end
If it's run in a background job, you could additionally call GC.start every n rows.
How it works
CSV.foreach operates on an IO stream, as you can see here:
def IO.foreach(path, options = Hash.new, &block)
# ...
open(path, options) do |csv|
csv.each(&block)
end
end
The csv.each part is a call to IO#each, which reads the file line by line (rb_io_getline_1 invokation) and leaves the line read to be garbage collected:
static VALUE
rb_io_each_line(int argc, VALUE *argv, VALUE io)
{
// ...
while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
rb_yield(str);
}
// ...
}

Reading the first line of a file in Ruby

I want to read only the first line of a file using Ruby in the fastest, simplest, most idiomatic way possible. What's the best approach?
(Specifically: I want to read the git commit UUID out of the REVISION file in my latest Capistrano-deployed Rails directory, and then output that to my tag. This will let me see at an http-glance what version is deployed to my server. If there's an entirely different & better way to do this, please let me know.)
This will read exactly one line and ensure that the file is properly closed immediately after.
strVar = File.open('somefile.txt') {|f| f.readline}
# or, in Ruby 1.8.7 and above: #
strVar = File.open('somefile.txt', &:readline)
puts strVar
Here's a concise idiomatic way to do it that properly opens the file for reading and closes it afterwards.
File.open('path.txt', &:gets)
If you want an empty file to cause an exception use this instead.
File.open('path.txt', &:readline)
Also, here's a quick & dirty implementation of head that would work for your purposes and in many other instances where you want to read a few more lines.
# Reads a set number of lines from the top.
# Usage: File.head('path.txt')
class File
def self.head(path, n = 1)
open(path) do |f|
lines = []
n.times do
line = f.gets || break
lines << line
end
lines
end
end
end
You can try this:
File.foreach('path_to_file').first
How to read the first line in a ruby file:
commit_hash = File.open("filename.txt").first
Alternatively you could just do a git-log from inside your application:
commit_hash = `git log -1 --pretty=format:"%H"`
The %H tells the format to print the full commit hash. There are also modules which allow you to access your local git repo from inside a Rails app in a more ruby-ish manner although I have never used them.
first_line = open("filename").gets
I think the jkupferman suggestion of investigating the git --pretty options makes the most sense, however yet another approach would be the head command e.g.
ruby -e 'puts `head -n 1 filename`' #(backtick before `head` and after `filename`)
Improving on the answer posted by #Chuck, I think it might be worthwhile to point out that if the file you are reading is empty, an EOFError exception will be thrown. Catch and ignore the exception:
def readit(filename)
text = ""
begin
text = File.open(filename, &:readline)
rescue EOFError
end
text
end
first_line = File.readlines('file_path').first.chomp

Resources