Class: RailsOnboarding::SessionManager

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_onboarding/session_manager.rb

Overview

Session Manager Handles browser refresh/navigation during onboarding Persists onboarding state to allow seamless resume

Constant Summary collapse

SESSION_KEY =
"rails_onboarding_session"
SESSION_TIMEOUT =
2.hours

Class Method Summary collapse

Class Method Details

.clear_session(user, session) ⇒ Object

Clear session data



141
142
143
144
145
146
147
148
# File 'lib/rails_onboarding/session_manager.rb', line 141

def clear_session(user, session)
  session.delete(SESSION_KEY)

  if user.respond_to?(:onboarding_session_data=)
    user.onboarding_session_data = nil
    user.save(validate: false) rescue nil
  end
end

.clear_step_data(user, session, step_name) ⇒ Object

Clear step data



110
111
112
113
114
# File 'lib/rails_onboarding/session_manager.rb', line 110

def clear_step_data(user, session, step_name)
  session_data = initialize_session(user, session)
  session_data[:form_data]&.delete(step_name.to_sym)
  persist_session(user, session, session_data)
end

.create_session(user) ⇒ Object

Create a new onboarding session



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/rails_onboarding/session_manager.rb', line 31

def create_session(user)
  {
    user_id: user.id,
    started_at: Time.current.iso8601,
    last_activity_at: Time.current.iso8601,
    current_step: user.onboarding_current_step,
    step_history: [],
    form_data: {},
    progress: user.onboarding_progress,
    session_id: SecureRandom.uuid
  }
end

.get_step_data(user, session, step_name) ⇒ Object

Get saved form data for a step



101
102
103
104
105
106
107
# File 'lib/rails_onboarding/session_manager.rb', line 101

def get_step_data(user, session, step_name)
  session_data = restore_session(user, session)
  return nil unless session_data

  step_data = session_data.dig(:form_data, step_name.to_sym)
  step_data ? step_data[:data] : nil
end

.initialize_session(user, session) ⇒ Hash

Initialize or restore onboarding session

Parameters:

  • user (User)

    The current user

  • session (ActionDispatch::Session)

    Rails session

Returns:

  • (Hash)

    Session data



15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/rails_onboarding/session_manager.rb', line 15

def initialize_session(user, session)
  session_data = restore_session(user, session)

  # If no existing session or expired, create new one
  if session_data.nil? || session_expired?(session_data)
    session_data = create_session(user)
  end

  # Update last activity
  session_data[:last_activity_at] = Time.current.iso8601
  persist_session(user, session, session_data)

  session_data
end

.persist_session(user, session, session_data) ⇒ Object

Persist session to storage



57
58
59
60
61
62
63
64
65
66
# File 'lib/rails_onboarding/session_manager.rb', line 57

def persist_session(user, session, session_data)
  # Store in Rails session
  session[SESSION_KEY] = session_data.to_json

  # Also persist to database if available
  if user.respond_to?(:onboarding_session_data=)
    user.onboarding_session_data = session_data.to_json
    user.save(validate: false) rescue nil
  end
end

.previous_step(user, session) ⇒ Object

Get previous step from history



124
125
126
127
128
# File 'lib/rails_onboarding/session_manager.rb', line 124

def previous_step(user, session)
  history = step_history(user, session)
  return nil if history.empty?
  history.last[:step]
end

.restore_session(user, session) ⇒ Object

Restore session from storage



45
46
47
48
49
50
51
52
53
54
# File 'lib/rails_onboarding/session_manager.rb', line 45

def restore_session(user, session)
  # Try session storage first
  session_data = session[SESSION_KEY]
  return parse_session_data(session_data) if session_data

  # Try database storage if available
  if user.respond_to?(:onboarding_session_data)
    parse_session_data(user.onboarding_session_data)
  end
end

.resume_session(user, session) ⇒ Object

Resume from saved session



151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/rails_onboarding/session_manager.rb', line 151

def resume_session(user, session)
  session_data = restore_session(user, session)

  return nil if session_data.nil? || session_expired?(session_data)

  # Sync user state with session
  if user.onboarding_current_step != session_data[:current_step]
    user.update(onboarding_current_step: session_data[:current_step]) rescue nil
  end

  session_data
end

.save_step_data(user, session, step_name, data) ⇒ Object

Save form data for a step



90
91
92
93
94
95
96
97
98
# File 'lib/rails_onboarding/session_manager.rb', line 90

def save_step_data(user, session, step_name, data)
  session_data = initialize_session(user, session)
  session_data[:form_data] ||= {}
  session_data[:form_data][step_name.to_sym] = {
    data: data,
    saved_at: Time.current.iso8601
  }
  persist_session(user, session, session_data)
end

.session_expired?(session_data) ⇒ Boolean

Check if session is expired

Returns:

  • (Boolean)


131
132
133
134
135
136
137
138
# File 'lib/rails_onboarding/session_manager.rb', line 131

def session_expired?(session_data)
  return true unless session_data&.dig(:last_activity_at)

  last_activity = Time.parse(session_data[:last_activity_at])
  Time.current - last_activity > SESSION_TIMEOUT
rescue StandardError
  true
end

.session_id(user, session) ⇒ Object

Get session ID for analytics tracking



165
166
167
168
# File 'lib/rails_onboarding/session_manager.rb', line 165

def session_id(user, session)
  session_data = restore_session(user, session)
  session_data&.dig(:session_id) || SecureRandom.uuid
end

.step_history(user, session) ⇒ Object

Get step history



117
118
119
120
121
# File 'lib/rails_onboarding/session_manager.rb', line 117

def step_history(user, session)
  session_data = restore_session(user, session)
  return [] unless session_data
  session_data[:step_history] || []
end

.update_step(user, session, step_name) ⇒ Object

Update current step in session



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/rails_onboarding/session_manager.rb', line 69

def update_step(user, session, step_name)
  session_data = initialize_session(user, session)

  # Add previous step to history
  if session_data[:current_step] && session_data[:current_step] != step_name
    session_data[:step_history] ||= []
    session_data[:step_history] << {
      step: session_data[:current_step],
      completed_at: Time.current.iso8601
    }
  end

  session_data[:current_step] = step_name.to_s
  session_data[:progress] = user.onboarding_progress
  session_data[:last_activity_at] = Time.current.iso8601

  persist_session(user, session, session_data)
  session_data
end