lib/recurly/schema.rb in recurly-3.0.0.beta.5 vs lib/recurly/schema.rb in recurly-3.0.0

- old
+ new

@@ -1,35 +1,34 @@ module Recurly # The class responsible for describing a schema. # This is used for requests and resources. class Schema # The attributes in the schema - # @return [Array<Attribute>] + # @return [Hash<String,Attribute>] attr_reader :attributes def initialize - @attributes = [] + @attributes = {} end # Adds an attribute to the schema definition # # @param name [Symbol] The name of the attribute # @param type [Class,Symbol] The type of the attribute. Use capitalized symbol for Recurly class. Example: :Account. - # @param options [Hash] The attribute options. See {Attribute#options} + # @param options [Schema::Attribute] The created and registered attribute object. def add_attribute(name, type, options) - attribute = Attribute.new(name, type, options) - @attributes.push(attribute) + attribute = Attribute.build(type, options) + @attributes[name.to_s] = attribute attribute end # Gets an attribute from this schema given a name # # @param name [String,Symbol] The name/key of the attribute # @return [Attribute,nil] The found Attribute. nil if not found. def get_attribute(name) - name = name.to_s - @attributes.find { |a| a.name.to_s == name } + @attributes[name.to_s] end # Gets a recurly class given a symbol name. # # @example @@ -44,77 +43,114 @@ if type == :Address Resources::Address elsif Requests.const_defined?(type) Requests.const_get(type) - elsif Resources.const_defined?(type) + elsif Recurly::Resources.const_defined?(type) Resources.const_get(type) else raise ArgumentError, "Recurly type '#{type}' is unknown" end end - # Describes a list attribute type - class List - # The type of the elements of the list - # @return [Symbol] - attr_accessor :item_type - - def initialize(item_type) - @item_type = item_type - end - - def to_s - "List<#{item_type}>" - end - end - - # Describes and attribute for a schema. class Attribute - # The name of the attribute. - # @return [Symbol] - attr_accessor :name - # The type of the attribute. Might be a class like `DateTime` # or could be a Recurly object. In this case a symbol should be used. - # Example: :Account + # Example: :Account. To get the Recurly type use #recurly_class # @return [Class,Symbol] - attr_accessor :type + attr_reader :type - # Options for the attribute. - # @return [Hash] - attr_accessor :options + PRIMITIVE_TYPES = [ + String, + Integer, + Float, + Hash, + ].freeze - # The description of the attribute for documentation. - # @return [String] - attr_accessor :description + def self.build(type, options = {}) + if PRIMITIVE_TYPES.include? type + PrimitiveAttribute.new(type) + elsif type == :Boolean + BooleanAttribute.new + elsif type == DateTime + DateTimeAttribute.new + elsif type.is_a? Symbol + ResourceAttribute.new(type) + elsif type == Array + item_attr = build(options[:item_type]) + ArrayAttribute.new(item_attr) + else + throw ArgumentError + end + end - def initialize(name, type, options = {}, description = nil) - @name = name + def initialize(type = nil) @type = type - @options = options - @description = description end - def read_only? - @options.fetch(:read_only, false) + def cast(value) + value end def recurly_class - Schema.get_recurly_class(type == Array ? options[:item_type] : type) + @recurly_class ||= Schema.get_recurly_class(type) end + end - def is_primitive? - t = type == Array ? options[:item_type] : type - t.is_a?(Class) || t == :Boolean + class PrimitiveAttribute < Attribute + def is_valid?(value) + value.is_a? self.type end end - private_constant :List - private_constant :Attribute + class BooleanAttribute < Attribute + def is_valid?(value) + [true, false].include? value + end + end + + class DateTimeAttribute < Attribute + def is_valid?(value) + value.is_a?(String) || value.is_a?(DateTime) + end + + def cast(value) + if value.is_a?(DateTime) + value + else + DateTime.parse(value) + end + end + + def type + DateTime + end + end + + class ResourceAttribute < Attribute + def is_valid?(value) + value.is_a? Hash + end + + def cast(value) + self.recurly_class.cast(value) + end + end + + class ArrayAttribute < Attribute + def is_valid?(value) + value.is_a? Array + end + + def cast(value) + value.map do |v| + self.type.cast(v) + end + end + end end require_relative "./schema/schema_factory" require_relative "./schema/schema_validator" - require_relative "./schema/json_deserializer" + require_relative "./schema/resource_caster" require_relative "./schema/request_caster" end