onboardable 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 894b017b45b6b272a764dfd1ea6185c971ccabcbeee82ae0a195d41a0593b3af
4
- data.tar.gz: f1a678edd9967f4e31d87f25cabd9d3da88c34a2c651a14c19e5881c13ac6b1c
3
+ metadata.gz: c7a359f33f51c9c573afe6ad4b438c7dbad0650ad3a665f5062ff0fb056a4e3d
4
+ data.tar.gz: d11d9642fae0159ef3055b1341ee6d6fffa9c25c7facf64244b98b6aed005bc4
5
5
  SHA512:
6
- metadata.gz: b41f0070e487e5b687f31275da0a274e849f4758fcf539c60dfa91366b75885bcc9f91532002aa98919247fd184565c5f4fe43752b7fc087315c4bac36baa79d
7
- data.tar.gz: 698e56a7902c725a3eb6062d3deb68874e18f854b025cd1cfbed7bd6dc0187034761d31c049c7d35febfe9f15adf3238a57f45adb3ce2d442070e6160ece637f
6
+ metadata.gz: 98d9460b91553ab1808e567989b7d05b6dac8fd4867a887461656e5202bbf60689cdeba416338f6b93c20e84e704721de31b77298197798542a72f64229472d5
7
+ data.tar.gz: 7d4c7a97f04bb61b0240f7c174f4a93b633f2af10396d547ae4537bce1eb734a05c98be14c547f0045e779bf011c153385d120cf7556553580b8075876d5bfc2
data/CHANGELOG.md CHANGED
@@ -2,9 +2,13 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [1.3.0] - 2024-06-10
6
+
7
+ - Added option to calculate onboarding progress using a custom formula.
8
+
5
9
  ## [1.2.2] - 2024-06-03
6
10
 
7
- - Fix the issue with the default `#current_step` method.
11
+ - Fixed the issue with the default `#current_step` method.
8
12
 
9
13
  ## [1.2.1] - 2024-06-01
10
14
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- onboardable (1.2.2)
4
+ onboardable (1.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -11,7 +11,7 @@ GEM
11
11
  docile (1.4.0)
12
12
  json (2.7.2)
13
13
  language_server-protocol (3.17.0.3)
14
- parallel (1.24.0)
14
+ parallel (1.25.1)
15
15
  parser (3.3.2.0)
16
16
  ast (~> 2.4.1)
17
17
  racc
@@ -19,8 +19,8 @@ GEM
19
19
  rainbow (3.1.1)
20
20
  rake (13.2.1)
21
21
  regexp_parser (2.9.2)
22
- rexml (3.2.8)
23
- strscan (>= 3.0.9)
22
+ rexml (3.2.9)
23
+ strscan
24
24
  rspec (3.13.0)
25
25
  rspec-core (~> 3.13.0)
26
26
  rspec-expectations (~> 3.13.0)
@@ -47,21 +47,21 @@ GEM
47
47
  unicode-display_width (>= 2.4.0, < 3.0)
48
48
  rubocop-ast (1.31.3)
49
49
  parser (>= 3.3.1.0)
50
- rubocop-capybara (2.20.0)
50
+ rubocop-capybara (2.21.0)
51
51
  rubocop (~> 1.41)
52
- rubocop-factory_bot (2.25.1)
52
+ rubocop-factory_bot (2.26.0)
53
53
  rubocop (~> 1.41)
54
54
  rubocop-performance (1.21.0)
55
55
  rubocop (>= 1.48.1, < 2.0)
56
56
  rubocop-ast (>= 1.31.1, < 2.0)
57
57
  rubocop-rake (0.6.0)
58
58
  rubocop (~> 1.0)
59
- rubocop-rspec (2.30.0)
59
+ rubocop-rspec (2.31.0)
60
60
  rubocop (~> 1.40)
61
61
  rubocop-capybara (~> 2.17)
62
62
  rubocop-factory_bot (~> 2.22)
63
63
  rubocop-rspec_rails (~> 2.28)
64
- rubocop-rspec_rails (2.28.3)
64
+ rubocop-rspec_rails (2.29.0)
65
65
  rubocop (~> 1.40)
66
66
  ruby-progressbar (1.13.0)
67
67
  simplecov (0.22.0)
@@ -84,7 +84,7 @@ DEPENDENCIES
84
84
  rubocop (~> 1.64, >= 1.64.1)
85
85
  rubocop-performance (~> 1.21)
86
86
  rubocop-rake (~> 0.6.0)
87
- rubocop-rspec (~> 2.30)
87
+ rubocop-rspec (~> 2.31)
88
88
  simplecov (~> 0.22.0)
89
89
 
90
90
  BUNDLED WITH
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # 🚀 Onboardable
2
2
 
3
+ ![Gem Version](https://img.shields.io/gem/v/onboardable)
3
4
  ![Build](https://img.shields.io/github/actions/workflow/status/dmrAnderson/onboardable/ci.yml)
4
5
  ![Code Coverage](https://img.shields.io/coverallsCoverage/github/dmrAnderson/onboardable)
6
+ ![Gem Total Downloads](https://img.shields.io/gem/dt/onboardable)
5
7
 
6
8
  The Onboardable gem is a Ruby module designed to simplify and streamline the
7
9
  process of managing and navigating through a series of steps or stages within
@@ -140,13 +142,36 @@ that allow step navigation and state verification:
140
142
 
141
143
  1. **Monitor Progress**
142
144
 
143
- Calculate the progress or completion percentage of the onboarding process
144
- to provide users with an indication of how far they have progressed.
145
+ - Calculate the progress or completion percentage of the onboarding process
146
+ to provide users with an indication of how far they have progressed.
145
147
 
146
148
  ```ruby
147
149
  onboarding.progress # Returns the completion percentage
148
150
  ```
149
151
 
152
+ - To customize the progress calculation formula, define a lambda function
153
+ that takes the current step index and the total number of steps as arguments.
154
+
155
+ ```ruby
156
+ CALCULATION = ->(step_index, steps_size) { step_index + steps_size }
157
+ onboarding.progress(CALCULATION)
158
+ ```
159
+
160
+ - Alternatively, set the custom progress calculation formula during the
161
+ onboarding definition to automatically calculate the progress.
162
+
163
+ ```ruby
164
+ class User
165
+ include Onboardable
166
+
167
+ CALCULATION = ->(step_index, steps_size) { step_index + steps_size }
168
+
169
+ has_onboarding progress_calculation: CALCULATION do
170
+ # ...
171
+ end
172
+ end
173
+ ```
174
+
150
175
  1. **Access Current Step Details**
151
176
 
152
177
  Retrieve details about the current step, which can include the name,
@@ -6,6 +6,8 @@ module Onboardable
6
6
  class Base
7
7
  include Navigation
8
8
 
9
+ PROGRESS_CALCULATION = ->(step_index, steps_size) { (step_index.to_f / steps_size) * 100 }
10
+
9
11
  # @return [Array<Step>] The steps in the list.
10
12
  attr_reader :steps
11
13
 
@@ -16,20 +18,27 @@ module Onboardable
16
18
  #
17
19
  # @param steps [Array<Step>] An array of steps comprising the onboarding process.
18
20
  # @param current_step [Step] The step currently active in the process.
19
- def initialize(steps, current_step)
21
+ # @param options [Hash] An options hash for the list.
22
+ def initialize(steps, current_step, options = {})
20
23
  self.steps = steps
21
24
  self.current_step = current_step
25
+ self.options = options
22
26
  end
23
27
 
24
28
  # Calculates and returns the onboarding progress as a percentage.
25
29
  #
26
- # @return [Float] The completion percentage of the onboarding process.
27
- def progress
28
- (step_index(current_step).to_f / steps.size) * 100
30
+ # @param progress_calculation [Proc, nil] An optional custom calculation for progress.
31
+ # @return [Float] The percentage of steps completed in the onboarding process.
32
+ def progress(progress_calculation = nil)
33
+ progress_calculation ||= options.fetch(:progress_calculation, PROGRESS_CALCULATION)
34
+ Float(progress_calculation[step_index(current_step), steps.size])
29
35
  end
30
36
 
31
37
  private
32
38
 
39
+ # @return [Hash] The options hash for the list.
40
+ attr_reader :options
41
+
33
42
  # Sets and validates the steps array, ensuring it is an Array of Step objects.
34
43
  #
35
44
  # @param steps [Array<Step>] The steps to be assigned to the list.
@@ -49,6 +58,14 @@ module Onboardable
49
58
  end
50
59
  end
51
60
 
61
+ # Sets and validates the options hash, ensuring it is a Hash object.
62
+ #
63
+ # @param options [Hash] The options to be assigned to the list.
64
+ # @return [Hash] The assigned options.
65
+ def options=(options)
66
+ @options = Hash(options).transform_keys(&:to_sym).freeze
67
+ end
68
+
52
69
  # Determines the index of a given step in the list, ensuring the step exists.
53
70
  #
54
71
  # @param raw_step [Step] The step for which the index is requested.
@@ -6,15 +6,19 @@ module Onboardable
6
6
  class Builder
7
7
  include Utils::Warnings
8
8
 
9
- # @return [Hash] A hash where keys are step names and values are Step objects.
10
- attr_reader :steps
9
+ # Stores the steps added to the builder.
10
+ #
11
+ # @return [Hash] A hash of steps added to the builder.
12
+ def steps
13
+ options[__method__] ||= {}
14
+ end
11
15
 
12
16
  # @return [Step] The current step in the building process, defaulting to the first added step.
13
17
  attr_accessor :current_step
14
18
 
15
19
  # Initializes a new instance of ListBuilder.
16
- def initialize
17
- self.steps = {}
20
+ def initialize(options = {})
21
+ self.options = options
18
22
  end
19
23
 
20
24
  # Creates a new Step object and adds it to the builder.
@@ -38,7 +42,7 @@ module Onboardable
38
42
 
39
43
  # Constructs a new List object from the steps added to the builder.
40
44
  #
41
- # @param current_step_name [String] The name of the current step.
45
+ # @param current_step_name [String, nil] The name of the current step.
42
46
  # @return [Base] A new List object initialized with the steps and the specified current step.
43
47
  def build(current_step_name = nil)
44
48
  Base.new(convert_to_steps!, convert_to_step!(current_step_name || current_step.name))
@@ -46,6 +50,16 @@ module Onboardable
46
50
 
47
51
  private
48
52
 
53
+ # @return [Hash] The options hash for the builder.
54
+ attr_reader :options
55
+
56
+ # Sets the options hash for the builder.
57
+ #
58
+ # @param options [Hash] The options hash to be set.
59
+ def options=(options)
60
+ @options = Hash(options)
61
+ end
62
+
49
63
  # Adds a step to the builder.
50
64
  #
51
65
  # @param step [Step] The step to be added.
@@ -59,13 +73,6 @@ module Onboardable
59
73
  step.tap { self.current_step ||= step }
60
74
  end
61
75
 
62
- # Assigns a hash of steps to the builder.
63
- #
64
- # @param raw_steps [Hash] The hash of steps to be assigned.
65
- def steps=(raw_steps)
66
- @steps = Hash(Hash.try_convert(raw_steps))
67
- end
68
-
69
76
  # Converts the internal hash of steps to an array of Step objects.
70
77
  #
71
78
  # @return [Array<Step>] An array of steps.
@@ -14,28 +14,42 @@ module Onboardable
14
14
  STATUSES = [PENDING_STATUS, CURRENT_STATUS, COMPLETED_STATUS].freeze
15
15
 
16
16
  class << self
17
- def try_convert(value)
18
- return unless value.respond_to?(CONVERSION_METHOD)
17
+ # Attempts to convert a class to a Step object using a specified conversion method.
18
+ #
19
+ # @param klass [Class] The class to convert to a Step
20
+ # @return [Step, nil] The converted Step object, or nil if the class does not respond to the conversion method
21
+ def try_convert(klass)
22
+ return unless klass.respond_to?(CONVERSION_METHOD)
19
23
 
20
- value.public_send(CONVERSION_METHOD).then do |step|
21
- step.is_a?(Step) ? step : raise(StepConversionError.new(value, step))
24
+ klass.public_send(CONVERSION_METHOD).then do |step|
25
+ step.is_a?(Step) ? step : conversion_error!(klass, step)
22
26
  end
23
27
  end
28
+
29
+ private
30
+
31
+ # Raises an error for a failed conversion attempt.
32
+ #
33
+ # @param klass [Class] The class that failed to convert
34
+ # @raise [StepConversionError] Raises an error for a failed conversion attempt
35
+ def conversion_error!(klass, step)
36
+ raise StepConversionError.new(klass, step)
37
+ end
24
38
  end
25
39
 
26
- # @return [String] the name of the step
40
+ # @return [String] The name of the step
27
41
  attr_reader :name
28
42
 
29
- # @return [Hash] custom data associated with the step
43
+ # @return [Hash] Custom data associated with the step
30
44
  attr_reader :data
31
45
 
32
- # @return [Symbol] the current status of the step
46
+ # @return [Symbol] The current status of the step
33
47
  attr_reader :status
34
48
 
35
49
  # Initializes a new Step with a name, optional custom data, and a default status.
36
50
  #
37
- # @param name [String] the name of the step
38
- # @param data [Hash] the custom data associated with the step, defaults to an empty hash
51
+ # @param name [String] The name of the step
52
+ # @param data [Hash] The custom data associated with the step, defaults to an empty hash
39
53
  def initialize(name, data = {})
40
54
  self.name = name
41
55
  self.data = data
@@ -46,7 +60,7 @@ module Onboardable
46
60
  # @!method {status_method}?
47
61
  # Checks if the step is in a specific status.
48
62
  #
49
- # @return [Boolean] true if the step is currently in the {status_method} status, false otherwise.
63
+ # @return [Boolean] True if the step is currently in the {status_method} status, false otherwise.
50
64
  define_method :"#{status_method}?" do
51
65
  status == status_method
52
66
  end
@@ -54,24 +68,23 @@ module Onboardable
54
68
 
55
69
  # Compares this step to another to determine if they are equivalent, based on the step name.
56
70
  #
57
- # @param other [Step] the step to compare with
58
- # @return [Boolean] true if both steps have the same name, false otherwise
71
+ # @param other [Step] The step to compare with
72
+ # @return [Boolean] True if both steps have the same name, false otherwise
59
73
  def ==(other)
60
74
  to_str == other.to_str
61
75
  end
62
76
 
63
77
  # Provides a string representation of the step, using its name.
64
78
  #
65
- # @return [String] the name of the step
79
+ # @return [String] The name of the step
66
80
  def to_str
67
81
  name
68
82
  end
69
83
 
70
84
  # Updates the status of the step based on a specified comparison result.
71
85
  #
72
- # @param comparison_result [Integer] the result of a comparison with the current step (-1, 0, or 1)
73
- # @return [Symbol] the new status of the step
74
- # @raise [ComparisonResultError] if the comparison result is not -1, 0, or 1
86
+ # @param comparison_result [Integer] The result of a comparison with the current step (-1, 0, or 1)
87
+ # @return [Symbol] The new status of the step
75
88
  def update_status!(comparison_result)
76
89
  self.status = case comparison_result
77
90
  when -1 then COMPLETED_STATUS
@@ -84,14 +97,14 @@ module Onboardable
84
97
 
85
98
  # Sets the name of the step, ensuring it is a valid String.
86
99
  #
87
- # @param raw_name [String] the raw name of the step
100
+ # @param raw_name [String] The raw name of the step
88
101
  def name=(raw_name)
89
- @name = String.new(String.try_convert(raw_name)).freeze
102
+ @name = String.new(raw_name).freeze
90
103
  end
91
104
 
92
105
  # Sets the status of the step.
93
106
  #
94
- # @param raw_status [Symbol] the new status of the step
107
+ # @param raw_status [Symbol] The new status of the step
95
108
  def status=(raw_status)
96
109
  STATUSES.include?(raw_status) || raise(StepStatusError.new(raw_status, STATUSES))
97
110
 
@@ -100,15 +113,15 @@ module Onboardable
100
113
 
101
114
  # Sets the custom data for the step, ensuring it is a valid Hash.
102
115
  #
103
- # @param raw_data [Hash] the raw custom data
116
+ # @param raw_data [Hash] The raw custom data
104
117
  def data=(raw_data)
105
- @data = Hash(Hash.try_convert(raw_data)).freeze
118
+ @data = Hash(raw_data).freeze
106
119
  end
107
120
 
108
121
  # Raises an error for an invalid comparison result.
109
122
  #
110
- # @param comparison_result [Integer] the invalid comparison result
111
- # @raise [ComparisonResultError] raises an error for an invalid comparison result
123
+ # @param comparison_result [Integer] The invalid comparison result
124
+ # @raise [ComparisonResultError] Raises an error for an invalid comparison result
112
125
  def comparison_result_error!(comparison_result)
113
126
  raise ComparisonResultError.new(comparison_result, (-1..1).to_a)
114
127
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Onboardable
4
- VERSION = '1.2.2'
4
+ VERSION = '1.3.0'
5
5
  end
data/lib/onboardable.rb CHANGED
@@ -21,21 +21,19 @@ module Onboardable
21
21
 
22
22
  # Class methods for managing the onboarding process, added to the class that includes the Onboardable module.
23
23
  module ClassMethods
24
- # Retrieves or initializes a ListBuilder for onboarding steps at the class level.
25
- #
26
- # @return [List::Builder] The ListBuilder associated with the class.
27
- def list_builder
28
- @list_builder ||= List::Builder.new
29
- end
24
+ # @return [List::Builder] The ListBuilder for configuring onboarding steps.
25
+ attr_accessor :list_builder
30
26
 
31
27
  # Configures onboarding steps via a ListBuilder with a provided block.
32
28
  #
29
+ # @param options [Hash] Optional configuration options for the ListBuilder.
33
30
  # @yield [List::Builder] Executes block in the context of List::Builder.
34
31
  # @return [Step] The current step in the building process.
35
- def list_builder=(&block)
32
+ def onboarding=(options = {}, &block)
33
+ self.list_builder = List::Builder.new(options)
36
34
  list_builder.instance_eval(&block)
37
35
  end
38
- alias has_onboarding list_builder=
36
+ alias has_onboarding onboarding=
39
37
 
40
38
  # Builds the onboarding list and optionally sets the current step.
41
39
  #
data/onboardable.gemspec CHANGED
@@ -44,7 +44,7 @@ Gem::Specification.new do |spec|
44
44
  spec.add_development_dependency 'rubocop', '~> 1.64', '>= 1.64.1'
45
45
  spec.add_development_dependency 'rubocop-performance', '~> 1.21'
46
46
  spec.add_development_dependency 'rubocop-rake', '~> 0.6.0'
47
- spec.add_development_dependency 'rubocop-rspec', '~> 2.30'
47
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.31'
48
48
  spec.add_development_dependency 'simplecov', '~> 0.22.0'
49
49
 
50
50
  spec.metadata['rubygems_mfa_required'] = 'true'
@@ -1,18 +1,22 @@
1
1
  module Onboardable
2
2
  module List
3
3
  class Base
4
+ PROGRESS_CALCULATION: Proc
5
+
4
6
  attr_reader steps: Array[Step]
5
7
  attr_reader current_step: Step
6
8
 
7
9
  def initialize: (Array[Step], Step) -> instance
8
10
 
9
- def progress: -> Float
11
+ def progress: (Proc?) -> Float
10
12
 
11
13
  private
12
14
 
13
15
  attr_writer steps: Array[Step]
14
16
  attr_writer current_step: Step
15
17
 
18
+ attr_accessor options: Hash[Symbol, untyped]
19
+
16
20
  def step_error!: (Step) -> void
17
21
 
18
22
  def step_index: (Step)-> Integer
@@ -4,7 +4,7 @@ module Onboardable
4
4
  attr_reader steps: Hash[String, Step]
5
5
  attr_accessor current_step: Step
6
6
 
7
- def initialize: () -> Hash[String, Step]
7
+ def initialize: (Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
8
8
 
9
9
  def create_step: (String, Hash[Symbol, untyped]) -> Step
10
10
  alias step create_step
@@ -16,7 +16,7 @@ module Onboardable
16
16
 
17
17
  private
18
18
 
19
- attr_writer steps: Hash[String, Step]
19
+ attr_accessor options: Hash[Symbol, untyped]
20
20
 
21
21
  def add_step: (Step) -> Step
22
22
 
@@ -7,7 +7,9 @@ module Onboardable
7
7
  DEFAULT_STATUS: Symbol
8
8
  STATUSES: Array[Symbol]
9
9
 
10
- def self.try_convert: -> Step?
10
+ def self.try_convert: (Class) -> Step?
11
+
12
+ def self.conversion_error!: (Class, untyped) -> void
11
13
 
12
14
  attr_reader name: String
13
15
  attr_reader data: Hash[Symbol, untyped]
data/sig/onboardable.rbs CHANGED
@@ -3,10 +3,10 @@ module Onboardable
3
3
  # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
4
 
5
5
  module ClassMethods
6
- attr_reader list_builder: List::Builder
6
+ attr_accessor list_builder: List::Builder
7
7
 
8
- def list_builder=: () { () -> List::Builder } -> Step
9
- alias has_onboarding list_builder=
8
+ def onboarding=: (Hash[Symbol, untyped]) { () -> List::Builder } -> Step
9
+ alias has_onboarding onboarding=
10
10
 
11
11
  def onboarding: (String?) -> List::Base
12
12
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: onboardable
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Skrynnyk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-03 00:00:00.000000000 Z
11
+ date: 2024-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -98,14 +98,14 @@ dependencies:
98
98
  requirements:
99
99
  - - "~>"
100
100
  - !ruby/object:Gem::Version
101
- version: '2.30'
101
+ version: '2.31'
102
102
  type: :development
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - "~>"
107
107
  - !ruby/object:Gem::Version
108
- version: '2.30'
108
+ version: '2.31'
109
109
  - !ruby/object:Gem::Dependency
110
110
  name: simplecov
111
111
  requirement: !ruby/object:Gem::Requirement