Exception: ReactOnRails::SmartError

Inherits:
Error
  • Object
show all
Defined in:
lib/react_on_rails/smart_error.rb

Overview

SmartError provides enhanced error messages with actionable suggestions rubocop:disable Metrics/ClassLength

Constant Summary collapse

DOCS_BASE_URL =
"https://reactonrails.com/docs/reference/error-reference"
UNKNOWN_ERROR_DEFINITION =
{
  code: "ROR000",
  title: "Unknown Error",
  summary: "An unexpected SmartError type was raised.",
  sample_context: {}.freeze
}.freeze
ERROR_DEFINITIONS =
{
  component_not_registered: {
    code: "ROR001",
    title: "Component Not Registered",
    summary: "React on Rails could not find the component in the client-side component registry.",
    sample_context: {
      component_name: "ProductCard",
      available_components: %w[ProductList ProductDetails UserProfile].freeze
    }.freeze
  }.freeze,
  missing_auto_loaded_bundle: {
    code: "ROR002",
    title: "Auto-loaded Bundle Missing",
    summary: "A component is configured for auto-loading, but its generated bundle is missing.",
    sample_context: {
      component_name: "Dashboard",
      expected_path: "app/javascript/packs/generated/Dashboard.js"
    }.freeze
  }.freeze,
  missing_auto_loaded_store_bundle: {
    code: "ROR003",
    title: "Auto-loaded Store Bundle Missing",
    summary: "A Redux store is configured for auto-loading, but its generated store bundle is missing.",
    sample_context: {
      component_name: "AppStore",
      expected_path: "app/javascript/packs/generated/AppStore.js"
    }.freeze
  }.freeze,
  hydration_mismatch: {
    code: "ROR004",
    title: "Hydration Mismatch",
    summary: "The server-rendered HTML does not match the React tree rendered in the browser.",
    sample_context: {
      component_name: "UserProfile"
    }.freeze
  }.freeze,
  server_rendering_error: {
    code: "ROR005",
    title: "Server Rendering Failed",
    summary: "Server-side rendering failed while rendering a React component.",
    sample_context: {
      component_name: "ComplexComponent",
      error_message: "window is not defined"
    }.freeze
  }.freeze,
  redux_store_not_found: {
    code: "ROR006",
    title: "Redux Store Not Found",
    summary: "A component requested a Redux store that was not registered.",
    sample_context: {
      store_name: "AppStore",
      available_stores: %w[UserStore ProductStore].freeze
    }.freeze
  }.freeze,
  configuration_error: {
    code: "ROR007",
    title: "Configuration Error",
    summary: "React on Rails detected invalid or incomplete configuration.",
    sample_context: {
      details: "config.server_bundle_js_file points to a missing file"
    }.freeze
  }.freeze
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(error_type:, component_name: nil, props: nil, js_code: nil, **additional_context) ⇒ SmartError

Returns a new instance of SmartError.



101
102
103
104
105
106
107
108
109
110
# File 'lib/react_on_rails/smart_error.rb', line 101

def initialize(error_type:, component_name: nil, props: nil, js_code: nil, **additional_context)
  @error_type = error_type
  @component_name = component_name
  @props = props
  @js_code = js_code
  @additional_context = additional_context

  message = build_error_message
  super(message)
end

Instance Attribute Details

#additional_contextObject (readonly)

Returns the value of attribute additional_context.



99
100
101
# File 'lib/react_on_rails/smart_error.rb', line 99

def additional_context
  @additional_context
end

#component_nameObject (readonly)

Returns the value of attribute component_name.



99
100
101
# File 'lib/react_on_rails/smart_error.rb', line 99

def component_name
  @component_name
end

#error_typeObject (readonly)

Returns the value of attribute error_type.



99
100
101
# File 'lib/react_on_rails/smart_error.rb', line 99

def error_type
  @error_type
end

#js_codeObject (readonly)

Returns the value of attribute js_code.



99
100
101
# File 'lib/react_on_rails/smart_error.rb', line 99

def js_code
  @js_code
end

#propsObject (readonly)

Returns the value of attribute props.



99
100
101
# File 'lib/react_on_rails/smart_error.rb', line 99

def props
  @props
end

Class Method Details

.docs_url_for(error_type) ⇒ Object



88
89
90
91
92
93
# File 'lib/react_on_rails/smart_error.rb', line 88

def self.docs_url_for(error_type)
  normalized_error_type = normalize_error_type(error_type)
  return unless error_definitions.key?(normalized_error_type)

  "#{DOCS_BASE_URL}##{error_definition_for(normalized_error_type).fetch(:code).downcase}"
end

.error_definition_for(error_type) ⇒ Object



84
85
86
# File 'lib/react_on_rails/smart_error.rb', line 84

def self.error_definition_for(error_type)
  ERROR_DEFINITIONS.fetch(normalize_error_type(error_type), UNKNOWN_ERROR_DEFINITION)
end

.error_definitionsObject



80
81
82
# File 'lib/react_on_rails/smart_error.rb', line 80

def self.error_definitions
  ERROR_DEFINITIONS
end

.normalize_error_type(error_type) ⇒ Object



95
96
97
# File 'lib/react_on_rails/smart_error.rb', line 95

def self.normalize_error_type(error_type)
  error_type.respond_to?(:to_sym) ? error_type.to_sym : error_type
end

Instance Method Details

#codeObject



112
113
114
# File 'lib/react_on_rails/smart_error.rb', line 112

def code
  error_definition.fetch(:code)
end

#docs_urlObject



116
117
118
119
120
# File 'lib/react_on_rails/smart_error.rb', line 116

def docs_url
  return unless self.class.error_definitions.key?(normalized_error_type)

  self.class.docs_url_for(normalized_error_type)
end

#solutionObject



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/react_on_rails/smart_error.rb', line 122

def solution
  case normalized_error_type
  when :component_not_registered
    component_not_registered_solution
  when :missing_auto_loaded_bundle
    missing_auto_loaded_bundle_solution
  when :missing_auto_loaded_store_bundle
    missing_auto_loaded_store_bundle_solution
  when :hydration_mismatch
    hydration_mismatch_solution
  when :server_rendering_error
    server_rendering_error_solution
  when :redux_store_not_found
    redux_store_not_found_solution
  when :configuration_error
    configuration_error_solution
  else
    default_solution
  end
end