module AlphaCard::Attribute::ClassMethods
Attributes class methods
* attribute * remove_attribute * attributes_set
Public Instance Methods
Adds attribute to the class. Defines reader and writer methods based on options hash. Adds attribute to the global Attributes Set.
@param name [Symbol, String] attribute name @param options [Hash] attribute options
@example
class User include AlphaCard::Attribute attribute :id, type: Integer, required: true, writable: false attribute :email, required: true, format: /.+@.+/ attribute :name, type: String attribute :role, default: 'admin', values: ['admin', 'regular'] attribute :status, types: [String, Symbol] attribute :metadata, type: Hash attribute :additional_info end
# File lib/alpha_card/attribute.rb, line 54 def attribute(name, options = {}) define_reader(name) define_writer(name, options) if options[:writable].nil? || options[:writable] attributes_set[name.to_sym] = options end
Defines Attributes Set for the class. Attributes set contains all the attributes names as key and it's options as the value.
@return [Hash] attributes set with options
# File lib/alpha_card/attribute.rb, line 29 def attributes_set @attributes_set ||= {} end
Removes attribute from the class (reader, writer and entry in Attributes Set).
@param name [String, Symbol] attribute name
@example
class User include AlphaCard::Attribute attribute :email attribute :name, default: 'John' end class Person < User attribute :email remove_attribute :name end
# File lib/alpha_card/attribute.rb, line 78 def remove_attribute(name) symbolized_name = name.to_sym if attributes_set.keys.include?(symbolized_name) undef_method(symbolized_name) undef_method("#{name}=") if method_defined?("#{name}=") attributes_set.delete(symbolized_name) end end
Private Instance Methods
Creates a reader method for the attribute.
@private
@param name [String, Symbol] attribute name
# File lib/alpha_card/attribute.rb, line 107 def define_reader(name) attr_reader name.to_sym end
Creates a writer method for the attribute with validation of setting value if options was passed.
@private
@raise [InvalidAttributeValue] when value is not included in the possible values list @raise [InvalidAttributeFormat] when value doesn't match the required format @raise [InvalidAttributeType] when value is not of valid type
@param name [Symbol] attribute name @param options [Hash] attribute options
# File lib/alpha_card/attribute.rb, line 123 def define_writer(name, options = {}) values = extract_values_from(options) format = extract_format_from(options) types = extract_types_from(options) define_method("#{name}=") do |value| raise InvalidAttributeValue.new(value, values) if values && !values.include?(value) raise InvalidAttributeFormat.new(value, format) if !format.nil? && value !~ format raise InvalidAttributeType.new(value, types) if value && types && types.none? { |klass| value.is_a?(klass) } instance_variable_set(:"@#{name}", value) end end
Extract and validate attribute value format from options hash.
@private
@param options [Hash] attribute options
@return [Regexp] attribute value format
# File lib/alpha_card/attribute.rb, line 163 def extract_format_from(options = {}) format = options[:format] || return raise ArgumentError, ':format must be Regexp!' unless format.is_a?(Regexp) format end
Extract and validate attribute type class from options hash.
@private
@param options [Hash] attribute options
@return [Object] possible attribute type(s)
# File lib/alpha_card/attribute.rb, line 178 def extract_types_from(options = {}) types = Array(options[:type] || options[:types]) return if types.empty? raise ArgumentError, 'attribute type must be a Class!' if types.any? { |type| !type.is_a?(Class) } types end
Extract and validate possible attribute values from options hash.
@private
@param options [Hash] attribute options
@return [Array] possible attribute values
# File lib/alpha_card/attribute.rb, line 147 def extract_values_from(options = {}) values = options[:values] || return raise ArgumentError, ':values option must be an Array or respond to .to_a!' unless values.is_a?(Array) || values.respond_to?(:to_a) raise ArgumentError, ":values option can't be empty!" if values.empty? values.to_a end
Writes Attributes Set to the superclass on inheritance.
@private
@param subclass [Class] inherited class
# File lib/alpha_card/attribute.rb, line 97 def inherited(subclass) subclass.instance_variable_set(:@attributes_set, attributes_set.dup) end