2

Building a website using Mason2. Each page should call 3 filters (methods, called by content):

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

I have 3 different implementation of those filters (methods). The default set of those 3 filters, are defined in the top level /Base.mc component.

Now, for a different parts of the site - (different routes), say for the

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

need use the above default set of filters/methods, but for another routes,

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

need use another set of filter1, filter2, filter3 and for the

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

want use the third set.

The methods can be easily redefined, in lower level components, but doing it as in (this question), isn't honors the DRY principe, e.g. in each

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

Need repeat the same 3

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

The question is:

  • how to write only once the 3 different implementations of the methods, and how to use them at once?

I tried make an compomponent, like: /set2.mi, /set3.mi, where I tried override those filter-methods, and called it in the needed /{c,d,e}/Base.mc as

<& /set2.mi &>

But this doesn't works.

How to write the 3 different methods implementatinons and call them at once in the needed deeprr Base.mc? Is it possible?

In standard perl i would probably use roles, so in the needed packages I would use something like:

with 'Set1';
with 'Set2';

Where the packages Set1 and Set2 would contain the implementations of the needed methods, or for dynamic loading would use the require ... . Is something like possible in the Mason2, or i must repeat the %ovverride?

Hope this make sense... if not, please add an comment and i will try update the question.

EDIT

Example, for shorting the code, using only one filter not 3.

The /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>

When in the /a/index.mc using it as

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

will output like:

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

now, have an another MyHead.

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

If I add the above code to my /b/Base.mc it will work, and calling the MyHead filter in the /b/index.mc

% $.MyHead('modal') {{
some other text
% }}

will call the redefined filter, and will output what i want

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

The problem is,

  • I don't want repeat the above filter code, in N other Base.mc components, like in /c/Base.mc and /d/Base.mc and so on.
  • How to achieve, to write the filter once and "use" it in many other components for "redefine" the default one.
Community
  • 1
  • 1
cajwine
  • 3,100
  • 1
  • 20
  • 41
  • You say "I have 3 different implementation of those filters (methods). The default set of those 3 filters, are defined in the top level /Base.mc component." -- can you give an example of one of the filters and how it differs depending on the part of the site you're in? – i alarmed alien Sep 21 '14 at 10:08
  • @ialarmedalien added an example, hope make sense.. – cajwine Sep 21 '14 at 11:45

1 Answers1

0

One solution could be (not a nice one and produces an "spaghetty" like code) playing with the inheritance chain, as next:

  1. Remove your "default" filter from the /Base.mc, so it would contains only the <%augment wrap
  2. Create one component called for example: BaseSetDefault.mc and enter into it, your "default" filter and explicitly set the inheritance chain to the top level /Base.mc
<%augment wrap><% inner() %></%augment>

<%filter MyHead($arg)><h1 class="<% $arg %>"><% $yield->() %></h1></%filter>

<%flags>
    extends => '/Base.mc'
</%flags>
  1. Similarly, create an another component say called as /BaseSet2.mc and put here your "Set2" filters, like:
<%augment wrap><% inner() %></%augment>

<%filter MyHead($arg)><h2 id="<% $arg %>"><% $yield->() %></h2></%filter>

<%flags>
    extends => '/Base.mc'
</%flags>
  1. Now, in the /a/Base.mc and /b/Base.mc - everywhere, you want the "default" set, change the chain
<%flags>
    extends => '/BaseSetDefault.mc'
</%flags>
  1. and in the /c/Base.mc and /d/Base.mc - everywhere you want the "Set2" filters, use the
<%flags>
    extends => '/BaseSet2.mc'
</%flags>

From now, the inheritance chain for /c/index.mc will be:

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

and the execution would be done as

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

and for the /a/index.mc inheritance chain

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

the execution

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

It is not very nice solution, but works...

clt60
  • 62,119
  • 17
  • 107
  • 194