Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make iterate a class method of TimeIterator #11

Merged
merged 2 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 8 additions & 20 deletions lib/time_iterator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,17 @@ module TimeIterator
}.freeze
ITERATE_BY = (PERIODS.keys + PERIODS.values).freeze

private def valid_period?(period)
raise ArgumentError, "Unknown time period: #{period}" unless PERIODS.include?(period)
end

private def method_for_period(method, period)
period = period.to_sym
valid_period?(period)
send("#{method}_#{period}")
end
class << self
def iterate(start, by:, every: 1)
by = by.to_sym

def iterate(by:, every: 1)
by = by.to_sym
raise ArgumentError, "Unknown period to iterate by: #{by}" unless ITERATE_BY.include?(by)

raise ArgumentError, "Unknown period to iterate by: #{by}" unless ITERATE_BY.include?(by)

Enumerator.new do |block|
(0..INFINITY).each do |num|
block << (self + (num.send(by) * every))
Enumerator.new do |block|
(0..INFINITY).each do |num|
block << (start + (num.send(by) * every))
end
end
end
end
end

class Time
include TimeIterator
end
10 changes: 10 additions & 0 deletions lib/time_iterator/core_ext/time.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Inject convenience methods into Time.
class Time
private def valid_period?(period)
raise ArgumentError, "Unknown time period: #{period}" unless TimeIterator::PERIODS.include?(period)
end

private def method_for_period(method, period)
period = period.to_sym
valid_period?(period)
send("#{method}_#{period}")
end

def beginning_of(period)
method_for_period(:beginning_of, period)
end
Expand Down
16 changes: 8 additions & 8 deletions spec/time_iterator/core_ext/time_spec.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
RSpec.describe Time do
let(:time) { described_class.now }

describe 'period check' do
it 'raises on invalid period' do
expect { time.beginning_of(:time) }.to raise_error(ArgumentError)
expect { time.end_of(:universe) }.to raise_error(ArgumentError)
expect { time.iterate(by: :colors) }.to raise_error(ArgumentError)
end
end

describe '#beginning_of' do
periods2methods = {
minute: :beginning_of_minute,
Expand All @@ -25,6 +17,10 @@
expect(time.beginning_of(period)).to eq time.send(method)
end
end

it 'raises on invalid period' do
expect { time.beginning_of(:time) }.to raise_error(ArgumentError)
end
end

describe '#end_of' do
Expand All @@ -43,6 +39,10 @@
expect(time.end_of(period)).to eq time.send(method)
end
end

it 'raises on invalid period' do
expect { time.end_of(:universe) }.to raise_error(ArgumentError)
end
end

describe '#days_in_month/year' do
Expand Down
16 changes: 11 additions & 5 deletions spec/time_iterator_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
RSpec.describe TimeIterator do
let(:time) { Time.now }

describe '#iterate' do
describe '.iterate' do
it 'uses an Enumerator' do
expect( time.iterate(by: :day) ).to be_a(Enumerator)
expect( described_class.iterate(time, by: :day) ).to be_a(Enumerator)
end

it 'raises on an invalid period' do
expect do
described_class.iterate(time, by: :colors)
end.to raise_error(ArgumentError)
end

[
Expand All @@ -12,20 +18,20 @@
].each do |period|
it "iterates by #{period}" do
expect(
time.iterate(by: period).take(3)
described_class.iterate(time, by: period).take(3)
).to eq [time, time + 1.send(period), time + 2.send(period)]
end
end

it 'iterates every X periods' do
expect(
time.iterate(by: :day, every: 3).take(3)
described_class.iterate(time, by: :day, every: 3).take(3)
).to eq [time, time + 3.days, time + 6.days]
end

it 'does not alter the original time' do
orig = time.clone
time.iterate(by: :day).take(5)
described_class.iterate(time, by: :day).take(5)
expect( time ).to eq orig
end
end
Expand Down