Class: Typisch::Registry
- Inherits:
-
Object
- Object
- Typisch::Registry
- Defined in:
- lib/typisch/registry.rb
Overview
A registry is a glorified hash lookup of types by name
-
provide a concise way of referring to more complex types
-
help with the wiring up of recursive types
-
Constant Summary collapse
- GLOBALS =
While loading, we’ll register various types in this hash of types (boolean, string, …) which we want to be included in all registries
{}
Instance Attribute Summary collapse
-
#types_by_class ⇒ Object
readonly
Returns the value of attribute types_by_class.
-
#types_by_class_and_version ⇒ Object
readonly
Returns the value of attribute types_by_class_and_version.
-
#types_by_name ⇒ Object
readonly
Returns the value of attribute types_by_name.
Class Method Summary collapse
Instance Method Summary collapse
- #[](name, version = nil) ⇒ Object
- #each_type_in_graph(*types) ⇒ Object
-
#initialize(&block) ⇒ Registry
constructor
A new instance of Registry.
-
#initialize_copy(other) ⇒ Object
Allow you to dup and merge registries.
- #merge(other) ⇒ Object
- #merge!(other) ⇒ Object
-
#register(&block) ⇒ Object
All registering of types in a registry needs to be done inside one of these blocks; it ensures that the any forward references or cyclic references are resolved (via canonicalize!-ing every type in the type graph) once you’ve finished registering types.
- #register_type(name, type, &callback_on_canonicalization) ⇒ Object (also: #[]=)
- #register_type_for_class(klass, type) ⇒ Object
- #register_version_type_for_class(klass, version, type) ⇒ Object
- #start_registering_types! ⇒ Object
- #stop_registering_types! ⇒ Object
- #to_s ⇒ Object
Constructor Details
Instance Attribute Details
#types_by_class ⇒ Object (readonly)
Returns the value of attribute types_by_class.
9 10 11 |
# File 'lib/typisch/registry.rb', line 9 def types_by_class @types_by_class end |
#types_by_class_and_version ⇒ Object (readonly)
Returns the value of attribute types_by_class_and_version.
9 10 11 |
# File 'lib/typisch/registry.rb', line 9 def types_by_class_and_version @types_by_class_and_version end |
#types_by_name ⇒ Object (readonly)
Returns the value of attribute types_by_name.
9 10 11 |
# File 'lib/typisch/registry.rb', line 9 def types_by_name @types_by_name end |
Class Method Details
.register_global_type(name, type) ⇒ Object
42 43 44 45 |
# File 'lib/typisch/registry.rb', line 42 def self.register_global_type(name, type) type.send(:name=, name) unless type.name GLOBALS[name] = type end |
Instance Method Details
#[](name, version = nil) ⇒ Object
19 20 21 22 23 |
# File 'lib/typisch/registry.rb', line 19 def [](name, version=nil) name = :"#{name}" if name.is_a?(::Module) name = :"#{name}__#{version}" if version @types_by_name[name] ||= Type::NamedPlaceholder.new(name, self) end |
#each_type_in_graph(*types) ⇒ Object
85 86 87 88 89 90 91 92 93 |
# File 'lib/typisch/registry.rb', line 85 def each_type_in_graph(*types) seen_so_far = {} while (type = types.pop) next if seen_so_far[type] seen_so_far[type] = true yield type types.push(*type.subexpression_types) end end |
#initialize_copy(other) ⇒ Object
Allow you to dup and merge registries
97 98 99 |
# File 'lib/typisch/registry.rb', line 97 def initialize_copy(other) @types_by_name = @types_by_name.dup end |
#merge(other) ⇒ Object
101 102 103 |
# File 'lib/typisch/registry.rb', line 101 def merge(other) dup.merge!(other) end |
#merge!(other) ⇒ Object
105 106 107 |
# File 'lib/typisch/registry.rb', line 105 def merge!(other) @types_by_name.merge!(other.types_by_name) end |
#register(&block) ⇒ Object
All registering of types in a registry needs to be done inside one of these blocks; it ensures that the any forward references or cyclic references are resolved (via canonicalize!-ing every type in the type graph) once you’ve finished registering types.
This also ensures that any uses of recursion are valid / well-founded, and does any other necessary validation of the type graph you’ve declared which isn’t possible to do upfront.
You can nest register blocks without ill-effect; it will only try to resolve forward references etc once the outermost block has exited.
Note, this is all very much non-threadsafe, wouldn’t be hard to make it so (probably just slap a big mutex around it) but not sure why exactly you’d want multi-threaded type registration anyway to anyway so leaving as-is for now.
62 63 64 65 66 67 68 69 70 |
# File 'lib/typisch/registry.rb', line 62 def register(&block) if @registering_types DSLContext.new(self).instance_eval(&block) else start_registering_types! DSLContext.new(self).instance_eval(&block) stop_registering_types! end end |
#register_type(name, type, &callback_on_canonicalization) ⇒ Object Also known as: []=
25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/typisch/registry.rb', line 25 def register_type(name, type, &callback_on_canonicalization) case @types_by_name[name] when Type::NamedPlaceholder @types_by_name[name].send(:target=, type) when NilClass else raise Error, "type already registered with name #{name.inspect}" end type.send(:name=, name) unless type.name @types_by_name[name] = type @pending_canonicalization[name] = [type, callback_on_canonicalization] end |
#register_type_for_class(klass, type) ⇒ Object
117 118 119 |
# File 'lib/typisch/registry.rb', line 117 def register_type_for_class(klass, type) @types_by_class[klass] = type end |
#register_version_type_for_class(klass, version, type) ⇒ Object
121 122 123 |
# File 'lib/typisch/registry.rb', line 121 def register_version_type_for_class(klass, version, type) @types_by_class_and_version[[klass, version]] = type end |
#start_registering_types! ⇒ Object
72 73 74 |
# File 'lib/typisch/registry.rb', line 72 def start_registering_types! @registering_types = true end |
#stop_registering_types! ⇒ Object
76 77 78 79 80 81 82 83 |
# File 'lib/typisch/registry.rb', line 76 def stop_registering_types! @registering_types = false types = @pending_canonicalization.values.map {|t,c| t} each_type_in_graph(*types) {|t| t.canonicalize!} @pending_canonicalization.each {|name,(type,callback)| callback.call if callback} @pending_canonicalization = {} end |
#to_s ⇒ Object
109 110 111 112 113 114 115 |
# File 'lib/typisch/registry.rb', line 109 def to_s pairs = @types_by_name.map do |n,t| next if GLOBALS[n] "r.register #{n.inspect}, #{t.to_s(0, ' ')}" end.compact "Typisch::Registry.new do |r|\n #{pairs.join("\n ")}\nend" end |