cercxtrova
cercxtrova

Reputation: 1673

File is not filled when puts is used

I'm trying to create a Rails locale file from a CSV. The file is created and the CSV is correctly parsed, but the file is not filled. I don't have errors so I don't know what is wrong...

This is my code:

# frozen_string_literal: true

class FillLanguages
  require 'csv'

  def self.get
    result = []
    file = File.new('config/locales/languages.yml', 'w')

    CSV.foreach('lib/csv/BCP-47_french.csv', headers: false, col_sep: ';') do |row|
      result.push(row[0])
      hash = {}
      key = row[0]
      hash[key] = row[1]

      file.puts(hash.to_yaml)
    end

    result
  end
end

Rails.logger.debug(hash) returns

{"af-ZA"=>"Africain (Afrique du Sud)"}
{"ar-AE"=>"Arabe (U.A.E.)"}
{"ar-BH"=>"Arabe (Bahreïn)"}
{"ar-DZ"=>"Arabe (Algérie)"}
{"ar-EG"=>"Arabe (Egypte)"}
{"ar-IQ"=>"Arabe (Irak)"}
...

as expected.

Rails.logger.debug(hash.to_yaml) returns

---
af-ZA: Africain (Afrique du Sud)

---
ar-AE: Arabe (U.A.E.)

---
ar-BH: Arabe (Bahreïn)

---
ar-DZ: Arabe (Algérie)

---
ar-EG: Arabe (Egypte)

---
ar-IQ: Arabe (Irak)
...

But the file still empty.

My CSV looks like:

https://i.gyazo.com/f3fa5ba8b1bfdd014018da5b46fa7ec0.png

Even if I try to puts a string like 'hello world' just after the line where I'm creating the file, it doesn't work...

Upvotes: 1

Views: 40

Answers (1)

mrzasa
mrzasa

Reputation: 23327

You forgot to close the file.

You can either do it explicitly (best practice to do it in ensure block) or using File.open with block.

UPDATE:

IO#close → nil

Closes ios and flushes any pending writes to the operating system. The stream is unavailable for any further data operations; an IOError is raised if such an attempt is made. I/O streams are automatically closed when they are claimed by the garbage collector.

https://ruby-doc.org/core-2.5.0/IO.html#method-i-close

So your changes are not flushed to disc from IO buffers. You can also use explicit IO#flush to do that, but it's better to close files you opened.

# explicit close
class FillLanguages
  require 'csv'

  def self.get
    result = []
    file = File.new('config/locales/languages.yml', 'w')

    CSV.foreach('lib/csv/BCP-47_french.csv', headers: false, col_sep: ';') do |row|
      result.push(row[0])
      hash = {}
      key = row[0]
      hash[key] = row[1]

      file.puts(hash.to_yaml)
    end

    result
  ensure
    file.close
  end
end

--

# block version
class FillLanguages
  require 'csv'

  def self.get
    result = []
    File.open('config/locales/languages.yml', 'w') do |file|

      CSV.foreach('lib/csv/BCP-47_french.csv', headers: false, col_sep: ';') do |row|
        result.push(row[0])
        hash = {}
        key = row[0]
        hash[key] = row[1]

        file.puts(hash.to_yaml)
      end
    end

    result
  end
end

Upvotes: 3

Related Questions