I’m learning Ruby (using the Pickaxe book) and I’ve encountered a little confusion with a block operation that goes a little like this:
class CsvReader
def initialize
@book_in_stock = []
end
def read_in_csv_data(csv_file_name)
CSV.foreach(csv_file_name, headers: true) do |row| # 1.
@book_in_stock << BookinStock.new(row["ISBN"], row["Amount"]) # 2.
end
end
end
My confusion exists on the commented “#1” and “#2”, I don’t understand how we get “123” and “456” from a csv_file_name of “test.csv” containing the data:
"ISBN","Amount"
"123","456"
How is it that row[“ISBN”] knows that the next row corresponds to it? Do all blocks behave this way? What are they really called? Could someone explain them a little better?
Blocks are a ruby idiom for describing a closure, or a block of code that has its own scope (it doesnt need to know about other parts of the code). Blocks have two styles, if the code goes on more than one line, you use the do syntax (given a data structure or some enumerable named @entries)
if it is on one line you can simplify the block as such
@entries.each{|entry| execute something here}explicitly, what either code block does is pass in one entry at a time, assigned to entry and do an operation over it. It is like an anonymous inner function.
They are a little hard to understand at first, but really useful and all over the ruby world. We have blockitis sometimes.
As a use case, consider that we want to do something to each value in an array.
what isn’t so obvious is that this function returns an array
[2,3,4]because the inner function takes care of the iteration over the data structure. This is much more convenient and declarative than having another function that operates over the array and another one yet to add one to each item.in the csv example you are taking each row and adding it to a data structure called
@books_in_stockbut its not as explicit, I think as the example I gave. Check out the Enumearble class http://apidock.com/ruby/Enumerable for many good examples of using blocks.