Mark
Mark

Reputation: 17132

ruby adding variable value to an array

I have a Ruby 1.8.6 script that is supposed to take a filename that contains a path, create the folders then move the file into the folders. I have an array created_paths to keep tracked of folders created (the script will loop through lots of files). I am having a problem adding to the created_paths array.

created_paths = Array.new
file_name = "first\\second\\third.txt"
parts = file_name.split('\\')
tmp_path = ""
parts.each_with_index { |part,i|
    if i == (parts.length - 1)                
        # copy file to new dir structure
    else
        tmp_path << part << "/"
        if !created_paths.include?(tmp_path)                   
            puts "add to array: #{tmp_path}"
            created_paths.push(tmp_path)
            # create folder
        end
    end
}
puts "size=#{created_paths.length}\n"
created_paths.each { |z| print z, "\n " }

When I push tmp_path on to the created_paths array it seems the reference to tmp_path has been added and not the value. On the second iteration of the loop created_paths.include?(tmp_path) is returning True. How do I get the value of tmp_path to be stored in my array, or maybe there is a scope issue i'm missing ?

My output:

add to array: first/
size=1
first/second/

My excepted output:

add to array: first/
add to array: first/second/
size=2
first/
first/second/

Upvotes: 2

Views: 12874

Answers (3)

Beanish
Beanish

Reputation: 1662

When I push tmp_path on to the created_paths array it seems the reference to tmp_path has been added and not the value.

Everything in ruby is by reference.

When you use << you're concatenating to the string. Using the dup method should work for you.

mystring = "test"
myarray = []

5.times do |x|
  mystring << x.to_s
  myarray << mystring
end

puts myarray

In the above snippet set << for the string assignment to = and see the difference in output.

Also as a side note in ruby you can just use puts to add a newline when printing. so created_paths.each { |z| print z, "\n " }

could read created_paths.each { |z| puts z }

Upvotes: 2

AShelly
AShelly

Reputation: 35520

The issue is that this line is modifying the original string object. The array holds a reference to that object.

  tmp_path << part << "/"    

To avoid it, you need to create a new object. Either do this when you add the paths

created_paths.push(tmp_path.dup)

Or do:

tmp_path += part + "/"

Either way, you are making a new string object, rather than modifying the existing one.

Upvotes: 1

Mladen Jablanović
Mladen Jablanović

Reputation: 44080

You can use tmp_path.dup to clone the string before pushing it to the array.

But I don't understand why you're doing all of it (keeping the list of created directories). Take a look at FileUtils#mkdir_p, you pass it a path to a directory you want to create and it creates it, along with all the missing parent directories.

Upvotes: 5

Related Questions