class TypedStruct
Like a Stuct, but automatically casts assignments to specific types.
Example:
class SomeRecord < TypedStruct["some_id:int amount:float name:string a,b,c:bool untyped_var"] end record = SomeRecord.new(69, 12348.871, "stringy", true, 1, "no", Object.new) another_record = SomeRecord.new :amount=>"1.5", :name=>"Steve", :c=>"true", :a=>"disable", :untyped_var=>Ratio.new(1/2) record.amount *= 3.141592653589793238462643383279
Recognized types, and what they get converted into:
<no type given> => Don't enforce a type -- any ruby object is allowed. ["str", "string"] => String ["sym", "symbol"] => Symbol ["int", "integer"] => Integer ["float"] => Float ["bigdecimal"] => BigDecimal ["hex"] => Integer ["date", "time", "datetime"] => DateTime (using DateTime.parse) ["timestamp", "unixtime"] => Time (using Time.at) ["bool", "boolean"] => Boolean, using the following rules: false when: false, nil, 0, "0", "off", "no", "false", "disabled", "disable" true when: true, 1, "1", "on", "yes", "true", "enabled", "enable"
Constants
- CONVERTERS
A perhaps-too-clever table of { “typename” => convert_proc } mappings.
Public Class Methods
[](specs)
click to toggle source
Initialize a new struct.
# File lib/epitools/typed_struct.rb, line 66 def self.[](specs) wildcard = false drop_unknown = false # create [name,type] pairs pairs = specs.split.map do |spec| case spec when "*" wildcard = true next when "-" drop_unknown = true next end names, type = spec.split(":") names.split(",").map do |name| type ||= :passthru raise "Unknown type: #{type}" unless converter = CONVERTERS[type] [name.to_sym, converter] end end.compact.flatten(1) raise "Error: Can't specify both wildcard ('*') and drop unknown ('-')" if wildcard and drop_unknown # initialize the Struct struct = new(*pairs.transpose.first) # overload setter methods to call the proc pairs.each do |field, converter| next if converter == :passthru struct.send(:define_method, "#{field}=") do |val| self[field] = ( val and converter.call val ) end end if wildcard struct.class_eval do def method_missing(name, val=nil) if name =~ /^(.+)=$/ @extra_slots ||= {} @extra_slots[$1.to_sym] = val else @extra_slots && @extra_slots[name] end end end end struct.class_eval do @@drop_unknown = drop_unknown end struct end
new(*args)
click to toggle source
# File lib/epitools/typed_struct.rb, line 123 def initialize(*args) if args.size == 1 and args.first.is_a? Hash opts = args.first else opts = members.zip(args) end if @@drop_unknown opts.each { |key,value| send "#{key}=", value if respond_to? "#{key}=" } else opts.each { |key,value| send "#{key}=", value } end end
Public Instance Methods
method_missing(name, val=nil)
click to toggle source
# File lib/epitools/typed_struct.rb, line 105 def method_missing(name, val=nil) if name =~ /^(.+)=$/ @extra_slots ||= {} @extra_slots[$1.to_sym] = val else @extra_slots && @extra_slots[name] end end