【问题标题】:Understanding yield in rails presenter了解 Rails Presenter 中的产量
【发布时间】:2013-09-26 06:09:14
【问题描述】:

在我正在阅读的“Rails View”书中,有关于演示者的代码

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”语句以及为什么不直接返回演示者变量?

【问题讨论】:

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


    【解决方案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 语句是如果给定则返回代码块的结果,否则返回演示者。这允许我们在代码块中的一堆地方需要 presenter 变量的 DRY 代码。

    【讨论】:

    • 超酷的解释。你用更少的语言解释了我花了很多时间理解的概念,并写了一篇更大的文章来解释自己。
    【解决方案2】:

    好的,让我们一步一步来。

    首先,您定义一个将@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 选项使这个代码-sn-p

    <% designer_status_for do |status| %>
      status.some_presenter_method
    <% end %>
    

    首先是可能的。这基本上说的是“获取该演示者对象,将其分配给一个名为 status 的变量,并使该变量可用于块。

    所以,如果您现在很难理解yield,请不要太担心。只需调用designer_status_for 本身的任何方法。在对象本身上使用块的好处是,您的代码变得不那么脆弱,但这是另一个话题。

    【讨论】:

      【解决方案3】:

      发布此问题后,我尝试重新阅读代码并尝试使用 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
      end
      

      yield answer 将答案变量传递给传递给方法的代码块。在这种情况下,answer 在块内作为 my_answer 变量传递,然后打印 100 次。

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

      1. 代码块如何获得分配的变量状态 回答:通过yield presenter 行。这里presenter 变量被传递给以名称status 接收参数的块。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-02
        • 2010-11-10
        • 2013-12-06
        • 1970-01-01
        • 2013-06-24
        相关资源
        最近更新 更多