Class: VisitorError

Inherits:
ApplicationRecord
  • Object
show all
Includes:
AASM, Discard::Model, PgSearch::Model, Ransackable
Defined in:
lib/generators/ruby_cms/templates/models/visitor_error.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.log_error(exception, request) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
# File 'lib/generators/ruby_cms/templates/models/visitor_error.rb', line 47

def self.log_error(exception, request)
  err = create!(
    **base_request_attrs(request),
    **exception_attrs(exception),
    request_params: sanitize_params(request.params)
  )
  notify_admins(err)
  err
rescue StandardError => e
  Rails.logger.error "Failed to log visitor error: #{e.message}"
end

.log_routing_error(request) ⇒ Object

Log routing errors (404s) from catch-all route. Called by RubyCms::ErrorsController#not_found



75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/generators/ruby_cms/templates/models/visitor_error.rb', line 75

def self.log_routing_error(request)
  return if Rails.env.development?
  return if request.path.start_with?("/admin")

  create!(
    **base_request_attrs(request),
    error_class: "ActionController::RoutingError",
    error_message: routing_error_message(request),
    backtrace: nil,
    request_params: nil
  )
rescue StandardError => e
  Rails.logger.error "Failed to log routing error: #{e.message}"
end

.notify_admins(err) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/generators/ruby_cms/templates/models/visitor_error.rb', line 59

def self.notify_admins(err)
  return unless defined?(::AdminAlertNotifier)

  AdminAlertNotifier.with(
    record: err,
    kind: :error,
    title: err.error_class.to_s,
    body: "#{err.request_path}#{err.error_message.to_s.truncate(120)}",
    url: Rails.application.routes.url_helpers.admin_visitor_error_path(err)
  ).deliver(User.where(admin: true))
rescue StandardError => e
  Rails.logger.warn("[VisitorError] notifier failed: #{e.class}: #{e.message}")
end

Instance Method Details

#browser_infoObject



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/generators/ruby_cms/templates/models/visitor_error.rb', line 104

def browser_info
  return "Unknown" if user_agent.blank?

  case user_agent
  when /Chrome/ then "Chrome"
  when /Firefox/ then "Firefox"
  when /Safari(?!.*Chrome)/ then "Safari"
  when /Edge/ then "Edge"
  else "Other"
  end
end

#codepathObject

Returns the code path: backtrace for exceptions, or synthetic path for routing errors



91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/generators/ruby_cms/templates/models/visitor_error.rb', line 91

def codepath
  if backtrace.present?
    backtrace
  elsif error_class == "ActionController::RoutingError"
    <<~TEXT.strip
      Request → Router (no matching route) → RubyCms::ErrorsController#not_found
      (Routing errors don't generate stack traces; the request never reached a controller action.)
    TEXT
  else
    "No stack trace available."
  end
end