2

I'm in the process of learning Ruby and reading through Chris Pine's book. I'm learning how to read (and write) files, and came upon this example:

require 'yaml' 
test_array = ['Give Quiche A Chance',
              'Mutants Out!',
              'Chameleonic Life-Forms, No Thanks']

test_string = test_array.to_yaml

filename = 'whatever.txt'

File.open filename, 'w' do |f|
f.write test_string
end

read_string = File.read filename

read_array = YAML::load read_string
puts(read_string == test_string)
puts(read_array == test_array )

The point of the example was to teach me about YAML, but my question is, if you can read a file with:

File.read filename 

Can you write to a file in a similar way?:

File.write filename test_string

Sorry if it's a dumb question. I was just curious why it's written the way it was and if it had to be written that way.

Bo G.
  • 107
  • 2
  • 9

3 Answers3

1

Can you write to a file in a similar way?

Actually, yes. And it's pretty much exactly as you guessed:

File.write 'whatever.txt', test_array.to_yaml

I think it is amazing how intuitive Ruby can be.

See IO.write for more details. Note that IO.binwrite is also available, along with IO.read and IO.binread.

Matheus Moreira
  • 17,106
  • 3
  • 68
  • 107
  • Thanks Matheus! And you're right, Ruby is insanely intuitive. And I'm glad to hear that my guess what mostly right. Any theory as to why the author, Chris Pine, decided to write it the way he did as opposed to the way you did? – Bo G. Mar 20 '14 at 00:28
  • @BoG, I don't know for sure. He might not have been aware of the `File.write` method. Nothing in the example code warrants using the block form; he's not sharing the file handle, it is possible to pass the opening mode to `File.write` and the block is just returning the result of `File#write`. They are pretty much equivalent, but the block form is unecessarily verbose in this case. – Matheus Moreira Mar 20 '14 at 00:35
  • I'm going to assume it was for ease of reading or something. Or, as you suggested, maybe he didn't know about File.write. Thanks for the follow up. – Bo G. Mar 20 '14 at 00:37
  • while I've got you here, maybe you can help me with something else I'm struggling to understand. read_array = YAML::load read_string The double colons - ::. Is that used because the load method is not a part of the YAML module? Meaning that you couldn't write YAML.load read_string. [EDIT] Please excuse the lack of formatting. I tried to format it, but I guess you can't in the comments. – Bo G. Mar 20 '14 at 00:53
  • @BoG, `YAML::load` and `YAML.load` will do the same thing and are pretty much equivalent in this context. The difference between them is that the scope resolution operator (`::`) will also resolve constant names, while the dot operator (`.`) always means method call. If you have further questions, you should search StackOverflow or ask a new question. – Matheus Moreira Mar 20 '14 at 00:58
0

The Ruby File class will give you new and open but it inherits from the IO class so you get the read and write methods too.

I think the right way to write into a file is the following:

File.open(yourfile, 'w') { |file| file.write("your text") }

To brake this line down:

  • We first open the file setting the access mode ('w' to overwrite, 'a' to append, etc.)

  • We then actually write into the file

LukeS
  • 481
  • 4
  • 14
  • Thanks for the detailed answer, Luke. The way you wrote it is close to the way it was written in the example. I was wondering if the do...end - the {...} in your example - and the code-block in between is even necessary. For example, can't you just write: File.write yourfile 'w' It seems like you're saying that's not correct. – Bo G. Mar 20 '14 at 00:25
  • Well you can't write in a file using `File.write yourfile 'w'`. Here is the irb output for such a statment: `>> File.write 'test.txt', "Hi there" NoMethodError: undefined method 'write' for File:Class ` You first need to open the file to access the stream and write in it. You can try yourself in irb. – LukeS Mar 20 '14 at 00:58
  • @LukeS, what do you mean it doesn't work? `File.write 'file', 'data', mode: 'a'` works here and in a couple sites I used to test. – Matheus Moreira Mar 20 '14 at 01:06
  • @LukeS Sorry, I wrote down my example incorrectly. File.write 'yourfile', string ---> Instead of File.write yourfile 'w'. – Bo G. Mar 20 '14 at 01:06
  • My answer gives you the good practice, one line way to write to a file. Note that `.open` is a synonym for `::new` [File.open](http://www.ruby-doc.org/core-2.1.0/File.html#method-c-open) – LukeS Mar 20 '14 at 01:07
  • What about the block form makes it the "good practice" or "best practice" in this case? – Matheus Moreira Mar 20 '14 at 01:08
  • @Matheus Moreira, try for yourself in irb. `>> File.write 'file', 'data', mode: 'w' NoMethodError: undefined method 'write' for File:Class` The `File` class doesn't have any `write` method. – LukeS Mar 20 '14 at 01:09
  • Interesting. I guess it's a change that was introduced in Ruby2.0 then. Because it definitely doesn't work on 1.9.3 -- [try ruby.org](http://tryruby.org/levels/1/challenges/0) is using 1.9.3 on their online irb, you can try it if you want. – LukeS Mar 20 '14 at 22:44
0

You can read or write to a file by specifying the mode you access it through. The Ruby File class is a subclass of IO.

The File class open or new methods take a path and a mode as arguments: File.open('path', 'mode') alternatively: File.new('path','mode')

Example: to write to an existing file somefile = File.open('./dir/subdirectory/file.txt', 'w') ##some code to write to file, eg: array_of_links.each {|link| somefile.puts link } somefile.close

See the source documentation as suggested above for more details, or similar question here: How to write to file in Ruby?

Community
  • 1
  • 1
kyle43982
  • 44
  • 2
  • Thanks Kyle. It seems to me that the File class would inhereit the write method from IO. So I think it would be possible to write it File.write "whatever.txt", text, too. Matheus, above, confirms that. – Bo G. Mar 20 '14 at 00:35