Skip to content

Commit

Permalink
each_with_progress に変更、テスト追加
Browse files Browse the repository at this point in the history
従来の find_each_with_progress の引数 target_scope が持つ find_each メソッドは「ブロック引数がなければ enumerator を返さなければならない」に変更。
  • Loading branch information
tkawa committed Apr 19, 2024
1 parent e378d76 commit 5045fe9
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 18 deletions.
15 changes: 5 additions & 10 deletions lib/dekiru/data_migration_operator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ def duration
((self.ended_at || Time.current) - self.started_at)
end

def with_progress(enum, options = {})
def each_with_progress(enum, options = {})
options = options.dup
options[:total] ||= ((enum.size == Float::INFINITY ? nil : enum.size) rescue nil)
options[:format] ||= options[:total] ? '%a |%b>>%i| %p%% %t' : '%a |%b>>%i| ??%% %t'
options[:output] ||= stream
options[:output] = stream

@pb = ::ProgressBar.create(options)
enum.each do |item|
Expand All @@ -68,14 +68,9 @@ def with_progress(enum, options = {})
end

def find_each_with_progress(target_scope, options = {}, &block)
enum =
if target_scope.is_a?(ActiveRecord::Batches)
target_scope.find_each
else
# ActiveRecord由来のfind_eachでないと思われる場合は明示的にenumeratorに変換
target_scope.enum_for(:find_each)
end
with_progress(enum, options, &block)
# `LocalJumpError: no block given (yield)` が出る場合、 find_each メソッドが enumerator を返していない可能性があります
# 直接 each_with_progress を使うか、 find_each が enumerator を返すように修正してください
each_with_progress(target_scope.find_each, options, &block)
end

private
Expand Down
70 changes: 62 additions & 8 deletions spec/dekiru/data_migration_operator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,38 @@ def flush
end
end

describe '#find_each_with_progress' do
describe '#each_with_progress' do
let(:record) { (0...10) }

it '進捗が表示される' do
allow(STDIN).to receive(:gets) do
"yes\n"
end

sum = 0
operator.execute do
each_with_progress(record, title: 'count up number') do |num|
sum += num
end
end

expect(sum).to eq(45)
expect(operator.result).to eq(true)
expect(operator.error).to eq(nil)
expect(operator.stream.out).to include('Are you sure to commit?')
expect(operator.stream.out).to include('count up number:')
expect(operator.stream.out).to include('Finished successfully:')
expect(operator.stream.out).to include('Total time:')
end

it 'total をオプションで渡すことができる' do
class Dekiru::DummyRecord
def self.count
10
raise "won't call"
end

def self.find_each
(0...count).to_a.each do |num|
yield(num)
end
def self.each
yield 99
end
end

Expand All @@ -126,7 +147,36 @@ def self.find_each

sum = 0
operator.execute do
find_each_with_progress(Dekiru::DummyRecord, title: 'count up number') do |num|
each_with_progress(Dekiru::DummyRecord, title: 'pass total as option', total: 1) do |num|
sum += num
end
end

expect(sum).to eq(99)
expect(operator.result).to eq(true)
expect(operator.error).to eq(nil)
expect(operator.stream.out).to include('Are you sure to commit?')
expect(operator.stream.out).to include('pass total as option:')
expect(operator.stream.out).to include('Finished successfully:')
expect(operator.stream.out).to include('Total time:')
end
end

describe '#find_each_with_progress' do
let(:record) do
(0...10).tap do |r|
r.singleton_class.alias_method(:find_each, :each)
end
end

it '進捗が表示される' do
allow(STDIN).to receive(:gets) do
"yes\n"
end

sum = 0
operator.execute do
find_each_with_progress(record, title: 'count up number') do |num|
sum += num
end
end
Expand All @@ -147,7 +197,11 @@ def self.count
end

def self.find_each
yield 99
if block_given?
yield 99
else
Enumerator.new { |y| y << 99 }
end
end
end

Expand Down

0 comments on commit 5045fe9

Please sign in to comment.