mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-09 08:47:11 -05:00
Extract update location sharing logic to a service object
This commit is contained in:
parent
018760812a
commit
6fb5d98b19
4 changed files with 165 additions and 48 deletions
|
|
@ -77,57 +77,17 @@ class FamiliesController < ApplicationController
|
|||
end
|
||||
|
||||
def update_location_sharing
|
||||
enabled = ActiveModel::Type::Boolean.new.cast(params[:enabled])
|
||||
duration = params[:duration]
|
||||
result = Families::UpdateLocationSharing.new(
|
||||
user: current_user,
|
||||
enabled: params[:enabled],
|
||||
duration: params[:duration]
|
||||
).call
|
||||
|
||||
if current_user.update_family_location_sharing!(enabled, duration: duration)
|
||||
response_data = {
|
||||
success: true,
|
||||
enabled: enabled,
|
||||
duration: current_user.family_sharing_duration,
|
||||
message: build_sharing_message(enabled, duration)
|
||||
}
|
||||
|
||||
if enabled && current_user.family_sharing_expires_at.present?
|
||||
response_data[:expires_at] = current_user.family_sharing_expires_at.iso8601
|
||||
response_data[:expires_at_formatted] = current_user.family_sharing_expires_at.strftime('%b %d at %I:%M %p')
|
||||
end
|
||||
|
||||
render json: response_data
|
||||
else
|
||||
render json: {
|
||||
success: false,
|
||||
message: 'Failed to update location sharing setting'
|
||||
}, status: :unprocessable_content
|
||||
end
|
||||
rescue => e
|
||||
render json: {
|
||||
success: false,
|
||||
message: 'An error occurred while updating location sharing'
|
||||
}, status: :internal_server_error
|
||||
render json: result.payload, status: result.status
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_sharing_message(enabled, duration)
|
||||
return 'Location sharing disabled' unless enabled
|
||||
|
||||
case duration
|
||||
when '1h'
|
||||
'Location sharing enabled for 1 hour'
|
||||
when '6h'
|
||||
'Location sharing enabled for 6 hours'
|
||||
when '12h'
|
||||
'Location sharing enabled for 12 hours'
|
||||
when '24h'
|
||||
'Location sharing enabled for 24 hours'
|
||||
when 'permanent', nil
|
||||
'Location sharing enabled'
|
||||
else
|
||||
duration.to_i > 0 ? "Location sharing enabled for #{duration.to_i} hours" : 'Location sharing enabled'
|
||||
end
|
||||
end
|
||||
|
||||
def set_family
|
||||
@family = current_user.family
|
||||
redirect_to new_family_path, alert: 'You are not in a family' unless @family
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Family::InvitationsController < ApplicationController
|
||||
before_action :authenticate_user!, except: %i[show accept]
|
||||
before_action :ensure_family_feature_enabled!, except: %i[show accept]
|
||||
before_action :authenticate_user!, except: %i[show]
|
||||
before_action :ensure_family_feature_enabled!, except: %i[show]
|
||||
before_action :set_family, except: %i[show accept]
|
||||
before_action :set_invitation_by_id_and_family, only: %i[destroy]
|
||||
before_action :set_invitation_by_id, only: %i[accept]
|
||||
|
|
|
|||
69
app/services/families/update_location_sharing.rb
Normal file
69
app/services/families/update_location_sharing.rb
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Families::UpdateLocationSharing
|
||||
Result = Struct.new(:success?, :payload, :status, keyword_init: true)
|
||||
|
||||
def initialize(user:, enabled:, duration:)
|
||||
@user = user
|
||||
@enabled_param = enabled
|
||||
@duration_param = duration
|
||||
@boolean_caster = ActiveModel::Type::Boolean.new
|
||||
end
|
||||
|
||||
def call
|
||||
if update_location_sharing
|
||||
success_result
|
||||
else
|
||||
failure_result('Failed to update location sharing setting', :unprocessable_content)
|
||||
end
|
||||
rescue => error
|
||||
Rails.logger.error("Failed to update family location sharing: #{error.message}") if defined?(Rails)
|
||||
failure_result('An error occurred while updating location sharing', :internal_server_error)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :user, :enabled_param, :duration_param, :boolean_caster
|
||||
|
||||
def update_location_sharing
|
||||
user.update_family_location_sharing!(enabled?, duration: duration_param)
|
||||
end
|
||||
|
||||
def enabled?
|
||||
@enabled ||= boolean_caster.cast(enabled_param)
|
||||
end
|
||||
|
||||
def success_result
|
||||
payload = {
|
||||
success: true,
|
||||
enabled: enabled?,
|
||||
duration: user.family_sharing_duration,
|
||||
message: build_sharing_message
|
||||
}
|
||||
|
||||
if enabled? && user.family_sharing_expires_at.present?
|
||||
payload[:expires_at] = user.family_sharing_expires_at.iso8601
|
||||
payload[:expires_at_formatted] = user.family_sharing_expires_at.strftime('%b %d at %I:%M %p')
|
||||
end
|
||||
|
||||
Result.new(success?: true, payload: payload, status: :ok)
|
||||
end
|
||||
|
||||
def failure_result(message, status)
|
||||
Result.new(success?: false, payload: { success: false, message: message }, status: status)
|
||||
end
|
||||
|
||||
def build_sharing_message
|
||||
return 'Location sharing disabled' unless enabled?
|
||||
|
||||
case duration_param
|
||||
when '1h' then 'Location sharing enabled for 1 hour'
|
||||
when '6h' then 'Location sharing enabled for 6 hours'
|
||||
when '12h' then 'Location sharing enabled for 12 hours'
|
||||
when '24h' then 'Location sharing enabled for 24 hours'
|
||||
when 'permanent', nil then 'Location sharing enabled'
|
||||
else
|
||||
duration_param.to_i.positive? ? "Location sharing enabled for #{duration_param.to_i} hours" : 'Location sharing enabled'
|
||||
end
|
||||
end
|
||||
end
|
||||
88
spec/services/families/update_location_sharing_spec.rb
Normal file
88
spec/services/families/update_location_sharing_spec.rb
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Families::UpdateLocationSharing do
|
||||
include ActiveSupport::Testing::TimeHelpers
|
||||
|
||||
describe '.call' do
|
||||
subject(:call_service) do
|
||||
described_class.new(user: user, enabled: enabled, duration: duration).call
|
||||
end
|
||||
|
||||
let(:duration) { '1h' }
|
||||
|
||||
context 'when the user is in a family' do
|
||||
let(:user) { create(:user) }
|
||||
let!(:family_membership) { create(:family_membership, user: user) }
|
||||
|
||||
context 'when enabling location sharing with a duration' do
|
||||
let(:enabled) { true }
|
||||
|
||||
around do |example|
|
||||
travel_to(Time.zone.local(2024, 1, 1, 12, 0, 0)) { example.run }
|
||||
end
|
||||
|
||||
it 'returns a successful result with the expected payload' do
|
||||
result = call_service
|
||||
|
||||
expect(result).to be_success
|
||||
expect(result.status).to eq(:ok)
|
||||
expect(result.payload[:success]).to be true
|
||||
expect(result.payload[:enabled]).to be true
|
||||
expect(result.payload[:duration]).to eq('1h')
|
||||
expect(result.payload[:message]).to eq('Location sharing enabled for 1 hour')
|
||||
expect(result.payload[:expires_at]).to eq(1.hour.from_now.iso8601)
|
||||
expect(result.payload[:expires_at_formatted]).to eq(1.hour.from_now.strftime('%b %d at %I:%M %p'))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when disabling location sharing' do
|
||||
let(:enabled) { false }
|
||||
let(:duration) { nil }
|
||||
|
||||
it 'returns a successful result without expiration details' do
|
||||
result = call_service
|
||||
|
||||
expect(result).to be_success
|
||||
expect(result.payload[:success]).to be true
|
||||
expect(result.payload[:enabled]).to be false
|
||||
expect(result.payload[:message]).to eq('Location sharing disabled')
|
||||
expect(result.payload).not_to have_key(:expires_at)
|
||||
expect(result.payload).not_to have_key(:expires_at_formatted)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when update raises an unexpected error' do
|
||||
let(:enabled) { true }
|
||||
|
||||
before do
|
||||
allow(user).to receive(:update_family_location_sharing!).and_raise(StandardError, 'boom')
|
||||
end
|
||||
|
||||
it 'returns a failure result with internal server error status' do
|
||||
result = call_service
|
||||
|
||||
expect(result).not_to be_success
|
||||
expect(result.status).to eq(:internal_server_error)
|
||||
expect(result.payload[:success]).to be false
|
||||
expect(result.payload[:message]).to eq('An error occurred while updating location sharing')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user is not in a family' do
|
||||
let(:user) { create(:user) }
|
||||
let(:enabled) { true }
|
||||
|
||||
it 'returns a failure result with unprocessable content status' do
|
||||
result = call_service
|
||||
|
||||
expect(result).not_to be_success
|
||||
expect(result.status).to eq(:unprocessable_content)
|
||||
expect(result.payload[:success]).to be false
|
||||
expect(result.payload[:message]).to eq('Failed to update location sharing setting')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in a new issue