rolemodel-rails 2.0.1 → 2.1.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: 2cbd3c1b81aa62c00354cd5faa3cc5bea47c48c2ede2c86470b391372751db9c
4
- data.tar.gz: c9bd14d2787122907369daaf9bfa26b63d0cc882449247ae5da26af15de9586f
3
+ metadata.gz: 4af0b11896cbe75d88cf7934e0322e9c8145656e115d13888473c642aac86716
4
+ data.tar.gz: ad3a3ab92a726d9ce7333ae9db2f45762ce02d5ded8a1c8b86b0923eb685c3c0
5
5
  SHA512:
6
- metadata.gz: d79a388d4221587a777dddeddaea260f389924272c49299fed129b7f5e364df154fa09161217b0087d975168fda59ce6c75e7fd36468c0b0a5b5767cddecea28
7
- data.tar.gz: 960b18a4e997a18092a6bacd69f0833da0154a54717d41215b401f4f8c9cf08034ba8aa10f4daf0fef560a7bd54154a470d650e4427122b3db6c47ac687087ee
6
+ metadata.gz: 0c3cbd55ba285c70505447bc34b0509b98df66093e4fe35b5ae1007cb2252cd080a5779c434a4033302096d461a63c0365ea11b6b288d488adbbc8e31267a797
7
+ data.tar.gz: 41ba42965a2ab047098f450cf3c1fe3d7b69cffda6b4a634da757c6df229f4173b0b1dabc403d77493d1feb891ad9b364f221b6ef61e6c739e76663658feb91f
data/README.md CHANGED
@@ -102,6 +102,117 @@ bin/rails g
102
102
  * [Tailored Select](./lib/generators/rolemodel/tailored_select)
103
103
  * [Lograge](./lib/generators/rolemodel/lograge)
104
104
 
105
+ ## Utilities
106
+
107
+ ### `Rolemodel::Utility::TaskTools`
108
+
109
+ A mixin of helper methods for writing friendlier, more informative Rake tasks. It provides consistent, migration-style console output, progress indication for long-running loops, an opt-in dry-run mode, and sanitized positional task arguments.
110
+
111
+ #### Requiring & Including
112
+
113
+ The module is available at runtime (rolemodel-rails must not be restricted to the `development` gem group). Require it and `include` it inside the `namespace` block of your `.rake` file:
114
+
115
+ ```ruby
116
+ require 'rolemodel/utility/task_tools'
117
+
118
+ namespace :reports do
119
+ include Rolemodel::Utility::TaskTools
120
+
121
+ task total: :environment do
122
+ @total = GeneratedReport.count
123
+ end
124
+
125
+ namespace :clear do
126
+ desc 'Delete all non-current report records'
127
+ task expired: :total do
128
+ say_with_time "Detecting & Deleting Expired Reports among #{@total} Total" do
129
+ deleted_reports = 0
130
+ GeneratedReport.find_each.with_index do |report, index|
131
+ indicate_progress(index, @total)
132
+ next if report.current?
133
+
134
+ report.destroy unless dry_run?
135
+ deleted_reports += 1
136
+ end
137
+ say "#{deleted_reports}/#{@total} Records Deleted"
138
+ end
139
+ end
140
+ end
141
+ end
142
+ ```
143
+
144
+ > [!NOTE]
145
+ > `include` inside a `namespace` block adds the helper methods to the anonymous object that evaluates your task bodies, making them (and any plain methods you define alongside them) available to every task in that namespace.
146
+
147
+ #### Helper Methods
148
+
149
+ ##### `say(message)`
150
+
151
+ Prints a message using the same style as Rails migrations. Pass `subitem: true` to indent the line beneath a preceding `say`.
152
+
153
+ ```ruby
154
+ say 'Doing some important stuff!'
155
+ say 'Like this one specific thing!', subitem: true
156
+ #=> -- Doing some important stuff!
157
+ #=> -> Like this one specific thing!
158
+ ```
159
+
160
+ ##### `say_with_time(message, &block)`
161
+
162
+ Wraps `say` and prints the block's real execution time as an indented subitem. Use it to announce and time a unit of work.
163
+
164
+ ```ruby
165
+ say_with_time "Deleting all #{@total} Records" do
166
+ GeneratedReport.destroy_all unless dry_run?
167
+ end
168
+ #=> -- Deleting all 42 Records
169
+ #=> -> 0.0198s
170
+ ```
171
+
172
+ ##### `indicate_progress(index, total = nil, report_interval: 9)`
173
+
174
+ Renders an animated spinner (and, when `total` is given, a completion percentage) for a long-running loop. Call it once per iteration with the current index; it only redraws every `report_interval` iterations so the animation stays eye-trackable. Pass a reduced `report_interval` when iterations are very slow.
175
+
176
+ ```ruby
177
+ GeneratedReport.find_each.with_index do |report, index|
178
+ indicate_progress(index, @total)
179
+ # ...
180
+ end
181
+ ```
182
+
183
+ ##### `dry_run?`
184
+
185
+ Returns `true` when the `DRY_RUN` environment variable is present, enabling a dry-run pattern for your tasks. Guard any code that writes to the database or file system with `unless dry_run?` so the task still produces its console feedback without performing the side effects.
186
+
187
+ ```ruby
188
+ report.destroy unless dry_run?
189
+ ```
190
+
191
+ ```shell
192
+ DRY_RUN=true rake reports:clear:expired
193
+ ```
194
+
195
+ ##### `sanitize_arguments(args, defaults = {})`
196
+
197
+ Improves the usability of positional `Rake::Task` arguments, which cannot declare default values and are awkward to skip. Pass the task's `args` and a hash of defaults; it returns a hash with whitespace stripped, blank/skipped values (passed as `_`) replaced by your defaults.
198
+
199
+ ```ruby
200
+ desc 'Seed a dev user with the given name and email'
201
+ task :dev, %i[name email] => :environment do |_, args|
202
+ name, email = sanitize_arguments(args, name: 'RoleModel', email: 'it-support@rolemodelsoftware.com').values_at(:name, :email)
203
+ say_with_time "Seeding Dev User (name: #{name}, email: #{email}, role: Admin)" do
204
+ User.find_or_create(name:, email:, role: 'admin') unless dry_run?
205
+ end
206
+ end
207
+ ```
208
+
209
+ ```shell
210
+ # Skip the name argument with `_` to fall back to its default
211
+ DRY_RUN=true rake users:dev[_,bob@example.com]
212
+ #=> -- Seeding Dev User (name: RoleModel, email: bob@example.com, role: Admin)
213
+ #=> -> 0.0000s
214
+ ```
215
+
105
216
  ## Development
106
217
 
107
218
  Install the versions of Node and Ruby specified in `.node-version` and `.ruby-version` on your machine. https://asdf-vm.com/ is a great tool for managing language versions. Then run `npm install -g yarn`.
@@ -12,6 +12,7 @@ module Rolemodel
12
12
  say '%.4fs' % time.real, subitem: true
13
13
  end
14
14
 
15
+ # based on the migration helper of the same name
15
16
  def say(message, subitem: false)
16
17
  puts "#{subitem ? ' ->' : '--'} #{message}" # rubocop:disable Rails/Output
17
18
  end
@@ -32,11 +33,37 @@ module Rolemodel
32
33
  print("#{PROGRESS.next} #{to_percent(index, total) if total}\r") # rubocop:disable Rails/Output
33
34
  end
34
35
 
36
+ ##
37
+ # Enables a pattern for dry-run mode in tasks. Assumes usage of other utility methods
38
+ # like `say_with_time` and `indicate_progress` that provide user feedback, separate from the actions they perform.
39
+ #
40
+ # Tasks can be updated to support this mode by adding `unless dry_run?` to lines of code that write to the file system or database.
41
+ def dry_run?
42
+ ENV['DRY_RUN'].present?
43
+ end
44
+
45
+ ##
46
+ # Improves the usability of Rake::Task arguments which are positional and don't support default values.
47
+ # This method allows invocation with skipped arguments via `_` and supports a defaults hash.
48
+ def sanitize_arguments(args, defaults = {})
49
+ defaults.merge(ArgumentSanitizer.new(args).to_h)
50
+ end
51
+
35
52
  private
36
53
 
37
54
  def to_percent(index, total)
38
55
  '%3.f%%' % (index / total.to_f * 100.0)
39
56
  end
40
57
  end
58
+
59
+ class ArgumentSanitizer
60
+ def initialize(args)
61
+ @args = args.to_h
62
+ end
63
+
64
+ def to_h
65
+ @args.transform_values { it.to_s.strip.match?('_') ? nil : it.to_s.strip }.compact
66
+ end
67
+ end
41
68
  end
42
69
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rolemodel
4
- VERSION = '2.0.1'
4
+ VERSION = '2.1.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rolemodel-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - RoleModel Software Inc