Sha256: 7847179eddd51c8bb26f5c148b5a625cf7af9fee3d11930e6ec7e517317253d4
Contents?: true
Size: 1.92 KB
Versions: 1
Compression:
Stored size: 1.92 KB
Contents
# # Like a Stuct, but automatically casts input to specific types. # # Example: # # class SomeRecord < TypedStruct["some_id:int amount:float x:string a,b,c:bool"]; end # record = SomeRecord.new(69, 12348.871, "stringy", true, 1, "no") # class TypedStruct < Struct ## TODO: Compact syntax: "a,b,c:int x:string y:date" ## TODO: Optional commas separating fields: "a, b, c:int, d:bool" ## TODO: booleans fields add "field?" methods # # A perhaps-too-clever table of { "typename" => convert_proc } mappings. # CONVERTERS = Hash[ *{ ["str", "string"] => :passthru, ["int", "integer"] => proc { |me| me.to_i }, ["hex"] => proc { |me| me.to_i(16) }, ["date", "time", "datetime"] => proc { |me| DateTime.parse me }, ["timestamp"] => proc { |me| Time.at me }, ["bool", "boolean"] => proc do |me| case me when false, 0, "0", "off", "no", "false", nil false when true, 1, "1", "on", "yes", "true" true else raise "Invalid boolean type: #{me.inspect}" end end }.map { |names, converter| names.map { |n| [n, converter] } }.flatten ] # # Initialize a new struct. # def self.[](specs) # create [name,type] pairs pairs = specs.split.map do |spec| name, type = spec.split(":") type ||= "string" unless converter = CONVERTERS[type] raise "Unknown type: #{type}" end [name.to_sym, converter] end # initialize the C 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 struct end def initialize(*args) members.zip(args).each { |field,value| send "#{field}=", value } end end
Version data entries
1 entries across 1 versions & 1 rubygems
Version | Path |
---|---|
epitools-0.5.9 | lib/epitools/typed_struct.rb |