I come from a java/c++ background 开发者_开发知识库and I just started learning Ruby. I am having problems understanding blocks attached to methods. This is a method used to migrate a database.
create_table :model_names do |t|
t.string :name
t.string :address
t.timestamps
end
My question is: when I use the rake db:migrate command. Does that call the create_table method and pass a TableDefinition object to it, which I grab as |t| and set that object attributes in my block?
When you pass a block to a method, as is the case in the example here, it is up to the method to decide how and if that block is used. You will need to read the documentation and/or source code of the method to understand what parameters your block will need, if any.
In the case of create_table
, an object is prepared and passed to you by the create_table
method itself. rake
and the associated task have nothing to do with it at this point, they are only used as a launch mechanism.
It's important to keep in mind that Ruby blocks can be called zero or more times, either immediately or in the future. This means you can't be sure if your block will be called right away, later on, or never, or how many times it will be called. The only expectation you can have is established by the method you send the block to.
You can even pass blocks to methods that don't want them where nothing will happen since that method never exercises your block with a yield
.
Blocks can be a bit confusing at first unless you come from a language that has a similar construct. JavaScript programmers will be familiar with passing in function
objects, which is basically all you're doing here, though in Ruby terms it's a Proc that's being sent in as an implicit argument.
In a more JavaScript flavored example, this would look like:
create_table('model_names', function(t) {
t.string('name');
t.string('address');
t.timestamps();
});
Spelled out like this it's obvious you're simply sending in a function, and it is up to the create_table
function to execute it. Ruby is structured in such a way that at a glance it might seem like that block gets executed right away, but there is a big difference between declaring a block with do ... end
and begin ... end
.
精彩评论