Module: Literal::Attributable

Includes:
Types
Included in:
Attributes, Structish
Defined in:
lib/literal/attributable.rb

Defined Under Namespace

Modules: Generators, Nodes Classes: Formatter

Constant Summary collapse

Visibility =
[:private, :protected, :public].freeze

Constants included from Monads

Monads::Either, Monads::Left, Monads::Maybe, Monads::Nothing, Monads::Result, Monads::Right, Monads::Some

Instance Method Summary collapse

Methods included from Types

#_Any, #_Array, #_Boolean, #_Callable, #_Class, #_Constraint, #_Descendant, #_Enumerable, #_Falsy, #_Float, #_Frozen, #_Hash, #_Integer, #_Interface, #_Intersection, #_Is, #_JSONData, #_Lambda, #_Map, #_Never, #_Nilable, #_Not, #_Procable, #_Range, #_Set, #_Shape, #_String, #_Symbol, #_Truthy, #_Tuple, #_Union, #_Void

Methods included from Monads

#Either, #Left, #Maybe, #Result, #Right, #Some, #Success

Instance Method Details

#attribute(name, type, special = nil, reader: false, writer: false, positional: false, default: nil, &coercion) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/literal/attributable.rb', line 8

def attribute(name, type, special = nil, reader: false, writer: false, positional: false, default: nil, &coercion)
	if default && !(Proc === default || default.frozen?)
		raise Literal::ArgumentError, "The `default` must be a frozen value or a Proc."
	end

	unless false == reader || Visibility.include?(reader)
		raise Literal::ArgumentError, "The `reader` must be one of #{Visibility.map(&:inspect).join(', ')}."
	end

	unless false == writer || Visibility.include?(writer)
		raise Literal::ArgumentError, "The `writer` must be one of #{Visibility.map(&:inspect).join(', ')}."
	end

	if special && positional
		raise Literal::ArgumentError, "The #{name} attribute cannot be #{special} and positional."
	end

	if :class == name && reader
		raise Literal::ArgumentError, "The `:class` attribute should not be defined as a reader because it breaks Ruby's `Object#class` method, which Literal itself depends on."
	end

	attribute = Literal::Attribute.new(
		name:,
		type:,
		special:,
		reader:,
		writer:,
		positional:,
		default:,
		coercion:
	)

	literal_attributes[name] = attribute

	include literal_extension

	define_literal_methods(attribute)
end

#define_literal_methods(attribute) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/literal/attributable.rb', line 57

def define_literal_methods(attribute)
	literal_extension.module_eval <<~RUBY, __FILE__, __LINE__ + 1
		# frozen_string_literal: true

		#{generate_literal_initializer}

		#{generate_literal_reader(attribute) if attribute.reader?}

		#{generate_literal_writer(attribute) if attribute.writer?}
	RUBY
end

#literal_attributesObject



47
48
49
50
51
52
53
54
55
# File 'lib/literal/attributable.rb', line 47

def literal_attributes
	return @literal_attributes if defined?(@literal_attributes)

	if superclass.is_a?(Literal::Attributable)
		@literal_attributes = superclass.literal_attributes.dup
	else
		@literal_attributes = Concurrent::Hash.new
	end
end

#literal_extensionObject



69
70
71
# File 'lib/literal/attributable.rb', line 69

def literal_extension
	defined?(@literal_extension) ? @literal_extension : @literal_extension = Module.new
end