balachandran has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have a class named "Host" that is with role 'Configurable' by default. The code is something like this
package Host; use Moose; with 'Configurable'; has 'configurable' => ) 'is' => 'rw', 'isa' => 'Bool' ); stuff...
By default, all hosts are always configurable. So, the class is "with 'Configurable'". But at run time, when need arises, the user can set
$host->configurable(0);
and that should remove the 'Configurable' role. So, is there something similar to Moose::Util::apply_all_roles() to remove specified roles ? Thanks

Replies are listed 'Best First'.
Re: Remove a role from a Moose object
by kevbot (Vicar) on Nov 07, 2016 at 04:47 UTC
      Thanks for the pointers. The "Remove roles for an object in perl moose" thread discusses the scenario where the roles have been applied to an instance rather than the class. But in my case, it is applied to the class and only in certain scenarios (less frequent) we need it removed from the instance. Thanks

        Maybe think of all classes as unconfigurable and only enable it for those cases where it needs to be configurable?

        I would look at this as having two classes and transferring the data from the ::Configurable class into the ::Unconfigurable class. The ::Unconfigurable class could be the naked Host package, and the Host::Configurable class could be Host with Configurable.

        thread discusses the scenario where the roles have been applied to an instance rather than the class. But in my case, it is applied to the class and only in certain scenarios (less frequent) we need it removed from the instance.

        Maybe the constructor for your class could apply the role to new instances, then you could remove the role, as needed, from individual instances.

Re: Remove a role from a Moose object
by Monk::Thomas (Friar) on Nov 07, 2016 at 15:24 UTC

    (I'm trying to understand what you are actually going to do with an object instance that dynamically modifies its interface.)

    Can you provide more detail on how you are using the role 'Configurable'? I do not understand why it would be necessary or appropriate to add/remove a role on a specific object instance.

    a) Are you using "$host->has_role('Configurable')" as a flag to determine whether $host is readonly or writeable?

    b) Does 'Configurable' provide the setters and you remove the role to hide them in order to prevent write access?

    c) ???

      The 'Configurable' role provides a bunch of methods that lets you modify some configuration files (ini and xml files). If a host is marked as read-only during the course of execution, then any attempt to configure that should result in an error.

      Now, to answer you questions

      a) the user checks  if ($host->configurable()) before using those methods. It is a syntactic sugar for has_role.

      b) Configurable provide getters/setters and a whole bunch of other methods. The epxectation is that the object should not expose any of those methods.

      c) What's the question ? I've no clue what '???' means.

      And as to why I am doing this, this(making nodes readonly) is quite a common scenario when you are working with a set of network devices acting together. Call it a cluster of nodes if you want. I am just trying to see if there is a simple way of achieving what I want. Thanks

        I am pondering whether you are doing something extremely clever (and I fail to see the point) or whether you're just doing it wrong. The reason why I consider 'you are doing it wrong' is because all instances of a specific class are supposed to have the same interface.

        Typical approaches to solve your requirements would be:

        • define separate classes (e.g. 'host_Configurable' and 'Host_NonConfigurable'), where one provides setters and the other doesn't
        • always provide the setter-Methods (but silently ignore or violently die()/croak() if 'configurable()' is set to false)

        In your case I suggest the second approach since you indicated the readonly/readwrite status may change at some point.