Commit c2bc1533 authored by Tomasz Maczukin's avatar Tomasz Maczukin

Refactorize ChronicDurationAttribute concern

parent 973e4030
...@@ -2,49 +2,38 @@ module ChronicDurationAttribute ...@@ -2,49 +2,38 @@ module ChronicDurationAttribute
extend ActiveSupport::Concern extend ActiveSupport::Concern
class_methods do class_methods do
def chronic_duration_attr(virtual_attribute, source_attribute)
chronic_duration_attr_reader(virtual_attribute, source_attribute)
chronic_duration_attr_writer(virtual_attribute, source_attribute)
end
def chronic_duration_attr_reader(virtual_attribute, source_attribute) def chronic_duration_attr_reader(virtual_attribute, source_attribute)
define_method(virtual_attribute) do define_method(virtual_attribute) do
value = self.send(source_attribute) # rubocop:disable GitlabSecurity/PublicSend chronic_duration_attributes[virtual_attribute] || output_chronic_duration_attribute(source_attribute)
return '' if value.nil?
ChronicDuration.output(value, format: :short)
end end
end end
def chronic_duration_attr_writer(virtual_attribute, source_attribute) def chronic_duration_attr_writer(virtual_attribute, source_attribute)
virtual_attribute_validator = "#{virtual_attribute}_validator".to_sym chronic_duration_attr_reader(virtual_attribute, source_attribute)
validation_error = "#{virtual_attribute}_error".to_sym
validate virtual_attribute_validator
attr_accessor validation_error
define_method("#{virtual_attribute}=") do |value| define_method("#{virtual_attribute}=") do |value|
begin chronic_duration_attributes[virtual_attribute] = value.presence || ''
self.send("#{validation_error}=", '') # rubocop:disable GitlabSecurity/PublicSend
new_value = begin
if value.blank? new_value = ChronicDuration.parse(value).to_i if value.present?
nil assign_attributes(source_attribute => new_value)
else rescue ChronicDuration::DurationParseError
ChronicDuration.parse(value).to_i # ignore error as it will be caught by validation
end end
self.send("#{source_attribute}=", new_value) # rubocop:disable GitlabSecurity/PublicSend
rescue ChronicDuration::DurationParseError => ex
self.send("#{validation_error}=", ex.message) # rubocop:disable GitlabSecurity/PublicSend
end end
validates virtual_attribute, allow_nil: true, duration: true
end end
define_method(virtual_attribute_validator) do alias_method :chronic_duration_attr, :chronic_duration_attr_writer
error = self.send(validation_error) # rubocop:disable GitlabSecurity/PublicSend
self.send('errors').add(source_attribute, error) unless error.blank? # rubocop:disable GitlabSecurity/PublicSend
end end
def chronic_duration_attributes
@chronic_duration_attributes ||= {}
end end
def output_chronic_duration_attribute(source_attribute)
value = attributes[source_attribute.to_s]
ChronicDuration.output(value, format: :short) if value
end end
end end
...@@ -12,10 +12,10 @@ shared_examples 'ChronicDurationAttribute reader' do ...@@ -12,10 +12,10 @@ shared_examples 'ChronicDurationAttribute reader' do
end end
context 'when value is set to nil' do context 'when value is set to nil' do
it 'outputs empty string' do it 'outputs nil' do
subject.send("#{source_field}=", nil) subject.send("#{source_field}=", nil)
expect(subject.send(virtual_field)).to be_empty expect(subject.send(virtual_field)).to be_nil
end end
end end
end end
...@@ -25,15 +25,15 @@ shared_examples 'ChronicDurationAttribute writer' do ...@@ -25,15 +25,15 @@ shared_examples 'ChronicDurationAttribute writer' do
expect(subject.class).to be_public_method_defined("#{virtual_field}=") expect(subject.class).to be_public_method_defined("#{virtual_field}=")
end end
it 'parses chronic duration input' do before do
subject.send("#{virtual_field}=", '10m') subject.send("#{virtual_field}=", '10m')
end
it 'parses chronic duration input' do
expect(subject.send(source_field)).to eq(600) expect(subject.send(source_field)).to eq(600)
end end
it 'passes validation' do it 'passes validation' do
subject.send("#{virtual_field}=", '10m')
expect(subject.valid?).to be_truthy expect(subject.valid?).to be_truthy
end end
...@@ -54,33 +54,34 @@ shared_examples 'ChronicDurationAttribute writer' do ...@@ -54,33 +54,34 @@ shared_examples 'ChronicDurationAttribute writer' do
subject.send("#{virtual_field}=", '-10m') subject.send("#{virtual_field}=", '-10m')
expect(subject.valid?).to be_falsey expect(subject.valid?).to be_falsey
expect(subject.errors&.messages).to include(virtual_field => ['is not a correct duration'])
end end
end end
context 'when empty input is used' do context 'when empty input is used' do
it 'writes nil' do before do
subject.send("#{virtual_field}=", '') subject.send("#{virtual_field}=", '')
end
it 'writes nil' do
expect(subject.send(source_field)).to be_nil expect(subject.send(source_field)).to be_nil
end end
it 'passes validation' do it 'passes validation' do
subject.send("#{virtual_field}=", '')
expect(subject.valid?).to be_truthy expect(subject.valid?).to be_truthy
end end
end end
context 'when nil input is used' do context 'when nil input is used' do
it 'writes nil' do before do
subject.send("#{virtual_field}=", nil) subject.send("#{virtual_field}=", nil)
end
it 'writes nil' do
expect(subject.send(source_field)).to be_nil expect(subject.send(source_field)).to be_nil
end end
it 'passes validation' do it 'passes validation' do
subject.send("#{virtual_field}=", nil)
expect(subject.valid?).to be_truthy expect(subject.valid?).to be_truthy
end end
...@@ -103,6 +104,7 @@ end ...@@ -103,6 +104,7 @@ end
describe 'ChronicDurationAttribute - reader' do describe 'ChronicDurationAttribute - reader' do
let(:source_field) {:timeout} let(:source_field) {:timeout}
let(:virtual_field) {:timeout_human_readable} let(:virtual_field) {:timeout_human_readable}
subject {Ci::BuildMetadata.new} subject {Ci::BuildMetadata.new}
it "doesn't contain dynamically created writer method" do it "doesn't contain dynamically created writer method" do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment