Module: Dry::Core::ClassAttributes

Includes:
Constants
Defined in:
lib/dry/core/class_attributes.rb

Overview

Internal support module for class-level settings

Constant Summary

Constants included from Constants

Dry::Core::Constants::EMPTY_ARRAY, Dry::Core::Constants::EMPTY_HASH, Dry::Core::Constants::EMPTY_OPTS, Dry::Core::Constants::EMPTY_SET, Dry::Core::Constants::EMPTY_STRING, Dry::Core::Constants::IDENTITY, Dry::Core::Constants::Undefined

Instance Method Summary collapse

Methods included from Constants

included

Instance Method Details

#defines(*args, type: ::Object, coerce: IDENTITY) ⇒ Object

Specify what attributes a class will use

Examples:

class ExtraClass
  extend Dry::Core::ClassAttributes

  defines :hello

  hello 'world'
end

with inheritance and type checking


class MyClass
  extend Dry::Core::ClassAttributes

  defines :one, :two, type: Integer

  one 1
  two 2
end

class OtherClass < MyClass
  two 3
end

MyClass.one # => 1
MyClass.two # => 2

OtherClass.one # => 1
OtherClass.two # => 3

with dry-types


class Foo
  extend Dry::Core::ClassAttributes

  defines :one, :two, type: Dry::Types['strict.int']
end

with coercion using Proc


class Bar
  extend Dry::Core::ClassAttributes

  defines :one, coerce: proc { |value| value.to_s }
end

with coercion using dry-types


class Bar
  extend Dry::Core::ClassAttributes

  defines :one, coerce: Dry::Types['coercible.string']
end


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/dry/core/class_attributes.rb', line 68

def defines(*args, type: ::Object, coerce: IDENTITY) # rubocop:disable Metrics/PerceivedComplexity
  unless coerce.respond_to?(:call)
    raise ::ArgumentError, "Non-callable coerce option: #{coerce.inspect}"
  end

  mod = ::Module.new do
    args.each do |name|
      ivar = :"@#{name}"

      define_method(name) do |value = Undefined|
        if Undefined.equal?(value)
          if instance_variable_defined?(ivar)
            instance_variable_get(ivar)
          else
            nil
          end
        elsif type === value # rubocop:disable Style/CaseEquality
          instance_variable_set(ivar, coerce.call(value))
        else
          raise InvalidClassAttributeValueError.new(name, value)
        end
      end
    end

    define_method(:inherited) do |klass|
      args.each { |name| klass.send(name, send(name)) }

      super(klass)
    end
  end

  extend(mod)
end