在我正在读的“Rails View”一书中,有一些关于presenters的代码
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 %>我很难理解代码块是如何获得变量状态的,为什么我们需要在helper函数中使用'if‘语句,为什么不直接返回presenter变量?
发布于 2013-09-26 14:30:18
让我们从视图开始
<% designer_status_for do |status| %>
"some html using <%= status %> variable"
<% end %>这将使用block代码调用方法designer_status_for,如下所示
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语句将返回代码块的结果,否则它将返回presenter。这允许干代码,我们需要在代码块中的一堆地方使用presenter变量。
发布于 2013-09-26 14:55:14
好的,让我们一步一步来。
首先,您定义了一个帮助器方法,它将@designer指定为默认值。这就是为什么你可以在视图中没有任何参数的情况下调用它的原因:
<% designer_status_for do |status| %>
# more code然后,DesignerStatus是实际的presenter,它是一个与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本身的任何方法即可。使用块而不是对象本身的好处是,您的代码变得不那么脆弱,但这是另一个主题。
发布于 2013-09-26 14:38:52
在发布了这个问题后,我尝试重新阅读代码,并在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.' }然而,我们在这里没有使用任何变量'answer‘。传递的代码块不能访问函数内部定义的变量。因此,为了给块一些访问方法内部定义的变量的权限,我们需要让块接受一些参数。请注意下面代码块中|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
endyield answer将answer变量传递给传递给该方法的代码块。在本例中,answer作为my_answer变量在块内传递,然后打印100次。
有了这样的理解,我对问题的回答
yield presenter行。这里,呈现器变量被传递给接收名称为status.presenter变量呢?我们可以很好地避免将整个erb作为块传递给方法,但是我们需要在show.html.erb:的顶部有一个如下所示的代码
状态,然后开始使用变量<% status = designer_status_for(@designer) %>。我认为使用block是一个美学问题,这样我们就可以避免使用赋值。方法中的if语句就是要使用这种语法,而不是使用块。
https://stackoverflow.com/questions/19020601
复制相似问题