了解rails演示者的收益率

时间:2013-09-26 06:09:14

标签: ruby-on-rails ruby ruby-on-rails-4

在我正在阅读的“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变量?

3 个答案:

答案 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对象。因此,presenterDesignerStatus

类型的新对象 正如您可能猜测的那样,

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次。

有了这个理解,我对问题的回答

  1. 代码块如何获得分配的变量状态 ans:行yield presenter。此处presenter变量传递给接收名称status中的参数的块。

  2. 为什么我们需要&#39;如果&#39;辅助函数中的语句为什么不直接返回presenter变量? 我们可以避免将整个erb作为块传递给方法,但是我们需要在show.html.erb的顶部有这样的代码:

  3. <% status = designer_status_for(@designer) %>然后开始使用变量status。我认为使用块是一个美学问题,这样我们就可以避免使用赋值。方法中的if语句是使用这种语法而不是使用块。