Output of a method to file?

Can anybody tell me how to take the output of a method and save it to a
file?

I have an array and I've created a method to take the strings I put into
the array and insert them into a place in a sentence. How do I execute
the method and save the output to a file? I just started with Ruby a
few days ago and I can have it save a file, but the file it saves is
empty.

Help, please?

···

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

Zoe Phoenix wrote:

Can anybody tell me how to take the output of a method and save it to a
file?

I have an array and I've created a method to take the strings I put into
the array and insert them into a place in a sentence. How do I execute
the method and save the output to a file? I just started with Ruby a
few days ago and I can have it save a file, but the file it saves is
empty.

Help, please?

Sure:
irb(main):003:0> to_file = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):004:0> File.open("a_file.txt","w") do |f|
irb(main):005:1* f.write to_file
irb(main):006:1> end
=> 5
irb(main):007:0> exit

C:\temp>cat a_file.txt
12345

Let's walk a bit through the code:
to_file is your average Array.

The File class allows you to interact with files (most commonly, reading
and writing).

Fil.open("a_file.txt","w") opens a file called "a_file.txt" in write
mode (the "w"). It's important to tell Ruby the mode you want to use.
"r" is the mode to read files, "a" is the mode to append to a file, and
Windows has the mode "b" to handle binary files.
You can find a quick reference for that here:

The |f| is a bloack variable. I use that in the next line, to actually
write to the file:
f.write to_file This writes the content of the Array to a file. Note
that the Array is dumped similar to Array#join "". You'll have to add
line breaks somehow, if you want lines.

Anyway: This step in the block writes to the file.

end closes the block, and with that, Ruby takes care of closing the
file, too, so that you don't have to.

I hope that helps. (I have to look it up myself, more often than I would
like).

- --
Phillip Gawlowski
Twitter: twitter.com/cynicalryan

~ YAAH! DEATH TO OATMEAL!
      -- Calvin

Maybe it would help if I posted the code, I'm not sure I understand...
For example..:

def cityList
c_list = ['Boston', 'Nashville', 'San Francisco', 'Houston', 'Portland',
'Atlanta', 'Chicago', 'Indianapolis', 'Charleston']

bar = '|| '

puts bar + c_list[0..2].join(' pets || ') + (' pets ||')

puts bar + c_list[3..5].join(' pets || ') + (' pets ||')

puts bar + c_list[6..8].join(' pets || ') + (' pets ||')

end

cityList

puts 'File completed. Save as..?'
save_as = gets.chomp

File::open('c:\rubyfiles\citylist-' + save_as + '.txt', 'w') do |f|

···

***********

I need it to take the output of that method that I created and write it
to a file... I'm not sure I understand how to do that with the example
you gave. Since I know the code that I had after "File::open", etc. was
wrong, I just left it out.

It would also be nice if I could have the method cycle through 3 items
in the array, then write 3 to a new line, the continue in increments of
3 until it reaches the end of the array. But, I'm not sure if I should
write another topic to ask that or if someone will answer that here.
Thanks for the help so far, though... I'm pretty new at this.
--
Posted via http://www.ruby-forum.com/.

Zoe Phoenix wrote:

Maybe it would help if I posted the code, I'm not sure I understand...
For example..:

def cityList
c_list = ['Boston', 'Nashville', 'San Francisco', 'Houston', 'Portland',
'Atlanta', 'Chicago', 'Indianapolis', 'Charleston']

bar = '|| '

puts bar + c_list[0..2].join(' pets || ') + (' pets ||')

puts bar + c_list[3..5].join(' pets || ') + (' pets ||')

puts bar + c_list[6..8].join(' pets || ') + (' pets ||')

end

cityList

puts 'File completed. Save as..?'
save_as = gets.chomp

File::open('c:\rubyfiles\citylist-' + save_as + '.txt', 'w') do |f|

***********

I need it to take the output of that method that I created and write it
to a file... I'm not sure I understand how to do that with the example
you gave. Since I know the code that I had after "File::open", etc. was
wrong, I just left it out.

If it is allowed, I'll add some Ruby idioms (you'll find these often,
and will find them useful, I hope).

I saved your file as "saving.rb", and it now produces the following:

File completed. Save as..?
temp #that's the name I saved the file as

C:\temp>less c:\rubyfiles\citylist-temp.txt # This is how the file looks.

Boston pets || Nashville pets || San Francisco pets ||
Houston pets || Portland pets || Atlanta pets ||
Chicago pets || Indianapolis pets || Charleston pets ||

This is the reworked script:

def cityList
~ c_list = [
~ 'Boston',
~ 'Nashville',
~ 'San Francisco',
~ 'Houston',
~ 'Portland',
~ 'Atlanta',
~ 'Chicago',
~ 'Indianapolis',
~ 'Charleston'
~ ] # I just changed that for readability.

~ bar = '|| ' # I left this, too.

~ temp_array = #This is a temporary array,
      #I use to store the results.
~ temp_array.push bar + c_list[0..2].join(' pets || ') + (' pets ||') +
"\n" # This pushes the result of into the Array. It gets stored at the
first index of the Array. You could access it via temp_array[0].

~ temp_array.push bar + c_list[3..5].join(' pets || ') + (' pets ||') +
"\n" #This does something similar, except that it is stored at the next
Array index, temp_array[1]

~ temp_array.push bar + c_list[6..8].join(' pets || ') + (' pets ||') +
"\n" # See above, except this time it is temp_array[2]. Notice that I
added "\n" to your code. This adds a new line. Just delete it, if you
don't want the whole output on a new line, or just leave the last one,
if every iteration shall be on a new line.

end

puts 'File completed. Save as..?'
save_as = gets.chomp

File.open("c:/rubyfiles/citylist-#{save_as}.txt","w") do |f| # Here, I
used string-interpolation, which only works with the double quotes (").
~ f.write cityList #This is a bit complex. f.write takes the result of
cityList, and writes it to a file. In Ruby, every method returns its
last action, so to speak. In this case, it is the Array with all three
lines. Also notice, that you don't have to use File::open, but that
should work, too.
end #ending the block again, and closing the file.

I hope that helps (In case it's not really readable, just copy and paste
the code into your favorite editor).

It would also be nice if I could have the method cycle through 3 items
in the array, then write 3 to a new line, the continue in increments of
3 until it reaches the end of the array. But, I'm not sure if I should
write another topic to ask that or if someone will answer that here.

Let me repeat, to see if I got that correctly:
You want to do cityList three times, and write all of these iterations
into 3 seperate files?

In that case, you could just wrap the File.open[..] part into a loop.
Like 3.times do
  File.open[...]
end

Thanks for the help so far, though... I'm pretty new at this.

We all were, at one time. :slight_smile:

I hope I can help you out.

In case you haven't found it: Chris Pine's Learn to Program helped me a
lot: pine.fm/LearnToProgram/

And _why's Piognant Guide to Ruby is good, too (although a bit..
strange): http://poignantguide.net/ruby/

- --
Phillip Gawlowski
Twitter: twitter.com/cynicalryan

~ There's never enough time to do all the nothing you want.
      -- Calvin

hm, let me re-phrase... I only have 9 items in that array, right? How
do I make the program continue through the array no matter how many
items are in it without having to go and edit the array that comes after
c_list?

~~temp_array.push c_list[0..2].join(' pets || ') + (' pets ||') +
"\n"

Like, say I added 3 more cities to the end of c_list, but I don't want
to have to add

~~temp_array.push c_list[9..11].join(' pets || ') + (' pets ||') +
"\n"

to the program. How can I make it cycle through the whole array without
having to edit c_list[number..number]? Is there a way to automate that,
so I only have to add cities to c_list without having to add more code?

And thanks, I've already found Mr. Pine's Learn To Program site and the
Poignant Guide.. :slight_smile: They've been a big help. I've tried to learn other
programming languages, but Ruby's been the easiest for me to understand.

···

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

Zoe Phoenix wrote:

hm, let me re-phrase... I only have 9 items in that array, right? How
do I make the program continue through the array no matter how many
items are in it without having to go and edit the array that comes after
c_list?

Oh, indeed you can.Array provides the #each and #each_with_index methods:

irb(main):001:0> array = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):002:0> array.each{|a| puts a}
1
2
3
4
5
=> [1, 2, 3, 4, 5]

The above is Array#each. It allows you to operate on each element of
your array.

irb(main):003:0> array.each_with_index{|a,b| puts a;puts b}
1
0
2
1
3
2
4
3
5
4
=> [1, 2, 3, 4, 5]

Here, you get the current index, too (that is the second variable, I've
called b). This, of course, works with Strings also (like your city names).

Together with the % (modulo) operator, you can test if the index can be
divided by 3 without a remainder, so that you can add a new line after
the third element.

If that doesn't help you write your own code, I'll be happy to provide
an annotated example again.

- --
Phillip Gawlowski
Twitter: twitter.com/cynicalryan

~ - You know you've been hacking too long when...
...after days with YACC, you start to parse your conversations.

[mailto:list-bounce@example.com] On Behalf Of Zoe Phoenix
# How can I make it cycle through the whole array without
# having to edit c_list[number..number]? Is there a way to
# automate that, so I only have to add cities to c_list
# without having to add more code?

of course, just do

  clist.join(' pets || ')

eg irb session,

irb(main):012:0> c_list=%w(Boston Nashville)
=> ["Boston", "Nashville"]

irb(main):013:0> c_list.join(' pets || ')
=> "Boston pets || Nashville"

irb(main):016:0> c_list += %w(Portland Atlanta Chicago)
=> ["Boston", "Nashville", "Portland", "Atlanta", "Chicago"]

irb(main):017:0> c_list.join(' pets || ')
=> "Boston pets || Nashville pets || Portland pets || Atlanta pets || Chicago"

irb(main):018:0> c_list += %w(Indianapolis Charleston Boston Nashville)
=> ["Boston", "Nashville", "Portland", "Atlanta", "Chicago", "Indianapolis", "Charleston", "Boston", "Nashville"]

irb(main):019:0> c_list.join(' pets || ')
=> "Boston pets || Nashville pets || Portland pets || Atlanta pets || Chicago pets || Indianapolis pets || Charleston pets || Boston pets || Nashville"

kind regards -botp

I think I understand what you're saying, but I'm not quite sure how to
apply it...

···

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

Zoe Phoenix wrote:

I think I understand what you're saying, but I'm not quite sure how to
apply it...

Let me show you an example:

irb(main):001:0> array = ["a","b","c","d","e"]
=> ["a", "b", "c", "d", "e"]
irb(main):002:0> array.each_with_index do |item, index|
irb(main):003:1* puts item if index % 3 == 0
irb(main):004:1> end
a
d
=> ["a", "b", "c", "d", "e"]

In this example, only the elements at an index that can be divided by 3
without a problem are printed. You can achieve a similar effect with a
counter, for example.

(My idea to use modulo was a bit off, sorry about that).

Translated to your problem:
saving.rb:

c_list = [
~ 'Boston',
~ 'Nashville',
~ 'San Francisco',
~ 'Houston',
~ 'Portland',
~ 'Atlanta',
~ 'Chicago',
~ 'Indianapolis',
~ 'Charleston'
~ ]

counter = 1
temp_array =
c_list.each_with_index do |item,index|
~ temp_array.push "|| " if index % 3 == 0
~ temp_array.push "#{item} "
~ temp_array.push "pets ||"
~ temp_array.push "\n" if counter % 3 == 0
~ counter +=1
end
puts 'File completed. Save as..?'
save_as = gets.chomp

File.open("c:/rubyfiles/citylist-#{save_as}.txt","w") do |f|
~ f.write temp_array
end

What am I doing here (this is a very naive implementation, nothing
fancy, but it does what it is supposed to do)?

First, I create the array of cities (you can get fancy later on, and
read it from a file, too).

Then, I create a counter to help me later on, as well as an empty array.

After that, I iterate over the c_list array with the help of the
each_with_index method.

Now the fun starts:

temp_array.push "|| " if index % 3 == 0

This only gets done, in the case that I can divide the index by 3
without a remainder. This works with 0, so I get the "|| " part.

temp_array.push "#{item} "

This uses Ruby's String interpolation to create, for example, "Boston ".
String interpolation allows you to execute Ruby code within Strings,
roughly speaking. You can test that by doing puts "#{Time.now}" in irb,
for example.

temp_array.push "\n" if counter % 3 == 0

This pushes the newline character into the array for file output, in the
case that the counter variable I introduced earlier can be divided by 3
without a remainder.

This should give you at least a starting point, in case I missed what
you wanted.

File block you already know. :slight_smile:

HTH,
- --
Phillip Gawlowski
Twitter: twitter.com/cynicalryan

~ - You know you've been hacking too long when...
...you begin to think in nested IF-THEN-ELSE clauses that would make a
bureaucrat get lost.

hmm, I see what you're doing there...

I still can't seem to get the file block to actually write the output of
the method to a file. The file it writes still comes up empty...

···

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

Zoe Phoenix wrote:

hmm, I see what you're doing there...

I still can't seem to get the file block to actually write the output of
the method to a file. The file it writes still comes up empty...

Are you explicitly calling the #write method? puts doesn't work (I fall
for that trap 9 times out of 10), unfortunately.

And are you opening the file in write / append mode?

Are you getting any errors from Ruby?

- --
Phillip Gawlowski
Twitter: twitter.com/cynicalryan

Each module should do one thing well.
~ - The Elements of Programming Style (Kernighan & Plaugher)

def cityList
c_list = [
    'Boston',
    'Nashville',
    'San Francisco',
    'Houston',
    'Portland',
    'Atlanta',
    'Chicago',
    'Indianapolis',
    'Charleston'
    ]

bar = '|| '

temp_array =

temp_array.push puts bar + c_list[0..2].join(' pets || ') + (' pets

'+'/n')

temp_array.push puts bar + c_list[3..5].join(' pets || ') + (' pets

'+'/n')

temp_array.push puts bar + c_list[6..8].join(' pets || ') + (' pets

'+'/n')

end

puts 'File completed. Save as..?'
save_as = gets.chomp

File::open("c:\rubyfiles\citylist-#{save_as}.txt", 'w') do |f|
  f.write cityList

end

···

********

This is the error it gives me...:

directory\rubyprograms\cities.rb:33:in 'initialize':
ubyfiles tylist-city1.txt (Errno::EINVAL)
   from directory\rubyprograms\cities.rb:33:in
'open'
   from directory\rubyprograms\cities.rb:33

********

There's something wrong with the code, I know, but I'm not sure what.
--
Posted via http://www.ruby-forum.com/\.

Zoe Phoenix wrote:

directory\rubyprograms\cities.rb:33:in 'initialize':
ubyfiles tylist-city1.txt (Errno::EINVAL)
   from directory\rubyprograms\cities.rb:33:in
'open'
   from directory\rubyprograms\cities.rb:33

********

There's something wrong with the code, I know, but I'm not sure what.

Yes, but something simple, actually, and easy to fix:

Ruby, like other programming languages, uses the backslash "\" as an
escape character. That means (in simple terms), Ruby ignores the
character directly after the backslash. Usually, because that character
means something special. An example is the newline character "\n", which
produces a newline in a file or screen output, for example. (Like
pressing enter, just done by Ruby).

printf "This text has\na new line" #demonstrates the \n character.

You have two options: You can change your back slashes to forward
slashes (from \ to /), or add another backslash to escape your backslashes:

This happens when you try to open the file to write into it.

The possible solutions:
File::open("c:\\rubyfiles\\citylist-#{save_as}.txt", 'w') #Escaping the
backslashes
File::open("c:/rubyfiles/citylist-#{save_as}.txt", 'w') #Using forward
slashes

Both solutions are fine. Windows can handle forward slashes, too (at
least in Windows XP).

I hope that helps. :slight_smile:

- --
Phillip Gawlowski
Twitter: twitter.com/cynicalryan

~ - You know you've been hacking too long when...
...after days with YACC, you start to parse your conversations.

Alright, I fixed the problem with the backslashes, but it's still
returning an empty file... it shows the output in the command line and
creates a file now, but it's still empty. :-/

I decided to go ahead and fix the file saving problem first before I
move on to the other part of it, so here's the original code. The output
is correct, but something's preventing it from being put into the file
it creates.

c_list = [
    'Boston',
    'Nashville',
    'San Francisco',
    'Houston',
    'Portland',
    'Atlanta',
    'Chicago',
    'Indianapolis',
    'Charleston'
    ]

bar = '|| '

temp_array =

  temp_array.push puts bar + c_list[0..2].join(' pets || ') + (' pets

'+ "\n")

  temp_array.push puts bar + c_list[3..5].join(' pets || ') + (' pets

'+"\n")

  temp_array.push puts bar + c_list[6..8].join(' pets || ') + (' pets

'+"\n")

puts 'File completed. Save as..?'
save_as = gets.chomp

File::open("c:\\rubyfiles\\citylist-#{save_as}.txt", 'w') do |f|
  f.write temp_array

end

What am I doing wrong?? :frowning:

···

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

# What am I doing wrong?? :frowning:

look at the contents of temp_array.

hint:

irb(main):005:0> puts "foo"
foo
=> nil

irb(main):006:0> [].push puts("foo")
foo
=> [nil]

kind regards -botp

···

From: Zoe Phoenix [mailto:dark_sgtphoenix@hotmail.com]

Ahh, I got it now... thank you! :slight_smile:

···

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