module AlphaCard::Attribute::ClassMethods

Attributes class methods

* attribute
* remove_attribute
* attributes_set

Public Instance Methods

attribute(name, options = {}) click to toggle source

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
attributes_set() click to toggle source

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
remove_attribute(name) click to toggle source

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

define_reader(name) click to toggle source

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
define_writer(name, options = {}) click to toggle source

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_format_from(options = {}) click to toggle source

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_types_from(options = {}) click to toggle source

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_values_from(options = {}) click to toggle source

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
inherited(subclass) click to toggle source

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