Class: Puppet::Interface::Action
Instance Attribute Summary collapse
-
#default ⇒ Object
Returns the value of attribute default.
-
#face ⇒ Object
readonly
Returns the value of attribute face.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#positional_arg_count ⇒ Object
readonly
We need to build an instance method as a wrapper, using normal code, to be able to expose argument defaulting between the caller and definer in the Ruby API.
-
#render_as ⇒ Object
Returns the value of attribute render_as.
-
#when_invoked ⇒ Object
Returns the value of attribute when_invoked.
Attributes included from FullDocs
#copyright_owner, #copyright_years
Instance Method Summary collapse
-
#__dup_and_rebind_to(to) ⇒ Object
This is not nice, but it is the easiest way to make us behave like the Ruby Method object rather than UnboundMethod.
- #add_option(option) ⇒ Object
- #default? ⇒ Boolean
- #get_option(name, with_inherited_options = true) ⇒ Object
-
#initialize(face, name, attrs = {}) ⇒ Action
constructor
A new instance of Action.
- #option?(name) ⇒ Boolean
- #options ⇒ Object
- #set_rendering_method_for(type, proc) ⇒ Object
- #synopsis ⇒ Object
- #to_s ⇒ Object
- #validate_and_clean(original) ⇒ Object
-
#when_rendering(type) ⇒ Object
Support for rendering formats and all.
Methods included from DocGen
Methods included from FullDocs
#author, #author=, #authors, #copyright, #munge_copyright_year, #short_description
Methods included from TinyDocs
Constructor Details
#initialize(face, name, attrs = {}) ⇒ Action
Returns a new instance of Action.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/vendor/puppet/interface/action.rb', line 9 def initialize(face, name, attrs = {}) raise "#{name.inspect} is an invalid action name" unless name.to_s =~ /^[a-z]\w*$/ @face = face @name = name.to_sym # The few bits of documentation we actually demand. The default license # is a favour to our end users; if you happen to get that in a core face # report it as a bug, please. --daniel 2011-04-26 @authors = [] @license = 'All Rights Reserved' attrs.each do |k, v| send("#{k}=", v) end # @options collects the added options in the order they're declared. # @options_hash collects the options keyed by alias for quick lookups. @options = [] @options_hash = {} @when_rendering = {} end |
Instance Attribute Details
#default ⇒ Object
Returns the value of attribute default.
42 43 44 |
# File 'lib/vendor/puppet/interface/action.rb', line 42 def default @default end |
#face ⇒ Object (readonly)
Returns the value of attribute face.
41 42 43 |
# File 'lib/vendor/puppet/interface/action.rb', line 41 def face @face end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
40 41 42 |
# File 'lib/vendor/puppet/interface/action.rb', line 40 def name @name end |
#positional_arg_count ⇒ Object (readonly)
We need to build an instance method as a wrapper, using normal code, to be able to expose argument defaulting between the caller and definer in the Ruby API. An extra method is, sadly, required for Ruby 1.8 to work since it doesn’t expose bind on a block.
Hopefully we can improve this when we finally shuffle off the last of Ruby 1.8 support, but that looks to be a few “enterprise” release eras away, so we are pretty stuck with this for now.
Patches to make this work more nicely with Ruby 1.9 using runtime version checking and all are welcome, provided that they don’t change anything outside this little ol’ bit of code and all.
Incidentally, we though about vendoring evil-ruby and actually adjusting the internal C structure implementation details under the hood to make this stuff work, because it would have been cleaner. Which gives you an idea how motivated we were to make this cleaner. Sorry. –daniel 2011-03-31
169 170 171 |
# File 'lib/vendor/puppet/interface/action.rb', line 169 def positional_arg_count @positional_arg_count end |
#render_as ⇒ Object
Returns the value of attribute render_as.
109 110 111 |
# File 'lib/vendor/puppet/interface/action.rb', line 109 def render_as @render_as end |
#when_invoked ⇒ Object
Returns the value of attribute when_invoked.
170 171 172 |
# File 'lib/vendor/puppet/interface/action.rb', line 170 def when_invoked @when_invoked end |
Instance Method Details
#__dup_and_rebind_to(to) ⇒ Object
This is not nice, but it is the easiest way to make us behave like the Ruby Method object rather than UnboundMethod. Duplication is vaguely annoying, but at least we are a shallow clone. –daniel 2011-04-12
32 33 34 35 36 |
# File 'lib/vendor/puppet/interface/action.rb', line 32 def __dup_and_rebind_to(to) bound_version = self.dup bound_version.instance_variable_set(:@face, to) return bound_version end |
#add_option(option) ⇒ Object
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/vendor/puppet/interface/action.rb', line 224 def add_option(option) option.aliases.each do |name| if conflict = get_option(name) then raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" elsif conflict = @face.get_option(name) then raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{@face}" end end @options << option.name option.aliases.each do |name| @options_hash[name] = option end option end |
#default? ⇒ Boolean
43 44 45 |
# File 'lib/vendor/puppet/interface/action.rb', line 43 def default? !!@default end |
#get_option(name, with_inherited_options = true) ⇒ Object
250 251 252 253 254 255 256 |
# File 'lib/vendor/puppet/interface/action.rb', line 250 def get_option(name, = true) option = @options_hash[name.to_sym] if option.nil? and option = @face.get_option(name) end option end |
#option?(name) ⇒ Boolean
242 243 244 |
# File 'lib/vendor/puppet/interface/action.rb', line 242 def option?(name) @options_hash.include? name.to_sym end |
#options ⇒ Object
246 247 248 |
# File 'lib/vendor/puppet/interface/action.rb', line 246 def @face. + @options end |
#set_rendering_method_for(type, proc) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/vendor/puppet/interface/action.rb', line 71 def set_rendering_method_for(type, proc) unless proc.is_a? Proc msg = "The second argument to set_rendering_method_for must be a Proc" msg += ", not #{proc.class.name}" unless proc.nil? raise ArgumentError, msg end if proc.arity != 1 and proc.arity != (@positional_arg_count + 1) msg = "the when_rendering method for the #{@face.name} face #{name} action " msg += "takes either just one argument, the result of when_invoked, " msg += "or the result plus the #{@positional_arg_count} arguments passed " msg += "to the when_invoked block, not " if proc.arity < 0 then msg += "a variable number" else msg += proc.arity.to_s end raise ArgumentError, msg end unless type.is_a? Symbol raise ArgumentError, "The rendering format must be a symbol, not #{type.class.name}" end if @when_rendering.has_key? type then raise ArgumentError, "You can't define a rendering method for #{type} twice" end # Now, the ugly bit. We add the method to our interface object, and # retrieve it, to rotate through the dance of getting a suitable method # object out of the whole process. --daniel 2011-04-18 @when_rendering[type] = @face.__send__( :__add_method, __render_method_name_for(type), proc) end |
#synopsis ⇒ Object
51 52 53 |
# File 'lib/vendor/puppet/interface/action.rb', line 51 def synopsis build_synopsis(@face.name, default? ? nil : name, arguments) end |
#to_s ⇒ Object
38 |
# File 'lib/vendor/puppet/interface/action.rb', line 38 def to_s() "#{@face}##{@name}" end |
#validate_and_clean(original) ⇒ Object
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/vendor/puppet/interface/action.rb', line 258 def validate_and_clean(original) # The final set of arguments; effectively a hand-rolled shallow copy of # the original, which protects the caller from the surprises they might # get if they passed us a hash and we mutated it... result = {} # Check for multiple aliases for the same option, and canonicalize the # name of the argument while we are about it. overlap = Hash.new do |h, k| h[k] = [] end unknown = [] original.keys.each do |name| if option = get_option(name) then canonical = option.name if result.has_key? canonical overlap[canonical] << name else result[canonical] = original[name] end elsif Puppet.settings.include? name result[name] = original[name] else unknown << name end end unless overlap.empty? msg = overlap.map {|k, v| "(#{k}, #{v.sort.join(', ')})" }.join(", ") raise ArgumentError, "Multiple aliases for the same option passed: #{msg}" end unless unknown.empty? msg = unknown.sort.join(", ") raise ArgumentError, "Unknown options passed: #{msg}" end # Inject default arguments and check for missing mandating options. missing = [] .map {|x| get_option(x) }.each do |option| name = option.name next if result.has_key? name if option.has_default? result[name] = option.default elsif option.required? missing << name end end unless missing.empty? msg = missing.sort.join(', ') raise ArgumentError, "The following options are required: #{msg}" end # All done. return result end |
#when_rendering(type) ⇒ Object
Support for rendering formats and all.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/vendor/puppet/interface/action.rb', line 57 def when_rendering(type) unless type.is_a? Symbol raise ArgumentError, "The rendering format must be a symbol, not #{type.class.name}" end # Do we have a rendering hook for this name? return @when_rendering[type].bind(@face) if @when_rendering.has_key? type # How about by another name? alt = type.to_s.sub(/^to_/, '').to_sym return @when_rendering[alt].bind(@face) if @when_rendering.has_key? alt # Guess not, nothing to run. return nil end |