class PropertyGroups
def self.from_xml(xml)
document = Document.new(xml)
properties = Hash.new
document.elements.each("Project/PropertyGroup/*") do |element|
properties[element.name] = element.text.strip
end
return PropertyGroups.new(properties)
end
def initialize(elements)
variable_regexp = /\$\([\w]+\)/
elements.each_pair do |key, value|
PropertyGroups.class_eval do
define_method key.to_sym do ||
replaced_value = value
while variable_regexp.match(replaced_value)
match = variable_regexp.match(replaced_value)
full_var = match[0]
var_name = full_var[2..-2]
if elements.key? var_name
replaced_value = replaced_value.sub(full_var, elements[var_name])
else
replaced_value = replaced_value.sub(full_var, "")
end
end
return replaced_value
end
end
end
end
end
Refactorings
No refactoring yet !
kotrin
August 8, 2009, August 08, 2009 04:03, permalink
class PropertyGroups
def self.from_xml(xml)
document = Document.new(xml)
properties = {}
document.elements.each("Project/PropertyGroup/*") do |element|
properties[element.name] = element.text.strip
end
PropertyGroups.new(properties)
end
def initialize(elements)
elements.each_pair { |k,v|
meta_def(k.to_sym) {
v.gsub(/\$\(([\w]+)\)/) { elements.key?($1) ? elements[$1] : "" }
}
}
end
def meta_def(m,&b)
(class<<self;self end).send(:define_method,m,&b)
end
end
The code is part of a library that parses .net msbuild project files containing property groups and is up at http://github.com/brunomlopes/ironbuildrake/ , together with tests.
Each property has a value that I want to access, and the value can be defined in function of other variables. A variable has the format $(varname).
This code is rather straightforward, but seems rather non-idiomatic.
The use of define_method in a class eval to avoid method_missing is a personal preference in order to avoid nasty recursive bugs and to allow for better runtime inspection of available methods.