Class: AttrJson::AttributeDefinition::Registry
- Inherits:
-
Object
- Object
- AttrJson::AttributeDefinition::Registry
- Defined in:
- lib/attr_json/attribute_definition/registry.rb
Overview
Attached to a class to record the json attributes registered, with either AttrJson::Record or AttrJson::Model.
Think of it as mostly like a hash keyed by attribute name, value an AttributeDefinition.
It is expected to be used by AttrJson::Record and AttrJson::Model, you shouldn't need to interact with it directly.
It is intentionally immutable to make it harder to accidentally mutate
a registry shared with superclass in a class_attribute
, instead of
properly assigning a new modified registry.
self.some_registry_attribute = self.some_registry_attribute.with(
attr_definition_1, attr_definition_2
)
# => Returns a NEW AttributeDefinition object
All references in code to "definition" are to a AttrJson::AttributeDefinition instance.
Instance Method Summary collapse
- #[](key) ⇒ Object
-
#attribute_names ⇒ Object
Returns all registered attributes as an array of symbols.
- #container_attribute_registered?(attribute_name:, model:) ⇒ Boolean
- #container_attributes ⇒ Object
- #definitions ⇒ Object
- #fetch(key, *args, &block) ⇒ Object
- #has_attribute?(key) ⇒ Boolean
-
#initialize(hash = {}) ⇒ Registry
constructor
A new instance of Registry.
-
#register_container_attribute(attribute_name:, model:) ⇒ Object
We need to lazily set the container type only the FIRST time.
-
#store_key_lookup(container_attribute, store_key) ⇒ Object
Can return nil if none found.
- #type_for_attribute(key) ⇒ Object
-
#with(*definitions) ⇒ Object
This is how you register additional definitions, as a non-mutating return-a-copy operation.
Constructor Details
#initialize(hash = {}) ⇒ Registry
Returns a new instance of Registry.
27 28 29 30 31 32 33 34 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 27 def initialize(hash = {}) @name_to_definition = hash.dup @store_key_to_definition = {} @name_to_definition.values.each { |d| store_key_index!(d) } @container_attributes_registered = Hash.new { Set.new } end |
Instance Method Details
#[](key) ⇒ Object
40 41 42 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 40 def [](key) @name_to_definition[key.to_sym] end |
#attribute_names ⇒ Object
Returns all registered attributes as an array of symbols
64 65 66 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 64 def attribute_names @name_to_definition.keys end |
#container_attribute_registered?(attribute_name:, model:) ⇒ Boolean
104 105 106 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 104 def container_attribute_registered?(attribute_name:, model:) @container_attributes_registered[attribute_name.to_sym].include?(model) end |
#container_attributes ⇒ Object
68 69 70 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 68 def container_attributes @store_key_to_definition.keys.collect { |s| AttrJson.efficient_to_s(s) } end |
#definitions ⇒ Object
58 59 60 61 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 58 def definitions # Since we are immutable, we can cache this to avoid allocation in a hot spot @stored_definitions ||= @name_to_definition.values end |
#fetch(key, *args, &block) ⇒ Object
36 37 38 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 36 def fetch(key, *args, &block) @name_to_definition.fetch(key.to_sym, *args, &block) end |
#has_attribute?(key) ⇒ Boolean
44 45 46 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 44 def has_attribute?(key) @name_to_definition.has_key?(key.to_sym) end |
#register_container_attribute(attribute_name:, model:) ⇒ Object
We need to lazily set the container type only the FIRST time
While also avoiding this triggering ActiveRecord to actually go to DB, we don't want DB connection forced on boot, that's a problem for many apps, including that may not have a DB connection in initial development. (#type_for_attribute forces DB connection)
AND we need to call container attriubte on SUB-CLASS AGAIN, iff sub-class has any of it's own new registrations, to make sure we get the right type in sub-class!
So we just keep track of whether we've registered ourselves, so we can first time we need to.
While current implementation is simple, this has ended up a bit fragile, a different API that doesn't require us to do this implicitly lazily might be preferred! But this is what we got for now.
100 101 102 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 100 def register_container_attribute(attribute_name:, model:) @container_attributes_registered[attribute_name.to_sym] << model end |
#store_key_lookup(container_attribute, store_key) ⇒ Object
Can return nil if none found.
53 54 55 56 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 53 def store_key_lookup(container_attribute, store_key) @store_key_to_definition[AttrJson.efficient_to_s(container_attribute)] && @store_key_to_definition[AttrJson.efficient_to_s(container_attribute)][AttrJson.efficient_to_s(store_key)] end |
#type_for_attribute(key) ⇒ Object
48 49 50 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 48 def type_for_attribute(key) self[key].type end |
#with(*definitions) ⇒ Object
This is how you register additional definitions, as a non-mutating return-a-copy operation.
74 75 76 77 78 79 80 |
# File 'lib/attr_json/attribute_definition/registry.rb', line 74 def with(*definitions) self.class.new(@name_to_definition).tap do |copied| definitions.each do |defin| copied.add!(defin) end end end |