lib/roxml/options.rb in Empact-roxml-2.2 vs lib/roxml/options.rb in Empact-roxml-2.3.0
- old
+ new
@@ -49,15 +49,15 @@
end
def to_ref(args, type, name)
case type
when :attr
- XMLAttributeRef.new(nil, to_hash_args(args, type, name))
+ XMLAttributeRef.new(to_hash_args(args, type, name))
when :text
- XMLTextRef.new(nil, to_hash_args(args, type, name))
+ XMLTextRef.new(to_hash_args(args, type, name))
when Symbol
- XMLTextRef.new(nil, to_hash_args(args, type, name))
+ XMLTextRef.new(to_hash_args(args, type, name))
else
raise ArgumentError, "Missing key description #{{:type => type, :name => name}.pp_s}"
end
end
@@ -77,18 +77,45 @@
end
end
end
class Opts # :nodoc:
- attr_reader :name, :type, :hash, :blocks
+ attr_reader :name, :type, :hash, :blocks, :default, :accessor
+ class << self
+ def silence_xml_name_warning?
+ @silence_xml_name_warning || (ROXML.const_defined?('SILENCE_XML_NAME_WARNING') && ROXML::SILENCE_XML_NAME_WARNING)
+ end
+
+ def silence_xml_name_warning!
+ @silence_xml_name_warning = true
+ end
+ end
+
def initialize(sym, *args, &block)
+ @accessor = sym
@opts = extract_options!(args)
+ @default = @opts.delete(:else)
- @opts.reverse_merge!(:from => sym.to_s, :as => [], :else => nil, :in => nil)
+ @opts.reverse_merge!(:as => [], :in => nil)
@opts[:as] = [*@opts[:as]]
+
@type = extract_type(args)
+ @opts[:as] << :bool if @accessor.to_s.ends_with?('?')
+
+ if @type.respond_to?(:xml_name?) && @type.xml_name?
+ unless self.class.silence_xml_name_warning?
+ warn "WARNING: As of 2.3, a breaking change has been in the naming of sub-objects. " +
+ "ROXML now considers the xml_name of the sub-object before falling back to the accessor name of the parent. " +
+ "Use :from on the parent declaration to override this behavior. Set ROXML::SILENCE_XML_NAME_WARNING to avoid this message."
+ self.class.silence_xml_name_warning!
+ end
+ @opts[:from] ||= @type.tag_name
+ else
+ @opts[:from] ||= variable_name
+ end
+
@blocks = collect_blocks(block, @opts[:as])
@name = @opts[:from].to_s
@name = @name.singularize if hash? || array?
if hash? && (hash.key.name? || hash.value.name?)
@@ -96,18 +123,18 @@
end
raise ArgumentError, "Can't specify both :else default and :required" if required? && default
end
+ def variable_name
+ accessor.to_s.ends_with?('?') ? accessor.to_s.chomp('?') : accessor.to_s
+ end
+
def hash
@hash ||= HashDesc.new(@opts.delete(:hash), name) if hash?
end
- def default
- @opts[:else]
- end
-
def hash?
@type == :hash
end
def content?
@@ -129,20 +156,72 @@
def required?
@opts[:required]
end
private
+ BLOCK_TO_FLOAT = lambda do |val|
+ if val.is_a? Array
+ val.collect do |v|
+ Float(v)
+ end
+ else
+ Float(val)
+ end
+ end
+
+ BLOCK_TO_INT = lambda do |val|
+ if val.is_a? Array
+ val.collect do |v|
+ Integer(v)
+ end
+ else
+ Integer(val)
+ end
+ end
+
+ TRUE_VALS = %w{TRUE True true 1}
+ FALSE_VALS = %w{FALSE False false 0}
+
BLOCK_SHORTHANDS = {
- :integer => lambda {|val| Integer(val) },
- Integer => lambda {|val| Integer(val) },
- :float => lambda {|val| Float(val) },
- Float => lambda {|val| Float(val) }
+ :integer => BLOCK_TO_INT,
+ Integer => BLOCK_TO_INT,
+ :float => BLOCK_TO_FLOAT,
+ Float => BLOCK_TO_FLOAT,
+ :bool => nil,
+ :bool_standalone => lambda do |val|
+ if TRUE_VALS.include? val
+ true
+ elsif FALSE_VALS.include? val
+ false
+ else
+ nil
+ end
+ end,
+
+ :bool_combined => lambda do |val|
+ if TRUE_VALS.include? val
+ true
+ elsif FALSE_VALS.include? val
+ false
+ else
+ val
+ end
+ end
}
def collect_blocks(block, as)
shorthands = as & BLOCK_SHORTHANDS.keys
- raise ArgumentError, "multiple block shorthands supplied #{shorthands.map(&:to_s).join(', ')}" if shorthands.size > 1
- [BLOCK_SHORTHANDS[shorthands.first], block].compact
+ if shorthands.size > 1
+ raise ArgumentError, "multiple block shorthands supplied #{shorthands.map(&:to_s).join(', ')}"
+ end
+
+ shorthand = shorthands.first
+ if shorthand == :bool
+ # if a second block is present, and we can't coerce the xml value
+ # to bool, we need to be able to pass it to the user-provided block
+ shorthand = block ? :bool_combined : :bool_standalone
+ end
+ [BLOCK_SHORTHANDS[shorthand], block].compact
end
def extract_options!(args)
opts = args.extract_options!
unless (opts.keys & HASH_KEYS).empty?
\ No newline at end of file