Thursday, October 28, 2010

Ruby Deal-breaker

Recently I have come across a very interesting thing while working with Ruby arrays. My goal was to convert the array into a SQL query. For example, converting the array [[1,2,3],[4,5,6,],[7,8,9,]] into the string "(1,2,3),(4,5,6),(7,8,9)". If one has any basic knowledge about iterators, it won’t be a difficulty at all.

Example below:
irb(main):001:0> array = [[1,2,3], [4,5,6], [7,8,9]]
=> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
irb(main):002:0> sql_values = array.map{|a| "(" + a.join(", ") + ")" }.join(", ")
=> "(1, 2, 3), (4, 5, 6), (7, 8, 9)"

`map` returns new array which we join using "," string.
Also, you can put the data into SQL query manually. For example, adding any random integer values to our data:

irb(main):003:0> sql_values = array.map{|a| "(" + (a << rand(100)).join(", ") + ")" }.join(", ")
=> "(1, 2, 3, 98), (4, 5, 6, 24), (7, 8, 9, 77)"

However, pay attention! Of course, `map` does return the new array, but you, probably, think that the `a << rand (100)` adds the new value to the output array only. You are wrong! The thing is that when you work with `a` inside the `map` iterator, you work with the basic array, as by default, the variables are passed by link in Ruby. Therefore, when the new data is added in the existing array, you will get the following:

irb(main):004:0> array
=> [[1, 2, 3, 98], [4, 5, 6, 24], [7, 8, 9, 77]]

To create a new instance you must use the operation like ‘+’

irb(main):005:0> sql_values = array.map{|a| "(" + (a + [rand(100)]).join(", ") + ")" }.join(", ")
=> "(1, 2, 3, 98, 93), (4, 5, 6, 24, 92), (7, 8, 9, 77, 10)"
irb(main):006:0> array
=> [[1, 2, 3, 98], [4, 5, 6, 24], [7, 8, 9, 77]]

Thus, don’t forget that variables in ruby are passed by link and when you work with ruby iterators you work with the basic data.

No comments:

Post a Comment