Module: RailsOnboarding::ProgressiveDisclosure

Extended by:
ActiveSupport::Concern
Defined in:
app/models/concerns/rails_onboarding/progressive_disclosure.rb

Overview

Concern for progressive disclosure of features Shows features gradually over time based on user behavior and progress

Examples:

Include in your User model

class User < ApplicationRecord
  include RailsOnboarding::Onboardable
  include RailsOnboarding::ProgressiveDisclosure
end

Configure progressive features

RailsOnboarding.configure do |config|
  config.progressive_disclosure_enabled = true
  config.progressive_features = [
    {
      key: :advanced_settings,
      reveal_condition: :time_based,
      delay: 7.days,
      title: "Advanced Settings",
      description: "Now that you're familiar with the basics..."
    },
    {
      key: :team_collaboration,
      reveal_condition: :action_based,
      check_method: :has_created_first_project?,
      title: "Team Collaboration",
      description: "Ready to invite your team?"
    }
  ]
end

Instance Method Summary collapse

Instance Method Details

#all_revealed_featuresArray<String>

Get all revealed features

Returns:

  • (Array<String>)

    Array of revealed feature keys



102
103
104
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 102

def all_revealed_features
  revealed_features || []
end

#estimated_reveal_time(feature) ⇒ Time?

Estimate when a feature will be revealed

Parameters:

  • feature (Hash)

    Feature configuration

Returns:

  • (Time, nil)

    Estimated reveal time or nil



181
182
183
184
185
186
187
188
189
190
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 181

def estimated_reveal_time(feature)
  case feature[:reveal_condition]
  when :time_based
    created_at + feature[:delay].seconds
  when :step_based
    nil # Can't estimate step-based reveals
  else
    nil
  end
end

#feature_ready?(feature) ⇒ Boolean

Check if a specific feature is ready to be revealed

Parameters:

  • feature (Hash)

    Feature configuration

Returns:

  • (Boolean)

    True if feature is ready



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 131

def feature_ready?(feature)
  case feature[:reveal_condition]
  when :time_based
    time_based_ready?(feature)
  when :action_based
    action_based_ready?(feature)
  when :step_based
    step_based_ready?(feature)
  when :milestone_based
    milestone_based_ready?(feature)
  when :engagement_based
    engagement_based_ready?(feature)
  else
    false
  end
rescue StandardError => e
  Rails.logger.error("Error checking feature readiness: #{e.message}") if defined?(Rails)
  false
end

#feature_revealed?(feature_key) ⇒ Boolean

Check if a feature has been revealed to the user

Examples:

user.feature_revealed?(:advanced_settings)
# => false

Parameters:

  • feature_key (String, Symbol)

    Feature key

Returns:

  • (Boolean)

    True if feature is revealed



53
54
55
56
57
58
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 53

def feature_revealed?(feature_key)
  return true unless RailsOnboarding.configuration.progressive_disclosure_enabled

  features = revealed_features || []
  features.include?(feature_key.to_s)
end

#features_ready_to_revealArray<Hash>

Get features that are ready to be revealed

Examples:

user.features_ready_to_reveal
# => [{key: :advanced_settings, title: "...", ...}]

Returns:

  • (Array<Hash>)

    Array of feature configurations ready to reveal



113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 113

def features_ready_to_reveal
  return [] unless RailsOnboarding.configuration.progressive_disclosure_enabled

  features = RailsOnboarding.configuration.progressive_features || []

  features.select do |feature|
    # Skip if already revealed
    next false if feature_revealed?(feature[:key])

    # Check if feature meets reveal conditions
    feature_ready?(feature)
  end
end

#hide_feature(feature_key) ⇒ Boolean

Hide a previously revealed feature

Parameters:

  • feature_key (String, Symbol)

    Feature key

Returns:

  • (Boolean)

    True if successfully hidden



92
93
94
95
96
97
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 92

def hide_feature(feature_key)
  return false unless revealed_features

  revealed_features.delete(feature_key.to_s)
  save if persisted?
end

#next_feature_to_revealHash?

Get the next feature that will be revealed

Returns:

  • (Hash, nil)

    Next feature configuration or nil



169
170
171
172
173
174
175
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 169

def next_feature_to_reveal
  features = RailsOnboarding.configuration.progressive_features || []

  features
    .reject { |f| feature_revealed?(f[:key]) }
    .min_by { |f| estimated_reveal_time(f) }
end

#pending_features_countInteger

Get a count of features pending reveal

Returns:

  • (Integer)

    Count of pending features



202
203
204
205
206
207
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 202

def pending_features_count
  return 0 unless RailsOnboarding.configuration.progressive_disclosure_enabled

  total_features = RailsOnboarding.configuration.progressive_features&.size || 0
  total_features - revealed_features_count
end

#reveal_feature(feature_key, metadata = {}) ⇒ Boolean

Mark a feature as revealed

Examples:

user.reveal_feature(:advanced_settings, source: :automatic)

Parameters:

  • feature_key (String, Symbol)

    Feature key

  • metadata (Hash) (defaults to: {})

    Additional metadata about the reveal

Returns:

  • (Boolean)

    True if successfully marked as revealed



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 68

def reveal_feature(feature_key,  = {})
  self.revealed_features ||= []
  return false if revealed_features.include?(feature_key.to_s)

  revealed_features << feature_key.to_s

  # Track the reveal event
  if respond_to?(:track_analytics_event)
    track_analytics_event(
      "feature_revealed",
      {
        feature_key: feature_key.to_s,
        reveal_time: Time.current
      }.merge()
    )
  end

  save if persisted?
end

#reveal_ready_features!Array<String>

Reveal all features that are ready

Returns:

  • (Array<String>)

    Array of newly revealed feature keys



154
155
156
157
158
159
160
161
162
163
164
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 154

def reveal_ready_features!
  newly_revealed = []

  features_ready_to_reveal.each do |feature|
    if reveal_feature(feature[:key], source: :automatic, condition: feature[:reveal_condition])
      newly_revealed << feature[:key].to_s
    end
  end

  newly_revealed
end

#revealed_features_countInteger

Get a count of how many features have been revealed

Returns:

  • (Integer)

    Count of revealed features



195
196
197
# File 'app/models/concerns/rails_onboarding/progressive_disclosure.rb', line 195

def revealed_features_count
  all_revealed_features.size
end