Class: Sessions::Generators::InstallGenerator
- Inherits:
-
Rails::Generators::Base
- Object
- Rails::Generators::Base
- Sessions::Generators::InstallGenerator
- Includes:
- ActiveRecord::Generators::Migration
- Defined in:
- lib/generators/sessions/install_generator.rb
Overview
‘rails generate sessions:install` — detects the app’s auth stack and writes the right pieces:
Rails 8 omakase auth → ONE migration extending the existing
`sessions` table (the Devise-extends-`users` precedent) + the
events table. The generated Session model stays untouched.
Devise → the Rails-8-shaped `sessions` table (plus our columns,
with token_digest populated by the Warden adapter) + the events
table + a 3-line app-owned Session shell model. The app converges
on the omakase shape: a future Devise→Rails-auth migration finds
its table already waiting.
Neither → aborts with guidance. The gem decorates a session of
record; it never creates one.
Plus, in every mode: the annotated initializer, the SessionsSweepJob (host-scheduled — the trackdown/nondisposable pattern), and the post-install steps.
Class Method Summary collapse
Instance Method Summary collapse
- #check_for_conflicting_sessions_table! ⇒ Object
- #create_initializer ⇒ Object
- #create_migration_files ⇒ Object
-
#create_session_model ⇒ Object
Devise mode only: the app-owned 3-line shell.
- #create_sweep_job ⇒ Object
- #detect_auth_stack! ⇒ Object
- #display_post_install_message ⇒ Object
Class Method Details
.next_migration_number(dir) ⇒ Object
38 39 40 |
# File 'lib/generators/sessions/install_generator.rb', line 38 def self.next_migration_number(dir) ActiveRecord::Generators::Base.next_migration_number(dir) end |
Instance Method Details
#check_for_conflicting_sessions_table! ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/generators/sessions/install_generator.rb', line 65 def check_for_conflicting_sessions_table! return unless conflicting_sessions_table? raise Thor::Error, <<~MSG ❌ A `#{table_name}` table exists but doesn't look like the Rails 8 auth shape (no user reference + ip_address + user_agent columns) — most likely a legacy table (activerecord-session_store?). Two ways forward: 1. Re-run with a different model: rails g sessions:install --model=SessionRecord (and set `config.session_class = "SessionRecord"` in the initializer) 2. Migrate/rename the legacy table first, then re-run. MSG end |
#create_initializer ⇒ Object
102 103 104 |
# File 'lib/generators/sessions/install_generator.rb', line 102 def create_initializer template "initializer.rb", "config/initializers/sessions.rb" end |
#create_migration_files ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/generators/sessions/install_generator.rb', line 81 def create_migration_files if adopt_existing_table? migration_template "add_sessions_columns.rb.erb", File.join(db_migrate_path, "add_sessions_columns_to_#{table_name}.rb") else migration_template "create_sessions.rb.erb", File.join(db_migrate_path, "create_#{table_name}.rb") end migration_template "create_sessions_events.rb.erb", File.join(db_migrate_path, "create_sessions_events.rb") end |
#create_session_model ⇒ Object
Devise mode only: the app-owned 3-line shell. All gem logic lives in the Sessions::Model concern, so this file never goes stale.
96 97 98 99 100 |
# File 'lib/generators/sessions/install_generator.rb', line 96 def create_session_model return if adopt_existing_table? || session_model_file? template "session.rb.erb", "app/models/#{model_name.underscore}.rb" end |
#create_sweep_job ⇒ Object
106 107 108 |
# File 'lib/generators/sessions/install_generator.rb', line 106 def create_sweep_job template "sessions_sweep_job.rb", "app/jobs/sessions_sweep_job.rb" end |
#detect_auth_stack! ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/generators/sessions/install_generator.rb', line 42 def detect_auth_stack! # Detection is MEMOIZED here, before anything is generated: # create_session_model writes app/models/session.rb a few steps # below, which would otherwise flip omakase_detected? mid-run and # make the post-install message claim the wrong stack. adopt_existing_table? detected_stack return if omakase_detected? || devise_detected? raise Thor::Error, <<~MSG ❌ sessions couldn't detect an authentication system to decorate. The gem tracks the session of record your app already has — it never creates one. Set one up first: • Rails 8+ omakase auth: bin/rails generate authentication • or Devise: https://github.com/heartcombo/devise …then run `rails generate sessions:install` again. MSG end |
#display_post_install_message ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/generators/sessions/install_generator.rb', line 110 def say "\n🔐 The `sessions` gem has been installed#{" (#{detected_stack} detected)" if detected_stack}.", :green say "\nTo complete the setup:" migrate_verb = adopt_existing_table? ? "enrich your sessions table" : "create the sessions tables" say " 1. Run 'rails db:migrate' to #{migrate_verb}." say " ⚠️ You must run migrations before starting your app!", :yellow say " 2. Add the macro to your auth model:" say " class User < ApplicationRecord" say " has_sessions" say " end" say " 3. Mount the \"Your devices\" page wherever you want it to live:" say " # config/routes.rb" if devise_detected? && !omakase_detected? say " authenticate :user do" say " mount Sessions::Engine => \"/settings/sessions\"" say " end" else say " mount Sessions::Engine => \"/settings/sessions\"" end say " 4. Schedule the sweep (retention purge + cap + opt-in expiry):" say " # config/recurring.yml (Solid Queue)" say " production:" say " sessions_sweep:" say " class: SessionsSweepJob" say " schedule: every day at 4am" say "\nEvery login now lands on the devices page and in the trail:" say " current_user.sessions.active # live devices, revocable" say " current_user.session_history # the trail — logins, failures, revocations" say "\nEvery session, every device, every login — tracked. 🔐✨\n", :green end |