Class: TurboBoost::Commands::State

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/turbo_boost/commands/state.rb

Overview

Class that encapsulates all the various forms of state.

  1. page - Client-side transient page state used for rendering remembered element attributes
  2. now - Server-side state for the current render only (discarded after rendering)
  3. signed - Server-side state that persists across renders (state that was used for the last server-side render)
  4. unsigned - Client-side state (optimistic client-side changes)
  5. current - Combined server-side state (signed + now)
  6. all - All state except unsigned (signed + now + page)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(payload = {}) ⇒ State

Returns a new instance of State.



18
19
20
21
22
23
24
25
26
# File 'lib/turbo_boost/commands/state.rb', line 18

def initialize(payload = {})
  payload = payload.respond_to?(:to_unsafe_h) ? payload.to_unsafe_h : payload.to_h
  payload = payload.with_indifferent_access

  @now = {}.with_indifferent_access
  @page = payload.fetch(:page, {}).with_indifferent_access
  @signed = TurboBoost::Commands::StateStore.new(payload.fetch(:signed, {}))
  @unsigned = payload.fetch(:unsigned, {}).with_indifferent_access
end

Instance Attribute Details

#nowHashWithIndifferentAccess (readonly)

Note:

Discarded after rendering

Server-side state for the current render only (similar to flash.now)

Returns:

  • (HashWithIndifferentAccess)


35
36
37
# File 'lib/turbo_boost/commands/state.rb', line 35

def now
  @now
end

#pageHashWithIndifferentAccess (readonly)

Client-side transient page state used for rendering remembered element attributes

Returns:

  • (HashWithIndifferentAccess)


30
31
32
# File 'lib/turbo_boost/commands/state.rb', line 30

def page
  @page
end

#signedTurboBoost::Commands::StateStore (readonly)

Server-side state that persists across renders This is the state that was used for the last server-side render (untampered by the client)



40
41
42
# File 'lib/turbo_boost/commands/state.rb', line 40

def signed
  @signed
end

#unsignedHashWithIndifferentAccess (readonly) Also known as: optimistic

Note:

There is a hook on Command instances to resolve state Command#resolve_state, where Command authors can determine how to properly handle optimistic client-side state.

Client-side state (optimistic client-side changes)

Returns:

  • (HashWithIndifferentAccess)


49
50
51
# File 'lib/turbo_boost/commands/state.rb', line 49

def unsigned
  @unsigned
end

Instance Method Details

#allHashWithIndifferentAccess

All state except unsigned (page + current).

Returns:

  • (HashWithIndifferentAccess)


62
63
64
# File 'lib/turbo_boost/commands/state.rb', line 62

def all
  page.merge current
end

#cache_keyObject

Returns a cache key representing "all" state



67
68
69
# File 'lib/turbo_boost/commands/state.rb', line 67

def cache_key
  "TurboBoost::Commands::State/#{Digest::MD5.base64digest(all.to_s)}"
end

#currentHashWithIndifferentAccess

Combined server-side state (signed + now)

Returns:

  • (HashWithIndifferentAccess)


54
55
56
# File 'lib/turbo_boost/commands/state.rb', line 54

def current
  signed.to_h.merge now
end

#tag_options(options = {}) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/turbo_boost/commands/state.rb', line 82

def tag_options(options = {})
  return options unless options.is_a?(Hash)

  options = options.deep_symbolize_keys
  return options unless options.key?(:turbo_boost)

  config = options.delete(:turbo_boost)
  return options unless config.is_a?(Hash)

  attributes = config[:remember]
  return options if attributes.blank?

  attributes = begin
    attributes.is_a?(Array) ? attributes : JSON.parse(attributes.to_s)
  rescue
    raise TurboBoost::Commands::StateError,
      "Invalid `turbo_boost` options! `attributes` must be an Array of attributes to remember!"
  end
  attributes ||= []
  attributes.map!(&:to_s).uniq!
  return options if attributes.blank?

  if options[:id].blank?
    raise TurboBoost::Commands::StateError, "An `id` attribute is required for remembering state!"
  end

  options[:aria] ||= {}
  options[:data] ||= {}
  options[:data][:turbo_boost_state_attributes] = attributes.to_json

  attributes.each do |name|
    value = page.dig(options[:id], name)
    case name
    in String if name.start_with?("aria-") then options[:aria][name.delete_prefix("aria-").to_sym] = value
    in String if name.start_with?("data-") then options[:data][name.delete_prefix("data-").to_sym] = value
    else options[name.to_sym] = value
    end
  end

  options
end

#to_jsonString

A JSON representation of state that can be sent to the client

Includes the following keys:

  • signed - The signed state (String)
  • unsigned - The unsigned state (Hash)

Returns:

  • (String)


78
79
80
# File 'lib/turbo_boost/commands/state.rb', line 78

def to_json
  {signed: signed.to_sgid_param, unsigned: signed.to_h}.to_json(camelize: false)
end