Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>First of all, roles are composed into a class, they have nothing to do with subclassing. A subclass is a full class that extends a parent (or more than one, but in my experience multiple inheritance should be avoided if it can be). A role is a piece of behaviour, or a parial interface that can be applied to a class. The role then directly modifies the class. There's no new class created in general.</p> <p>So inheritance and role composition are really two different things and two different kinds of design. Thus you can't simply exchange one for the other. Both have different design-implications.</p> <p>My strategy with <code>HTML::FormHandler</code> has been to make a real subclass for each form that I require, and put the different behaviours of the form that I wanted to re-use into roles.</p> <p>I'd think this question (how to implement the extensions you need in a clean and sane way) can't really be answered without knowing the actual design you're aiming for.</p> <p><strong>Update:</strong> I see what you mean and that's a tricky case. <code>HTML::FormHandler</code> is primarily targetted at extension by inheritance. So I think the best strategy would indeed be to have two subclasses, one for <code>HTML::FormHandler</code> and one for <code>HTML::FormHandler::Model::DBIC</code>. It seems teadious at first, but you might want to have different settings for them in the long run anyway. To avoid repeating the actual configuration (the default values) I'd try the following (this example is plain HFH, without DBIC):</p> <pre><code>package MyApp::Form; use Moose; use namespace::autoclean; extends 'HTML::FormHandler'; with 'MyApp::Form::DefaultSettings'; # only using two fields as example for my $field (qw( html_prefix field_traits )) { has "+$field", default =&gt; sub { my $self = shift; my $init = "_get_default_$field"; my $method = $self-&gt;can($init) or die sprintf q{Class %s does not implement %s method}, ref($self), $init; return $self-&gt;$method; }; } 1; </code></pre> <p>Note that you'd need to make an attribute lazy if it requires the values of another attribute for its computation. The above base class would look for hooks to find the initialized values. You'd have to do this in both classes, but you could put the default subroutine generation into a function you import from a library. Since the above doesn't require direct manipulation of the attribute anymore to change the default values, you can put that stuff in a role I called <code>MyApp::Form::DefaultSettings</code> above:</p> <pre><code>package MyApp::Form::DefaultSettings; use Moose::Role; use namespace::autoclean; sub _build_html_prefix { 1 } sub _build_field_traits { ['MyApp::Form::Trait::Field'] } 1; </code></pre> <p>This method will allow your roles to influence the default value construction. For example, you could have a role based on the one above that modifies the value with <code>around</code>.</p> <p>There is also a very simple, but in my opinion kind-of ugly way: You could have a role provide a <code>BUILD</code> method that changes the values. This seems pretty straight-forward and easy at first, but it's trading extendability/flexibility with simplicity. It works simple, but also only works for very simple cases. Since the amount of forms in web applications is usually rather high, and the needs can be quite diverse, I'd recommend going with the more flexible solution.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload