Skip to content

Commit

Permalink
Support setting retires_on and retirement_warn for services from dialogs
Browse files Browse the repository at this point in the history
Pass user so time parsing occurs in proper timezone.
  • Loading branch information
gmcculloug committed Sep 2, 2018
1 parent d025d39 commit 8a41883
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 14 deletions.
2 changes: 1 addition & 1 deletion app/models/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,6 @@ def configuration_script
end

private def update_attributes_from_dialog
Service::DialogProperties.parse(options[:dialog]).each { |key, value| self[key] = value }
Service::DialogProperties.parse(options[:dialog], evm_owner).each { |key, value| self[key] = value }
end
end
11 changes: 8 additions & 3 deletions app/models/service/dialog_properties.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
class Service
class DialogProperties
def initialize(options)
require_nested :Retirement

def initialize(options, user)
@attributes = {}
@options = options || {}
@user = user
end

def self.parse(options)
new(options).parse
def self.parse(options, user)
new(options, user).parse
end

def parse
@attributes[:name] = @options['dialog_service_name'] if @options['dialog_service_name'].present?
@attributes[:description] = @options['dialog_service_description'] if @options['dialog_service_description'].present?

@attributes.merge!(Service::DialogProperties::Retirement.parse(@options, @user))
end
end
end
97 changes: 97 additions & 0 deletions app/models/service/dialog_properties/retirement.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
class Service
class DialogProperties
class Retirement
RETIREMENT_WARN_FIELD_NAMES = %w(warn_on warn_in_days warn_in_hours warn_offset_days warn_offset_hours).freeze

def initialize(options, user)
@attributes = {}
@options = options || {}
@user = user
end

def self.parse(options, user)
new(options, user).parse
end

def parse
@attributes.tap { parse_options }
end

private

def parse_options
if @options['dialog_service_retires_on'].present?
field_name = 'dialog_service_retires_on'
self.retire_on_date = time_parse(@options[field_name])
elsif @options['dialog_service_retires_in_hours'].present?
field_name = 'dialog_service_retires_in_hours'
retires_in_duration(@options[field_name], :hours)
elsif @options['dialog_service_retires_in_days'].present?
field_name = 'dialog_service_retires_in_days'
retires_in_duration(@options[field_name], :days)
end
rescue StandardError
$log.error("Error parsing dialog retirement property [#{field_name}] with value [#{@options[field_name].inspect}]. Error: #{$!}")
end

def retires_in_duration(value, modifier)
self.retire_on_date = time_now + offset_set(value, modifier)
end

def offset_set(value, modifier)
value.to_i.send(modifier).tap do |offset|
raise "Offset cannot be a zero or negative value" if offset.zero? || offset.negative?
end
end

def retire_on_date=(value)
@attributes[:retires_on] = value
retirement_warning
end

def retirement_warning
warn_value = parse_retirement_warn
@attributes[:retirement_warn] = warn_value if warn_value
end

def parse_retirement_warn
warn_key, value = retirement_warn_properties

case warn_key
when 'warn_on'
time_parse(value)
when 'warn_in_days'
time_now + offset_set(value, :days)
when 'warn_in_hours'
time_now + offset_set(value, :hours)
when 'warn_offset_days'
@attributes[:retires_on] - offset_set(value, :days)
when 'warn_offset_hours'
@attributes[:retires_on] - offset_set(value, :hours)
end
end

def retirement_warn_properties
warn_name = RETIREMENT_WARN_FIELD_NAMES.detect do |field_name|
@options["dialog_service_retirement_#{field_name}"].present?
end

return warn_name, @options["dialog_service_retirement_#{warn_name}"] if warn_name
end

def time_parse(value)
with_user_timezone { Time.zone.parse(value).utc }
end

def time_now
with_user_timezone { Time.zone.now.utc }
end

def with_user_timezone
user = @user || User.current_user

user ? user.with_my_timezone { yield } : yield
end
end
end
end
135 changes: 135 additions & 0 deletions spec/models/service/dialog_properties/retirement_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
describe Service::DialogProperties::Retirement do
let(:time) { Time.new(2018, 7, 21, 12, 20, 0, 0) }

it 'with a nil parameter' do
options = nil
expect(described_class.parse(options, nil)).to eq({})
end

it 'with an empty hash' do
options = {}
expect(described_class.parse(options, nil)).to eq({})
end

context 'when setting retirement date' do
describe 'retires_on' do
it 'with invalid time' do
options = {'dialog_service_retires_on' => 'xyz'}
parsed_results = described_class.parse(options, nil)

expect(parsed_results[:retires_on]).to be_nil
expect(parsed_results[:retirement_warn]).to be_nil
end

it 'with valid time' do
Timecop.freeze(time) do
options = {'dialog_service_retires_on' => time.to_s}
parsed_results = described_class.parse(options, nil)

expect(parsed_results[:retires_on]).to eq(time)
expect(parsed_results[:retirement_warn]).to be_nil
end
end
end

describe 'retires_in_hours' do
it 'with invalid time' do
options = {'dialog_service_retires_in_hours' => 'xyz'}
parsed_results = described_class.parse(options, nil)

expect(parsed_results[:retires_on]).to be_nil
expect(parsed_results[:retirement_warn]).to be_nil
end

it 'with valid time' do
Timecop.freeze(time) do
options = {'dialog_service_retires_in_hours' => 5}
parsed_results = described_class.parse(options, nil)

expect(parsed_results[:retires_on]).to eq(time + 5.hours)
expect(parsed_results[:retirement_warn]).to be_nil
end
end
end

describe 'retires_in_days' do
it 'with invalid time' do
options = {'dialog_service_retires_in_days' => 'xyz'}
parsed_results = described_class.parse(options, nil)

expect(parsed_results[:retires_on]).to be_nil
expect(parsed_results[:retirement_warn]).to be_nil
end

it 'with valid time' do
Timecop.freeze(time) do
options = {'dialog_service_retires_in_days' => 5}
parsed_results = described_class.parse(options, nil)

expect(parsed_results[:retires_on]).to eq(time + 5.days)
expect(parsed_results[:retirement_warn]).to be_nil
end
end
end
end

context 'when setting retirement warn date' do
it 'with retirement_warn_on' do
user = FactoryGirl.create(:user)
expect(user).to receive(:with_my_timezone).and_yield.twice

Timecop.freeze(time) do
options = {'dialog_service_retires_in_days' => 5,
'dialog_service_retirement_warn_on' => (time + 1.day).to_s}
parsed_results = described_class.parse(options, user)

expect(parsed_results[:retires_on]).to eq(time + 5.days)
expect(parsed_results[:retirement_warn]).to eq(time + 1.day)
end
end

it 'with retirement_warn_in_days' do
Timecop.freeze(time) do
options = {'dialog_service_retires_in_days' => 5,
'dialog_service_retirement_warn_in_days' => 1}
parsed_results = described_class.parse(options, nil)

expect(parsed_results[:retires_on]).to eq(time + 5.days)
expect(parsed_results[:retirement_warn]).to eq(time + 1.day)
end
end

it 'with retirement_warn_offset_days' do
Timecop.freeze(time) do
options = {'dialog_service_retires_in_days' => 5,
'dialog_service_retirement_warn_offset_days' => 4}
parsed_results = described_class.parse(options, nil)

expect(parsed_results[:retires_on]).to eq(time + 5.days)
expect(parsed_results[:retirement_warn]).to eq(time + 1.day)
end
end

it 'with retirement_warn_in_hours' do
Timecop.freeze(time) do
options = {'dialog_service_retires_in_hours' => 5,
'dialog_service_retirement_warn_in_hours' => 1}
parsed_results = described_class.parse(options, nil)

expect(parsed_results[:retires_on]).to eq(time + 5.hours)
expect(parsed_results[:retirement_warn]).to eq(time + 1.hour)
end
end

it 'with retirement_warn_offset_hours' do
Timecop.freeze(time) do
options = {'dialog_service_retires_in_hours' => 5,
'dialog_service_retirement_warn_offset_hours' => 4}
parsed_results = described_class.parse(options, nil)

expect(parsed_results[:retires_on]).to eq(time + 5.hours)
expect(parsed_results[:retirement_warn]).to eq(time + 1.hour)
end
end
end
end
25 changes: 15 additions & 10 deletions spec/models/service/dialog_properties_spec.rb
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
describe Service::DialogProperties do
it 'with a nil parameter' do
it 'with a nil parameter and nil user' do
options = nil
expect(described_class.parse(options)).to eq({})
expect(described_class.parse(options, nil)).to eq({})
end

it 'with an empty hash' do
it 'with an empty hash parameter and nil user' do
options = {}
expect(described_class.parse(options)).to eq({})
expect(described_class.parse(options, nil)).to eq({})
end

context 'name' do
it `will call the Retirement class` do
expect(Service::DialogProperties::Retirement).to receive(:parse).with({}, nil).and_return({})
described_class.parse(nil, nil)
end

describe 'name' do
it 'with an empty name' do
options = {'dialog_service_name' => ' '}
expect(described_class.parse(options)).to eq({})
expect(described_class.parse(options, nil)).to eq({})
end

it 'with option name' do
options = {'dialog_service_name' => 'name from dialog'}
expect(described_class.parse(options)).to eq(:name => 'name from dialog')
expect(described_class.parse(options, nil)).to eq(:name => 'name from dialog')
end
end

context 'description' do
describe 'description' do
it 'with an empty description' do
options = {'dialog_service_description' => ' '}
expect(described_class.parse(options)).to eq({})
expect(described_class.parse(options, nil)).to eq({})
end

it 'with option description' do
options = {'dialog_service_description' => 'test description from dialog'}
expect(described_class.parse(options)).to eq(:description => 'test description from dialog')
expect(described_class.parse(options, nil)).to eq(:description => 'test description from dialog')
end
end
end

0 comments on commit 8a41883

Please sign in to comment.