module OrangeData::GeneratedAttributes
Public Class Methods
from_schema(klass, schema)
click to toggle source
# File lib/orange_data/generated_attributes.rb, line 25 def self.from_schema(klass, schema) klass.class_eval{ extend GeneratedAttributes generate_accessors_from_schema(schema) } end
Protected Instance Methods
generate_accessors_from_schema(schema)
click to toggle source
# File lib/orange_data/generated_attributes.rb, line 34 def generate_accessors_from_schema(schema) plain_types = %w[integer string number] schema["properties"].each_pair do |property, info| property_name = info["x-name"] || property.underscore if plain_types.include?(info["type"]) || info["type"].is_a?(Array) && plain_types.include?(info["type"].first) && info["type"].last == "null" && info["type"].size == 2 if info["x-enum"] inverse_map = info["x-enum"].map{|k, v| [v['val'], k.to_sym] }.to_h define_method(property_name){ return nil if @payload[property].nil? inverse_map[@payload[property]] || raise("unknown value #{@payload[property].inspect} for field #{property}") } define_method(:"#{property_name}="){|val| unless val.nil? val = ( info["x-enum"][val.to_s] || raise(ArgumentError, "unknown value #{val.inspect} for property #{property}") )["val"] end @payload[property] = val } elsif info["x-bitfield"] bitmap = info["x-bitfield"].map{|k, v| [k.to_sym, 1 << v['bit']] }.to_h # TODO: return wrapper so that :<< etc will work define_method(property_name){ return nil if @payload[property].nil? data = @payload[property].to_i # FIXME: unknown bits will be silently lost bitmap.reject{|_, v| (data & v).zero? }.map(&:first) } define_method(:"#{property_name}="){|val| unless val.nil? val = [val] unless val.is_a?(Array) val = val.map{|v| bitmap[v] || raise(ArgumentError, "unknown value #{v.inspect} for property #{property}") }.reduce(:|) end @payload[property] = val } else # primitive define_method(property_name){ @payload[property] } define_method(:"#{property_name}="){|val| @payload[property] = val } end elsif info["type"] == 'array' if info["items"] && plain_types.include?(info["items"]["type"]) define_method(property_name){ @payload[property] } define_method(:"#{property_name}="){|val| val = [val] unless val.is_a?(Array) @payload[property] = val } # else # ref? end # else end if info["x-alias"] alias_method info['x-alias'].to_s, property_name alias_method "#{info['x-alias']}=", "#{property_name}=" end end end