Rails create_table是如何工作的?

时间:2017-06-25 06:27:58

标签: ruby-on-rails ruby

这比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_nameblock如何映射到函数签名?

我也理解*是一个接受x个参数的splat。 **是一个双重splat(我认为),它接受x个哈希值(即键,值对)。

所以我不确定**options是否与传递block有关。

参考:http://api.rubyonrails.org/v5.1/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-create_table

2 个答案:

答案 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
...

Passing blocks

yield

还有两种使用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)将是方法正文中参数的哈希值。