Class: RailsOnboarding::Engine

Inherits:
Rails::Engine
  • Object
show all
Defined in:
lib/rails_onboarding/engine.rb

Class Method Summary collapse

Class Method Details

.configure_importmap_assets(app) ⇒ Object

Configure Importmap-based asset loading



137
138
139
140
141
142
143
144
# File 'lib/rails_onboarding/engine.rb', line 137

def self.configure_importmap_assets(app)
  # Importmap handles JavaScript, but we still need stylesheets
  if app.config.respond_to?(:assets)
    app.config.assets.paths << root.join("app", "assets", "stylesheets")
  end

  Rails.logger.info "RailsOnboarding: Configured Importmap asset loading"
end

.configure_modern_bundler_assets(app) ⇒ Object

Configure for modern bundlers (ESBuild, Webpack, etc.)



147
148
149
150
151
152
153
154
155
# File 'lib/rails_onboarding/engine.rb', line 147

def self.configure_modern_bundler_assets(app)
  # Add asset paths if assets config is available
  if app.config.respond_to?(:assets)
    app.config.assets.paths << root.join("app", "assets", "stylesheets")
    app.config.assets.paths << root.join("app", "assets", "javascripts")
  end

  Rails.logger.info "RailsOnboarding: Configured for modern bundler (ESBuild/Webpack/etc.)"
end

.configure_propshaft_assets(app) ⇒ Object

Configure Propshaft-based asset pipeline



128
129
130
131
132
133
134
# File 'lib/rails_onboarding/engine.rb', line 128

def self.configure_propshaft_assets(app)
  # Propshaft automatically includes all assets from engine paths
  app.config.assets.paths << root.join("app", "assets", "stylesheets")
  app.config.assets.paths << root.join("app", "assets", "javascripts")

  Rails.logger.info "RailsOnboarding: Configured Propshaft asset pipeline"
end

.configure_sprockets_assets(app) ⇒ Object

Configure Sprockets-based asset pipeline



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/rails_onboarding/engine.rb', line 104

def self.configure_sprockets_assets(app)
  app.config.assets.paths << root.join("app", "assets", "stylesheets")
  app.config.assets.paths << root.join("app", "assets", "javascripts")

  # Precompile all CSS and JavaScript assets
  app.config.assets.precompile += %w[
    rails_onboarding/application.css
    rails_onboarding/tooltips.css
    rails_onboarding/utilities.css
    rails_onboarding/accessibility.css
    rails_onboarding/tour.css
    rails_onboarding/mobile.css
    rails_onboarding/milestones.css
    rails_onboarding/progressive_disclosure.css
    rails_onboarding/flash_messages.css
    rails_onboarding/admin.css
    rails_onboarding/application.js
    rails_onboarding/*.js
  ]

  Rails.logger.info "RailsOnboarding: Configured Sprockets asset pipeline"
end

.detect_asset_pipeline(app) ⇒ Object

Detect which asset pipeline is being used



91
92
93
94
95
96
97
98
99
100
101
# File 'lib/rails_onboarding/engine.rb', line 91

def self.detect_asset_pipeline(app)
  if defined?(Propshaft)
    :propshaft
  elsif defined?(Sprockets) && app.config.respond_to?(:assets)
    :sprockets
  elsif importmap_available?(app)
    :importmap
  else
    :modern_bundler
  end
end

.importmap_available?(app) ⇒ Boolean

Returns:

  • (Boolean)


172
173
174
175
176
# File 'lib/rails_onboarding/engine.rb', line 172

def self.importmap_available?(app)
  defined?(Importmap) &&
    defined?(Importmap::Map) &&
    app.config.respond_to?(:importmap)
end

.setup_importmap_integration(app) ⇒ Object



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/rails_onboarding/engine.rb', line 178

def self.setup_importmap_integration(app)
  begin
    importmap_path = root.join("config", "importmap.rb")
    if File.exist?(importmap_path)
      # importmap-rails draws app.config.importmap.paths into app.importmap
      # during its own "importmap" initializer, which has already run by the
      # time this after_initialize hook fires - appending to that array here
      # would be a no-op. Draw directly into the live map instead so the
      # engine's pins actually get registered.
      app.importmap.draw(importmap_path)
      Rails.logger.info "RailsOnboarding: Importmap integration enabled"
    end
  rescue => e
    Rails.logger.warn "RailsOnboarding: Could not setup importmap integration: #{e.message}"
  end
end

.setup_stimulus_integration(app) ⇒ Object



163
164
165
166
167
168
169
170
# File 'lib/rails_onboarding/engine.rb', line 163

def self.setup_stimulus_integration(app)
  begin
    app.config.stimulus.paths << root.join("app", "assets", "javascripts", "rails_onboarding")
    Rails.logger.info "RailsOnboarding: Stimulus integration enabled"
  rescue => e
    Rails.logger.warn "RailsOnboarding: Could not setup Stimulus integration: #{e.message}"
  end
end

.stimulus_available?(app) ⇒ Boolean

Returns:

  • (Boolean)


157
158
159
160
161
# File 'lib/rails_onboarding/engine.rb', line 157

def self.stimulus_available?(app)
  defined?(StimulusRails) &&
    app.config.respond_to?(:stimulus) &&
    app.config.stimulus.respond_to?(:paths)
end

.warn_if_controllers_stale(app) ⇒ Object

Warn (dev only) when a bundler app's vendored copy of the Stimulus controllers has drifted from the installed gem version. rails g rails_onboarding:update stamps the copy with a version marker; we compare that marker to RailsOnboarding::VERSION. Checks the flat layout (controllers copied straight into controllers/, the current recommendation) as well as the legacy controllers/rails_onboarding/ subfolder so an un-migrated app still gets nudged. Never raises - a warning must not take down boot.



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/rails_onboarding/engine.rb', line 202

def self.warn_if_controllers_stale(app)
  controllers = app.root.join("app", "javascript", "controllers")
  return unless Dir.exist?(controllers)

  legacy = controllers.join("rails_onboarding")
  marker =
    if File.exist?(controllers.join(".rails_onboarding_version"))
      controllers.join(".rails_onboarding_version")
    elsif File.exist?(legacy.join(".rails_onboarding_version"))
      legacy.join(".rails_onboarding_version")
    end

  # Is a copy vendored here at all? A marker, the legacy subfolder, or a
  # signature controller (onboarding_controller.js is distinctively ours,
  # so it won't be confused with a host controller in the flat layout).
  vendored = marker ||
             Dir.exist?(legacy) ||
             File.exist?(controllers.join("onboarding_controller.js"))
  return unless vendored

  current = RailsOnboarding::VERSION
  cmd     = "bin/rails generate rails_onboarding:update"

  unless marker
    Rails.logger.warn(
      "[rails_onboarding] Vendored Stimulus controllers have no version marker, so " \
      "they may be stale relative to gem v#{current}. Run `#{cmd}` to re-sync and " \
      "stamp them, then rebuild your JS bundle."
    )
    return
  end

  stamped = File.read(marker).strip
  if stamped != current
    Rails.logger.warn(
      "[rails_onboarding] Vendored Stimulus controllers were generated for v#{stamped} " \
      "but the gem is v#{current}. Run `#{cmd}` to re-sync, then rebuild your JS bundle."
    )
  end
rescue => e
  Rails.logger.debug "RailsOnboarding: controller staleness check skipped: #{e.message}"
end