require 'real_page/attribute_parser' require_relative 'base/attribute_store' module RealPage module Model # Base class for models, which are the return values from Requests class Base class << self attr_accessor :attribute_store end # Create a DSL to define the models attributes and their data types. This # bit of meta-programming will create a class method for each data type # to define the model's attributes of the type, e.g. # # class LostAndFound < Base # date_attr :found_date, :lost_date # end # # When a new LostAndFound is initialized (from a RealPage response hash, # that may have the keys 'founddate' and 'lostdate'), it will create # attribute readers for #found_date and #lost_date that return Date # instances. # # Boolean attributes will have the existential '?', e.g. # # class LostAndFound < Base # boolean_attr :found # end # # lost_and_found = LostAndFound.new('foundbit' => '1') # lost_and_found.found? # # => true %i[boolean date date_time decimal integer object string].each do |data_type| define_singleton_method "#{data_type}_attrs" do |*attrs| self.attribute_store ||= AttributeStore.new(self) attribute_store.add(data_type, attrs).each do |attribute| define_method attribute.accessor_name do instance_variable_get("@#{attribute.name}") end end end end # Initialize a new model with the response hash from RealPage. Attribute # values are parsed into their configured data types. # # @param attrs [Hash] the response hash from RealPage. # Attribute keys are case insensitive. def initialize(attrs = {}) attrs.each do |attr, value| attribute = self.class.attribute_store.find(attr) next unless attribute parser = AttributeParser.new(value: value, type: attribute.type) instance_variable_set("@#{attribute.name}", parser.parse) end end end private_constant :Base end end