在Rails中,form_for究竟是什么?看起来很神奇

时间:2010-12-08 08:11:05

标签: ruby-on-rails ruby

首先,我意识到我应该在跳进Rails之前尝试完全掌握Ruby。然而,Ruby中的任何内容似乎都难以快速掌握(直到这个!),所以我决定开始,而我仍然热衷于学习。 ,__,

无论如何,这是form_for

的超浓缩示例
<%= form_for(@post) do |f| %>
    <div class="field">
        <%= f.label :name %><br />
        <%= f.text_field :name %>
    </div>
<% end %>

我知道Ruby中的方法不需要用括号调用。但是,使用括号调用form_for ,但不知何故,似乎do |f|块被传递给它!

form_for是否返回一个接受块的方法,然后通过传递do |f|块来立即调用 方法(没有括号)?这是怎么回事?

4 个答案:

答案 0 :(得分:3)

Ruby使用了许多所谓的“语法糖”,因为它在某些操作的解释方面比其他语言更灵活。

例如:

model.property = "something"

实际上是一个函数调用:

model.property=("something")

您的form_for示例是类似的情况。块作为参数静默地传递给Ruby函数。

my_block = Proc.new { some code }
my_function(param1, param2, &my_block)

相当于

my_function param1, param2 do
  some code
end

my_function的函数def中你可以写:

def my_function(param1, param2, &block)

您可以通过参数访问该块,以及yield

所以当你使用块语法时,它被解释为一个参数,但实际上并非如此。

答案 1 :(得分:2)

这里发生的只是在同一个调用中使用参数和块调用form_for方法。

以下是同时采用参数和块的方法的基本示例,以说明原理:

def hello(name)
  puts "Hello, #{name}!"
  yield if block_given?
  puts "Goodbye, #{name}!"
end

可以使用单个参数或参数和块调用此方法:

> hello("John")
Hello, John!
Goodbye, John!

> hello("John") do
*   puts "Inside the block"
* end
Hello, John!
Inside the block
Goodbye, John!

关于评论中的问题:

  

为什么只有第一个参数的括号?在form_for之后遇到open + closed括号之后,Ruby如何知道它应该在调用方法之前“等待”?

如果我正确理解了您的问题,您会问为什么@post调用中form_for周围只有括号,而不是整个块周围。这是将块传递给Ruby中的方法的语法 - 如果块紧跟在方法及其常规参数之后,则块与参数一起传递给方法。

以下是一些在Ruby中调用方法的最常用方法:

# Calling a method without a block
mymethod(param1, param2)

# Same as above, but leaving out parentheses
mymethod param1, param2

# Calling a method with a block that takes no arguments
# (this works without parentheses too)
mymethod(param1, param2) { do_stuff_in_block() }

# or
# (this works without parentheses too)
mymethod(param1, param2) do
  do_stuff_in_block()
end

# Calling a method with a block that takes arguments
# (this works without parentheses too)
mymethod(param1, param2) do |arg1, arg2|
  do_stuff_in_block(arg1, arg2)
end

# or
# (this works without parentheses too)
mymethod(param1, param2) { |arg1, arg2| do_stuff_in_block(arg1, arg2) }

查看Blocks and Iterators in Programming Ruby以获取有关如何使用块调用方法以及如何编写自己接受块的方法的更多详细信息。

答案 2 :(得分:1)

有两个单独的问题,但我会首先回答更紧迫的问题:

form_for @product do |f|
  # stuff here
end

form_for(@product) do |f|
  # stuff here
end

完全相同的事情。 form_for是一种将block作为参数以及其他参数的方法。

答案 3 :(得分:1)

ruby​​中的方法可以传递参数(例如@post)和一个块(例如do ... end内的所有内容。)

如果你看一下form_for is defined within rails将会看到的结果:

def form_for(record, options = {}, &proc)
  # a lot of funky magical rails stuff ...
end

do块中的所有内容都会在proc中捕获。方法定义中的前面的&表示proc是一个块并且可以执行。在某条线上,rails将执行proc

积木是红宝石神奇惊人的重要组成部分。检查this awesome free ruby e-book以获取有关块的更多信息。块是一种“闭包”,ruby具有不同的闭包风格,其行为略有不同(另一个常见的闭包是lambda)。如果您想深入了解闭包在Ruby中的工作方式,请查看this great tutorial