Module: Ruact::Serializable::ClassMethods
- Defined in:
- lib/ruact/serializable.rb
Instance Method Summary collapse
-
#ruact_deferred_props_list ⇒ Array<Symbol>
Names whose eager loud check was deferred to first serialize (lazy ActiveRecord attributes).
-
#ruact_lazy_attribute_class? ⇒ Boolean
True when this class defines its attribute reader methods lazily, i.e.
-
#ruact_props(*attrs) ⇒ Object
Declare which instance methods should be included in the serialized payload.
-
#ruact_props_list ⇒ Array<Symbol>
Returns the list of declared prop names as symbols.
-
#ruact_validate_deferred_props!(instance) ⇒ Object
Run the deferred loud check once, on first
ruact_serialize.
Instance Method Details
#ruact_deferred_props_list ⇒ Array<Symbol>
Names whose eager loud check was deferred to first serialize (lazy ActiveRecord attributes). Read from the same class that declared the props, so subclasses share the parent declaration.
94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/ruact/serializable.rb', line 94 def ruact_deferred_props_list klass = self while klass if klass.instance_variable_defined?(:@ruact_props) return klass.instance_variable_get(:@ruact_deferred_props) || [] end klass = klass.superclass end [] end |
#ruact_lazy_attribute_class? ⇒ Boolean
True when this class defines its attribute reader methods lazily, i.e.
an ActiveRecord model. Detected WITHOUT a hard ActiveRecord dependency
(the gem stays single-dep nokogiri): the constant is only referenced
when it is already defined in the host.
137 138 139 |
# File 'lib/ruact/serializable.rb', line 137 def ruact_lazy_attribute_class? !!(defined?(ActiveRecord::Base) && self < ActiveRecord::Base) end |
#ruact_props(*attrs) ⇒ Object
Declare which instance methods should be included in the serialized payload.
The loud-omission guarantee is preserved: a name with no corresponding
method still raises a clean ArgumentError. Only the timing of that
check depends on the class:
- PORO — checked eagerly at class-load (macro-invocation) time, as before. A typo'd/absent prop raises immediately.
- ActiveRecord model — ActiveRecord defines its attribute reader
methods lazily (on first instance access), so at macro-invocation time
method_defined?(:title)isfalseeven for a real column. Checking eagerly would either reject a valid model at boot or require a live DB connection at class-load (a Rails anti-pattern). So for a lazy-attribute class the not-yet-defined names are recorded and their loud check is deferred to the firstruact_serialize(viarespond_to?on the instance), where the DB is up. A genuine typo still raises the same cleanArgumentError— just at first render of that model, not at boot.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/ruact/serializable.rb', line 55 def ruact_props(*attrs) deferred = [] attrs.each do |attr| next if method_defined?(attr) # Lazy-attribute (ActiveRecord) class: the reader may still appear on # first instance access. Record it and check loudly on first serialize # instead of failing a valid model at boot. if ruact_lazy_attribute_class? deferred << attr next end raise ArgumentError, "ruact_props: method `#{attr}` is not defined on #{self}" end @ruact_props = attrs @ruact_deferred_props = deferred end |
#ruact_props_list ⇒ Array<Symbol>
Returns the list of declared prop names as symbols. Walks the ancestor chain so subclasses inherit parent declarations.
79 80 81 82 83 84 85 86 87 |
# File 'lib/ruact/serializable.rb', line 79 def ruact_props_list klass = self while klass return klass.instance_variable_get(:@ruact_props) if klass.instance_variable_defined?(:@ruact_props) klass = klass.superclass end [] end |
#ruact_validate_deferred_props!(instance) ⇒ Object
Run the deferred loud check once, on first ruact_serialize. A recorded
name that the instance does not respond_to? (a typo, or a genuinely
absent column) raises the same clean ArgumentError the eager path would.
Memoization keys on the validated deferred list itself (not a bare boolean), so any change to the effective declaration — a re-declaration on this class OR on an ancestor whose props a subclass inherits — is detected and re-validated loudly on the next serialize. Once a given list has been validated it costs one array comparison per serialize.
118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/ruact/serializable.rb', line 118 def ruact_validate_deferred_props!(instance) deferred = ruact_deferred_props_list return if @ruact_deferred_props_validated == deferred deferred.each do |attr| next if instance.respond_to?(attr) raise ArgumentError, "ruact_props: method `#{attr}` is not defined on #{self}" end @ruact_deferred_props_validated = deferred end |