Re: Trying to create an attribute trait that prompts for a value if none specified
[email protected] ("Todd Lorenz")
| Newsgroups | perl.moose |
|---|---|
| Message-ID | <[email protected]> |
Not quite... We're not changing the default metaclass for everything, but rather applying a metarole to the metaclass of the consuming class. (I think that's how it goes -- I'm still not sure of the correct terminology.) And there's still an attribute "trait" involved there, albeit a minimal one that adds a "prompt" option to affected attributes. The new_object/_inline_new_object wrappers simply look for those attributes at the end of construction and ask the user to fill in the blanks. (If you're concerned about prompting during cloning and/or reblessing, there'll be a little more work to do.) Don't know if it's a good approach by Moose Cabal standards, but it's direct. You'd want to add in other stuff probably, like mutual exclusion with defaults, etc. -----Original Message----- From: Buddy Burden Sent: Thursday, December 22, 2011 2:40 PM To: Edward Allen Cc: [email protected] Subject: Re: Trying to create an attribute trait that prompts for a value if none specified Guys, I'm still experimenting here, but I had a couple of questions. ealleniii, I like your solution; very clever, particularly where you install the bulder sub as a default instead of a builder, which neatly gets around the problem that a builder has to be the name of a method of the class. But the crux of it is here: > # The real magic: > $attr = $attr->clone_and_inherit_options( > default => $builder, > lazy => 1 > ); > $class->add_attribute($attr); and my gut instinct is to wonder: doesn't that mean the attribute gets added to the class twice? Now, admittedly I haven't actually tried it yet, but it also occurred to me to wonder how you could even _tell_ if the attribute was installed twice ... could it conceivably generate a silent failure that just resulted in weirdness down the road? or something that works today but not tomorrow when Moose guts are changed? If the author--or anyone else--has some insight on that issue, I'd really love to hear it. Todd, I'm assuming you replied off-list just because you didn't want the zip file to land in everyone's inbox, for which I'm sure they're appreciative. :-) So, after staring at your approach for quite a while, I finally figured out what's going on: you're actually _changing_ the default metaclass for everything by applying a new role to it. Said new role contains this: > around new_object => sub { > > my ($orig_method, $self_aka_class) = (shift, shift); > > my $instance = $self_aka_class->$orig_method(@_); > > for my $attr ($self_aka_class->get_all_attributes) { > > next unless $attr->has_prompt; > > unless ($attr->has_value($instance)) { > > my $prompted_val = Term::Prompt::prompt('x', > $attr->prompt, 'help prompt', 'foo'); > > $attr->set_value($instance, $prompted_val); > } > } > > return $instance; > }; Again, very clever. But definitely very different from the approach I was going for, which was an attribute trait. (Although the provided test file proves handily that it really works.) Can you--or anyone--tell me what the practical differences would be between the two approaches, and why I might prefer one over the other? Thanx again for the help guys. -- Buddy