Module: EcsRails::Lazy::Entity
Overview
Mixed into EcsRails::Entity. The reader itself is generated per component by the DSL, into generated_component_methods; this supplies the machinery it calls, and the save cascade.
Instance Method Summary collapse
-
#ecs_component(name) ⇒ Object
private
The instance
entity.emailhands back. -
#ecs_forget_component(name) ⇒ Object
private
Forgets a component, so the next read rebuilds it as virtual.
-
#reload ⇒ Object
Drops the memo, so the next read goes back to the database.
Instance Method Details
#ecs_component(name) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The instance entity.email hands back. Called by the readers the DSL
generates; the block reaches the has_one reader underneath.
Memoised per entity instance, which RFC-0006 requires and the money path
depends on: user.email.address = "x"; user.save! only works if the
instance the caller mutated is the instance the cascade later sees.
Reading twice must not throw the first read’s assignment away.
The memo caches the row case too, not just the virtual one. It costs nothing (the association has its own cache, holding the same object) and it means the cascade can simply walk the memo, rather than interrogating ActiveRecord about which associations happen to be loaded.
70 71 72 73 74 75 |
# File 'lib/ecs_rails/lazy.rb', line 70 def ecs_component(name) cache = (@ecs_components ||= {}) return cache[name] if cache.key?(name) cache[name] = yield || ecs_build_component(name) end |
#ecs_forget_component(name) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Forgets a component, so the next read rebuilds it as virtual.
Public only because a component calls it on its entity, from across the object boundary — unlike #ecs_component, which the generated readers call on themselves.
Called by a component’s after_destroy (see Lazy::Component). Clearing the memo is not enough on its own: if the row was read through the reader then ActiveRecord’s association is also holding it, and #super in the generated reader would hand the frozen, destroyed object straight back. Both caches have to go.
The association is left marked loaded-with-nil rather than reset, because that is not a guess: the row was just deleted, and a component appears at most once per entity (ADR-0005), so there is provably nothing left to find. Resetting would buy an identical answer for one SELECT.
95 96 97 98 99 100 |
# File 'lib/ecs_rails/lazy.rb', line 95 def ecs_forget_component(name) @ecs_components&.delete(name) return unless self.class.reflect_on_association(name) association(name).target = nil end |
#reload ⇒ Object
Drops the memo, so the next read goes back to the database.
ActiveRecord’s #reload clears the association cache; the memo is a second cache over the same rows and has to be cleared with it or reload would be a lie — the caller would get their stale virtual back.
51 52 53 54 |
# File 'lib/ecs_rails/lazy.rb', line 51 def reload(*) @ecs_components = nil super end |