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

在Sinatra helper方法中使用here字符串和lambda

  •  0
  • craig  · 技术社区  · 7 年前

    我试图创建一个Sinatra助手,它返回一个动态生成的HTML。我想我会用一个here字符串作为静态位,用一个lambda来计算动态部分。

    foo_helper.rb :

    require 'erb'
    module FooHelper
    
      def tabs(selected)
    
        template = ERB.new <<~HERE
          <ul class="nav nav-tabs">
            <li class="nav-item"><a class="nav-link <%= 'active' if selected == 'favorites' %>" href="/foo/favorites">Favorites</a></li>
            <li class="nav-item"><a class="nav-link <%= 'active' if selected == 'all' %>" href="/foo">All</a></li>
            <%= alpha.call %>
          </ul>
          HERE
    
        # binding to a string works as expected    
        # alpha = "<li class='nav-item'><a class='nav-link' href='/foo/a'>A</a></li>"
    
        # binding to a lambda, doesn't
        alpha = lambda {
          ('a'..'z').each do |letter|
            "<li class='nav-item'><a class='nav-link #{ 'active' if selected == letter }' href='/foo/#{letter}'>#{letter}</a></li>"
          end
        }
    
        template.result(binding)
    
      end
    
    end
    

    foo_controller.rb :

    class FooController < ApplicationController
      helpers FooHelper if defined?(FooHelper)
      ...
    end
    

    index.erb :

    ...
    <%= tabs('favorites') %>
    ...
    

    enter image description here

    显示范围,而不是单个 li s。

    **编辑**

    改正了许多错误。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Aetherus    7 年前

    你的代码中有太多的错误。

    1. @nav 在模块级定义,但在实例级访问,因此 nil 当你需要的时候。
    2. 当调用lambda时,需要在变量名和左括号之间加一个点,如 foo.(123)
    3. @nav.foo(binding) @导航 foo ?
    4. <%= foo %> 不会执行 ,因为它是局部变量,而不是方法。
        2
  •  0
  •   Jyrki    7 年前

    a..z 是因为 Range#each 方法(从lambda中调用)为每个元素执行给定的块,然后再次返回范围本身。

    你想在这里用的是 Enumerable#map 方法。类似 #each 它还为每个元素执行一个块,但所述块的返回值在新数组中返回。

    p ("a".."c").each { |x| x.upcase }
    #=> "a".."c"
    
    p ("a".."c").map  { |x| x.upcase }
    #=> ["A", "B", "C"]
    
    推荐文章