Ruby has built-in modules, which can be think of as containers or tool-boxes that stores methods. An enumerable method can be use by a class that has a defined each. You can also find out which class uses enumerable like so:
| Array.included_modules #=> [Enumerable, Kernel]
Hash.included_modules #=> [Enumerable, Kernel]
|
The map belongs in the enumerable module and it is the non-destructive twin of map!(more on the evil twin later). It accepts an enumerable object, such as array or hash, and a block of code. It runs the block for each element inside the object. Since it is non-destructive, meaning it will not alter the object passed on it, the results from the block are stored inside a new array. Like so:
| original_array = [1,2,3]
new_array = original_array.map{|element| element+=1}
original_array #=>[1,2,3]
new_array #=> [2,3,4]
|
As you can see from the example, the original array contains 3 elements, and passed on map with the block element += 1. The block is run by each element, increasing each by one, and stores the results inside a new array which we set to the variable: new_array, and the original_array stays intact.
Now onto the evil twin, map!. It does the same thing as map, but destructively. A destructive method will alerts the original object, instead of returning a new object, it returns the modified object.
| original_array = [1,2,3]
new_array = original_array.map!{|element| element+=1}
original_array #=>[2,3,4]
new_array #=> [2,3,4]
|
From the example above we can see that original_array is being altered even if we set a variable to catch the results. It is replacing each element by the result return from the given block, and then returns self (the original_array). This also means that the variable new_array is pointing at the same object as original_array.