在我正在阅读的“Rails视图”一书中,有关于演示者的代码
app/helpers/designers_helper.rb
module DesignerHelper
def designer_status_for(designer = @designer)
presenter = DesignerStatus.new(designer)
if block_given?
yield presenter
else
presenter
end
end
end
然后在show.html.erb
<% designer_status_for do |status| %>
some html using <%= status %> variable
<% end %>
我很难理解代码块如何获得分配的变量状态,为什么我们需要帮助函数中的'if'语句,为什么不直接返回presenter变量?
答案 0 :(得分:1)
让我们从视图开始
<% designer_status_for do |status| %>
"some html using <%= status %> variable"
<% end %>
这会使用designer_status_for
代码调用方法block
,如下所示
designer_status_for {|status| "some html using <%= status %> variable" }
在方法中,
presenter = DesignerStatus.new(designer)
#=>since no `designer` is given it takes the default value of `@designer`
# and finds the related presenter
if block_given?
#=> is true since a block is given
yield presenter
#=> here the method "yields" to the block
# i.e. passes the presenter as a variable to the block and executes it.
# For e.g. array.map{|x| x+1} works the same way
# `map` iterates over the array and yields each element to the given block.
{|status| "some html using <%= status %> variable"}
#=> status is the variable received from method which is presenter
# This block returns the html to the method that called it
end
#=>the last statement was yield which was equal to the html returned from block
# returns the html received from the block
方法中的if
语句是返回代码块的结果,如果给定,则返回演示者。这允许DRY代码,我们在代码块中的一堆地方需要presenter
变量。
答案 1 :(得分:1)
好的,让我们一步一步来做。
首先,定义一个将@designer
指定为默认值的辅助方法。这就是为什么你可以在视图中没有任何参数的情况下调用它的原因:
<% designer_status_for do |status| %>
# more code
然后,DesignerStatus
是实际的演示者,它是与Designer不同的类,并创建一个全新的对象,但它基于@designer
对象。因此,presenter
是DesignerStatus
block_given?
检查是否应该将此对象传递给某个块,或者它是否应该作为普通对象。这很可能是你理解困难的棘手部分。所以让我以相反的方式解释它。你可以这样打电话
designer_status_for.some_presenter_method
在您看来,它会起作用。它起作用,因为没有给出块并返回designer
对象(换句话说,else
部分被触发),您可以在其上直接调用some_presenter_method
。所以,你可以在整个视图中使用它,你就可以了。
然而,有一个更好的选择,即yield
这个对象变成一个块。 yield
选项是制作此代码段的原因
<% designer_status_for do |status| %>
status.some_presenter_method
<% end %>
首先可能。这基本上说的是“获取该presenter对象,将其分配给名为status
的变量,并使该变量可用于该块。
所以,如果你现在很难绕过yield
,请不要担心。只需在designer_status_for
本身上调用任何方法即可。使用块对象本身的好处是,您的代码变得不那么脆弱,但这是另一个主题。
答案 2 :(得分:0)
在发布此问题后,我尝试重新阅读代码并尝试使用irb中的一些示例,以下是可以回答我的问题的结果。
在Ruby中,任何方法都可以使用一段代码。例如。
def method_can_take_block?
answer = 'yes it can take block of code'
end
method_can_take_block? { puts 'this code is not executed but gets passed to method' }
让我的代码块执行,需要在方法内部产生。只需在方法中调用yield
即可完成代码块的处理。通过明确地调用yield
,我们可以控制执行代码块的行。
def method_can_take_block?
answer = 'yes it can take block of code'
yield
end
method_can_take_block? { puts 'this code gets executed after the variable 'answer' gets assigned with some value.' }
但是,我们不能使用变量&#39;答案&#39;这里。传递的代码块不能访问函数内定义的变量。因此,为了让块能够访问方法中定义的变量,我们需要让块接受一些参数。注意使用| my_answer |在下面的代码块中。
method_can_take_block? { |my_answer| 100.times { puts answer } }
现在我们已经向块添加了一个参数,我们需要在调用代码块时传递这个参数。所以这是通过使用其他参数调用yield
来完成的。
def method_can_take_block?
answer = 'yes it can take block of code'
yield answer
end
yield answer
将answer变量传递给传递给该方法的代码块。在这种情况下,answer
作为my_answer
变量传递到块中,然后将其打印100次。
有了这个理解,我对问题的回答
代码块如何获得分配的变量状态
ans:行yield presenter
。此处presenter
变量传递给接收名称status
中的参数的块。
为什么我们需要&#39;如果&#39;辅助函数中的语句为什么不直接返回presenter变量? 我们可以避免将整个erb作为块传递给方法,但是我们需要在show.html.erb的顶部有这样的代码:
<% status = designer_status_for(@designer) %>
然后开始使用变量status。我认为使用块是一个美学问题,这样我们就可以避免使用赋值。方法中的if语句是使用这种语法而不是使用块。