代码之家  ›  专栏  ›  技术社区  ›  Schwern

懒洋洋地枚举,直到块为假

  •  2
  • Schwern  · 技术社区  · 6 年前

    class Pager
      include Enumerable
    
      def initialize(&fetch_next_page)
        @fetch_next_page = fetch_next_page
        reset
      end
    
      def reset
        @page_number = 0
      end
    
      private def next_page
        @page_number += 1
    
        return @fetch_next_page.call(@page_number)
      end
    
      def each(&block)
        if block_given?
          while resp = next_page
            resp.each(&block)
          end
          reset
        else
          to_enum(:each)
        end
      end
    end
    

    下面是一个如何使用它的示例。

    pager = Pager.new do |page_number|
      response = fetch_page( page: page_number, **some_options )
    
      response.page <= response.total_pages ? response.stuff : false
    end
    

    pager = Pager.new { |page_number|
      page_number <= 3 ? 1.upto(page_number) : false
    }
    
    # [1, 1, 2, 1, 2, 3]
    puts pager.to_a.inspect
    

    有没有更简单的方法?我已经接近了枚举器,但无法得到平坦的工作。

    def paginate(&fetch_next)
      return Enumerator.new do |yielder|
        page_number = 1
        while ret = fetch_next.call(page_number)
          yielder.yield(*ret)
          page_number += 1
        end
      end
    end
    
    pager = paginate { |page_number|
      page_number <= 3 ? 1.upto(page_number) : false
    }
    
    # [1, [1, 2], [1, 2, 3]]
    puts pager.to_a.inspect
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   3limin4t0r    6 年前

    枚举器输出不正确的原因确实与splat运算符有关。

    产量

    { |page_number| page_number <= 3 ? 1.upto(page_number) : false }
    

    这将产生3个收益率。第一个有论点 1 1, 2 第三个是争论 1, 2, 3

    yielder.yield(*ret)
    
    # should be changed to
    
    ret.each { |e| yielder.yield e }
    # or
    ret.each { |e| yielder << e }
    # depending on your preference
    

    pager.to_a
    #=> [1, 1, 2, 1, 2, 3]