Skip to content
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
12 changes: 11 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,17 @@ Style/FrozenStringLiteralComment:
Metrics/MethodLength:
Max: 30

# Rake DSL uses long task blocks by nature
Metrics/ClassLength:
Exclude:
- 'app/controllers/sismos_controller.rb'
- 'test/controllers/sismos_controller_filters_test.rb'
- 'test/controllers/sismos_controller_test.rb'
- 'test/models/sismo_test.rb'

# Rake DSL and specific test suites use long blocks by nature
Metrics/BlockLength:
Exclude:
- 'lib/tasks/**/*.rake'
- 'test/controllers/sismos_controller_filters_test.rb'
- 'test/controllers/sismos_controller_test.rb'
- 'test/models/sismo_test.rb'
22 changes: 21 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help backend install clean dev-build dev-up dev-down dev-down-clean dev-setup dev-install dev-shell-backend
.PHONY: help backend install clean lint lint-fix dev-build dev-up dev-down dev-down-clean dev-setup dev-install dev-lint dev-lint-fix dev-shell-backend

# Colors for terminal output
GREEN = \033[0;32m
Expand All @@ -9,6 +9,8 @@ help: ## Show help information
@echo " make help - Show this help message"
@echo " make install - Install all dependencies (host)"
@echo " make backend - Start backend server (host)"
@echo " make lint - Run RuboCop linter (host)"
@echo " make lint-fix - Run RuboCop auto-correct (host)"
@echo " make clean - Clean temporary files (host)"
@echo ""
@echo " Docker dev commands:"
Expand All @@ -18,6 +20,8 @@ help: ## Show help information
@echo " make dev-down-clean - Stop containers + remove volumes (fresh start)"
@echo " make dev-setup - Full setup: build, create DB, run migrations"
@echo " make dev-install - Install/update dependencies inside containers"
@echo " make dev-lint - Run RuboCop linter inside backend container"
@echo " make dev-lint-fix - Run RuboCop auto-correct inside backend container"
@echo " make dev-shell-backend - Open shell in backend container"

install: ## Install dependencies
Expand All @@ -28,6 +32,14 @@ backend: ## Start backend server
@echo "$(GREEN)Starting backend server...$(NC)"
@bin/rails s

lint: ## Run RuboCop linter (host)
@echo "$(GREEN)Running RuboCop...$(NC)"
@bundle exec rubocop

lint-fix: ## Run RuboCop auto-correct (host)
@echo "$(GREEN)Running RuboCop auto-correct...$(NC)"
@bundle exec rubocop -A

clean: ## Clean temporary files
@echo "$(GREEN)Cleaning temporary files...$(NC)"
@rm -rf tmp/cache
Expand Down Expand Up @@ -68,5 +80,13 @@ dev-install: ## Install/update dependencies inside containers
@echo "$(GREEN)Installing backend dependencies...$(NC)"
docker compose exec backend bundle install

dev-lint: ## Run RuboCop linter inside backend container
@echo "$(GREEN)Running RuboCop inside backend container...$(NC)"
docker compose exec -T backend bundle exec rubocop

dev-lint-fix: ## Run RuboCop auto-correct inside backend container
@echo "$(GREEN)Running RuboCop auto-correct inside backend container...$(NC)"
docker compose exec -T backend bundle exec rubocop -A

Comment thread
Euler-B marked this conversation as resolved.
dev-shell-backend: ## Open shell in backend container
docker compose exec backend bash
120 changes: 117 additions & 3 deletions app/controllers/sismos_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class SismosController < ApplicationController
MAX_PER_PAGE = 1000
def index
filtered_sismos = filter_sismos
return if performed?

paginated_sismos = filtered_sismos.paginate(page: params[:page], per_page: params[:per_page])

Expand All @@ -17,14 +18,127 @@ def index
def filter_sismos
sismos = Sismo.all

if params[:filters].present? && params[:filters][:mag_type].present?
mag_types = params[:filters][:mag_type].split(',')
sismos = sismos.where(magType: mag_types)
sismos = apply_mag_type_filter(sismos)
sismos = apply_magnitude_range_filter(sismos)
return unless sismos

sismos = apply_date_range_filter(sismos)
return unless sismos

apply_tsunami_filter(sismos)
end

def apply_mag_type_filter(sismos)
return sismos unless filter_param(:mag_type).present?

mag_types = filter_param(:mag_type).split(',')
sismos.by_mag_type(mag_types)
Comment thread
Euler-B marked this conversation as resolved.
end
Comment thread
Euler-B marked this conversation as resolved.

def apply_magnitude_range_filter(sismos)
if filter_param(:mag_min).present?
mag_min = parse_float_filter(filter_param(:mag_min))
if mag_min.nil?
render json: { error: 'Invalid value for filter: mag_min' }, status: :bad_request
return nil
end
sismos = sismos.by_mag_min(mag_min)
end

if filter_param(:mag_max).present?
mag_max = parse_float_filter(filter_param(:mag_max))
if mag_max.nil?
render json: { error: 'Invalid value for filter: mag_max' }, status: :bad_request
return nil
end
sismos = sismos.by_mag_max(mag_max)
end

sismos
end

def parse_float_filter(value)
return nil if value.blank?

Float(value.to_s.strip)
rescue ArgumentError, TypeError
nil
end

def apply_date_range_filter(sismos)
if filter_param(:date_from).present?
date_from = parse_date_filter(filter_param(:date_from), is_date_to: false)
unless date_from
render json: { error: 'Invalid date format for filter: date_from' }, status: :bad_request
return nil
end
sismos = sismos.by_date_from(date_from)
end

if filter_param(:date_to).present?
date_to = parse_date_filter(filter_param(:date_to), is_date_to: true)
unless date_to
render json: { error: 'Invalid date format for filter: date_to' }, status: :bad_request
return nil
end
sismos = sismos.by_date_to(date_to)
end

sismos
end
Comment thread
coderabbitai[bot] marked this conversation as resolved.

def parse_date_filter(value, is_date_to: false)
return nil if value.blank?

str = value.to_s.strip
return parse_iso_date(str, is_date_to: is_date_to) if str.match?(/\A\d{4}-\d{2}-\d{2}\z/)

parse_datetime_string(str)
end

def parse_iso_date(str, is_date_to:)
date = Date.iso8601(str)
is_date_to ? date.in_time_zone.end_of_day : date.in_time_zone.beginning_of_day
rescue StandardError
nil
end

def parse_datetime_string(str)
parsed = Time.zone.parse(str)
return nil if parsed.nil? || parsed.year < 1000 || parsed.year > 9999

parsed
rescue StandardError
nil
end

def apply_tsunami_filter(sismos)
tsunami_param = filter_param(:tsunami)
return sismos if tsunami_param.blank?

tsunami_val = parse_boolean_filter(tsunami_param)
if tsunami_val.nil?
render json: { error: 'Invalid value for filter: tsunami' }, status: :bad_request
return nil
end

sismos.by_tsunami(tsunami_val)
end

def parse_boolean_filter(value)
str = value.to_s.strip.downcase
return nil unless %w[true false 1 0 t f].include?(str)

ActiveModel::Type::Boolean.new.cast(str)
end
Comment thread
Euler-B marked this conversation as resolved.

def filter_param(key)
filters = params[:filters]
return nil unless filters.is_a?(ActionController::Parameters)

filters[key]
end

Comment thread
Euler-B marked this conversation as resolved.
def serialize_sismos(sismos)
serialized_sismos = sismos.map do |sismo|
{
Expand Down
11 changes: 11 additions & 0 deletions app/models/sismo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,15 @@ class Sismo < ApplicationRecord
validates :mag, inclusion: { in: -1.0..10.0 }
validates :latitude, inclusion: { in: -90.0..90.0 }
validates :longitude, inclusion: { in: -180.0..180.0 }

# ── Filter scopes ──────────────────────────────────────────────────
scope :by_mag_type, ->(types) { where(magType: types) }
scope :by_mag_min, ->(min) { where('mag >= ?', Float(min)) }
scope :by_mag_max, ->(max) { where('mag <= ?', Float(max)) }
scope :by_date_from, ->(date) { where('created_at >= ?', date) }
scope :by_date_to, ->(date) { where('created_at <= ?', date) }
scope :by_tsunami, lambda { |val|
tsunami = ActiveModel::Type::Boolean.new.cast(val)
tsunami ? where(tsunami: true) : where(tsunami: [false, nil])
}
end
9 changes: 9 additions & 0 deletions db/migrate/20260803034001_add_filter_indexes_to_sismos.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class AddFilterIndexesToSismos < ActiveRecord::Migration[7.2]
disable_ddl_transaction!

def change
add_index :sismos, :mag, algorithm: :concurrently
add_index :sismos, :magType, algorithm: :concurrently
add_index :sismos, :created_at, algorithm: :concurrently
end
end
Comment thread
coderabbitai[bot] marked this conversation as resolved.
5 changes: 4 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading