Mason2中的多个方法覆盖

时间:2014-09-21 07:18:30

标签: perl mason

使用Mason2建立网站。每个页面应调用3个过滤器(方法,按内容调用):

<% $.filter1(args...) {{ %>
<% $.filter2(args...) {{ %>
<% $.filter3(args...) {{ %>

我有3种不同的过滤器(方法)实现。这3个过滤器的默认集合在顶级/Base.mc组件中定义。

现在,对于网站的不同部分 - (不同的路线),比如

/a/all/paths>/...>
/b/.....

需要使用上面的默认过滤器/方法集,但对于其他路由,

/c/...
/d/...
/e/...

需要使用另一组filter1filter2filter3

/x/....
/y/...

想要使用第三套。

这些方法可以在较低级别的组件中轻松重新定义,但在(this question)中执行,并不尊重DRY原则,例如:在每个

/c/Base.mc
/d/Base.mc
/e/Base.mc

需要重复相同的3

<%override filter1>
...
<%override filter2>
...
<%override filter3>

问题是:

  • 如何只编写方法的3种不同实现,以及如何一次使用

我尝试制作一个组件,例如:/set2.mi/set3.mi,我尝试覆盖这些过滤器方法,并在所需的/{c,d,e}/Base.mc中调用它作为

<& /set2.mi &>

但这不起作用。

如何编写3种不同的方法,并在所需的deeprr Base.mc中一次调用它们?有可能吗?

在标准perl中我可能会使用角色,所以在需要的包中我会使用类似的东西:

with 'Set1';
with 'Set2';

Set1Set2将包含所需方法的实现,或动态加载将使用require ...。在Mason2中是可能的,或者我必须重复%ovverride

希望这有意义......如果没有,请添加评论,我会尝试更新问题。

修改

示例,用于缩短代码,仅使用一个不是3的过滤器。

/Base.mc

<%augment wrap><% inner() %></%augment>

% #this is the "default" MyHead filter
<%filter MyHead($arg)>
    <!-- in the real code it is more complicated, but for an illustration it is enough -->
    <h1 class="<% $arg %>"><% $yield->() %></h1>
</%filter>

/a/index.mc中使用

% $.MyHead('big') {{
some head text
% }}

将输出如下:

<h1 class="big">some head text</h1>

现在,再来一个MyHead

<%filter MyHead($arg)>
    <!-- in the real code it is more complicated - basically want output different thing -->
    <h2 id="<% $arg %>"><% $yield->() %></h2>
</%filter>

如果我将上述代码添加到我的/b/Base.mc,它会有效,并调用MyHead

中的/b/index.mc过滤器
% $.MyHead('modal') {{
some other text
% }}

将调用重新定义的过滤器,并输出我想要的内容

<h2 id="modal">some other text</h2>

问题是,

  • 我不想在N个其他Base.mc组件中重复上述过滤器代码,例如/c/Base.mc/d/Base.mc等等。
  • 如何实现,一次编写过滤器&#34;使用&#34;它在许多其他组件中用于&#34;重新定义&#34;默认的。

1 个答案:

答案 0 :(得分:0)

一个解决方案可能是(不是一个很好的解决方案并产生类似代码的“spaghetty”)与继承链一起玩,如下:

  1. /Base.mc移除“默认”过滤器,因此它只包含<%augment wrap
  2. 创建一个名为例如BaseSetDefault.mc的组件并输入它,您的“默认”过滤器并明确将继承链设置为顶级/Base.mc
  3. <%augment wrap><% inner() %></%augment>
    
    <%filter MyHead($arg)><h1 class="<% $arg %>"><% $yield->() %></h1></%filter>
    
    <%flags>
        extends => '/Base.mc'
    </%flags>
    
    1. 同样,创建另一个名为/BaseSet2.mc的组件,并在此处放置“Set2”过滤器,例如:
    2. <%augment wrap><% inner() %></%augment>
      
      <%filter MyHead($arg)><h2 id="<% $arg %>"><% $yield->() %></h2></%filter>
      
      <%flags>
          extends => '/Base.mc'
      </%flags>
      
      1. 现在,在/a/Base.mc/b/Base.mc - 无处不在,您需要“默认”设置,更改链
      2. <%flags>
            extends => '/BaseSetDefault.mc'
        </%flags>
        
        1. 并在/c/Base.mc/d/Base.mc - 您想要“Set2”过滤器的任何地方,使用
        2. <%flags>
              extends => '/BaseSet2.mc'
          </%flags>
          

          从现在开始,/c/index.mc的继承链将是:

          /c/index.mc -> /c/Base.mc -> /BaseSet2.mc -> /Base.mc
          

          ,执行将以

          完成
          /Base.mc -augment-> /BaseSet2.mc -augment-> /c/Base.mc -main-> /c/index.mc
                              ^^^^^^^^^^^^ - defines the Set2 filters
          

          /a/index.mc继承链

          /a/index.mc -> /a/Base.mc -> /BaseSetDefault.mc -> /Base.mc
          

          执行

          /Base.mc -augment-> /BaseSetDefault.mc -augment-> /a/Base.mc -main-> /a/index.mc
                              ^^^^^^^^^^^^^^^^^^ - defines the "Default" filters
          

          这不是一个很好的解决方案,但有效......