Class: ViewComponent::Serializable::Proxy
- Inherits:
-
Object
- Object
- ViewComponent::Serializable::Proxy
- Defined in:
- lib/view_component/serializable/proxy.rb
Overview
A proxy that wraps a component class and its initialization arguments, deferring component instantiation until render time. This allows slot calls and other post-initialize configuration to be captured and replayed, and enables the proxy itself (rather than a live component instance) to be serialized for background jobs (e.g. ActiveJob / Turbo Streams).
Instance Attribute Summary collapse
-
#component_class ⇒ Object
readonly
Returns the value of attribute component_class.
-
#initialize_args ⇒ Object
readonly
Returns the value of attribute initialize_args.
-
#slot_calls ⇒ Object
readonly
Returns the value of attribute slot_calls.
Class Method Summary collapse
-
.deserialize(hash) ⇒ Object
Rebuilds a Proxy from a serialized hash produced by
serialize.
Instance Method Summary collapse
-
#format ⇒ Object
Rails expects us to define
formaton all renderables, but we do not know theformatof a ViewComponent until runtime. -
#initialize(component_class, *args) ⇒ Proxy
constructor
A new instance of Proxy.
- #method_missing(method_name, *args, &block) ⇒ Object
-
#render_in(view_context, &block) ⇒ Object
Implements the Rails renderable interface.
- #respond_to_missing?(method_name, include_private = false) ⇒ Boolean
-
#serialize ⇒ Object
Returns a hash that can be rebuilt into a Proxy instance using
deserialize.
Constructor Details
#initialize(component_class, *args) ⇒ Proxy
Returns a new instance of Proxy.
30 31 32 33 34 35 36 37 38 |
# File 'lib/view_component/serializable/proxy.rb', line 30 def initialize(component_class, *args) if component_class.name.nil? raise UnserializableError, "Cannot serialize anonymous component class #{component_class.inspect}" end @component_class = component_class @initialize_args = args @slot_calls = [] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
49 50 51 52 53 54 55 |
# File 'lib/view_component/serializable/proxy.rb', line 49 def method_missing(method_name, *args, &block) if slot_method?(method_name) capture_slot_call(method_name, args, &block) else super end end |
Instance Attribute Details
#component_class ⇒ Object (readonly)
Returns the value of attribute component_class.
28 29 30 |
# File 'lib/view_component/serializable/proxy.rb', line 28 def component_class @component_class end |
#initialize_args ⇒ Object (readonly)
Returns the value of attribute initialize_args.
28 29 30 |
# File 'lib/view_component/serializable/proxy.rb', line 28 def initialize_args @initialize_args end |
#slot_calls ⇒ Object (readonly)
Returns the value of attribute slot_calls.
28 29 30 |
# File 'lib/view_component/serializable/proxy.rb', line 28 def slot_calls @slot_calls end |
Class Method Details
.deserialize(hash) ⇒ Object
Rebuilds a Proxy from a serialized hash produced by serialize
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/view_component/serializable/proxy.rb', line 12 def self.deserialize(hash) klass = hash["component_class"].safe_constantize raise ArgumentError, "Cannot deserialize unknown component: #{hash["component_class"]}" unless klass args = ActiveJob::Arguments.deserialize(hash["initialize_args"] || []) proxy = new(klass, *args) Array(hash["slot_calls"]).each do |call| method_name = call["method"].to_sym slot_args = ActiveJob::Arguments.deserialize(call["args"]) proxy.public_send(method_name, *slot_args) end proxy end |
Instance Method Details
#format ⇒ Object
Rails expects us to define format on all renderables,
but we do not know the format of a ViewComponent until runtime.
81 82 83 |
# File 'lib/view_component/serializable/proxy.rb', line 81 def format nil end |
#render_in(view_context, &block) ⇒ Object
Implements the Rails renderable interface
42 43 44 45 46 47 |
# File 'lib/view_component/serializable/proxy.rb', line 42 def render_in(view_context, &block) if block raise UnserializableError, "Cannot serialize render_in with a block" end build_component.render_in(view_context) end |
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
58 59 60 |
# File 'lib/view_component/serializable/proxy.rb', line 58 def respond_to_missing?(method_name, include_private = false) slot_method?(method_name) || super end |
#serialize ⇒ Object
Returns a hash that can be rebuilt into a Proxy instance using deserialize
63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/view_component/serializable/proxy.rb', line 63 def serialize serialized_slot_calls = @slot_calls.map do |call| { "method" => call[:method].to_s, "args" => ActiveJob::Arguments.serialize(call[:args]) } end { "component_class" => @component_class.name, "initialize_args" => ActiveJob::Arguments.serialize(@initialize_args), "slot_calls" => serialized_slot_calls } end |