为什么迁移需要表块参数?
为什么 ruby on Rails 迁移语法看起来像这样:
create_table :my_table do |t|
t.integer :col
t.integer :col2
t.integer :col3
end
而不是: 就
create_table :my_table do
integer :col
integer :col2
integer :col3
end
我个人而言,我发现第二个片段更具可读性,该实现使用第一个片段是否有任何原因?
Why does the ruby on rails migration syntax look like this:
create_table :my_table do |t|
t.integer :col
t.integer :col2
t.integer :col3
end
And not:
create_table :my_table do
integer :col
integer :col2
integer :col3
end
Personally I find the second snippet much more readable, are there any reasons why the implementation uses the first?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
两种方法的根本实现是不同的。
在第一种(也是实际的)情况下,
create_table
使用TableDefinition
对象调用yield
。因此,示例块中的t
指向该TableDefinition
。另一种方法是使用instance_eval。这看起来像:采取哪种方式部分取决于偏好。然而,有些人不喜欢 eval,所以他们喜欢避免这种情况。此外,使用
yield
方法可以更清楚地显示您正在使用的对象。The fundamental implementation of the two approaches is different.
In the first (and actual) case,
create_table
callsyield
with aTableDefinition
object. Sot
in your example block points to thatTableDefinition
. The alternative method is to use instance_eval. This would look something like:Which way you do it is partially a matter of preference. However, some people are not fans of eval so they like to avoid this. Also, using the
yield
method makes it clearer what object you're working with.我的理解是 ruby 是词法范围的,这意味着“整数”必须引用它在代码中出现时定义的东西。您需要动态范围来完成您所要求的。
也许我错了,过程、块和 lambda 中至少有一个是动态作用域的,但你仍然有答案——期望程序员知道作用域行为方式的模糊细节并不是一件好事。
My understanding is that ruby is lexically scoped, meaning that "integer" has to refer to something defined at the point it occurs in the code. You'd need dynamic scoping to accomplish what you're asking for.
It may be that I'm wrong and at least one of procs, blocks and lambdas is dynamically scoped, but then you still have your answer -- obscure details of how scope behaves is not a good thing to expect a programmer to know.
基本上,界面设计者应该选择这样做,因为这个关于作用域的小技巧以及
eval
和instance_eval
的工作方式,请检查这个示例:有2个类
Foo< /code> 和
Boo
具有以下定义:一般来说,这在大多数情况下应该可以正常工作,但在某些情况下,例如以下语句将发出错误:
我们无法访问此处
Foo
实例中Boo
的实例方法,因为我们使用的是instance_eval
,所以方法name
为Boo
实例定义的内容不在Foo
实例的范围内。为了克服此类问题,最好重新定义生成,如下所示:
这是一个灵活的接口,您可以根据传递的块参数来评估代码块。现在,当我们需要调用当前的 foo 对象的实例方法时,我们必须将其作为参数传递,让我们重新定义
Boo
,检查express
和talk
:Basically the interface designer should have chosen to do so due to this little trick regarding scopes and how
eval
andinstance_eval
work, check this example:Having 2 classes
Foo
andBoo
with the following definitions:Generally this should work fine for most cases, but some situations like the following statement will issue an error:
We don't have access here to the instance methods of
Boo
insideFoo
instances that's because we are usinginstance_eval
, so the methodname
which is defined forBoo
instances is not in the scope forFoo
instances.To overcome such problems it’s better to redefine generate as follows:
This is a flexible interface where you evaluate the code block depending on the passed block params. Now we have to pass the current foo object as a param when we need to call instance methods on it, let's redefine
Boo
, checkexpress
andtalk
: