Simplify some services by removing unused parameters and validations

This commit is contained in:
Eugene Burmakin 2025-09-18 20:02:18 +02:00
parent 0905ef65a5
commit 3fd7634657
9 changed files with 24 additions and 103 deletions

View file

@ -4,21 +4,21 @@ class Api::V1::Maps::HexagonsController < ApiController
skip_before_action :authenticate_api_key, if: :public_sharing_request?
def index
return unless public_sharing_request? || validate_required_parameters
result = Maps::HexagonRequestHandler.call(
result = Maps::HexagonRequestHandler.new(
params: params,
current_api_user: current_api_user
)
).call
render json: result
rescue ActionController::ParameterMissing => e
render json: { error: "Missing required parameter: #{e.param}" }, status: :bad_request
rescue ActionController::BadRequest => e
render json: { error: e.message }, status: :bad_request
rescue Maps::HexagonContextResolver::SharedStatsNotFoundError => e
render json: { error: e.message }, status: :not_found
rescue Maps::DateParameterCoercer::InvalidDateFormatError => e
render json: { error: e.message }, status: :bad_request
rescue Maps::H3HexagonCenters::TooManyHexagonsError,
Maps::H3HexagonCenters::InvalidCoordinatesError,
Maps::H3HexagonCenters::PostGISError => e
rescue Maps::H3HexagonCenters::PostGISError => e
render json: { error: e.message }, status: :bad_request
rescue StandardError => _e
handle_service_error
@ -56,10 +56,6 @@ class Api::V1::Maps::HexagonsController < ApiController
private
def hexagon_params
params.permit(:uuid, :start_date, :end_date)
end
def handle_service_error
render json: { error: 'Failed to generate hexagon grid' }, status: :internal_server_error
end
@ -67,39 +63,4 @@ class Api::V1::Maps::HexagonsController < ApiController
def public_sharing_request?
params[:uuid].present?
end
def validate_required_parameters
required_params = %i[min_lon max_lon min_lat max_lat start_date end_date]
missing_params = required_params.select { |param| params[param].blank? }
unless missing_params.empty?
error_message = "Missing required parameters: #{missing_params.join(', ')}"
render json: { error: error_message }, status: :bad_request
return false
end
# Validate coordinate ranges
unless valid_coordinate_ranges?
render json: { error: 'Invalid coordinate ranges' }, status: :bad_request
return false
end
true
end
def valid_coordinate_ranges?
min_lon = params[:min_lon].to_f
max_lon = params[:max_lon].to_f
min_lat = params[:min_lat].to_f
max_lat = params[:max_lat].to_f
# Check longitude range (-180 to 180)
return false unless (-180..180).cover?(min_lon) && (-180..180).cover?(max_lon)
# Check latitude range (-90 to 90)
return false unless (-90..90).cover?(min_lat) && (-90..90).cover?(max_lat)
# Check that min values are less than max values
return false unless min_lon < max_lon && min_lat < max_lat
true
end
end

View file

@ -4,10 +4,9 @@ module Maps
class BoundsCalculator
class NoUserFoundError < StandardError; end
class NoDateRangeError < StandardError; end
class NoDataFoundError < StandardError; end
def initialize(target_user:, start_date:, end_date:)
@target_user = target_user
def initialize(user:, start_date:, end_date:)
@user = user
@start_date = start_date
@end_date = end_date
end
@ -18,7 +17,7 @@ module Maps
start_timestamp = Maps::DateParameterCoercer.new(@start_date).call
end_timestamp = Maps::DateParameterCoercer.new(@end_date).call
points_relation = @target_user.points.where(timestamp: start_timestamp..end_timestamp)
points_relation = @user.points.where(timestamp: start_timestamp..end_timestamp)
point_count = points_relation.count
return build_no_data_response if point_count.zero?
@ -30,7 +29,7 @@ module Maps
private
def validate_inputs!
raise NoUserFoundError, 'No user found' unless @target_user
raise NoUserFoundError, 'No user found' unless @user
raise NoDateRangeError, 'No date range specified' unless @start_date && @end_date
end
@ -42,7 +41,7 @@ module Maps
WHERE user_id = $1
AND timestamp BETWEEN $2 AND $3",
'bounds_query',
[@target_user.id, start_timestamp, end_timestamp]
[@user.id, start_timestamp, end_timestamp]
).first
end

View file

@ -7,15 +7,10 @@ class Maps::H3HexagonCenters
DEFAULT_H3_RESOLUTION = 8 # Small hexagons for good detail
MAX_HEXAGONS = 10_000 # Maximum number of hexagons to prevent memory issues
# Validation error classes
class TooManyHexagonsError < StandardError; end
class InvalidCoordinatesError < StandardError; end
class PostGISError < StandardError; end
attr_reader :user_id, :start_date, :end_date, :h3_resolution
validates :user_id, presence: true
def initialize(user_id:, start_date:, end_date:, h3_resolution: DEFAULT_H3_RESOLUTION)
@user_id = user_id
@start_date = start_date
@ -24,8 +19,6 @@ class Maps::H3HexagonCenters
end
def call
validate!
points = fetch_user_points
return [] if points.empty?
@ -104,10 +97,4 @@ class Maps::H3HexagonCenters
service.call
end
def validate!
return if valid?
raise InvalidCoordinatesError, errors.full_messages.join(', ')
end
end

View file

@ -96,7 +96,6 @@ module Maps
def build_hexagon_properties(index, earliest, latest)
{
'hex_id' => index + 1,
'hex_size' => 1000,
'earliest_point' => earliest ? Time.zone.at(earliest).iso8601 : nil,
'latest_point' => latest ? Time.zone.at(latest).iso8601 : nil
}
@ -107,7 +106,6 @@ module Maps
'type' => 'FeatureCollection',
'features' => hexagon_features,
'metadata' => {
'hex_size_m' => 1000,
'count' => hexagon_features.count,
'user_id' => target_user.id,
'pre_calculated' => true

View file

@ -2,13 +2,9 @@
module Maps
class HexagonRequestHandler
def self.call(params:, current_api_user: nil)
new(params: params, current_api_user: current_api_user).call
end
def initialize(params:, current_api_user: nil)
def initialize(params:, user: nil)
@params = params
@current_api_user = current_api_user
@user = user
end
def call
@ -34,16 +30,15 @@ module Maps
private
attr_reader :params, :current_api_user
attr_reader :params, :user
def resolve_context
Maps::HexagonContextResolver.call(
params: params,
current_api_user: current_api_user
user: user
)
end
def find_matching_stat(context)
return unless context[:target_user] && context[:start_date]

View file

@ -103,9 +103,7 @@ class Stats::CalculateMonth
Rails.logger.info "Pre-calculated #{result.size} H3 hexagon centers for user #{user.id}, #{year}-#{month}"
result
rescue Maps::H3HexagonCenters::TooManyHexagonsError,
Maps::H3HexagonCenters::InvalidCoordinatesError,
Maps::H3HexagonCenters::PostGISError => e
rescue Maps::H3HexagonCenters::PostGISError => e
Rails.logger.warn "H3 hexagon centers calculation failed for user #{user.id}, #{year}-#{month}: #{e.message}"
nil
end

View file

@ -17,7 +17,6 @@ RSpec.describe 'Api::V1::Maps::Hexagons', type: :request do
min_lat: 40.6,
max_lon: -73.9,
max_lat: 40.8,
hex_size: 1000,
start_date: '2024-06-01T00:00:00Z',
end_date: '2024-06-30T23:59:59Z'
}
@ -57,7 +56,7 @@ RSpec.describe 'Api::V1::Maps::Hexagons', type: :request do
expect(response).to have_http_status(:bad_request)
json_response = JSON.parse(response.body)
expect(json_response['error']).to include('Missing required parameters')
expect(json_response['error']).to include('Missing required parameter')
expect(json_response['error']).to include('min_lon')
end
@ -69,15 +68,6 @@ RSpec.describe 'Api::V1::Maps::Hexagons', type: :request do
expect(response).to have_http_status(:bad_request)
end
it 'uses custom hex_size when provided' do
custom_params = valid_params.merge(hex_size: 500)
get '/api/v1/maps/hexagons', params: custom_params, headers: headers
expect(response).to have_http_status(:success)
end
context 'with no data points' do
let(:empty_user) { create(:user) }
let(:empty_headers) { { 'Authorization' => "Bearer #{empty_user.api_key}" } }
@ -233,7 +223,6 @@ RSpec.describe 'Api::V1::Maps::Hexagons', type: :request do
# Verify properties include timestamp data
expect(feature['properties']['earliest_point']).to be_present
expect(feature['properties']['latest_point']).to be_present
expect(feature['properties']['hex_size']).to eq(1000)
end
it 'generates proper hexagon polygons from centers' do

View file

@ -48,7 +48,6 @@ RSpec.describe Maps::HexagonCenterManager do
properties = feature['properties']
expect(properties['hex_id']).to eq(index + 1)
expect(properties['hex_size']).to eq(1000)
expect(properties['earliest_point']).to be_present
expect(properties['latest_point']).to be_present
end
@ -126,4 +125,4 @@ RSpec.describe Maps::HexagonCenterManager do
end
end
end
end
end

View file

@ -5,10 +5,10 @@ require 'rails_helper'
RSpec.describe Maps::HexagonRequestHandler do
describe '.call' do
subject(:handle_request) do
described_class.call(
described_class.new(
params: params,
current_api_user: current_api_user
)
).call
end
let(:user) { create(:user) }
@ -32,7 +32,6 @@ RSpec.describe Maps::HexagonRequestHandler do
min_lat: 40.6,
max_lon: -73.9,
max_lat: 40.8,
hex_size: 1000,
start_date: '2024-06-01T00:00:00Z',
end_date: '2024-06-30T23:59:59Z'
}
@ -68,8 +67,7 @@ RSpec.describe Maps::HexagonRequestHandler do
min_lon: -74.1,
min_lat: 40.6,
max_lon: -73.9,
max_lat: 40.8,
hex_size: 1000
max_lat: 40.8
}
)
end
@ -94,8 +92,7 @@ RSpec.describe Maps::HexagonRequestHandler do
min_lon: -74.1,
min_lat: 40.6,
max_lon: -73.9,
max_lat: 40.8,
hex_size: 1000
max_lat: 40.8
}
)
end
@ -123,8 +120,7 @@ RSpec.describe Maps::HexagonRequestHandler do
min_lon: -74.1,
min_lat: 40.6,
max_lon: -73.9,
max_lat: 40.8,
hex_size: 1000
max_lat: 40.8
}
)
end
@ -148,7 +144,6 @@ RSpec.describe Maps::HexagonRequestHandler do
end
end
context 'error handling' do
let(:params) do
ActionController::Parameters.new(