Class: Rhales::Hydrator

Inherits:
Object
  • Object
show all
Defined in:
lib/rhales/hydrator.rb

Overview

Data Hydrator for RSFC client-side data injection

RSFC Security Model: Server-to-Client Security Boundary

The Hydrator enforces a critical security boundary between server and client:

Server Side (Template Rendering)

  • Templates have FULL server context access (like ERB/HAML)
  • Can access user objects, database connections, internal APIs
  • Can access secrets, configuration, authentication state
  • Can process sensitive business logic

Client Side (Data Hydration)

  • Only data declared in section reaches the browser
  • Creates explicit allowlist like designing a REST API
  • Server-side variable interpolation processes secrets safely
  • JSON serialization validates data structure

Process Flow

  1. Server processes section with full context access
  2. Variables like {user{user.name} are interpolated server-side
  3. Result is serialized as JSON and sent to client
  4. Client receives only the processed, safe data

Example

```rue

{ "user_name": "{user{user.name}", // Safe: just the name "theme": "{user{user.theme_preference}" // Safe: just the theme }

```

Server template can access {user{user.admin?} and {internal_config}, but client only gets the declared user_name and theme values.

This creates an API-like boundary where data is serialized once and parsed once, enforcing the same security model as REST endpoints.

Note: With the new two-pass architecture, the Hydrator’s role is greatly simplified. All data merging happens server-side in the HydrationDataAggregator, so this class only handles JSON generation for individual templates (used during the aggregation phase).

Defined Under Namespace

Classes: HydrationError, JSONSerializationError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parser, context) ⇒ Hydrator

Returns a new instance of Hydrator.



57
58
59
60
61
# File 'lib/rhales/hydrator.rb', line 57

def initialize(parser, context)
  @parser           = parser
  @context          = context
  @window_attribute = parser.window_attribute || 'data'
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



55
56
57
# File 'lib/rhales/hydrator.rb', line 55

def context
  @context
end

#parserObject (readonly)

Returns the value of attribute parser.



55
56
57
# File 'lib/rhales/hydrator.rb', line 55

def parser
  @parser
end

#window_attributeObject (readonly)

Returns the value of attribute window_attribute.



55
56
57
# File 'lib/rhales/hydrator.rb', line 55

def window_attribute
  @window_attribute
end

Class Method Details

.generate(parser, context) ⇒ Object

Convenience method to generate hydration HTML DEPRECATED: Use the two-pass rendering architecture instead



125
126
127
128
# File 'lib/rhales/hydrator.rb', line 125

def generate(parser, context)
  warn '[DEPRECATION] Hydrator.generate is deprecated. Use the two-pass rendering architecture instead.'
  new(parser, context).generate_hydration_html
end

.generate_data_hash(parser, context) ⇒ Object

Generate data hash (for internal processing)



136
137
138
# File 'lib/rhales/hydrator.rb', line 136

def generate_data_hash(parser, context)
  new(parser, context).processed_data_hash
end

.generate_json(parser, context) ⇒ Object

Generate only JSON data (for testing or API endpoints)



131
132
133
# File 'lib/rhales/hydrator.rb', line 131

def generate_json(parser, context)
  new(parser, context).process_data_section
end

Instance Method Details

#build_template_pathObject (private)

Build template path with line number for error reporting (Used by HydrationDataAggregator)



111
112
113
114
115
116
117
118
119
120
# File 'lib/rhales/hydrator.rb', line 111

def build_template_path
  data_node   = @parser.section_node('data')
  line_number = data_node ? data_node.location.start_line : 1

  if @parser.file_path
    "#{@parser.file_path}:#{line_number}"
  else
    "<inline>:#{line_number}"
  end
end

#generate_hydration_htmlObject

This method is now deprecated in favor of the two-pass architecture It’s kept for backward compatibility but will be removed in future versions



65
66
67
68
# File 'lib/rhales/hydrator.rb', line 65

def generate_hydration_html
  warn '[DEPRECATION] Hydrator#generate_hydration_html is deprecated. Use the two-pass rendering architecture instead.'
  ''
end

#process_data_sectionObject

Process section and return JSON string



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/rhales/hydrator.rb', line 71

def process_data_section
  data_content = @parser.section('data')
  return '{}' unless data_content

  # Process variable interpolations in the data section
  processed_content = process_data_variables(data_content)

  # Validate and return JSON
  validate_json(processed_content)
  processed_content
rescue JSON::ParserError => ex
  raise JSONSerializationError, "Invalid JSON in data section: #{ex.message}"
end

#process_data_variables(data_content) ⇒ Object (private)

Process variable interpolations in data section Uses Rhales consistently for all template processing



97
98
99
100
# File 'lib/rhales/hydrator.rb', line 97

def process_data_variables(data_content)
  rhales = TemplateEngine.new(data_content, @context)
  rhales.render
end

#processed_data_hashObject

Get processed data as Ruby hash (for internal use)



86
87
88
89
90
91
# File 'lib/rhales/hydrator.rb', line 86

def processed_data_hash
  json_string = process_data_section
  JSON.parse(json_string)
rescue JSON::ParserError => ex
  raise JSONSerializationError, "Cannot parse processed data as JSON: #{ex.message}"
end

#validate_json(json_string) ⇒ Object (private)

Validate that processed content is valid JSON



103
104
105
106
107
# File 'lib/rhales/hydrator.rb', line 103

def validate_json(json_string)
  JSON.parse(json_string)
rescue JSON::ParserError => ex
  raise JSONSerializationError, "Processed data section is not valid JSON: #{ex.message}"
end