2010-12-08 44 views
2

首先,我意识到我应该尝试在跳入Rails之前完全掌握Ruby。然而,Ruby中没有任何东西看起来太难以快速掌握(直到这个!),所以我决定在我仍然热衷于学习的时候开始。 ,__,在Rails中,form_for究竟是什么?这似乎很神奇

无论如何,这里是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|块称为(无括号)?这里发生了什么?

+0

没有什么是铁轨中的巫毒。擦拭你的眼镜,你会看到它的全部只是红宝石! – Chirantan 2010-12-08 08:26:24

+0

也许这会有助于查看源代码:https://github.com/rails/rails/blob/master/actionpack/lib/action_view/helpers/form_helper.rb以查看最终参数是&proc,并且是需要: `def form_for(record,options = {},&proc)raise ArgumentError,“Missing block”unless block_given?` – 2010-12-08 08:42:25

+0

每个人都给出了令人敬畏的答案!谢谢,并为所有人+1。 谢谢杰德!我会看看这个。 – ClosureCowboy 2010-12-08 08:43:47

回答

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 

,并在功能DEF为my_function你可以写:

def my_function(param1, param2, &block) 

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

所以当你使用块语法时,它被解释为一个参数,但它确实不是。

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如何知道在调用方法之前它应该“等待”?

如果我理解你的问题正确,你问为什么只有在form_for调用的括号@post,而不是整个块左右。这是在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如需详细了解双方如何调用与块,以及如何的方法来写你自己的方法接受块。

1

有2个独立的问题,我会回答更迫切的一个第一:

form_for @product do |f| 
    # stuff here 
end 

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

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

1

红宝石中的方法可以通过参数(例如@post)和块(例如do ... end内的所有东西)。

如果你看一下你将如何form_for is defined within rails看到:在do

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

一切都在proc被捕获。方法定义中前面的&表示proc是一个块,可以执行。沿线的某处,轨道将执行proc

块是红宝石的神奇迷人的重要组成部分。查询this awesome free ruby e-book获取更多关于街区的信息。块是一种“封闭”,红宝石具有不同的封闭味道,其表现略有不同(另一种常见封闭是lambda)。如果您想深入了解Ruby中的闭包如何工作,请查看this great tutorial