这比Ruby
更多Rails
个问题。
功能签名:
def create_table(table_name, comment: nil, **options)
...
end
用法:
create_table(:suppliers) do |t|
t.string :name, limit: 60
# Other fields here
end
鉴于create_table
的函数签名,使用情况如何映射到它?
例如,
:suppliers
映射到table_name
,block
如何映射到函数签名?
我也理解*
是一个接受x
个参数的splat。
**
是一个双重splat(我认为),它接受x
个哈希值(即键,值对)。
所以我不确定**options
是否与传递block
有关。
答案 0 :(得分:2)
当您检查链接时,您已添加。你可以阅读解释本身。
**options
表示x
个哈希值,在这种情况下,您可以指定:id
,:primary_key
,....
块作为隐式部分传递,而不是作为参数传递,并将使用方法内的yield
关键字执行。
检查create_table
方法时,您将看到代码行
...
yield td if block_given?
#This part will execute the block that you pass
#If you pass any block to the method
...
还有两种使用t
参数的方法。它代表表本身,您可以在其上调用column
方法(将创建列)或例如string
方法,它将创建一个字符串列(简写)。
create_table(:suppliers) do |t|
t.column :name, :string, limit: 60
# Other fields here
end
或者
create_table(:suppliers) do |t|
t.string :name, limit: 60
# Other fields here
end
在这两种方式中,您都在tableObject上执行方法,这些方法将向表中添加列。如果未传递块,则在执行方法时不会创建任何列,但您仍可以通过执行ActiveRecord::ConnectionAdapters::SchemaStatements
方法将列添加到表中
create_table(:suppliers)
# Add a column to 'suppliers'.
add_column(:suppliers, :name, :string, {limit: 60})
答案 1 :(得分:1)
每个Ruby方法也采用签名中不需要的隐式块参数。如果你研究create_table
的方法体,你会发现:yield td if block_given?
这意味着:如果给出(或提供)了一个块,则使用td
局部变量作为块参数(在您的示例中为t
)调用隐式块。
只要您不需要直接访问提供的块,就不需要将块作为方法参数。如果你需要它,你可以将它声明为方法参数,如下所示:
def create_table(table_name, comment: nil, **options, &block)
# do something with block
end
您可以使用显式方法块参数并调用yield td
,而不是使用隐式方法阻止argumentsmet并调用block.call(td)
。 ruby实现在这两者之间有所不同,屈服可能总是更快。
你是对的:*args
用于splat参数,其中args
将是方法体中的参数数组。 **kwargs
(或**options
此处)用于关键字参数,其中kwargs
(或options
)将是方法正文中参数的哈希值。