Module: Sessions::EngineHelper
- Defined in:
- app/helpers/sessions/engine_helper.rb
Overview
View helpers for the devices page (and for the host-renderable partials).
Constant Summary collapse
- DEVICE_ICONS =
{ "desktop" => "🖥", "smartphone" => "📱", "tablet" => "📱", "native_ios" => "📱", "native_android" => "📱", "bot" => "🤖" }.freeze
- DEVICE_ICON_NAMES =
Semantic icon names (Heroicons vocabulary — map them onto whatever icon helper your app uses) so custom views don’t re-derive the device_type → icon mapping the gem already knows.
{ "desktop" => "computer-desktop", "smartphone" => "device-phone-mobile", "tablet" => "device-tablet", "native_ios" => "device-phone-mobile", "native_android" => "device-phone-mobile", "bot" => "bug-ant" }.freeze
- EVENT_ICON_NAMES =
{ "login" => "check-circle", "failed_login" => "x-circle", "logout" => "arrow-right-on-rectangle", "revoked" => "no-symbol", "expired" => "clock" }.freeze
Class Method Summary collapse
-
.engine_mount_name ⇒ Object
The name of the route that mounts Sessions::Engine in the host app (“sessions” for a plain mount, the ‘as:` value otherwise).
- .reset_engine_mount_name! ⇒ Object
Instance Method Summary collapse
- #sessions_device_icon(session) ⇒ Object
- #sessions_device_icon_name(session) ⇒ Object
-
#sessions_engine_routes ⇒ Object
The engine’s route proxy when it’s mounted, nil otherwise — partials rendered inside a host that didn’t mount the engine simply omit the revoke buttons.
- #sessions_event_icon_name(event) ⇒ Object
-
#sessions_format_date(date) ⇒ Object
“Signed in May 2, 2026” — localized when the host bundles date formats (rails-i18n or its own locale files), with a safe fallback so a bare host never 500s over a missing ‘date.formats.long`.
- #sessions_format_time(time) ⇒ Object
-
#sessions_last_active_in_words(session) ⇒ Object
“Active now” within the touch window, else “Active 3 minutes ago”.
Class Method Details
.engine_mount_name ⇒ Object
The name of the route that mounts Sessions::Engine in the host app (“sessions” for a plain mount, the ‘as:` value otherwise). Memoized per-process; in development a changed mount name reloads routes and to_prepare re-touches this helper file, clearing the memo.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'app/helpers/sessions/engine_helper.rb', line 74 def self.engine_mount_name return @engine_mount_name if defined?(@engine_mount_name) @engine_mount_name = begin route = Rails.application.routes.routes.find do |candidate| # The mount sits behind a Constraints wrapper; unwrap a bounded # number of times, checking BEFORE each unwrap — Rails::Engine # itself responds to #app (its middleware stack), so an unguarded # `while app.respond_to?(:app)` would walk straight past it. app = candidate.app matched = false 3.times do matched = (app == Sessions::Engine) break if matched || !app.respond_to?(:app) app = app.app end matched end route&.name rescue StandardError nil end end |
.reset_engine_mount_name! ⇒ Object
99 100 101 |
# File 'app/helpers/sessions/engine_helper.rb', line 99 def self.reset_engine_mount_name! remove_instance_variable(:@engine_mount_name) if defined?(@engine_mount_name) end |
Instance Method Details
#sessions_device_icon(session) ⇒ Object
36 37 38 |
# File 'app/helpers/sessions/engine_helper.rb', line 36 def sessions_device_icon(session) DEVICE_ICONS.fetch(session.device_type.to_s, "🌐") end |
#sessions_device_icon_name(session) ⇒ Object
40 41 42 |
# File 'app/helpers/sessions/engine_helper.rb', line 40 def sessions_device_icon_name(session) DEVICE_ICON_NAMES.fetch(session.device_type.to_s, "globe-alt") end |
#sessions_engine_routes ⇒ Object
The engine’s route proxy when it’s mounted, nil otherwise — partials rendered inside a host that didn’t mount the engine simply omit the revoke buttons. The proxy method is named after the mount (‘sessions` by default, or whatever `as:` was given), so it’s DISCOVERED from the host’s named routes rather than assumed.
65 66 67 68 |
# File 'app/helpers/sessions/engine_helper.rb', line 65 def sessions_engine_routes name = Sessions::EngineHelper.engine_mount_name name && respond_to?(name) ? public_send(name) : nil end |
#sessions_event_icon_name(event) ⇒ Object
44 45 46 |
# File 'app/helpers/sessions/engine_helper.rb', line 44 def sessions_event_icon_name(event) EVENT_ICON_NAMES.fetch(event.event.to_s, "information-circle") end |
#sessions_format_date(date) ⇒ Object
“Signed in May 2, 2026” — localized when the host bundles date formats (rails-i18n or its own locale files), with a safe fallback so a bare host never 500s over a missing ‘date.formats.long`.
106 107 108 109 110 |
# File 'app/helpers/sessions/engine_helper.rb', line 106 def sessions_format_date(date) I18n.l(date, format: :long) rescue I18n::MissingTranslationData, I18n::ArgumentError date.strftime("%Y-%m-%d") end |
#sessions_format_time(time) ⇒ Object
112 113 114 115 116 |
# File 'app/helpers/sessions/engine_helper.rb', line 112 def sessions_format_time(time) I18n.l(time, format: :short) rescue I18n::MissingTranslationData, I18n::ArgumentError time.strftime("%Y-%m-%d %H:%M") end |
#sessions_last_active_in_words(session) ⇒ Object
“Active now” within the touch window, else “Active 3 minutes ago”.
49 50 51 52 53 54 55 56 57 58 |
# File 'app/helpers/sessions/engine_helper.rb', line 49 def sessions_last_active_in_words(session) # active_now? owns the window (config.touch_every) — the badge can't # honestly claim more freshness than the throttle records. return t("sessions.devices.active_now") if session.respond_to?(:active_now?) && session.active_now? time = session.last_active_at return nil unless time t("sessions.devices.active_ago", time: time_ago_in_words(time)) end |