Class: XML::Digester::SetPropertiesRule

Inherits:
RulesBase
  • Object
show all
Defined in:
lib/xml/digestr.rb

Overview

Rule that sets attributes on the top object on the stack based on values from the current element’s attributes. This rule often follows an ObjectCreateRule with the same pattern in order to configure the newly created object. The attributes are set in the begin event.

Instance Attribute Summary

Attributes inherited from RulesBase

#digester, #next, #pattern, #prev

Instance Method Summary collapse

Methods inherited from RulesBase

#body, #end, #finish

Constructor Details

#initialize(pattern, mapping = Hash.new { |h,k| h[k] = k }, &blk) ⇒ SetPropertiesRule

call-seq:

SetPropertiesRule.new(pattern, [mapping])
SetPropertiesRule.new(pattern, [mapping]) { |target, attr, value| ... }

Create a new SetPropertiesRule. The optional mapping parameter allows a mapping between XML attribute names and the corresponding ruby attribute name/type. It should quack like a hash, and return entries of the form:

xml_name => ruby_name
xml_name => coerce_type
xml_name => [ruby_name, coerce_type]

where ruby_name is the name of the attribute that is to be set, coerce_type is the class (for which a coercion method must be defined on Kernel) the attribute value should be coerced to. The mapping may mix entries of the three forms.

If a block is supplied, it is called (during begin) for each attribute that is to be set. The target argument supplies the top stack object, while attr and value supply the attribute name and value, processed according to the mapping rules.



164
165
166
167
168
169
170
# File 'lib/xml/digestr.rb', line 164

def initialize(pattern, 
               mapping = Hash.new { |h,k| h[k] = k }, 
               &blk)
  super(pattern)
  @mapping = mapping
  @blk = blk
end

Instance Method Details

#begin(namespace, name, attrs) ⇒ Object

:nodoc:



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/xml/digestr.rb', line 172

def begin(namespace, name, attrs) #:nodoc:
  if (top = @digester.peek)
    attrs.each do |k,v|
      obj_attr, coerce = @mapping[k] || k
      
      # allow a single class to be specified if same
      # name is to be used
      if obj_attr.kind_of? Module
        coerce, obj_attr = obj_attr, k
      end
        
      if coerce && coerce != String
        v = send(coerce.name, v)            
      end
      
      unless obj_attr == :nil
        if b = @blk
          b.call(top,obj_attr,v)
        else
          setter = "#{obj_attr}="
          begin
            top.send(setter,v)
          rescue NoMethodError
            if @digester.pedantic?
              raise Error,
                  "Unknown property attribute: #{name} for #{top.inspect}"
            end
            nil
          end
        end
      end
    end
  end
end